]>
Commit | Line | Data |
---|---|---|
c90f71dd RD |
1 | /******************************************************************************* |
2 | * Simplified Wrapper and Interface Generator (SWIG) | |
3 | * | |
4 | * Author : David Beazley | |
5 | * | |
6 | * Department of Computer Science | |
7 | * University of Chicago | |
8 | * 1100 E 58th Street | |
9 | * Chicago, IL 60637 | |
10 | * beazley@cs.uchicago.edu | |
11 | * | |
12 | * Please read the file LICENSE for the copyright and terms by which SWIG | |
13 | * can be used and distributed. | |
14 | *******************************************************************************/ | |
15 | /*********************************************************************** | |
16 | * $Header$ | |
17 | * | |
18 | * main.cxx | |
19 | * | |
20 | * The main program. | |
21 | * | |
22 | ***********************************************************************/ | |
23 | ||
24 | #define WRAP | |
25 | ||
26 | #include "internal.h" | |
27 | #include "ascii.h" | |
28 | #include "latex.h" | |
29 | #include "html.h" | |
30 | #include "nodoc.h" | |
31 | #include <time.h> | |
32 | #include <stdlib.h> | |
33 | #include <stdio.h> | |
34 | #include <ctype.h> | |
35 | ||
36 | class SwigException {}; | |
37 | ||
38 | static char *usage = "\ | |
39 | \nDocumentation Options\n\ | |
40 | -dascii - ASCII documentation.\n\ | |
41 | -dhtml - HTML documentation.\n\ | |
42 | -dlatex - LaTeX documentation.\n\ | |
43 | -dnone - No documentation.\n\n\ | |
44 | General Options\n\ | |
45 | -c - Produce raw wrapper code (omit support code)\n\ | |
46 | -c++ - Enable C++ processing\n\ | |
47 | -ci - Check a file into the SWIG library\n\ | |
48 | -co - Check a file out of the SWIG library\n\ | |
49 | -d docfile - Set name of the documentation file.\n\ | |
50 | -Dsymbol - Define a symbol (for conditional compilation)\n\ | |
51 | -I<dir> - Look for SWIG files in <dir>\n\ | |
52 | -l<ifile> - Include SWIG library file.\n\ | |
53 | -make_default - Create default constructors/destructors\n\ | |
54 | -nocomment - Ignore all comments (for documentation).\n\ | |
55 | -o outfile - Set name of the output file.\n\ | |
56 | -objc - Enable Objective C processing\n\ | |
57 | -stat - Print statistics\n\ | |
58 | -strict n - Set pointer type-checking strictness\n\ | |
59 | -swiglib - Report location of SWIG library and exit\n\ | |
60 | -t typemap_file - Use a typemap file.\n\ | |
61 | -v - Run in verbose mode\n\ | |
62 | -version - Print SWIG version number\n\ | |
63 | -help - This output.\n\n"; | |
64 | ||
65 | //----------------------------------------------------------------- | |
66 | // main() | |
67 | // | |
68 | // Main program. Initializes the files and starts the parser. | |
69 | //----------------------------------------------------------------- | |
70 | ||
71 | char infilename[256]; | |
72 | char filename[256]; | |
73 | char fn_header[256]; | |
74 | char fn_wrapper[256]; | |
75 | char fn_init[256]; | |
76 | char output_dir[512]; | |
77 | ||
78 | #ifdef MACSWIG | |
79 | FILE *swig_log; | |
80 | #endif | |
81 | ||
82 | char *SwigLib; | |
83 | ||
84 | //char** __argv; | |
85 | //int __argc; | |
86 | ||
87 | int SWIG_main(int argc, char *argv[], Language *l, Documentation *d) { | |
88 | ||
89 | int i; | |
90 | char *c; | |
91 | extern FILE *LEX_in; | |
92 | extern void add_directory(char *); | |
93 | extern char *get_time(); | |
94 | char temp[512]; | |
95 | char infile[512]; | |
96 | ||
97 | char *outfile_name = 0; | |
98 | extern int add_iname(char *); | |
99 | int help = 0; | |
100 | int ignorecomments = 0; | |
101 | int checkout = 0; | |
102 | int checkin = 0; | |
103 | char *typemap_file = 0; | |
104 | char *includefiles[256]; | |
105 | int includecount = 0; | |
106 | extern void check_suffix(char *); | |
107 | extern void scanner_file(FILE *); | |
108 | ||
109 | #ifdef MACSWIG | |
110 | try { | |
111 | #endif | |
112 | ||
113 | f_wrappers = 0; | |
114 | f_init = 0; | |
115 | f_header = 0; | |
116 | ||
117 | //__argc = argc; | |
118 | //__argv = argv; | |
119 | lang = l; | |
120 | doc = d; | |
121 | Status = 0; | |
122 | TypeStrict = 2; // Very strict type checking | |
123 | Verbose = 0; | |
124 | char *doc_file = 0; | |
125 | ||
126 | DataType::init_typedef(); // Initialize the type handler | |
127 | ||
128 | // Set up some default symbols (available in both SWIG interface files | |
129 | // and C files) | |
130 | ||
131 | add_symbol("SWIG",0,0); // Define the SWIG symbol | |
132 | #ifdef MACSWIG | |
133 | add_symbol("SWIGMAC",0,0); | |
134 | #endif | |
135 | #ifdef SWIGWIN32 | |
136 | add_symbol("SWIGWIN32",0,0); | |
137 | #endif | |
138 | ||
139 | strcpy(LibDir, getSwigLib()); | |
140 | SwigLib = copy_string(LibDir); // Make a copy of the real library location | |
141 | #ifdef MACSWIG | |
142 | sprintf(temp,"%s:config", LibDir); | |
143 | add_directory(temp); | |
144 | add_directory(":swig_lib:config"); | |
145 | add_directory(LibDir); | |
146 | add_directory(":swig_lib"); | |
147 | #else | |
148 | sprintf(temp,"%s/config", LibDir); | |
149 | add_directory(temp); | |
150 | add_directory("./swig_lib/config"); | |
151 | add_directory(LibDir); | |
152 | add_directory("./swig_lib"); | |
153 | sprintf(InitName,"init_wrap"); | |
154 | #endif | |
155 | ||
156 | sprintf(InitName,"init_wrap"); | |
157 | ||
158 | // Get options | |
159 | for (i = 1; i < argc; i++) { | |
160 | if (argv[i]) { | |
161 | if (strncmp(argv[i],"-I",2) == 0) { | |
162 | // Add a new directory search path | |
163 | includefiles[includecount++] = copy_string(argv[i]+2); | |
164 | mark_arg(i); | |
165 | } else if (strncmp(argv[i],"-D",2) == 0) { | |
166 | // Create a symbol | |
167 | add_symbol(argv[i]+2, (DataType *) 0, (char *) 0); | |
168 | mark_arg(i); | |
169 | } else if (strcmp(argv[i],"-strict") == 0) { | |
170 | if (argv[i+1]) { | |
171 | TypeStrict = atoi(argv[i+1]); | |
172 | mark_arg(i); | |
173 | mark_arg(i+1); | |
174 | i++; | |
175 | } else { | |
176 | arg_error(); | |
177 | } | |
178 | } else if ((strcmp(argv[i],"-verbose") == 0) || (strcmp(argv[i],"-v") == 0)) { | |
179 | Verbose = 1; | |
180 | mark_arg(i); | |
181 | } else if (strcmp(argv[i],"-dascii") == 0) { | |
182 | doc = new ASCII; | |
183 | mark_arg(i); | |
184 | } else if (strcmp(argv[i],"-dnone") == 0) { | |
185 | doc = new NODOC; | |
186 | mark_arg(i); | |
187 | } else if (strcmp(argv[i],"-dhtml") == 0) { | |
188 | doc = new HTML; | |
189 | mark_arg(i); | |
190 | } else if (strcmp(argv[i],"-dlatex") == 0) { | |
191 | doc = new LATEX; | |
192 | mark_arg(i); | |
193 | } else if (strcmp(argv[i],"-nocomment") == 0) { | |
194 | ignorecomments = 1; | |
195 | mark_arg(i); | |
196 | } else if (strcmp(argv[i],"-stat") == 0) { | |
197 | Stats=1; | |
198 | mark_arg(i); | |
199 | } else if (strcmp(argv[i],"-c++") == 0) { | |
200 | CPlusPlus=1; | |
201 | mark_arg(i); | |
202 | } else if (strcmp(argv[i],"-objc") == 0) { | |
203 | ObjC = 1; | |
204 | mark_arg(i); | |
205 | } else if (strcmp(argv[i],"-c") == 0) { | |
206 | NoInclude=1; | |
207 | mark_arg(i); | |
208 | } else if (strcmp(argv[i],"-make_default") == 0) { | |
209 | GenerateDefault = 1; | |
210 | mark_arg(i); | |
211 | } else if (strcmp(argv[i],"-swiglib") == 0) { | |
212 | printf("%s\n", LibDir); | |
213 | SWIG_exit(0); | |
214 | } else if (strcmp(argv[i],"-o") == 0) { | |
215 | mark_arg(i); | |
216 | if (argv[i+1]) { | |
217 | outfile_name = copy_string(argv[i+1]); | |
218 | mark_arg(i+1); | |
219 | i++; | |
220 | } else { | |
221 | arg_error(); | |
222 | } | |
223 | } else if (strcmp(argv[i],"-d") == 0) { | |
224 | mark_arg(i); | |
225 | if (argv[i+1]) { | |
226 | doc_file = copy_string(argv[i+1]); | |
227 | mark_arg(i+1); | |
228 | i++; | |
229 | } else { | |
230 | arg_error(); | |
231 | } | |
232 | } else if (strcmp(argv[i],"-t") == 0) { | |
233 | mark_arg(i); | |
234 | if (argv[i+1]) { | |
235 | typemap_file = copy_string(argv[i+1]); | |
236 | mark_arg(i+1); | |
237 | i++; | |
238 | } else { | |
239 | arg_error(); | |
240 | } | |
241 | } else if (strcmp(argv[i],"-version") == 0) { | |
242 | fprintf(stderr,"\nSWIG Version %d.%d %s\n", SWIG_MAJOR_VERSION, | |
243 | SWIG_MINOR_VERSION, SWIG_SPIN); | |
244 | fprintf(stderr,"Copyright (c) 1995-98\n"); | |
245 | fprintf(stderr,"University of Utah and the Regents of the University of California\n"); | |
246 | fprintf(stderr,"\nCompiled with %s\n", SWIG_CC); | |
247 | SWIG_exit(0); | |
248 | } else if (strncmp(argv[i],"-l",2) == 0) { | |
249 | // Add a new directory search path | |
250 | library_add(argv[i]+2); | |
251 | mark_arg(i); | |
252 | } else if (strcmp(argv[i],"-co") == 0) { | |
253 | checkout = 1; | |
254 | mark_arg(i); | |
255 | } else if (strcmp(argv[i],"-ci") == 0) { | |
256 | checkin = 1; | |
257 | mark_arg(i); | |
258 | } else if (strcmp(argv[i],"-help") == 0) { | |
259 | fputs(usage,stderr); | |
260 | mark_arg(i); | |
261 | help = 1; | |
262 | } | |
263 | } | |
264 | } | |
265 | ||
266 | while (includecount > 0) { | |
267 | add_directory(includefiles[--includecount]); | |
268 | } | |
269 | ||
270 | // Create a new documentation handler | |
271 | ||
272 | if (doc == 0) doc = new ASCII; | |
273 | ||
274 | // Open up a comment handler | |
275 | ||
276 | comment_handler = new CommentHandler(); | |
277 | comment_handler->parse_args(argc,argv); | |
278 | if (ignorecomments) comment_handler->style("ignore",0); | |
279 | ||
280 | // Create a new documentation entry | |
281 | ||
282 | doctitle = new DocTitle("",0); | |
283 | doctitle->parse_args(argc,argv); | |
284 | doc_entry = doctitle; | |
285 | ||
286 | // Handle documentation module options | |
287 | ||
288 | doc->parse_args(argc,argv); | |
289 | ||
290 | // Parse language dependent options | |
291 | ||
292 | lang->parse_args(argc,argv); | |
293 | ||
294 | if (help) SWIG_exit(0); // Exit if we're in help mode | |
295 | ||
296 | // Check all of the options to make sure we're cool. | |
297 | ||
298 | check_options(); | |
299 | ||
300 | // If we made it this far, looks good. go for it.... | |
301 | ||
302 | // Create names of temporary files that are created | |
303 | ||
304 | sprintf(infilename,"%s", argv[argc-1]); | |
305 | input_file = new char[strlen(infilename)+1]; | |
306 | strcpy(input_file, infilename); | |
307 | ||
308 | // If the user has requested to check out a file, handle that | |
309 | ||
310 | if (checkout) { | |
311 | int stat; | |
312 | char *outfile = input_file; | |
313 | if (outfile_name) | |
314 | outfile = outfile_name; | |
315 | stat = checkout_file(input_file,outfile); | |
316 | if (!stat) { | |
317 | fprintf(stderr,"%s checked out from the SWIG library\n",input_file); | |
318 | } else { | |
319 | FILE * f = fopen(input_file,"r"); | |
320 | if (f) { | |
321 | fprintf(stderr,"Unable to check-out %s. File already exists.\n", input_file); | |
322 | fclose(f); | |
323 | } else { | |
324 | fprintf(stderr,"Unable to check-out %s\n", input_file); | |
325 | } | |
326 | } | |
327 | } else if (checkin) { | |
328 | // Try to check-in a file to the SWIG library | |
329 | int stat; | |
330 | char *outname = input_file; | |
331 | if (outfile_name) | |
332 | outname = outfile_name; | |
333 | stat = checkin_file(SwigLib, LibDir, input_file, outname); | |
334 | if (!stat) { | |
335 | fprintf(stderr,"%s checked-in to %s/%s/%s\n", input_file, SwigLib, LibDir, outname); | |
336 | } else { | |
337 | fprintf(stderr,"Unable to check-in %s to %s/%s\n", input_file, SwigLib, LibDir); | |
338 | } | |
339 | } else { | |
340 | doctitle->file = copy_string(input_file); | |
341 | doctitle->line_number = -1000; | |
342 | doctitle->end_line = -1000; | |
343 | ||
344 | // Check the suffix for a .c file. If so, we're going to | |
345 | // declare everything we see as "extern" | |
346 | ||
347 | check_suffix(infilename); | |
348 | ||
349 | // Strip off suffix | |
350 | ||
351 | c = infilename + strlen(infilename); | |
352 | while (c != infilename) { | |
353 | if (*c == '.') { | |
354 | *c = 0; | |
355 | break; | |
356 | } else { | |
357 | c--; | |
358 | } | |
359 | } | |
360 | ||
361 | if (!outfile_name) { | |
362 | sprintf(fn_header,"%s_wrap.c",infilename); | |
363 | strcpy(infile,infilename); | |
364 | strcpy(output_dir,""); | |
365 | } else { | |
366 | sprintf(fn_header,"%s",outfile_name); | |
367 | // Try to identify the output directory | |
368 | char *cc = outfile_name; | |
369 | char *lastc = outfile_name; | |
370 | while (*cc) { | |
371 | #ifdef MACSWIG | |
372 | if (*cc == ':') lastc = cc+1; | |
373 | #else | |
374 | if (*cc == '/') lastc = cc+1; | |
375 | #endif | |
376 | cc++; | |
377 | } | |
378 | cc = outfile_name; | |
379 | char *dd = output_dir; | |
380 | while (cc != lastc) { | |
381 | *dd = *cc; | |
382 | dd++; | |
383 | cc++; | |
384 | } | |
385 | *dd = 0; | |
386 | // Patch up the input filename | |
387 | cc = infilename + strlen(infilename); | |
388 | while (cc != infilename) { | |
389 | #ifdef MACSWIG | |
390 | if (*cc == ':') { | |
391 | cc++; | |
392 | break; | |
393 | } | |
394 | #else | |
395 | if (*cc == '/') { | |
396 | cc++; | |
397 | break; | |
398 | } | |
399 | #endif | |
400 | cc--; | |
401 | } | |
402 | strcpy(infile,cc); | |
403 | } | |
404 | ||
405 | sprintf(fn_wrapper,"%s%s_wrap.wrap",output_dir,infile); | |
406 | sprintf(fn_init,"%s%s_wrap.init",output_dir,infile); | |
407 | ||
408 | sprintf(title,"%s", fn_header); | |
409 | ||
410 | // Open up files | |
411 | ||
412 | if ((f_input = fopen(input_file,"r")) == 0) { | |
413 | // Okay. File wasn't found right away. Let's see if we can | |
414 | // extract it from the SWIG library instead. | |
415 | if ((checkout_file(input_file,input_file)) == -1) { | |
416 | fprintf(stderr,"Unable to open %s\n", input_file); | |
417 | SWIG_exit(0); | |
418 | } else { | |
419 | // Successfully checked out a file from the library, print a warning and | |
420 | // continue | |
421 | checkout = 1; | |
422 | fprintf(stderr,"%s checked out from the SWIG library.\n",input_file); | |
423 | if ((f_input = fopen(input_file,"r")) == 0) { | |
424 | fprintf(stderr,"Unable to open %s\n", input_file); | |
425 | SWIG_exit(0); | |
426 | } | |
427 | } | |
428 | } | |
429 | ||
430 | // Add to the include list | |
431 | ||
432 | add_iname(infilename); | |
433 | ||
434 | // Initialize the scanner | |
435 | ||
436 | LEX_in = f_input; | |
437 | scanner_file(LEX_in); | |
438 | ||
439 | // printf("fn_header = %s\n", fn_header); | |
440 | // printf("fn_wrapper = %s\n", fn_wrapper); | |
441 | // printf("fn_init = %s\n", fn_init); | |
442 | ||
443 | if((f_header = fopen(fn_header,"w")) == 0) { | |
444 | fprintf(stderr,"Unable to open %s\n", fn_header); | |
445 | exit(0); | |
446 | } | |
447 | if((f_wrappers = fopen(fn_wrapper,"w")) == 0) { | |
448 | fprintf(stderr,"Unable to open %s\n",fn_wrapper); | |
449 | exit(0); | |
450 | } | |
451 | if ((f_init = fopen(fn_init,"w")) == 0) { | |
452 | fprintf(stderr,"Unable to open %s\n",fn_init); | |
453 | exit(0); | |
454 | } | |
455 | ||
456 | // Open up documentation | |
457 | ||
458 | if (doc_file) { | |
459 | doc->init(doc_file); | |
460 | } else { | |
461 | doc_file = new char[strlen(infile)+strlen(output_dir)+8]; | |
462 | sprintf(doc_file,"%s%s_wrap",output_dir,infile); | |
463 | doc->init(doc_file); | |
464 | } | |
465 | ||
466 | // Set up the typemap for handling new return strings | |
467 | { | |
468 | DataType *temp_t = new DataType(T_CHAR); | |
469 | temp_t->is_pointer++; | |
470 | if (CPlusPlus) | |
471 | typemap_register("newfree",typemap_lang,temp_t,"","delete [] $source;\n",0); | |
472 | else | |
473 | typemap_register("newfree",typemap_lang,temp_t,"","free($source);\n",0); | |
474 | ||
475 | delete temp_t; | |
476 | } | |
477 | ||
478 | // Define the __cplusplus symbol | |
479 | if (CPlusPlus) | |
480 | add_symbol("__cplusplus",0,0); | |
481 | ||
482 | ||
483 | // Load up the typemap file if given | |
484 | ||
485 | if (typemap_file) { | |
486 | if (include_file(typemap_file) == -1) { | |
487 | fprintf(stderr,"Unable to locate typemap file %s. Aborting.\n", typemap_file); | |
488 | SWIG_exit(1); | |
489 | } | |
490 | } | |
491 | ||
492 | // If in Objective-C mode. Load in a configuration file | |
493 | ||
494 | if (ObjC) { | |
495 | // Add the 'id' object type as a void * | |
496 | /* DataType *t = new DataType(T_VOID); | |
497 | t->is_pointer = 1; | |
498 | t->implicit_ptr = 0; | |
499 | t->typedef_add("id"); | |
500 | delete t; | |
501 | */ | |
502 | } | |
503 | ||
504 | // Pass control over to the specific language interpreter | |
505 | ||
506 | lang->parse(); | |
507 | ||
508 | fclose(f_wrappers); | |
509 | fclose(f_init); | |
510 | ||
511 | swig_append(fn_wrapper,f_header); | |
512 | swig_append(fn_init,f_header); | |
513 | ||
514 | fclose(f_header); | |
515 | ||
516 | // Print out documentation. Due to tree-like nature of documentation, | |
517 | // printing out the title prints out everything. | |
518 | ||
519 | while(doctitle) { | |
520 | doctitle->output(doc); | |
521 | doctitle = doctitle->next; | |
522 | } | |
523 | ||
524 | doc->close(); | |
525 | ||
526 | // Remove temporary files | |
527 | ||
528 | remove(fn_wrapper); | |
529 | remove(fn_init); | |
530 | ||
531 | // If only producing documentation, remove the wrapper file as well | |
532 | ||
533 | if (DocOnly) | |
534 | remove(fn_header); | |
535 | ||
536 | // Check for undefined types that were used. | |
537 | ||
538 | if (Verbose) | |
539 | type_undefined_check(); | |
540 | ||
541 | if (Stats) { | |
542 | fprintf(stderr,"Wrapped %d functions\n", Stat_func); | |
543 | fprintf(stderr,"Wrapped %d variables\n", Stat_var); | |
544 | fprintf(stderr,"Wrapped %d constants\n", Stat_const); | |
545 | type_undefined_check(); | |
546 | } | |
547 | ||
548 | if (checkout) { | |
549 | // File was checked out from the SWIG library. Remove it now | |
550 | remove(input_file); | |
551 | } | |
552 | } | |
553 | #ifdef MACSWIG | |
554 | fclose(swig_log); | |
555 | } catch (SwigException) { | |
556 | fclose(swig_log); | |
557 | } | |
558 | #else | |
559 | exit(error_count); | |
560 | #endif | |
561 | return(error_count); | |
562 | } | |
563 | ||
564 | // -------------------------------------------------------------------------- | |
565 | // SWIG_exit() | |
566 | // | |
567 | // Fatal parser error. Exit and cleanup | |
568 | // -------------------------------------------------------------------------- | |
569 | ||
570 | void SWIG_exit(int) { | |
571 | ||
572 | if (f_wrappers) { | |
573 | fclose(f_wrappers); | |
574 | remove(fn_wrapper); | |
575 | } | |
576 | if (f_header) { | |
577 | fclose(f_header); | |
578 | remove(fn_header); | |
579 | } | |
580 | if (f_init) { | |
581 | fclose(f_init); | |
582 | remove(fn_init); | |
583 | } | |
584 | #ifndef MACSWIG | |
585 | exit(1); | |
586 | #else | |
587 | throw SwigException(); | |
588 | #endif | |
589 | } | |
590 | ||
591 | ||
592 | // -------------------------------------------------------------------------- | |
593 | // swig_pragma(char *name, char *value) | |
594 | // | |
595 | // Handle pragma directives. Not many supported right now | |
596 | // -------------------------------------------------------------------------- | |
597 | ||
598 | void swig_pragma(char *name, char *value) { | |
599 | ||
600 | if (strcmp(name,"make_default") == 0) { | |
601 | GenerateDefault = 1; | |
602 | } | |
603 | if (strcmp(name,"no_default") == 0) { | |
604 | GenerateDefault = 0; | |
605 | } | |
606 | if (strcmp(name,"objc_new") == 0) { | |
607 | objc_construct = copy_string(value); | |
608 | } | |
609 | if (strcmp(name,"objc_delete") == 0) { | |
610 | objc_destruct = copy_string(value); | |
611 | } | |
612 | } | |
613 | ||
614 | ||
615 | ||
616 | char* getSwigLib() { | |
617 | char* c; | |
618 | char* rv; | |
619 | ||
620 | // Check for SWIG_LIB environment variable | |
621 | if ((c = getenv("SWIG_LIB")) != (char *) 0) { | |
622 | rv = c; | |
623 | } else { | |
624 | #ifdef SWIG_LIB | |
625 | rv = SWIG_LIB; | |
626 | #else | |
627 | // use executable location | |
628 | static char path[256]; | |
629 | char* last; | |
630 | strcpy(path, __argv[0]); | |
631 | last = strrchr(path, '/'); | |
632 | if (! last) last = strrchr(path, '\\'); | |
633 | if (last) | |
634 | strcpy(last+1, "swig_lib"); | |
635 | else | |
636 | strcpy(path, "swig_lib"); | |
637 | rv = path; | |
638 | #endif | |
639 | } | |
640 | printf("Using swig lib at: %s\n", rv); | |
641 | return rv; | |
642 | } | |
643 |