source: trunk/nomc/c/nomc.c@ 389

Last change on this file since 389 was 386, checked in by cinc, 17 years ago

Use 'public' instead of 'impl' as keyword for methods.

  • Property svn:executable set to *
File size: 13.8 KB
Line 
1/* ***** BEGIN LICENSE BLOCK *****
2* Version: CDDL 1.0/LGPL 2.1
3*
4* The contents of this file are subject to the COMMON DEVELOPMENT AND
5* DISTRIBUTION LICENSE (CDDL) Version 1.0 (the "License"); you may not use
6* this file except in compliance with the License. You may obtain a copy of
7* the License at http://www.sun.com/cddl/
8*
9* Software distributed under the License is distributed on an "AS IS" basis,
10* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11* for the specific language governing rights and limitations under the
12* License.
13*
14* The Original Code is "NOM" Netlabs Object Model
15*
16* The Initial Developer of the Original Code is
17* netlabs.org: Chris Wohlgemuth <cinc-ml@netlabs.org>.
18* Portions created by the Initial Developer are Copyright (C) 2008
19* the Initial Developer. All Rights Reserved.
20*
21* Contributor(s):
22*
23* Alternatively, the contents of this file may be used under the terms of
24* the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
25* case the provisions of the LGPL are applicable instead of those above. If
26* you wish to allow use of your version of this file only under the terms of
27* the LGPL, and not to allow others to use your version of this file under
28* the terms of the CDDL, indicate your decision by deleting the provisions
29* above and replace them with the notice and other provisions required by the
30* LGPL. If you do not delete the provisions above, a recipient may use your
31* version of this file under the terms of any one of the CDDL or the LGPL.
32*
33* ***** END LICENSE BLOCK ***** */
34#ifdef __OS2__
35# define INCL_DOSPROCESS
36# define INCL_DOS
37# define INCL_DOSPROFILE
38# define INCL_DOSERRORS
39# include <os2.h>
40#endif /* __OS2__ */
41
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45
46#ifdef HAVE_IO_H
47# include <io.h>
48#endif
49#ifdef HAVE_UNISTD_H
50# include <unistd.h>
51#endif
52#include <fcntl.h>
53#include <sys/stat.h>
54
55#include <glib.h>
56#include <glib/gprintf.h>
57
58#include "nom.h"
59#include "nomtk.h"
60
61#define INCL_FILE
62#include "parser.h"
63
64static gchar* chrOutputDir="";
65static gboolean fOptionEmitH=FALSE;
66static gboolean fOptionEmitIH=FALSE;
67static gboolean fOptionEmitC=FALSE;
68
69/* Command line options */
70static GOptionEntry gOptionEntries[] =
71{
72 {"directory", 'd', 0, G_OPTION_ARG_FILENAME, &chrOutputDir, "Output directory", NULL},
73 {"emit-h", 0, 0, G_OPTION_ARG_NONE, &fOptionEmitH, "Emmit a header file (*.h)", NULL},
74 {"emit-ih", 0, 0, G_OPTION_ARG_NONE, &fOptionEmitIH, "Emmit an include header (*.ih)", NULL},
75 {"emit-c", 0, 0, G_OPTION_ARG_NONE, &fOptionEmitC, "Emmit an implementation template (*.c)", NULL},
76 {NULL}
77};
78
79
80
81/* Symbols defined for our IDL language.
82 Keep this in synch with the defined enums in parser.h! */
83SYMBOL idlSymbols[]={
84 {"interface", IDL_SYMBOL_INTERFACE, KIND_UNKNOWN},
85 {"class", NOMC_SYMBOL_CLASS, KIND_UNKNOWN}, /* 71 */
86 {"public", NOMC_SYMBOL_PUBLIC, KIND_UNKNOWN},
87 {"NOMINSTANCEVAR", IDL_SYMBOL_INSTANCEVAR, KIND_UNKNOWN},
88 {"override", IDL_SYMBOL_OVERRIDE2, KIND_UNKNOWN},
89 {"NOMREGISTEREDIFACE", IDL_SYMBOL_REGINTERFACE, KIND_TYPESPEC},
90 {"NOMCLASSNAME", IDL_SYMBOL_CLSNAME, KIND_UNKNOWN},
91 {"NOMMETACLASS", IDL_SYMBOL_OLDMETACLASS, KIND_UNKNOWN},
92 {"metaclass", IDL_SYMBOL_METACLASS, KIND_UNKNOWN},
93 {"filestem", IDL_SYMBOL_FILESTEM, KIND_UNKNOWN},
94 {"native", IDL_SYMBOL_NATIVE, KIND_UNKNOWN},
95 {"gulong", IDL_SYMBOL_GULONG, KIND_TYPESPEC},
96 {"gint", IDL_SYMBOL_GINT, KIND_TYPESPEC},
97 {"gpointer", IDL_SYMBOL_GPOINTER, KIND_TYPESPEC},
98 {"gboolean", IDL_SYMBOL_GBOOLEAN, KIND_TYPESPEC},
99 {"gchar", IDL_SYMBOL_GCHAR, KIND_TYPESPEC},
100 {"void", IDL_SYMBOL_VOID, KIND_TYPESPEC},
101
102 {"boolean", IDL_SYMBOL_BOOLEAN, KIND_TYPESPEC},
103 {"string", IDL_SYMBOL_STRING, KIND_TYPESPEC},
104 {"long", IDL_SYMBOL_LONG, KIND_TYPESPEC},
105 {"unsigned", IDL_SYMBOL_LONG, KIND_TYPESPEC},
106
107 {"in", IDL_SYMBOL_IN, KIND_DIRECTION},
108 {"out", IDL_SYMBOL_OUT, KIND_DIRECTION},
109 {"inout", IDL_SYMBOL_INOUT, KIND_DIRECTION},
110 {"define", IDL_SYMBOL_DEFINE, KIND_UNKNOWN},
111 {"ifdef", IDL_SYMBOL_IFDEF, KIND_UNKNOWN},
112 {"endif", IDL_SYMBOL_ENDIF, KIND_UNKNOWN},
113 {NULL, 0, KIND_UNKNOWN}
114},*pSymbols=idlSymbols;
115
116GScanner *gScanner;
117
118/* Holding the current state of parsing and pointers to necessary lists.
119 Referenced by gScanner-user_data. */
120PARSEINFO parseInfo={0};
121//PPARSEINFO pParseInfo=&parseInfo; /* This pointer will go away, don't use */
122
123
124/**
125 Helper function which returns a copy of the typespec string of the current token.
126 That is e.g. 'gint' or 'gpointer'. Note that this function is only called when the
127 current token is indeed a type specification in the IDL file.
128 */
129gchar* getTypeSpecStringFromCurToken(void)
130{
131 GTokenValue value;
132
133 value=gScanner->value;
134
135 switch(gScanner->token)
136 {
137 case G_TOKEN_IDENTIFIER:
138 return g_strdup(value.v_identifier);
139 break;
140 case G_TOKEN_SYMBOL:
141 {
142 /* It's one of our symbols. */
143 PSYMBOL pCurSymbol;
144
145 pCurSymbol=value.v_symbol;
146 return g_strdup(pCurSymbol->chrSymbolName);
147 break;
148 }
149 default:
150 g_scanner_unexp_token(gScanner,
151 G_TOKEN_SYMBOL,
152 NULL,
153 NULL,
154 NULL,
155 "",
156 TRUE); /* is_error */
157
158 break;
159 }
160 return "unknown";
161}
162
163
164/**
165 This is the root parse function. Here starts the fun. When a token is found in the
166 input stream which matches one of the known token types the respective parsing function
167 is called for further processing. In case of an error the parsing function in question
168 prints an error which describes the problem and exits the application.
169
170 This function scans the input until EOF is hit.
171 */
172void parseIt(void)
173{
174
175 while(g_scanner_peek_next_token(gScanner) != G_TOKEN_EOF) {
176 GTokenType token;
177 GTokenValue value;
178
179 parseInfo.fPrintToken=FALSE;
180
181 // g_printf(":: %d %d\n", gScanner->position, parseInfo.uiCurPos);
182 getNextTokenFromStream();
183 // g_printf("::: %d %d\n", gScanner->position, parseInfo.uiCurPos);
184
185 printToFile(gScanner->token);
186
187 token=gScanner->token;
188 value=gScanner->value;
189
190 //printToFile(token);
191
192 switch(token)
193 {
194 case '#':
195 parseInfo.fPrintToken=TRUE;
196 printToFile(token);
197 parseHash(); /* e.g. for correct line numbers */
198 break;
199 case G_TOKEN_SYMBOL:
200 {
201 PSYMBOL pCurSymbol=value.v_symbol;
202 switch(pCurSymbol->uiSymbolToken)
203 {
204 case NOMC_SYMBOL_CLASS:
205 parseClass(token);
206 break;
207 case IDL_SYMBOL_INTERFACE:
208 parseInterface(token);
209 break;
210#if 0
211 case IDL_SYMBOL_NATIVE:
212 parseNative();
213 break;
214 case IDL_SYMBOL_CLSNAME:
215 parseClassName();
216 break;
217 case IDL_SYMBOL_OLDMETACLASS:
218 parseOldMetaClass();
219 break;
220#endif
221 default:
222 break;
223 }
224 break;
225 }
226#if 0
227 case G_TOKEN_IDENTIFIER:
228 g_message("Token: %d (G_TOKEN_IDENTIFIER)\t\t%s", token, value.v_identifier);
229 break;
230 case G_TOKEN_STRING:
231 g_message("Token: %d (G_TOKEN_STRING)\t\t\t%s", token, value.v_string);
232 break;
233 case G_TOKEN_LEFT_PAREN:
234 g_message("Token: %d (G_TOKEN_LEFT_PAREN)\t\t(", token);
235 break;
236 case G_TOKEN_RIGHT_PAREN:
237 g_message("Token: %d (G_TOKEN_RIGHT_PAREN)\t\t)", token);
238 break;
239 case ':':
240 g_message("Token: %d (colon)\t\t:", token);
241 break;
242 case ';':
243 g_message("Token: %d (semicolon)\t\t\t;", token);
244 break;
245 case '/':
246 g_message("Token: %d (slash)\t\t\t/ %s", token, value.v_comment);
247 break;
248 case G_TOKEN_COMMA:
249 g_message("Token: %d (G_TOKEN_COMMA)\t\t\t,", token);
250 break;
251 case G_TOKEN_INT:
252 g_message("Token: %d (G_TOKEN_INT)\t\t\t%ld", token, value.v_int);
253 break;
254 case IDL_SYMBOL_DEFINE:
255 g_message("Token: %d (IDL_SYMBOL_DEFINE)\t\t\t", token);
256 break;
257 case IDL_SYMBOL_IFDEF:
258 g_message("Token: %d (IDL_SYMBOL_IFDEF)\t\t\t", token);
259 break;
260 case IDL_SYMBOL_ENDIF:
261 g_message("Token: %d (IDL_SYMBOL_ENDIF)\t\t\t", token);
262 break;
263#endif
264 default:
265 printToken(token);
266 break;
267 }
268 // printToken(token);
269
270 }
271}
272
273/**
274 Support function to show help for the IDL compiler. gContext must be valid.
275*/
276static void outputCompilerHelp(GOptionContext *gContext, gchar* chrExeName)
277{
278 GError *gError = NULL;
279 int argc2=2;
280 char *helpCmd[]={"","--help"};
281 char** argv2=helpCmd;
282 helpCmd[0]=chrExeName;
283
284 g_printf("The output filename is specified in the IDL file using the 'filestem' keyword.\n\
285-If no directory is specified the output name is built from the current directory\n\
286 path and the given filename.\n\
287-If the directory is a relative path the output name is built from the current\n\
288 directory path, the given directory name (or path) and the filename.\n\
289-If the directory is a full path the output name is built from the directory\n\
290 path and the given filename.\n\n\
291Note that an emitter specific extension will always be appended to the output\n\
292filename\n\n");
293
294 /* This prints the standard option help to screen. */
295 g_option_context_parse (gContext, &argc2, &argv2, &gError);
296}
297
298/*
299 Compare function for the tree holding our private symbols.
300 */
301static gint funcSymbolCompare(gconstpointer a, gconstpointer b)
302{
303 if(a==b)
304 return 0;
305
306 if(a<b)
307 return -1;
308
309 return 1;
310};
311
312/**
313 Message output handler for the scanner. The default handler isn't used because the preprocessor
314 mangles all include files together and thus the line numbers are not as expected by the user.
315 This function prints the error messages with corrected linenumbers and the source file name
316 in which to find the problem.
317 */
318void funcMsgHandler(GScanner *gScanner, gchar *message, gboolean error)
319{
320 g_printf("%s:%d: error: %s (%d %d)\n",
321 parseInfo.chrCurrentSourceFile ? parseInfo.chrCurrentSourceFile : "<null>", /* glib doesn't check for NULL like printf. */
322 g_scanner_cur_line(gScanner)-parseInfo.uiLineCorrection, message,
323 g_scanner_cur_line(gScanner), parseInfo.uiLineCorrection);
324}
325
326/**
327 Main entry point for the compiler.
328 */
329int main(int argc, char **argv)
330{
331 int a;
332 int fd;
333 /* Vars for filename building */
334 char* chrOutputFileName="";
335
336 GError *gError = NULL;
337 GOptionContext* gContext;
338
339 /* Parse command line options */
340 gContext = g_option_context_new ("file");
341 g_option_context_add_main_entries (gContext, gOptionEntries, NULL);
342
343 if(!g_option_context_parse (gContext, &argc, &argv, &gError))
344 {
345 outputCompilerHelp(gContext, argv[0]);
346 }
347#if 0
348 /* Correct emitter options? Exactly one emitter must be specified. */
349 a=0;
350 if(fOptionEmitH)
351 a++;
352 if(fOptionEmitIH)
353 a++;
354 if(fOptionEmitC)
355 a++;
356
357 if(!a){
358 g_printf("An emitter must be specified.\n\n");
359 outputCompilerHelp(gContext, argv[0]);
360 }
361 if(a>1){
362 g_printf("Only one emitter must be specified.\n\n");
363 outputCompilerHelp(gContext, argv[0]);
364 }
365#endif
366 g_option_context_free(gContext);
367
368
369 if(argc<2)
370 {
371 g_printf("No input file name given.\n\nUse %s --help for options.\n\n", argv[0]);
372 return 1;
373 }
374
375#if 0
376 for(a=0; a<argc; a++)
377 {
378 g_message("arg %d: %s", a, argv[a]);
379 }
380#endif
381
382 /*** Create output path name ****/
383 if(g_path_is_absolute(chrOutputDir))
384 chrOutputFileName=chrOutputDir;
385 else
386 {
387 /* Yes this is a memory leak but I don't care */
388 chrOutputFileName=g_build_filename(g_get_current_dir(), chrOutputDir, NULL);
389 }
390
391 g_message("Output path: %s", chrOutputFileName);
392 parseInfo.chrOutfilePath=chrOutputFileName;
393
394 /* Open input */
395 if(!strcmp(argv[1], "-"))
396 fd=0; /* Read from stdin */
397 else
398 fd=open(argv[1], O_RDONLY);
399
400 if(-1==fd)
401 {
402 g_message("Can't open input file %s", argv[1]);
403 exit(1);
404 }
405
406 g_printf("\n");
407
408 gScanner=g_scanner_new(NULL);
409 gScanner->user_data=(gpointer)&parseInfo;
410
411 gScanner->msg_handler=funcMsgHandler;
412 parseInfo.pInterfaceArray=g_ptr_array_new();
413
414 g_scanner_input_file(gScanner, fd);
415 gScanner->config->case_sensitive=TRUE;
416 /* No single line comments */
417 gScanner->config->skip_comment_single=FALSE;
418 gScanner->config->cpair_comment_single="";
419 gScanner->config->scan_float=FALSE;
420 /* This string is used in error messages of the parser */
421 gScanner->input_name=IDL_COMPILER_STRING;
422
423 g_scanner_set_scope(gScanner, ID_SCOPE);
424 /* Load our own symbols into the scanner. We use the default scope for now. */
425 parseInfo.pSymbolTree=g_tree_new((GCompareFunc) funcSymbolCompare);
426 while(pSymbols->chrSymbolName)
427 {
428#ifndef _MSC_VER
429# warning !!! Create a copy here so it is the same as with new symbols added later.
430#endif
431 g_scanner_scope_add_symbol(gScanner, ID_SCOPE, pSymbols->chrSymbolName,
432 pSymbols);
433 g_tree_insert(parseInfo.pSymbolTree, pSymbols, pSymbols->chrSymbolName);
434 pSymbols++;
435 }
436
437 if((parseInfo.outFile=openOutfile(gScanner, "out.txt"))!=NULL)
438 parseIt();
439
440#if 0
441 /* Write the output file */
442 if(fOptionEmitH)
443 emitHFile(parseInfo.pInterfaceArray);
444 else if(fOptionEmitIH)
445 emitIHFile(parseInfo.pInterfaceArray);
446 else if(fOptionEmitC)
447 emitCFile(parseInfo.pInterfaceArray);
448#endif
449 g_scanner_destroy(gScanner);
450 if(0!=fd)
451 close(fd); /* We read from stdin */
452 if(parseInfo.outFile)
453 fclose(parseInfo.outFile);
454 return 0;
455}
456
457#if 0
458 /* We are a folder somwhere in the chain */
459 nomRetval=WPFileSystem_wpQueryFileName((WPFileSystem*)wpParent, bFullPath, NULLHANDLE);
460
461 nomRetval=wpParent.wpQueryFileName(bFullPath, NULLHANDLE);
462
463 nomPath=NOMPathNew();
464 nomPath= (PNOMPath) NOMPath_assignCString(nomPath, _pszFullPath, ev);
465
466 return (PNOMPath)NOMPath_appendPath(nomRetval, nomPath, NULLHANDLE);
467
468#endif
469
470
471
472
473
474
475
476
477
Note: See TracBrowser for help on using the repository browser.