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.
7 * An implementation of a C preprocessor plus some support for additional
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 * ----------------------------------------------------------------------------- */
16 char cvsroot_cpp_c[] = "$Id: cpp.c 11098 2009-01-30 10:32:59Z bhy $";
19 #include "preprocessor.h"
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 */
33 /* Test a character to see if it starts an identifier */
34 #define isidentifier(c) ((isalpha(c)) || (c == '_') || (c == '$'))
36 /* Test a character to see if it valid in an identifier (after the first letter) */
37 #define isidchar(c) ((isalnum(c)) || (c == '_') || (c == '$'))
39 DOH *Preprocessor_replace(DOH *);
42 static void skip_whitespace(String *s, String *out) {
44 while ((c = Getc(s)) != EOF) {
53 /* Skip to a specified character taking line breaks into account */
54 static int skip_tochar(String *s, int ch, String *out) {
56 while ((c = Getc(s)) != EOF) {
63 if ((c != EOF) && (out))
72 static void copy_location(const DOH *s1, DOH *s2) {
73 Setfile(s2, Getfile((DOH *) s1));
74 Setline(s2, Getline((DOH *) s1));
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)) {
85 Setattr(included_files, file, file);
88 /* XXX(bhy) may not need the seek */
89 /* Seek(fn, 0, SEEK_SET); */
91 Swig_warning(WARN_PP_MISSING_FILE, Getfile(fn), Getline(fn), "Unable to find '%s'\n", fn);
93 Swig_error(Getfile(fn), Getline(fn), "Unable to find '%s'\n", fn);
99 dependencies = NewList();
101 lf = Copy(Swig_last_file());
102 Append(dependencies, lf);
108 List *Preprocessor_depend(void) {
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;
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;
144 static String *kpp_LINE = 0;
145 static String *kpp_FILE = 0;
147 void Preprocessor_init(void) {
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");
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");
180 kpp_LINE = NewString("__LINE__");
181 kpp_FILE = NewString("__FILE__");
185 Setattr(cpp, kpp_symbols, s);
187 Preprocessor_expr_init(); /* Initialize the expression evaluator */
188 included_files = NewHash();
190 id_scan = NewScanner();;
194 void Preprocessor_delete(void) {
201 Delete(kpp_expanded);
206 Delete(kpp_swigmacro);
218 Delete(kpp_dinclude);
228 Delete(included_files);
229 Preprocessor_expr_delete();
232 Delete(dependencies);
234 Delete(Swig_add_directory(0));
237 /* -----------------------------------------------------------------------------
238 * void Preprocessor_include_all() - Instruct preprocessor to include all files
239 * ----------------------------------------------------------------------------- */
240 void Preprocessor_include_all(int a) {
244 void Preprocessor_import_all(int a) {
248 void Preprocessor_ignore_missing(int a) {
252 void Preprocessor_error_as_warning(int a) {
253 error_as_warning = a;
257 /* -----------------------------------------------------------------------------
258 * Preprocessor_define()
260 * Defines a new C preprocessor symbol. swigmacro specifies whether or not the macro has
261 * SWIG macro semantics.
262 * ----------------------------------------------------------------------------- */
265 String *Macro_vararg_name(const_String_or_char_ptr str, const_String_or_char_ptr line) {
272 dots = strchr(s, '.');
278 if (strcmp(dots, "...") != 0) {
279 Swig_error(Getfile(line), Getline(line), "Illegal macro argument name '%s'\n", str);
284 varargname = NewString("__VA_ARGS__");
287 varargname = NewString(s);
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;
304 /* First make sure that string is actually a string */
305 if (DohCheck(_str)) {
307 copy_location(_str, s);
310 str = NewString((char *) _str);
312 Seek(str, 0, SEEK_SET);
316 /* Skip over any leading whitespace */
317 skip_whitespace(str, 0);
319 /* Now look for a macro name */
320 macroname = NewStringEmpty();
321 while ((c = Getc(str)) != EOF) {
323 argstr = NewStringEmpty();
324 copy_location(str, argstr);
325 /* It is a macro. Go extract its argument string */
326 while ((c = Getc(str)) != EOF) {
333 Swig_error(Getfile(str), Getline(str), "Missing \')\' in macro parameters\n");
337 } else if (isidchar(c) || (c == '%')) {
339 } else if (isspace(c)) {
341 } else if (c == '\\') {
349 /*Swig_error(Getfile(str),Getline(str),"Illegal character in macro name\n");
356 skip_whitespace(str, 0);
357 macrovalue = NewStringEmpty();
358 while ((c = Getc(str)) != EOF) {
362 /* If there are any macro arguments, convert into a list */
364 String *argname, *varargname;
366 Seek(argstr, 0, SEEK_SET);
367 argname = NewStringEmpty();
368 while ((c = Getc(argstr)) != EOF) {
370 varargname = Macro_vararg_name(argname, str);
373 Swig_error(Getfile(str), Getline(str), "Variable-length macro argument must be last parameter\n");
375 Append(arglist, argname);
378 argname = NewStringEmpty();
379 } else if (isidchar(c) || (c == '.')) {
381 } else if (!(isspace(c) || (c == '\\'))) {
383 Swig_error(Getfile(str), Getline(str), "Illegal character in macro argument name\n");
388 /* Check for varargs */
389 varargname = Macro_vararg_name(argname, str);
391 Append(arglist, varargname);
395 Append(arglist, argname);
402 Replace(macrovalue, "\\\n", " ", DOH_REPLACE_NOQUOTE);
405 /* Look for special # substitutions. We only consider # that appears
406 outside of quotes and comments */
410 char *cc = Char(macrovalue);
418 else if (*cc == '\'')
420 else if (*cc == '\"')
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);
477 while (strstr(Char(macrovalue), " \001")) {
478 Replace(macrovalue, " \001", "\001", DOH_REPLACE_ANY);
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);
487 /* Go create the macro */
489 Setattr(macro, kpp_name, macroname);
492 Setattr(macro, kpp_args, arglist);
495 Setattr(macro, kpp_varargs, "1");
498 Setattr(macro, kpp_value, macrovalue);
499 Setline(macro, line);
500 Setfile(macro, file);
502 Setattr(macro, kpp_swigmacro, "1");
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);
512 Setattr(symbols, macroname, macro);
532 /* -----------------------------------------------------------------------------
533 * Preprocessor_undef()
536 * ----------------------------------------------------------------------------- */
537 void Preprocessor_undef(const_String_or_char_ptr str) {
540 symbols = Getattr(cpp, kpp_symbols);
541 Delattr(symbols, str);
544 /* -----------------------------------------------------------------------------
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) {
556 /* Create a new list */
558 copy_location(s, args);
560 /* First look for a '(' */
562 skip_whitespace(s, 0);
564 /* Now see if the next character is a '(' */
567 /* Not a macro, bail out now! */
568 Seek(s, pos, SEEK_SET);
573 /* Okay. This appears to be a macro so we will start isolating arguments */
576 skip_whitespace(s, 0); /* Skip leading whitespace */
579 str = NewStringEmpty();
580 copy_location(s, str);
585 skip_tochar(s, '\"', str);
588 } else if (c == '\'') {
590 skip_tochar(s, '\'', str);
594 if ((c == ',') && (level == 0))
596 if ((c == ')') && (level == 0))
609 if (Len(args) || Len(str))
613 /* if (Len(str) && (c != ')'))
621 Swig_error(Getfile(args), Getline(args), "Unterminated macro call.\n");
625 /* -----------------------------------------------------------------------------
626 * DOH *get_filename(DOH *str)
628 * Read a filename from str. A filename can be enclose in quotes, angle brackets,
630 * ----------------------------------------------------------------------------- */
632 static String *get_filename(String *str, int *sysfile) {
636 skip_whitespace(str, 0);
637 fn = NewStringEmpty();
638 copy_location(str, fn);
642 while (((c = Getc(str)) != EOF) && (c != '\"'))
644 } else if (c == '<') {
646 while (((c = Getc(str)) != EOF) && (c != '>'))
650 while (((c = Getc(str)) != EOF) && (!isspace(c)))
655 Swig_filename_correct(fn);
656 Seek(fn, 0, SEEK_SET);
660 static String *get_options(String *str) {
663 skip_whitespace(str, 0);
668 opt = NewString("(");
669 while (((c = Getc(str)) != EOF)) {
687 /* -----------------------------------------------------------------------------
690 * Perform macro expansion and return a new string. Returns NULL if some sort
692 * ----------------------------------------------------------------------------- */
694 static String *expand_macro(String *name, List *args) {
696 DOH *symbols, *macro, *margs, *mvalue, *temp, *tempa, *e;
700 symbols = Getattr(cpp, kpp_symbols);
704 /* See if the name is actually defined */
705 macro = Getattr(symbols, name);
708 if (Getattr(macro, kpp_expanded)) {
709 ns = NewStringEmpty();
712 int lenargs = Len(args);
715 for (i = 0; i < lenargs; i++) {
716 Append(ns, Getitem(args, i));
717 if (i < (lenargs - 1))
726 /* Get macro arguments and value */
727 mvalue = Getattr(macro, kpp_value);
729 margs = Getattr(macro, kpp_args);
731 if (args && Getattr(macro, kpp_varargs)) {
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)) {
737 String *vararg = NewStringEmpty();
740 for (i = vi; i < na; i++) {
741 Append(vararg, Getitem(args, i));
746 /* Remove arguments */
747 for (i = vi; i < na; i++) {
750 Append(args, vararg);
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);
761 Swig_error(Getfile(args), Getline(args), "Macro '%s' expects no arguments\n", name);
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);
770 /* Copy the macro value */
772 copy_location(mvalue, ns);
774 /* Tag the macro as being expanded. This is to avoid recursion in
777 temp = NewStringEmpty();
778 tempa = NewStringEmpty();
781 for (i = 0; i < l; i++) {
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 */
791 Printf(temp, "\001%s", aname);
792 Printf(tempa, "\"%s\"", arg);
793 Replace(ns, temp, tempa, DOH_REPLACE_ID_END);
795 if (strstr(Char(ns), "\002")) {
796 /* Look for concatenation tokens */
799 Printf(temp, "\002%s", aname);
800 Append(tempa, "\002\003");
801 Replace(ns, temp, tempa, DOH_REPLACE_ID_END);
804 Printf(temp, "%s\002", aname);
805 Append(tempa, "\003\002");
806 Replace(ns, temp, tempa, DOH_REPLACE_ID_BEGIN);
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
813 if (strchr(Char(ns), '`')) {
817 Printf(temp, "`%s`", aname);
823 Printf(tempa, "\"%s\"", arg);
826 Replace(ns, temp, rep, DOH_REPLACE_ANY);
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);
834 Printf(temp, "\004%s", aname);
835 Replace(ns, temp, marg, DOH_REPLACE_ID_END);
838 if (strstr(Char(ns), "\005")) {
839 String *marg = Swig_string_mangle(arg);
842 Printf(temp, "\005%s", aname);
843 Printf(tempa, "\"%s\"", marg);
844 Replace(ns, temp, tempa, DOH_REPLACE_ID_END);
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;
854 namelen = Len(aname);
857 char ca = a[namelen + 1];
858 if (!isidchar((int) ca)) {
859 /* Matched the entire vararg name, not just a prefix */
864 if (isspace((int) *t))
866 else if (*t == ',') {
873 a = strstr(a + namelen, name);
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 */
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) */
886 /* Expand this macro even further */
887 Setattr(macro, kpp_expanded, "1");
889 e = Preprocessor_replace(ns);
891 Delattr(macro, kpp_expanded);
894 if (Getattr(macro, kpp_swigmacro)) {
896 String *f = NewStringEmpty();
897 Seek(e, 0, SEEK_SET);
898 copy_location(macro, e);
899 g = Preprocessor_parse(e);
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);
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);
909 Printf(f, "/*@SWIG:%s@*/%s/*@SWIG@*/", name, g);
925 /* -----------------------------------------------------------------------------
928 * Evaluate the arguments of a macro
929 * ----------------------------------------------------------------------------- */
931 List *evaluate_args(List *x) {
933 List *nl = NewList();
935 for (i = First(x); i.item; i = Next(i)) {
936 Append(nl, Preprocessor_replace(i.item));
941 /* -----------------------------------------------------------------------------
942 * DOH *Preprocessor_replace(DOH *s)
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 * ----------------------------------------------------------------------------- */
950 /* #define SWIG_PUT_BUFF */
952 DOH *Preprocessor_replace(DOH *s) {
953 DOH *ns, *symbols, *m;
956 String *id = NewStringEmpty();
959 symbols = Getattr(cpp, kpp_symbols);
961 ns = NewStringEmpty();
962 copy_location(s, ns);
963 Seek(s, 0, SEEK_SET);
965 /* Try to locate identifiers in s and replace them with macro replacements */
966 while ((c = Getc(s)) != EOF) {
969 if (isidentifier(c) || (c == '%')) {
973 } else if (c == '\"') {
975 skip_tochar(s, '\"', ns);
976 } else if (c == '\'') {
978 skip_tochar(s, '\'', ns);
979 } else if (c == '/') {
986 case 1: /* An identifier */
991 /* We found the end of a valid identifier */
993 /* See if this is the special "defined" macro */
994 if (Equal(kpp_defined, id)) {
997 /* See whether or not a paranthesis has been used */
998 skip_whitespace(s, 0);
1002 args = find_args(s);
1003 } else if (isidchar(c)) {
1004 DOH *arg = NewStringEmpty();
1007 while (((c = Getc(s)) != EOF)) {
1018 Seek(s, -1, SEEK_CUR);
1020 lenargs = Len(args);
1021 if ((!args) || (!lenargs)) {
1022 /* This is not a defined() macro. */
1027 for (i = 0; i < lenargs; i++) {
1028 DOH *o = Getitem(args, i);
1029 if (!Getattr(symbols, o)) {
1041 if (Equal(kpp_LINE, id)) {
1042 Printf(ns, "%d", Getline(s));
1046 if (Equal(kpp_FILE, id)) {
1047 String *fn = Copy(Getfile(s));
1048 Replaceall(fn, "\\", "\\\\");
1049 Printf(ns, "\"%s\"", fn);
1054 /* See if the macro is defined in the preprocessor symbol table */
1055 if ((m = Getattr(symbols, id))) {
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);
1069 e = expand_macro(id, args);
1116 /* Identifier at the end */
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))) {
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");
1128 e = expand_macro(id, 0);
1140 /* -----------------------------------------------------------------------------
1141 * int checkpp_id(DOH *s)
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) {
1150 Scanner *scan = id_scan;
1152 Seek(s, 0, SEEK_SET);
1154 Scanner_clear(scan);
1156 Seek(s, SEEK_SET, 0);
1157 Scanner_push(scan, s);
1158 while ((c = Scanner_token(scan))) {
1160 if ((c == SWIG_TOKEN_ID) || (c == SWIG_TOKEN_LBRACE) || (c == SWIG_TOKEN_RBRACE))
1168 /* addline(). Utility function for adding lines to a chunk */
1169 static void addline(DOH *s1, DOH *s2, int allow) {
1182 static void add_chunk(DOH *ns, DOH *chunk, int allow) {
1184 Seek(chunk, 0, SEEK_SET);
1186 echunk = Preprocessor_replace(chunk);
1187 addline(ns, echunk, allow);
1190 addline(ns, chunk, 0);
1196 push/pop_imported(): helper functions for defining and undefining
1197 SWIGIMPORTED (when %importing a file).
1199 static void push_imported() {
1200 if (imported_depth == 0) {
1201 Preprocessor_define("SWIGIMPORTED 1", 0);
1206 static void pop_imported() {
1208 if (imported_depth == 0) {
1209 Preprocessor_undef("SWIGIMPORTED");
1214 /* -----------------------------------------------------------------------------
1215 * Preprocessor_parse()
1217 * Parses the string s. Returns a new string containing the preprocessed version.
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 * ----------------------------------------------------------------------------- */
1227 String *Preprocessor_parse(String *s) {
1228 String *ns; /* New string containing the preprocessed text */
1229 String *chunk, *decl;
1231 String *id = 0, *value = 0, *comment = 0;
1238 int start_level = 0;
1240 int cond_lines[256];
1242 /* Blow away all carriage returns */
1243 Replace(s, "\015", "", DOH_REPLACE_ANY);
1245 ns = NewStringEmpty(); /* Return result */
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);
1257 while ((c = Getc(s)) != EOF) {
1259 case 0: /* Initial state - in first column */
1260 /* Look for C preprocessor directives. Otherwise, go directly to state 1 */
1262 add_chunk(ns, chunk, allow);
1263 copy_location(s, chunk);
1266 } else if (isspace(c)) {
1268 skip_whitespace(s, chunk);
1274 case 1: /* Non-preprocessor directive */
1275 /* Look for SWIG directives */
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);
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);
1293 } else if (c == '/')
1294 state = 30; /* Comment */
1297 case 30: /* Possibly a comment string of some sort */
1298 start_line = Getline(s);
1325 case 40: /* Start of a C preprocessor directive */
1329 } else if (isspace(c)) {
1332 /* Got the start of a preprocessor directive */
1335 copy_location(s, id);
1340 case 41: /* Build up the name of the preprocessor directive */
1341 if ((isspace(c) || (!isalpha(c)))) {
1354 copy_location(s, value);
1360 case 42: /* Strip any leading space before preprocessor value */
1369 /* no break intended here */
1372 /* Get preprocessor value */
1376 } else if (c == '/') {
1378 } else if (c == '\"') {
1380 skip_tochar(s, '\"', value);
1381 } else if (c == '\'') {
1383 skip_tochar(s, '\'', value);
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 */
1409 else if (c == '\n') {
1446 /* Check for various preprocessor directives */
1448 if (Equal(id, kpp_define)) {
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));
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);
1464 Printf(ns, "%%constant %s = %s; /*%s*/\n", Getattr(m, kpp_name), v1, comment);
1472 } else if (Equal(id, kpp_undef)) {
1474 Preprocessor_undef(value);
1475 } else if (Equal(id, kpp_ifdef)) {
1476 cond_lines[level] = Getline(id);
1479 start_level = level;
1480 /* See if the identifier is in the hash table */
1481 if (!Getattr(symbols, value))
1485 } else if (Equal(id, kpp_ifndef)) {
1486 cond_lines[level] = Getline(id);
1489 start_level = level;
1490 /* See if the identifier is in the hash table */
1491 if (Getattr(symbols, value))
1495 } else if (Equal(id, kpp_else)) {
1497 Swig_error(Getfile(s), Getline(id), "Misplaced #else.\n");
1499 cond_lines[level - 1] = Getline(id);
1503 } else if (level == start_level) {
1507 } else if (Equal(id, kpp_endif)) {
1510 Swig_error(Getfile(id), Getline(id), "Extraneous #endif.\n");
1513 if (level < start_level) {
1518 } else if (Equal(id, kpp_if)) {
1519 cond_lines[level] = Getline(id);
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);
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);
1533 Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "Error: '%s'\n", msg);
1541 } else if (Equal(id, kpp_elif)) {
1543 Swig_error(Getfile(s), Getline(id), "Misplaced #elif.\n");
1545 cond_lines[level - 1] = Getline(id);
1549 } else if (level == start_level) {
1551 String *sval = Preprocessor_replace(value);
1552 Seek(sval, 0, SEEK_SET);
1553 val = Preprocessor_expr(sval, &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);
1559 Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "Error: '%s'\n", msg);
1569 } else if (Equal(id, kpp_warning)) {
1571 Swig_warning(WARN_PP_CPP_WARNING, Getfile(s), Getline(id), "CPP #warning, %s\n", value);
1573 } else if (Equal(id, kpp_error)) {
1575 if (error_as_warning) {
1576 Swig_warning(WARN_PP_CPP_ERROR, Getfile(s), Getline(id), "CPP #error \"%s\".\n", value);
1578 Swig_error(Getfile(s), Getline(id), "CPP #error \"%s\". Use the -cpperraswarn option to continue swig processing.\n", value);
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;
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");
1591 Seek(value, 0, SEEK_SET);
1592 fn = get_filename(value, &sysfile);
1593 s1 = cpp_include(fn, sysfile);
1596 Printf(ns, "%%includefile \"%s\" [\n", Swig_last_file());
1597 else if (import_all) {
1598 Printf(ns, "%%importfile \"%s\" [\n", Swig_last_file());
1602 /* See if the filename has a directory component */
1603 dirname = Swig_file_dirname(Swig_last_file());
1604 if (sysfile || !strlen(dirname))
1607 dirname[strlen(dirname) - 1] = 0; /* Kill trailing directory delimiter */
1608 Swig_push_directory(dirname);
1610 s2 = Preprocessor_parse(s1);
1611 addline(ns, s2, allow);
1614 Swig_pop_directory();
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)))
1630 if (strncmp(c, "nowarn=", 7) == 0) {
1631 String *val = NewString(c + 7);
1632 String *nowarn = Preprocessor_replace(val);
1633 Swig_warnfilter(nowarn, 1);
1636 } else if (strncmp(c, "cpperraswarn=", 13) == 0) {
1637 error_as_warning = atoi(c + 13);
1639 Swig_error(Getfile(s), Getline(id), "Unknown SWIG pragma: %s\n", c);
1643 } else if (Equal(id, kpp_level)) {
1644 Swig_error(Getfile(s), Getline(id), "cpp debug: level = %d, startlevel = %d\n", level, start_level);
1646 for (i = 0; i < cpp_lines; i++)
1651 /* Swig directives */
1655 start_line = Getline(s);
1656 add_chunk(ns, chunk, allow);
1657 copy_location(s, chunk);
1662 /* %#cpp - an embedded C preprocessor directive (we strip off the %) */
1663 else if (c == '#') {
1664 add_chunk(ns, chunk, allow);
1667 } else if (isidentifier(c)) {
1689 addline(ns, chunk, allow);
1691 copy_location(s, chunk);
1700 addline(ns, chunk, allow);
1703 } else if (c == '\\') {
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 */
1720 DOH *s1, *s2, *fn, *opt;
1723 if (Equal(decl, kpp_dextern)) {
1724 Swig_warning(WARN_DEPRECATED_EXTERN, Getfile(s), Getline(s), "%%extern is deprecated. Use %%import instead.\n");
1726 Append(decl, "%%import");
1728 opt = get_options(s);
1729 fn = get_filename(s, &sysfile);
1730 s1 = cpp_include(fn, sysfile);
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)) {
1739 dirname = Swig_file_dirname(Swig_last_file());
1740 if (sysfile || !strlen(dirname))
1743 dirname[strlen(dirname) - 1] = 0; /* Kill trailing directory delimiter */
1744 Swig_push_directory(dirname);
1746 s2 = Preprocessor_parse(s1);
1748 Swig_pop_directory();
1750 if (Equal(decl, kpp_dimport)) {
1753 addline(ns, s2, allow);
1761 } else if (Equal(decl, kpp_dline)) {
1762 /* Got a line directive */
1764 } else if (Equal(decl, kpp_ddefine)) {
1765 /* Got a define directive */
1767 add_chunk(ns, chunk, allow);
1768 copy_location(s, chunk);
1770 copy_location(s, value);
1773 Append(chunk, decl);
1781 /* Searching for the end of a %define statement */
1785 const char *ed = "enddef";
1786 const char *df = "define";
1789 for (i = 0; i < 6;) {
1792 statement[i++] = (char)c;
1793 if (strncmp(statement, ed, i) && strncmp(statement, df, i))
1798 if ((i == 6) && (isspace(c))) {
1799 if (strncmp(statement, df, i) == 0) {
1802 if (strncmp(statement, ed, i) == 0) {
1806 for (i = 0; i < 7; i++) {
1807 Delitem(value, DOH_END);
1810 Seek(value, 0, SEEK_SET);
1811 Preprocessor_define(value, 1);
1813 /* Putc('\n',ns); */
1814 addline(ns, value, 0);
1823 Printf(stderr, "cpp: Invalid parser state %d\n", state);
1829 Swig_error(Getfile(s), -1, "Missing #endif for conditional starting on line %d\n", cond_lines[level - 1]);
1833 Seek(value, 0, SEEK_SET);
1834 Swig_error(Getfile(s), -1, "Missing %%enddef for macro starting on line %d\n", Getline(value));
1836 if ((state >= 105) && (state < 107)) {
1837 Swig_error(Getfile(s), -1, "Unterminated %%{ ... %%} block starting on line %d\n", start_line);
1839 if ((state >= 30) && (state < 40)) {
1840 Swig_error(Getfile(s), -1, "Unterminated comment starting on line %d\n", start_line);
1842 add_chunk(ns, chunk, allow);
1843 copy_location(s, chunk);
1845 /* DelScope(scp); */
1852 /* fprintf(stderr,"cpp: %d\n", Len(Getattr(cpp,"symbols"))); */