import source from 1.3.40
[external/swig.git] / Source / Preprocessor / cpp.c
1 /* -----------------------------------------------------------------------------
2  * See the LICENSE file for information on copyright, usage and redistribution
3  * of SWIG, and the README file for authors - http://www.swig.org/release.html.
4  *
5  * cpp.c
6  *
7  * An implementation of a C preprocessor plus some support for additional
8  * SWIG directives.
9  *
10  * - SWIG directives such as %include, %extern, and %import are handled
11  * - A new macro %define ... %enddef can be used for multiline macros
12  * - No preprocessing is performed in %{ ... %} blocks
13  * - Lines beginning with %# are stripped down to #... and passed through.
14  * ----------------------------------------------------------------------------- */
15
16 char cvsroot_cpp_c[] = "$Id: cpp.c 11098 2009-01-30 10:32:59Z bhy $";
17
18 #include "swig.h"
19 #include "preprocessor.h"
20 #include <ctype.h>
21
22 static Hash *cpp = 0;           /* C preprocessor data */
23 static int include_all = 0;     /* Follow all includes */
24 static int ignore_missing = 0;
25 static int import_all = 0;      /* Follow all includes, but as %import statements */
26 static int imported_depth = 0;  /* Depth of %imported files */
27 static int single_include = 1;  /* Only include each file once */
28 static Hash *included_files = 0;
29 static List *dependencies = 0;
30 static Scanner *id_scan = 0;
31 static int error_as_warning = 0;        /* Understand the cpp #error directive as a special #warning */
32
33 /* Test a character to see if it starts an identifier */
34 #define isidentifier(c) ((isalpha(c)) || (c == '_') || (c == '$'))
35
36 /* Test a character to see if it valid in an identifier (after the first letter) */
37 #define isidchar(c) ((isalnum(c)) || (c == '_') || (c == '$'))
38
39 DOH *Preprocessor_replace(DOH *);
40
41 /* Skip whitespace */
42 static void skip_whitespace(String *s, String *out) {
43   int c;
44   while ((c = Getc(s)) != EOF) {
45     if (!isspace(c)) {
46       Ungetc(c, s);
47       break;
48     } else if (out)
49       Putc(c, out);
50   }
51 }
52
53 /* Skip to a specified character taking line breaks into account */
54 static int skip_tochar(String *s, int ch, String *out) {
55   int c;
56   while ((c = Getc(s)) != EOF) {
57     if (out)
58       Putc(c, out);
59     if (c == ch)
60       break;
61     if (c == '\\') {
62       c = Getc(s);
63       if ((c != EOF) && (out))
64         Putc(c, out);
65     }
66   }
67   if (c == EOF)
68     return -1;
69   return 0;
70 }
71
72 static void copy_location(const DOH *s1, DOH *s2) {
73   Setfile(s2, Getfile((DOH *) s1));
74   Setline(s2, Getline((DOH *) s1));
75 }
76
77 static String *cpp_include(const_String_or_char_ptr fn, int sysfile) {
78   String *s = sysfile ? Swig_include_sys(fn) : Swig_include(fn);
79   if (s && single_include) {
80     String *file = Getfile(s);
81     if (Getattr(included_files, file)) {
82       Delete(s);
83       return 0;
84     }
85     Setattr(included_files, file, file);
86   }
87   if (!s) {
88     /* XXX(bhy) may not need the seek */
89     /* Seek(fn, 0, SEEK_SET); */
90     if (ignore_missing) {
91       Swig_warning(WARN_PP_MISSING_FILE, Getfile(fn), Getline(fn), "Unable to find '%s'\n", fn);
92     } else {
93       Swig_error(Getfile(fn), Getline(fn), "Unable to find '%s'\n", fn);
94     }
95   } else {
96     String *lf;
97     Seek(s, 0, SEEK_SET);
98     if (!dependencies) {
99       dependencies = NewList();
100     }
101     lf = Copy(Swig_last_file());
102     Append(dependencies, lf);
103     Delete(lf);
104   }
105   return s;
106 }
107
108 List *Preprocessor_depend(void) {
109   return dependencies;
110 }
111
112 /* -----------------------------------------------------------------------------
113  * void Preprocessor_cpp_init() - Initialize the preprocessor
114  * ----------------------------------------------------------------------------- */
115 static String *kpp_args = 0;
116 static String *kpp_define = 0;
117 static String *kpp_defined = 0;
118 static String *kpp_elif = 0;
119 static String *kpp_else = 0;
120 static String *kpp_endif = 0;
121 static String *kpp_expanded = 0;
122 static String *kpp_if = 0;
123 static String *kpp_ifdef = 0;
124 static String *kpp_ifndef = 0;
125 static String *kpp_name = 0;
126 static String *kpp_swigmacro = 0;
127 static String *kpp_symbols = 0;
128 static String *kpp_undef = 0;
129 static String *kpp_value = 0;
130 static String *kpp_varargs = 0;
131 static String *kpp_error = 0;
132 static String *kpp_warning = 0;
133 static String *kpp_line = 0;
134 static String *kpp_include = 0;
135 static String *kpp_pragma = 0;
136 static String *kpp_level = 0;
137
138 static String *kpp_dline = 0;
139 static String *kpp_ddefine = 0;
140 static String *kpp_dinclude = 0;
141 static String *kpp_dimport = 0;
142 static String *kpp_dextern = 0;
143
144 static String *kpp_LINE = 0;
145 static String *kpp_FILE = 0;
146
147 void Preprocessor_init(void) {
148   Hash *s;
149
150   kpp_args = NewString("args");
151   kpp_define = NewString("define");
152   kpp_defined = NewString("defined");
153   kpp_else = NewString("else");
154   kpp_elif = NewString("elif");
155   kpp_endif = NewString("endif");
156   kpp_expanded = NewString("*expanded*");
157   kpp_if = NewString("if");
158   kpp_ifdef = NewString("ifdef");
159   kpp_ifndef = NewString("ifndef");
160   kpp_name = NewString("name");
161   kpp_swigmacro = NewString("swigmacro");
162   kpp_symbols = NewString("symbols");
163   kpp_undef = NewString("undef");
164   kpp_value = NewString("value");
165   kpp_error = NewString("error");
166   kpp_warning = NewString("warning");
167   kpp_pragma = NewString("pragma");
168   kpp_level = NewString("level");
169   kpp_line = NewString("line");
170   kpp_include = NewString("include");
171   kpp_varargs = NewString("varargs");
172
173   kpp_dinclude = NewString("%include");
174   kpp_dimport = NewString("%import");
175   kpp_dextern = NewString("%extern");
176   kpp_ddefine = NewString("%define");
177   kpp_dline = NewString("%line");
178
179
180   kpp_LINE = NewString("__LINE__");
181   kpp_FILE = NewString("__FILE__");
182
183   cpp = NewHash();
184   s = NewHash();
185   Setattr(cpp, kpp_symbols, s);
186   Delete(s);
187   Preprocessor_expr_init();     /* Initialize the expression evaluator */
188   included_files = NewHash();
189
190   id_scan = NewScanner();;
191
192 }
193
194 void Preprocessor_delete(void) {
195   Delete(kpp_args);
196   Delete(kpp_define);
197   Delete(kpp_defined);
198   Delete(kpp_else);
199   Delete(kpp_elif);
200   Delete(kpp_endif);
201   Delete(kpp_expanded);
202   Delete(kpp_if);
203   Delete(kpp_ifdef);
204   Delete(kpp_ifndef);
205   Delete(kpp_name);
206   Delete(kpp_swigmacro);
207   Delete(kpp_symbols);
208   Delete(kpp_undef);
209   Delete(kpp_value);
210   Delete(kpp_error);
211   Delete(kpp_warning);
212   Delete(kpp_pragma);
213   Delete(kpp_level);
214   Delete(kpp_line);
215   Delete(kpp_include);
216   Delete(kpp_varargs);
217
218   Delete(kpp_dinclude);
219   Delete(kpp_dimport);
220   Delete(kpp_dextern);
221   Delete(kpp_ddefine);
222   Delete(kpp_dline);
223
224
225   Delete(kpp_LINE);
226   Delete(kpp_FILE);
227   Delete(cpp);
228   Delete(included_files);
229   Preprocessor_expr_delete();
230   DelScanner(id_scan);
231
232   Delete(dependencies);
233
234   Delete(Swig_add_directory(0));
235 }
236
237 /* -----------------------------------------------------------------------------
238  * void Preprocessor_include_all() - Instruct preprocessor to include all files
239  * ----------------------------------------------------------------------------- */
240 void Preprocessor_include_all(int a) {
241   include_all = a;
242 }
243
244 void Preprocessor_import_all(int a) {
245   import_all = a;
246 }
247
248 void Preprocessor_ignore_missing(int a) {
249   ignore_missing = a;
250 }
251
252 void Preprocessor_error_as_warning(int a) {
253   error_as_warning = a;
254 }
255
256
257 /* -----------------------------------------------------------------------------
258  * Preprocessor_define()
259  *
260  * Defines a new C preprocessor symbol.   swigmacro specifies whether or not the macro has
261  * SWIG macro semantics.
262  * ----------------------------------------------------------------------------- */
263
264
265 String *Macro_vararg_name(const_String_or_char_ptr str, const_String_or_char_ptr line) {
266   String *argname;
267   String *varargname;
268   char *s, *dots;
269
270   argname = Copy(str);
271   s = Char(argname);
272   dots = strchr(s, '.');
273   if (!dots) {
274     Delete(argname);
275     return NULL;
276   }
277
278   if (strcmp(dots, "...") != 0) {
279     Swig_error(Getfile(line), Getline(line), "Illegal macro argument name '%s'\n", str);
280     Delete(argname);
281     return NULL;
282   }
283   if (dots == s) {
284     varargname = NewString("__VA_ARGS__");
285   } else {
286     *dots = '\0';
287     varargname = NewString(s);
288   }
289   Delete(argname);
290   return varargname;
291 }
292
293 Hash *Preprocessor_define(const_String_or_char_ptr _str, int swigmacro) {
294   String *macroname = 0, *argstr = 0, *macrovalue = 0, *file = 0, *s = 0;
295   Hash *macro = 0, *symbols = 0, *m1;
296   List *arglist = 0;
297   int c, line;
298   int varargs = 0;
299   String *str;
300
301   assert(cpp);
302   assert(_str);
303
304   /* First make sure that string is actually a string */
305   if (DohCheck(_str)) {
306     s = Copy(_str);
307     copy_location(_str, s);
308     str = s;
309   } else {
310     str = NewString((char *) _str);
311   }
312   Seek(str, 0, SEEK_SET);
313   line = Getline(str);
314   file = Getfile(str);
315
316   /* Skip over any leading whitespace */
317   skip_whitespace(str, 0);
318
319   /* Now look for a macro name */
320   macroname = NewStringEmpty();
321   while ((c = Getc(str)) != EOF) {
322     if (c == '(') {
323       argstr = NewStringEmpty();
324       copy_location(str, argstr);
325       /* It is a macro.  Go extract its argument string */
326       while ((c = Getc(str)) != EOF) {
327         if (c == ')')
328           break;
329         else
330           Putc(c, argstr);
331       }
332       if (c != ')') {
333         Swig_error(Getfile(str), Getline(str), "Missing \')\' in macro parameters\n");
334         goto macro_error;
335       }
336       break;
337     } else if (isidchar(c) || (c == '%')) {
338       Putc(c, macroname);
339     } else if (isspace(c)) {
340       break;
341     } else if (c == '\\') {
342       c = Getc(str);
343       if (c != '\n') {
344         Ungetc(c, str);
345         Ungetc('\\', str);
346         break;
347       }
348     } else {
349       /*Swig_error(Getfile(str),Getline(str),"Illegal character in macro name\n");
350          goto macro_error; */
351       Ungetc(c, str);
352       break;
353     }
354   }
355   if (!swigmacro)
356     skip_whitespace(str, 0);
357   macrovalue = NewStringEmpty();
358   while ((c = Getc(str)) != EOF) {
359     Putc(c, macrovalue);
360   }
361
362   /* If there are any macro arguments, convert into a list */
363   if (argstr) {
364     String *argname, *varargname;
365     arglist = NewList();
366     Seek(argstr, 0, SEEK_SET);
367     argname = NewStringEmpty();
368     while ((c = Getc(argstr)) != EOF) {
369       if (c == ',') {
370         varargname = Macro_vararg_name(argname, str);
371         if (varargname) {
372           Delete(varargname);
373           Swig_error(Getfile(str), Getline(str), "Variable-length macro argument must be last parameter\n");
374         } else {
375           Append(arglist, argname);
376         }
377         Delete(argname);
378         argname = NewStringEmpty();
379       } else if (isidchar(c) || (c == '.')) {
380         Putc(c, argname);
381       } else if (!(isspace(c) || (c == '\\'))) {
382         Delete(argname);
383         Swig_error(Getfile(str), Getline(str), "Illegal character in macro argument name\n");
384         goto macro_error;
385       }
386     }
387     if (Len(argname)) {
388       /* Check for varargs */
389       varargname = Macro_vararg_name(argname, str);
390       if (varargname) {
391         Append(arglist, varargname);
392         Delete(varargname);
393         varargs = 1;
394       } else {
395         Append(arglist, argname);
396       }
397     }
398     Delete(argname);
399   }
400
401   if (!swigmacro) {
402     Replace(macrovalue, "\\\n", " ", DOH_REPLACE_NOQUOTE);
403   }
404
405   /* Look for special # substitutions.   We only consider # that appears
406      outside of quotes and comments */
407
408   {
409     int state = 0;
410     char *cc = Char(macrovalue);
411     while (*cc) {
412       switch (state) {
413       case 0:
414         if (*cc == '#')
415           *cc = '\001';
416         else if (*cc == '/')
417           state = 10;
418         else if (*cc == '\'')
419           state = 20;
420         else if (*cc == '\"')
421           state = 30;
422         break;
423       case 10:
424         if (*cc == '*')
425           state = 11;
426         else if (*cc == '/')
427           state = 15;
428         else {
429           state = 0;
430           cc--;
431         }
432         break;
433       case 11:
434         if (*cc == '*')
435           state = 12;
436         break;
437       case 12:
438         if (*cc == '/')
439           state = 0;
440         else if (*cc != '*')
441           state = 11;
442         break;
443       case 15:
444         if (*cc == '\n')
445           state = 0;
446         break;
447       case 20:
448         if (*cc == '\'')
449           state = 0;
450         if (*cc == '\\')
451           state = 21;
452         break;
453       case 21:
454         state = 20;
455         break;
456       case 30:
457         if (*cc == '\"')
458           state = 0;
459         if (*cc == '\\')
460           state = 31;
461         break;
462       case 31:
463         state = 30;
464         break;
465       default:
466         break;
467       }
468       cc++;
469     }
470   }
471
472   /* Get rid of whitespace surrounding # */
473   /*  Replace(macrovalue,"#","\001",DOH_REPLACE_NOQUOTE); */
474   while (strstr(Char(macrovalue), "\001 ")) {
475     Replace(macrovalue, "\001 ", "\001", DOH_REPLACE_ANY);
476   }
477   while (strstr(Char(macrovalue), " \001")) {
478     Replace(macrovalue, " \001", "\001", DOH_REPLACE_ANY);
479   }
480   /* Replace '##' with a special token */
481   Replace(macrovalue, "\001\001", "\002", DOH_REPLACE_ANY);
482   /* Replace '#@' with a special token */
483   Replace(macrovalue, "\001@", "\004", DOH_REPLACE_ANY);
484   /* Replace '##@' with a special token */
485   Replace(macrovalue, "\002@", "\005", DOH_REPLACE_ANY);
486
487   /* Go create the macro */
488   macro = NewHash();
489   Setattr(macro, kpp_name, macroname);
490
491   if (arglist) {
492     Setattr(macro, kpp_args, arglist);
493     Delete(arglist);
494     if (varargs) {
495       Setattr(macro, kpp_varargs, "1");
496     }
497   }
498   Setattr(macro, kpp_value, macrovalue);
499   Setline(macro, line);
500   Setfile(macro, file);
501   if (swigmacro) {
502     Setattr(macro, kpp_swigmacro, "1");
503   }
504   symbols = Getattr(cpp, kpp_symbols);
505   if ((m1 = Getattr(symbols, macroname))) {
506     if (!Checkattr(m1, kpp_value, macrovalue)) {
507       Swig_error(Getfile(str), Getline(str), "Macro '%s' redefined,\n", macroname);
508       Swig_error(Getfile(m1), Getline(m1), "previous definition of '%s'.\n", macroname);
509       goto macro_error;
510     }
511   } else {
512     Setattr(symbols, macroname, macro);
513     Delete(macro);
514   }
515
516   Delete(macroname);
517   Delete(macrovalue);
518
519   Delete(str);
520   Delete(argstr);
521   return macro;
522
523 macro_error:
524   Delete(str);
525   Delete(argstr);
526   Delete(arglist);
527   Delete(macroname);
528   Delete(macrovalue);
529   return 0;
530 }
531
532 /* -----------------------------------------------------------------------------
533  * Preprocessor_undef()
534  *
535  * Undefines a macro.
536  * ----------------------------------------------------------------------------- */
537 void Preprocessor_undef(const_String_or_char_ptr str) {
538   Hash *symbols;
539   assert(cpp);
540   symbols = Getattr(cpp, kpp_symbols);
541   Delattr(symbols, str);
542 }
543
544 /* -----------------------------------------------------------------------------
545  * find_args()
546  *
547  * Isolates macro arguments and returns them in a list.   For each argument,
548  * leading and trailing whitespace is stripped (ala K&R, pg. 230).
549  * ----------------------------------------------------------------------------- */
550 static List *find_args(String *s) {
551   List *args;
552   String *str;
553   int c, level;
554   long pos;
555
556   /* Create a new list */
557   args = NewList();
558   copy_location(s, args);
559
560   /* First look for a '(' */
561   pos = Tell(s);
562   skip_whitespace(s, 0);
563
564   /* Now see if the next character is a '(' */
565   c = Getc(s);
566   if (c != '(') {
567     /* Not a macro, bail out now! */
568     Seek(s, pos, SEEK_SET);
569     Delete(args);
570     return 0;
571   }
572   c = Getc(s);
573   /* Okay.  This appears to be a macro so we will start isolating arguments */
574   while (c != EOF) {
575     if (isspace(c)) {
576       skip_whitespace(s, 0);    /* Skip leading whitespace */
577       c = Getc(s);
578     }
579     str = NewStringEmpty();
580     copy_location(s, str);
581     level = 0;
582     while (c != EOF) {
583       if (c == '\"') {
584         Putc(c, str);
585         skip_tochar(s, '\"', str);
586         c = Getc(s);
587         continue;
588       } else if (c == '\'') {
589         Putc(c, str);
590         skip_tochar(s, '\'', str);
591         c = Getc(s);
592         continue;
593       }
594       if ((c == ',') && (level == 0))
595         break;
596       if ((c == ')') && (level == 0))
597         break;
598       Putc(c, str);
599       if (c == '(')
600         level++;
601       if (c == ')')
602         level--;
603       c = Getc(s);
604     }
605     if (level > 0) {
606       goto unterm;
607     }
608     Chop(str);
609     if (Len(args) || Len(str))
610       Append(args, str);
611     Delete(str);
612
613     /*    if (Len(str) && (c != ')'))
614        Append(args,str); */
615
616     if (c == ')')
617       return args;
618     c = Getc(s);
619   }
620 unterm:
621   Swig_error(Getfile(args), Getline(args), "Unterminated macro call.\n");
622   return args;
623 }
624
625 /* -----------------------------------------------------------------------------
626  * DOH *get_filename(DOH *str)
627  *
628  * Read a filename from str.   A filename can be enclose in quotes, angle brackets,
629  * or bare.
630  * ----------------------------------------------------------------------------- */
631
632 static String *get_filename(String *str, int *sysfile) {
633   String *fn;
634   int c;
635
636   skip_whitespace(str, 0);
637   fn = NewStringEmpty();
638   copy_location(str, fn);
639   c = Getc(str);
640   *sysfile = 0;
641   if (c == '\"') {
642     while (((c = Getc(str)) != EOF) && (c != '\"'))
643       Putc(c, fn);
644   } else if (c == '<') {
645     *sysfile = 1;
646     while (((c = Getc(str)) != EOF) && (c != '>'))
647       Putc(c, fn);
648   } else {
649     Putc(c, fn);
650     while (((c = Getc(str)) != EOF) && (!isspace(c)))
651       Putc(c, fn);
652     if (isspace(c))
653       Ungetc(c, str);
654   }
655   Swig_filename_correct(fn);
656   Seek(fn, 0, SEEK_SET);
657   return fn;
658 }
659
660 static String *get_options(String *str) {
661
662   int c;
663   skip_whitespace(str, 0);
664   c = Getc(str);
665   if (c == '(') {
666     String *opt;
667     int level = 1;
668     opt = NewString("(");
669     while (((c = Getc(str)) != EOF)) {
670       Putc(c, opt);
671       if (c == ')') {
672         level--;
673         if (!level)
674           return opt;
675       }
676       if (c == '(')
677         level++;
678     }
679     Delete(opt);
680     return 0;
681   } else {
682     Ungetc(c, str);
683     return 0;
684   }
685 }
686
687 /* -----------------------------------------------------------------------------
688  * expand_macro()
689  *
690  * Perform macro expansion and return a new string.  Returns NULL if some sort
691  * of error occurred.
692  * ----------------------------------------------------------------------------- */
693
694 static String *expand_macro(String *name, List *args) {
695   String *ns;
696   DOH *symbols, *macro, *margs, *mvalue, *temp, *tempa, *e;
697   int i, l;
698   int isvarargs = 0;
699
700   symbols = Getattr(cpp, kpp_symbols);
701   if (!symbols)
702     return 0;
703
704   /* See if the name is actually defined */
705   macro = Getattr(symbols, name);
706   if (!macro)
707     return 0;
708   if (Getattr(macro, kpp_expanded)) {
709     ns = NewStringEmpty();
710     Append(ns, name);
711     if (args) {
712       int lenargs = Len(args);
713       if (lenargs)
714         Putc('(', ns);
715       for (i = 0; i < lenargs; i++) {
716         Append(ns, Getitem(args, i));
717         if (i < (lenargs - 1))
718           Putc(',', ns);
719       }
720       if (i)
721         Putc(')', ns);
722     }
723     return ns;
724   }
725
726   /* Get macro arguments and value */
727   mvalue = Getattr(macro, kpp_value);
728   assert(mvalue);
729   margs = Getattr(macro, kpp_args);
730
731   if (args && Getattr(macro, kpp_varargs)) {
732     isvarargs = 1;
733     /* Variable length argument macro.  We need to collect all of the extra arguments into a single argument */
734     if (Len(args) >= (Len(margs) - 1)) {
735       int i;
736       int vi, na;
737       String *vararg = NewStringEmpty();
738       vi = Len(margs) - 1;
739       na = Len(args);
740       for (i = vi; i < na; i++) {
741         Append(vararg, Getitem(args, i));
742         if ((i + 1) < na) {
743           Append(vararg, ",");
744         }
745       }
746       /* Remove arguments */
747       for (i = vi; i < na; i++) {
748         Delitem(args, vi);
749       }
750       Append(args, vararg);
751       Delete(vararg);
752     }
753   }
754   /* If there are arguments, see if they match what we were given */
755   if (args && (margs) && (Len(margs) != Len(args))) {
756     if (Len(margs) > (1 + isvarargs))
757       Swig_error(Getfile(args), Getline(args), "Macro '%s' expects %d arguments\n", name, Len(margs) - isvarargs);
758     else if (Len(margs) == (1 + isvarargs))
759       Swig_error(Getfile(args), Getline(args), "Macro '%s' expects 1 argument\n", name);
760     else
761       Swig_error(Getfile(args), Getline(args), "Macro '%s' expects no arguments\n", name);
762     return 0;
763   }
764
765   /* If the macro expects arguments, but none were supplied, we leave it in place */
766   if (!args && (margs) && Len(margs) > 0) {
767     return NewString(name);
768   }
769
770   /* Copy the macro value */
771   ns = Copy(mvalue);
772   copy_location(mvalue, ns);
773
774   /* Tag the macro as being expanded.   This is to avoid recursion in
775      macro expansion */
776
777   temp = NewStringEmpty();
778   tempa = NewStringEmpty();
779   if (args && margs) {
780     l = Len(margs);
781     for (i = 0; i < l; i++) {
782       DOH *arg, *aname;
783       String *reparg;
784       arg = Getitem(args, i);   /* Get an argument value */
785       reparg = Preprocessor_replace(arg);
786       aname = Getitem(margs, i);        /* Get macro argument name */
787       if (strstr(Char(ns), "\001")) {
788         /* Try to replace a quoted version of the argument */
789         Clear(temp);
790         Clear(tempa);
791         Printf(temp, "\001%s", aname);
792         Printf(tempa, "\"%s\"", arg);
793         Replace(ns, temp, tempa, DOH_REPLACE_ID_END);
794       }
795       if (strstr(Char(ns), "\002")) {
796         /* Look for concatenation tokens */
797         Clear(temp);
798         Clear(tempa);
799         Printf(temp, "\002%s", aname);
800         Append(tempa, "\002\003");
801         Replace(ns, temp, tempa, DOH_REPLACE_ID_END);
802         Clear(temp);
803         Clear(tempa);
804         Printf(temp, "%s\002", aname);
805         Append(tempa, "\003\002");
806         Replace(ns, temp, tempa, DOH_REPLACE_ID_BEGIN);
807       }
808
809       /* Non-standard macro expansion.   The value `x` is replaced by a quoted
810          version of the argument except that if the argument is already quoted
811          nothing happens */
812
813       if (strchr(Char(ns), '`')) {
814         String *rep;
815         char *c;
816         Clear(temp);
817         Printf(temp, "`%s`", aname);
818         c = Char(arg);
819         if (*c == '\"') {
820           rep = arg;
821         } else {
822           Clear(tempa);
823           Printf(tempa, "\"%s\"", arg);
824           rep = tempa;
825         }
826         Replace(ns, temp, rep, DOH_REPLACE_ANY);
827       }
828
829       /* Non-standard mangle expansions.  
830          The #@Name is replaced by mangle_arg(Name). */
831       if (strstr(Char(ns), "\004")) {
832         String *marg = Swig_string_mangle(arg);
833         Clear(temp);
834         Printf(temp, "\004%s", aname);
835         Replace(ns, temp, marg, DOH_REPLACE_ID_END);
836         Delete(marg);
837       }
838       if (strstr(Char(ns), "\005")) {
839         String *marg = Swig_string_mangle(arg);
840         Clear(temp);
841         Clear(tempa);
842         Printf(temp, "\005%s", aname);
843         Printf(tempa, "\"%s\"", marg);
844         Replace(ns, temp, tempa, DOH_REPLACE_ID_END);
845         Delete(marg);
846       }
847
848       if (isvarargs && i == l - 1 && Len(arg) == 0) {
849         /* Zero length varargs macro argument.   We search for commas that might appear before and nuke them */
850         char *a, *s, *t, *name;
851         int namelen;
852         s = Char(ns);
853         name = Char(aname);
854         namelen = Len(aname);
855         a = strstr(s, name);
856         while (a) {
857           char ca = a[namelen + 1];
858           if (!isidchar((int) ca)) {
859             /* Matched the entire vararg name, not just a prefix */
860             t = a - 1;
861             if (*t == '\002') {
862               t--;
863               while (t >= s) {
864                 if (isspace((int) *t))
865                   t--;
866                 else if (*t == ',') {
867                   *t = ' ';
868                 } else
869                   break;
870               }
871             }
872           }
873           a = strstr(a + namelen, name);
874         }
875       }
876       /*      Replace(ns, aname, arg, DOH_REPLACE_ID); */
877       Replace(ns, aname, reparg, DOH_REPLACE_ID);       /* Replace expanded args */
878       Replace(ns, "\003", arg, DOH_REPLACE_ANY);        /* Replace unexpanded arg */
879       Delete(reparg);
880     }
881   }
882   Replace(ns, "\002", "", DOH_REPLACE_ANY);     /* Get rid of concatenation tokens */
883   Replace(ns, "\001", "#", DOH_REPLACE_ANY);    /* Put # back (non-standard C) */
884   Replace(ns, "\004", "#@", DOH_REPLACE_ANY);   /* Put # back (non-standard C) */
885
886   /* Expand this macro even further */
887   Setattr(macro, kpp_expanded, "1");
888
889   e = Preprocessor_replace(ns);
890
891   Delattr(macro, kpp_expanded);
892   Delete(ns);
893
894   if (Getattr(macro, kpp_swigmacro)) {
895     String *g;
896     String *f = NewStringEmpty();
897     Seek(e, 0, SEEK_SET);
898     copy_location(macro, e);
899     g = Preprocessor_parse(e);
900
901 #if 0
902     /* Drop the macro in place, but with a marker around it */
903     Printf(f, "/*@%s,%d,%s@*/%s/*@@*/", Getfile(macro), Getline(macro), name, g);
904 #else
905     /* Use simplified around markers to properly count lines in cscanner.c */
906     if (strchr(Char(g), '\n')) {
907       Printf(f, "/*@SWIG:%s,%d,%s@*/%s/*@SWIG@*/", Getfile(macro), Getline(macro), name, g);
908 #if 0
909       Printf(f, "/*@SWIG:%s@*/%s/*@SWIG@*/", name, g);
910 #endif
911     } else {
912       Append(f, g);
913     }
914 #endif
915
916     Delete(g);
917     Delete(e);
918     e = f;
919   }
920   Delete(temp);
921   Delete(tempa);
922   return e;
923 }
924
925 /* -----------------------------------------------------------------------------
926  * evaluate_args()
927  *
928  * Evaluate the arguments of a macro 
929  * ----------------------------------------------------------------------------- */
930
931 List *evaluate_args(List *x) {
932   Iterator i;
933   List *nl = NewList();
934
935   for (i = First(x); i.item; i = Next(i)) {
936     Append(nl, Preprocessor_replace(i.item));
937   }
938   return nl;
939 }
940
941 /* -----------------------------------------------------------------------------
942  * DOH *Preprocessor_replace(DOH *s)
943  *
944  * Performs a macro substitution on a string s.  Returns a new string with
945  * substitutions applied.   This function works by walking down s and looking
946  * for identifiers.   When found, a check is made to see if they are macros
947  * which are then expanded.
948  * ----------------------------------------------------------------------------- */
949
950 /* #define SWIG_PUT_BUFF  */
951
952 DOH *Preprocessor_replace(DOH *s) {
953   DOH *ns, *symbols, *m;
954   int c, i, state = 0;
955
956   String *id = NewStringEmpty();
957
958   assert(cpp);
959   symbols = Getattr(cpp, kpp_symbols);
960
961   ns = NewStringEmpty();
962   copy_location(s, ns);
963   Seek(s, 0, SEEK_SET);
964
965   /* Try to locate identifiers in s and replace them with macro replacements */
966   while ((c = Getc(s)) != EOF) {
967     switch (state) {
968     case 0:
969       if (isidentifier(c) || (c == '%')) {
970         Clear(id);
971         Putc(c, id);
972         state = 1;
973       } else if (c == '\"') {
974         Putc(c, ns);
975         skip_tochar(s, '\"', ns);
976       } else if (c == '\'') {
977         Putc(c, ns);
978         skip_tochar(s, '\'', ns);
979       } else if (c == '/') {
980         Putc(c, ns);
981         state = 10;
982       } else {
983         Putc(c, ns);
984       }
985       break;
986     case 1:                     /* An identifier */
987       if (isidchar(c)) {
988         Putc(c, id);
989         state = 1;
990       } else {
991         /* We found the end of a valid identifier */
992         Ungetc(c, s);
993         /* See if this is the special "defined" macro */
994         if (Equal(kpp_defined, id)) {
995           int lenargs = 0;
996           DOH *args = 0;
997           /* See whether or not a paranthesis has been used */
998           skip_whitespace(s, 0);
999           c = Getc(s);
1000           if (c == '(') {
1001             Ungetc(c, s);
1002             args = find_args(s);
1003           } else if (isidchar(c)) {
1004             DOH *arg = NewStringEmpty();
1005             args = NewList();
1006             Putc(c, arg);
1007             while (((c = Getc(s)) != EOF)) {
1008               if (!isidchar(c)) {
1009                 Ungetc(c, s);
1010                 break;
1011               }
1012               Putc(c, arg);
1013             }
1014             if (Len(arg))
1015               Append(args, arg);
1016             Delete(arg);
1017           } else {
1018             Seek(s, -1, SEEK_CUR);
1019           }
1020           lenargs = Len(args);
1021           if ((!args) || (!lenargs)) {
1022             /* This is not a defined() macro. */
1023             Append(ns, id);
1024             state = 0;
1025             break;
1026           }
1027           for (i = 0; i < lenargs; i++) {
1028             DOH *o = Getitem(args, i);
1029             if (!Getattr(symbols, o)) {
1030               break;
1031             }
1032           }
1033           if (i < lenargs)
1034             Putc('0', ns);
1035           else
1036             Putc('1', ns);
1037           Delete(args);
1038           state = 0;
1039           break;
1040         }
1041         if (Equal(kpp_LINE, id)) {
1042           Printf(ns, "%d", Getline(s));
1043           state = 0;
1044           break;
1045         }
1046         if (Equal(kpp_FILE, id)) {
1047           String *fn = Copy(Getfile(s));
1048           Replaceall(fn, "\\", "\\\\");
1049           Printf(ns, "\"%s\"", fn);
1050           Delete(fn);
1051           state = 0;
1052           break;
1053         }
1054         /* See if the macro is defined in the preprocessor symbol table */
1055         if ((m = Getattr(symbols, id))) {
1056           DOH *args = 0;
1057           DOH *e;
1058           /* See if the macro expects arguments */
1059           if (Getattr(m, kpp_args)) {
1060             /* Yep.  We need to go find the arguments and do a substitution */
1061             args = find_args(s);
1062             if (!Len(args)) {
1063               Delete(args);
1064               args = 0;
1065             }
1066           } else {
1067             args = 0;
1068           }
1069           e = expand_macro(id, args);
1070           if (e) {
1071             Append(ns, e);
1072           }
1073           Delete(e);
1074           Delete(args);
1075         } else {
1076           Append(ns, id);
1077         }
1078         state = 0;
1079       }
1080       break;
1081     case 10:
1082       if (c == '/')
1083         state = 11;
1084       else if (c == '*')
1085         state = 12;
1086       else {
1087         Ungetc(c, s);
1088         state = 0;
1089         break;
1090       }
1091       Putc(c, ns);
1092       break;
1093     case 11:
1094       Putc(c, ns);
1095       if (c == '\n')
1096         state = 0;
1097       break;
1098     case 12:
1099       Putc(c, ns);
1100       if (c == '*')
1101         state = 13;
1102       break;
1103     case 13:
1104       Putc(c, ns);
1105       if (c == '/')
1106         state = 0;
1107       else if (c != '*')
1108         state = 12;
1109       break;
1110     default:
1111       state = 0;
1112       break;
1113     }
1114   }
1115
1116   /* Identifier at the end */
1117   if (state == 1) {
1118     /* See if this is the special "defined" macro */
1119     if (Equal(kpp_defined, id)) {
1120       Swig_error(Getfile(s), Getline(s), "No arguments given to defined()\n");
1121     } else if ((m = Getattr(symbols, id))) {
1122       DOH *e;
1123       /* Yes.  There is a macro here */
1124       /* See if the macro expects arguments */
1125       /*      if (Getattr(m,"args")) {
1126          Swig_error(Getfile(id),Getline(id),"Macro arguments expected.\n");
1127          } */
1128       e = expand_macro(id, 0);
1129       Append(ns, e);
1130       Delete(e);
1131     } else {
1132       Append(ns, id);
1133     }
1134   }
1135   Delete(id);
1136   return ns;
1137 }
1138
1139
1140 /* -----------------------------------------------------------------------------
1141  * int checkpp_id(DOH *s)
1142  *
1143  * Checks the string s to see if it contains any unresolved identifiers.  This
1144  * function contains the heuristic that determines whether or not a macro
1145  * definition passes through the preprocessor as a constant declaration.
1146  * ----------------------------------------------------------------------------- */
1147 static int checkpp_id(DOH *s) {
1148   int c;
1149   int hastok = 0;
1150   Scanner *scan = id_scan;
1151
1152   Seek(s, 0, SEEK_SET);
1153
1154   Scanner_clear(scan);
1155   s = Copy(s);
1156   Seek(s, SEEK_SET, 0);
1157   Scanner_push(scan, s);
1158   while ((c = Scanner_token(scan))) {
1159     hastok = 1;
1160     if ((c == SWIG_TOKEN_ID) || (c == SWIG_TOKEN_LBRACE) || (c == SWIG_TOKEN_RBRACE))
1161       return 1;
1162   }
1163   if (!hastok)
1164     return 1;
1165   return 0;
1166 }
1167
1168 /* addline().  Utility function for adding lines to a chunk */
1169 static void addline(DOH *s1, DOH *s2, int allow) {
1170   if (allow) {
1171     Append(s1, s2);
1172   } else {
1173     char *c = Char(s2);
1174     while (*c) {
1175       if (*c == '\n')
1176         Putc('\n', s1);
1177       c++;
1178     }
1179   }
1180 }
1181
1182 static void add_chunk(DOH *ns, DOH *chunk, int allow) {
1183   DOH *echunk;
1184   Seek(chunk, 0, SEEK_SET);
1185   if (allow) {
1186     echunk = Preprocessor_replace(chunk);
1187     addline(ns, echunk, allow);
1188     Delete(echunk);
1189   } else {
1190     addline(ns, chunk, 0);
1191   }
1192   Clear(chunk);
1193 }
1194
1195 /*
1196   push/pop_imported(): helper functions for defining and undefining
1197   SWIGIMPORTED (when %importing a file).
1198  */
1199 static void push_imported() {
1200   if (imported_depth == 0) {
1201     Preprocessor_define("SWIGIMPORTED 1", 0);
1202   }
1203   ++imported_depth;
1204 }
1205
1206 static void pop_imported() {
1207   --imported_depth;
1208   if (imported_depth == 0) {
1209     Preprocessor_undef("SWIGIMPORTED");
1210   }
1211 }
1212
1213
1214 /* -----------------------------------------------------------------------------
1215  * Preprocessor_parse()
1216  *
1217  * Parses the string s.  Returns a new string containing the preprocessed version.
1218  *
1219  * Parsing rules :
1220  *       1.  Lines starting with # are C preprocessor directives
1221  *       2.  Macro expansion inside strings is not allowed
1222  *       3.  All code inside false conditionals is changed to blank lines
1223  *       4.  Code in %{, %} is not parsed because it may need to be
1224  *           included inline (with all preprocessor directives included).
1225  * ----------------------------------------------------------------------------- */
1226
1227 String *Preprocessor_parse(String *s) {
1228   String *ns;                   /* New string containing the preprocessed text */
1229   String *chunk, *decl;
1230   Hash *symbols;
1231   String *id = 0, *value = 0, *comment = 0;
1232   int i, state, e, c;
1233   int start_line = 0;
1234   int allow = 1;
1235   int level = 0;
1236   int dlevel = 0;
1237   int mask = 0;
1238   int start_level = 0;
1239   int cpp_lines = 0;
1240   int cond_lines[256];
1241
1242   /* Blow away all carriage returns */
1243   Replace(s, "\015", "", DOH_REPLACE_ANY);
1244
1245   ns = NewStringEmpty();        /* Return result */
1246
1247   decl = NewStringEmpty();
1248   id = NewStringEmpty();
1249   value = NewStringEmpty();
1250   comment = NewStringEmpty();
1251   chunk = NewStringEmpty();
1252   copy_location(s, chunk);
1253   copy_location(s, ns);
1254   symbols = Getattr(cpp, kpp_symbols);
1255
1256   state = 0;
1257   while ((c = Getc(s)) != EOF) {
1258     switch (state) {
1259     case 0:                     /* Initial state - in first column */
1260       /* Look for C preprocessor directives.   Otherwise, go directly to state 1 */
1261       if (c == '#') {
1262         add_chunk(ns, chunk, allow);
1263         copy_location(s, chunk);
1264         cpp_lines = 1;
1265         state = 40;
1266       } else if (isspace(c)) {
1267         Putc(c, chunk);
1268         skip_whitespace(s, chunk);
1269       } else {
1270         state = 1;
1271         Ungetc(c, s);
1272       }
1273       break;
1274     case 1:                     /* Non-preprocessor directive */
1275       /* Look for SWIG directives */
1276       if (c == '%') {
1277         state = 100;
1278         break;
1279       }
1280       Putc(c, chunk);
1281       if (c == '\n')
1282         state = 0;
1283       else if (c == '\"') {
1284         start_line = Getline(s);
1285         if (skip_tochar(s, '\"', chunk) < 0) {
1286           Swig_error(Getfile(s), -1, "Unterminated string constant starting at line %d\n", start_line);
1287         }
1288       } else if (c == '\'') {
1289         start_line = Getline(s);
1290         if (skip_tochar(s, '\'', chunk) < 0) {
1291           Swig_error(Getfile(s), -1, "Unterminated character constant starting at line %d\n", start_line);
1292         }
1293       } else if (c == '/')
1294         state = 30;             /* Comment */
1295       break;
1296
1297     case 30:                    /* Possibly a comment string of some sort */
1298       start_line = Getline(s);
1299       Putc(c, chunk);
1300       if (c == '/')
1301         state = 31;
1302       else if (c == '*')
1303         state = 32;
1304       else
1305         state = 1;
1306       break;
1307     case 31:
1308       Putc(c, chunk);
1309       if (c == '\n')
1310         state = 0;
1311       break;
1312     case 32:
1313       Putc(c, chunk);
1314       if (c == '*')
1315         state = 33;
1316       break;
1317     case 33:
1318       Putc(c, chunk);
1319       if (c == '/')
1320         state = 1;
1321       else if (c != '*')
1322         state = 32;
1323       break;
1324
1325     case 40:                    /* Start of a C preprocessor directive */
1326       if (c == '\n') {
1327         Putc('\n', chunk);
1328         state = 0;
1329       } else if (isspace(c)) {
1330         state = 40;
1331       } else {
1332         /* Got the start of a preprocessor directive */
1333         Ungetc(c, s);
1334         Clear(id);
1335         copy_location(s, id);
1336         state = 41;
1337       }
1338       break;
1339
1340     case 41:                    /* Build up the name of the preprocessor directive */
1341       if ((isspace(c) || (!isalpha(c)))) {
1342         Clear(value);
1343         Clear(comment);
1344         if (c == '\n') {
1345           Ungetc(c, s);
1346           state = 50;
1347         } else {
1348           state = 42;
1349           if (!isspace(c)) {
1350             Ungetc(c, s);
1351           }
1352         }
1353
1354         copy_location(s, value);
1355         break;
1356       }
1357       Putc(c, id);
1358       break;
1359
1360     case 42:                    /* Strip any leading space before preprocessor value */
1361       if (isspace(c)) {
1362         if (c == '\n') {
1363           Ungetc(c, s);
1364           state = 50;
1365         }
1366         break;
1367       }
1368       state = 43;
1369       /* no break intended here */
1370
1371     case 43:
1372       /* Get preprocessor value */
1373       if (c == '\n') {
1374         Ungetc(c, s);
1375         state = 50;
1376       } else if (c == '/') {
1377         state = 45;
1378       } else if (c == '\"') {
1379         Putc(c, value);
1380         skip_tochar(s, '\"', value);
1381       } else if (c == '\'') {
1382         Putc(c, value);
1383         skip_tochar(s, '\'', value);
1384       } else {
1385         Putc(c, value);
1386         if (c == '\\')
1387           state = 44;
1388       }
1389       break;
1390
1391     case 44:
1392       if (c == '\n') {
1393         Putc(c, value);
1394         cpp_lines++;
1395       } else {
1396         Ungetc(c, s);
1397       }
1398       state = 43;
1399       break;
1400
1401       /* States 45-48 are used to remove, but retain comments from macro values.  The comments
1402          will be placed in the output in an alternative form */
1403
1404     case 45:
1405       if (c == '/')
1406         state = 46;
1407       else if (c == '*')
1408         state = 47;
1409       else if (c == '\n') {
1410         Putc('/', value);
1411         Ungetc(c, s);
1412         cpp_lines++;
1413         state = 50;
1414       } else {
1415         Putc('/', value);
1416         Putc(c, value);
1417         state = 43;
1418       }
1419       break;
1420     case 46:
1421       if (c == '\n') {
1422         Ungetc(c, s);
1423         cpp_lines++;
1424         state = 50;
1425       } else
1426         Putc(c, comment);
1427       break;
1428     case 47:
1429       if (c == '*')
1430         state = 48;
1431       else
1432         Putc(c, comment);
1433       break;
1434     case 48:
1435       if (c == '/')
1436         state = 43;
1437       else if (c == '*')
1438         Putc(c, comment);
1439       else {
1440         Putc('*', comment);
1441         Putc(c, comment);
1442         state = 47;
1443       }
1444       break;
1445     case 50:
1446       /* Check for various preprocessor directives */
1447       Chop(value);
1448       if (Equal(id, kpp_define)) {
1449         if (allow) {
1450           DOH *m, *v, *v1;
1451           Seek(value, 0, SEEK_SET);
1452           m = Preprocessor_define(value, 0);
1453           if ((m) && !(Getattr(m, kpp_args))) {
1454             v = Copy(Getattr(m, kpp_value));
1455             if (Len(v)) {
1456               Swig_error_silent(1);
1457               v1 = Preprocessor_replace(v);
1458               Swig_error_silent(0);
1459               /*              Printf(stdout,"checking '%s'\n", v1); */
1460               if (!checkpp_id(v1)) {
1461                 if (Len(comment) == 0)
1462                   Printf(ns, "%%constant %s = %s;\n", Getattr(m, kpp_name), v1);
1463                 else
1464                   Printf(ns, "%%constant %s = %s; /*%s*/\n", Getattr(m, kpp_name), v1, comment);
1465                 cpp_lines--;
1466               }
1467               Delete(v1);
1468             }
1469             Delete(v);
1470           }
1471         }
1472       } else if (Equal(id, kpp_undef)) {
1473         if (allow)
1474           Preprocessor_undef(value);
1475       } else if (Equal(id, kpp_ifdef)) {
1476         cond_lines[level] = Getline(id);
1477         level++;
1478         if (allow) {
1479           start_level = level;
1480           /* See if the identifier is in the hash table */
1481           if (!Getattr(symbols, value))
1482             allow = 0;
1483           mask = 1;
1484         }
1485       } else if (Equal(id, kpp_ifndef)) {
1486         cond_lines[level] = Getline(id);
1487         level++;
1488         if (allow) {
1489           start_level = level;
1490           /* See if the identifier is in the hash table */
1491           if (Getattr(symbols, value))
1492             allow = 0;
1493           mask = 1;
1494         }
1495       } else if (Equal(id, kpp_else)) {
1496         if (level <= 0) {
1497           Swig_error(Getfile(s), Getline(id), "Misplaced #else.\n");
1498         } else {
1499           cond_lines[level - 1] = Getline(id);
1500           if (allow) {
1501             allow = 0;
1502             mask = 0;
1503           } else if (level == start_level) {
1504             allow = 1 * mask;
1505           }
1506         }
1507       } else if (Equal(id, kpp_endif)) {
1508         level--;
1509         if (level < 0) {
1510           Swig_error(Getfile(id), Getline(id), "Extraneous #endif.\n");
1511           level = 0;
1512         } else {
1513           if (level < start_level) {
1514             allow = 1;
1515             start_level--;
1516           }
1517         }
1518       } else if (Equal(id, kpp_if)) {
1519         cond_lines[level] = Getline(id);
1520         level++;
1521         if (allow) {
1522           int val;
1523           String *sval = Preprocessor_replace(value);
1524           start_level = level;
1525           Seek(sval, 0, SEEK_SET);
1526           /*      Printf(stdout,"Evaluating '%s'\n", sval); */
1527           val = Preprocessor_expr(sval, &e);
1528           if (e) {
1529             char *msg = Preprocessor_expr_error();
1530             Seek(value, 0, SEEK_SET);
1531             Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "Could not evaluate '%s'\n", value);
1532             if (msg)
1533               Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "Error: '%s'\n", msg);
1534             allow = 0;
1535           } else {
1536             if (val == 0)
1537               allow = 0;
1538           }
1539           mask = 1;
1540         }
1541       } else if (Equal(id, kpp_elif)) {
1542         if (level == 0) {
1543           Swig_error(Getfile(s), Getline(id), "Misplaced #elif.\n");
1544         } else {
1545           cond_lines[level - 1] = Getline(id);
1546           if (allow) {
1547             allow = 0;
1548             mask = 0;
1549           } else if (level == start_level) {
1550             int val;
1551             String *sval = Preprocessor_replace(value);
1552             Seek(sval, 0, SEEK_SET);
1553             val = Preprocessor_expr(sval, &e);
1554             if (e) {
1555               char *msg = Preprocessor_expr_error();
1556               Seek(value, 0, SEEK_SET);
1557               Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "Could not evaluate '%s'\n", value);
1558               if (msg)
1559                 Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "Error: '%s'\n", msg);
1560               allow = 0;
1561             } else {
1562               if (val)
1563                 allow = 1 * mask;
1564               else
1565                 allow = 0;
1566             }
1567           }
1568         }
1569       } else if (Equal(id, kpp_warning)) {
1570         if (allow) {
1571           Swig_warning(WARN_PP_CPP_WARNING, Getfile(s), Getline(id), "CPP #warning, %s\n", value);
1572         }
1573       } else if (Equal(id, kpp_error)) {
1574         if (allow) {
1575           if (error_as_warning) {
1576             Swig_warning(WARN_PP_CPP_ERROR, Getfile(s), Getline(id), "CPP #error \"%s\".\n", value);
1577           } else {
1578             Swig_error(Getfile(s), Getline(id), "CPP #error \"%s\". Use the -cpperraswarn option to continue swig processing.\n", value);
1579           }
1580         }
1581       } else if (Equal(id, kpp_line)) {
1582       } else if (Equal(id, kpp_include)) {
1583         if (((include_all) || (import_all)) && (allow)) {
1584           String *s1, *s2, *fn;
1585           char *dirname;
1586           int sysfile = 0;
1587           if (include_all && import_all) {
1588             Swig_warning(WARN_PP_INCLUDEALL_IMPORTALL, Getfile(s), Getline(id), "Both includeall and importall are defined: using includeall\n");
1589             import_all = 0;
1590           }
1591           Seek(value, 0, SEEK_SET);
1592           fn = get_filename(value, &sysfile);
1593           s1 = cpp_include(fn, sysfile);
1594           if (s1) {
1595             if (include_all)
1596               Printf(ns, "%%includefile \"%s\" [\n", Swig_last_file());
1597             else if (import_all) {
1598               Printf(ns, "%%importfile \"%s\" [\n", Swig_last_file());
1599               push_imported();
1600             }
1601
1602             /* See if the filename has a directory component */
1603             dirname = Swig_file_dirname(Swig_last_file());
1604             if (sysfile || !strlen(dirname))
1605               dirname = 0;
1606             if (dirname) {
1607               dirname[strlen(dirname) - 1] = 0; /* Kill trailing directory delimiter */
1608               Swig_push_directory(dirname);
1609             }
1610             s2 = Preprocessor_parse(s1);
1611             addline(ns, s2, allow);
1612             Append(ns, "\n]");
1613             if (dirname) {
1614               Swig_pop_directory();
1615             }
1616             if (import_all) {
1617               pop_imported();
1618             }
1619             Delete(s2);
1620           }
1621           Delete(s1);
1622           Delete(fn);
1623         }
1624       } else if (Equal(id, kpp_pragma)) {
1625         if (Strncmp(value, "SWIG ", 5) == 0) {
1626           char *c = Char(value) + 5;
1627           while (*c && (isspace((int) *c)))
1628             c++;
1629           if (*c) {
1630             if (strncmp(c, "nowarn=", 7) == 0) {
1631               String *val = NewString(c + 7);
1632               String *nowarn = Preprocessor_replace(val);
1633               Swig_warnfilter(nowarn, 1);
1634               Delete(nowarn);
1635               Delete(val);
1636             } else if (strncmp(c, "cpperraswarn=", 13) == 0) {
1637               error_as_warning = atoi(c + 13);
1638             } else {
1639               Swig_error(Getfile(s), Getline(id), "Unknown SWIG pragma: %s\n", c);
1640             }
1641           }
1642         }
1643       } else if (Equal(id, kpp_level)) {
1644         Swig_error(Getfile(s), Getline(id), "cpp debug: level = %d, startlevel = %d\n", level, start_level);
1645       }
1646       for (i = 0; i < cpp_lines; i++)
1647         Putc('\n', ns);
1648       state = 0;
1649       break;
1650
1651       /* Swig directives  */
1652     case 100:
1653       /* %{,%} block  */
1654       if (c == '{') {
1655         start_line = Getline(s);
1656         add_chunk(ns, chunk, allow);
1657         copy_location(s, chunk);
1658         Putc('%', chunk);
1659         Putc(c, chunk);
1660         state = 105;
1661       }
1662       /* %#cpp -  an embedded C preprocessor directive (we strip off the %)  */
1663       else if (c == '#') {
1664         add_chunk(ns, chunk, allow);
1665         Putc(c, chunk);
1666         state = 107;
1667       } else if (isidentifier(c)) {
1668         Clear(decl);
1669         Putc('%', decl);
1670         Putc(c, decl);
1671         state = 110;
1672       } else {
1673         Putc('%', chunk);
1674         Putc(c, chunk);
1675         state = 1;
1676       }
1677       break;
1678
1679     case 105:
1680       Putc(c, chunk);
1681       if (c == '%')
1682         state = 106;
1683       break;
1684
1685     case 106:
1686       Putc(c, chunk);
1687       if (c == '}') {
1688         state = 1;
1689         addline(ns, chunk, allow);
1690         Clear(chunk);
1691         copy_location(s, chunk);
1692       } else {
1693         state = 105;
1694       }
1695       break;
1696
1697     case 107:
1698       Putc(c, chunk);
1699       if (c == '\n') {
1700         addline(ns, chunk, allow);
1701         Clear(chunk);
1702         state = 0;
1703       } else if (c == '\\') {
1704         state = 108;
1705       }
1706       break;
1707
1708     case 108:
1709       Putc(c, chunk);
1710       state = 107;
1711       break;
1712
1713     case 110:
1714       if (!isidchar(c)) {
1715         Ungetc(c, s);
1716         /* Look for common Swig directives  */
1717         if (Equal(decl, kpp_dinclude) || Equal(decl, kpp_dimport) || Equal(decl, kpp_dextern)) {
1718           /* Got some kind of file inclusion directive  */
1719           if (allow) {
1720             DOH *s1, *s2, *fn, *opt;
1721             int sysfile = 0;
1722
1723             if (Equal(decl, kpp_dextern)) {
1724               Swig_warning(WARN_DEPRECATED_EXTERN, Getfile(s), Getline(s), "%%extern is deprecated. Use %%import instead.\n");
1725               Clear(decl);
1726               Append(decl, "%%import");
1727             }
1728             opt = get_options(s);
1729             fn = get_filename(s, &sysfile);
1730             s1 = cpp_include(fn, sysfile);
1731             if (s1) {
1732               char *dirname;
1733               add_chunk(ns, chunk, allow);
1734               copy_location(s, chunk);
1735               Printf(ns, "%sfile%s \"%s\" [\n", decl, opt, Swig_last_file());
1736               if (Equal(decl, kpp_dimport)) {
1737                 push_imported();
1738               }
1739               dirname = Swig_file_dirname(Swig_last_file());
1740               if (sysfile || !strlen(dirname))
1741                 dirname = 0;
1742               if (dirname) {
1743                 dirname[strlen(dirname) - 1] = 0;       /* Kill trailing directory delimiter */
1744                 Swig_push_directory(dirname);
1745               }
1746               s2 = Preprocessor_parse(s1);
1747               if (dirname) {
1748                 Swig_pop_directory();
1749               }
1750               if (Equal(decl, kpp_dimport)) {
1751                 pop_imported();
1752               }
1753               addline(ns, s2, allow);
1754               Append(ns, "\n]");
1755               Delete(s2);
1756               Delete(s1);
1757             }
1758             Delete(fn);
1759           }
1760           state = 1;
1761         } else if (Equal(decl, kpp_dline)) {
1762           /* Got a line directive  */
1763           state = 1;
1764         } else if (Equal(decl, kpp_ddefine)) {
1765           /* Got a define directive  */
1766           dlevel++;
1767           add_chunk(ns, chunk, allow);
1768           copy_location(s, chunk);
1769           Clear(value);
1770           copy_location(s, value);
1771           state = 150;
1772         } else {
1773           Append(chunk, decl);
1774           state = 1;
1775         }
1776       } else {
1777         Putc(c, decl);
1778       }
1779       break;
1780
1781       /* Searching for the end of a %define statement  */
1782     case 150:
1783       Putc(c, value);
1784       if (c == '%') {
1785         const char *ed = "enddef";
1786         const char *df = "define";
1787         char statement[7];
1788         int i = 0;
1789         for (i = 0; i < 6;) {
1790           c = Getc(s);
1791           Putc(c, value);
1792           statement[i++] = (char)c;
1793           if (strncmp(statement, ed, i) && strncmp(statement, df, i))
1794             break;
1795         }
1796         c = Getc(s);
1797         Ungetc(c, s);
1798         if ((i == 6) && (isspace(c))) {
1799           if (strncmp(statement, df, i) == 0) {
1800             ++dlevel;
1801           } else {
1802             if (strncmp(statement, ed, i) == 0) {
1803               --dlevel;
1804               if (!dlevel) {
1805                 /* Got the macro  */
1806                 for (i = 0; i < 7; i++) {
1807                   Delitem(value, DOH_END);
1808                 }
1809                 if (allow) {
1810                   Seek(value, 0, SEEK_SET);
1811                   Preprocessor_define(value, 1);
1812                 }
1813                 /* Putc('\n',ns); */
1814                 addline(ns, value, 0);
1815                 state = 0;
1816               }
1817             }
1818           }
1819         }
1820       }
1821       break;
1822     default:
1823       Printf(stderr, "cpp: Invalid parser state %d\n", state);
1824       abort();
1825       break;
1826     }
1827   }
1828   while (level > 0) {
1829     Swig_error(Getfile(s), -1, "Missing #endif for conditional starting on line %d\n", cond_lines[level - 1]);
1830     level--;
1831   }
1832   if (state == 150) {
1833     Seek(value, 0, SEEK_SET);
1834     Swig_error(Getfile(s), -1, "Missing %%enddef for macro starting on line %d\n", Getline(value));
1835   }
1836   if ((state >= 105) && (state < 107)) {
1837     Swig_error(Getfile(s), -1, "Unterminated %%{ ... %%} block starting on line %d\n", start_line);
1838   }
1839   if ((state >= 30) && (state < 40)) {
1840     Swig_error(Getfile(s), -1, "Unterminated comment starting on line %d\n", start_line);
1841   }
1842   add_chunk(ns, chunk, allow);
1843   copy_location(s, chunk);
1844
1845   /*  DelScope(scp); */
1846   Delete(decl);
1847   Delete(id);
1848   Delete(value);
1849   Delete(comment);
1850   Delete(chunk);
1851
1852   /*  fprintf(stderr,"cpp: %d\n", Len(Getattr(cpp,"symbols"))); */
1853   return ns;
1854 }