]> SALOME platform Git repositories - modules/paravis.git/blob - src/VTKWrapping/ParaView/vtkParsePreprocess.c
Salome HOME
Minor: removing annoying print message
[modules/paravis.git] / src / VTKWrapping / ParaView / vtkParsePreprocess.c
1 /*=========================================================================
2
3   Program:   Visualization Toolkit
4   Module:    vtkParsePreprocess.c
5
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13
14 =========================================================================*/
15 /*-------------------------------------------------------------------------
16   Copyright (c) 2010 David Gobbi.
17
18   Contributed to the VisualizationToolkit by the author in June 2010
19   under the terms of the Visualization Toolkit 2008 copyright.
20 -------------------------------------------------------------------------*/
21
22 #include "vtkParsePreprocess.h"
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <errno.h>
27 #include <sys/stat.h>
28
29 /**
30   This file handles preprocessor directives via a simple
31   recursive-descent parser that only evaluates integers.
32 */
33
34 #define PREPROC_DEBUG 0
35
36 /** Block size for reading files */
37 #define FILE_BUFFER_SIZE 8192
38
39 /** Size of hash table must be a power of two */
40 #define PREPROC_HASH_TABLE_SIZE 1024u
41
42 /** Hashes for preprocessor keywords */
43 #define HASH_IFDEF      0x0fa4b283u
44 #define HASH_IFNDEF     0x04407ab1u
45 #define HASH_IF         0x00597834u
46 #define HASH_ELIF       0x7c964b25u
47 #define HASH_ELSE       0x7c964c6eu
48 #define HASH_ENDIF      0x0f60b40bu
49 #define HASH_DEFINED    0x088998d4u
50 #define HASH_DEFINE     0xf8804a70u
51 #define HASH_UNDEF      0x10823b97u
52 #define HASH_INCLUDE    0x9e36af89u
53 #define HASH_ERROR      0x0f6321efu
54 #define HASH_LINE       0x7c9a15adu
55 #define HASH_PRAGMA     0x1566a9fdu
56
57 /** Various possible char types */
58 #define CPRE_ID         0x01  /* A-Z a-z and _ */
59 #define CPRE_DIGIT      0x02  /* 0-9 */
60 #define CPRE_IDGIT      0x03  /* 0-9 A-Z a-z and _ */
61 #define CPRE_HEX        0x04  /* 0-9A-Fa-f */
62 #define CPRE_EXP        0x08  /* EPep (exponents for floats) */
63 #define CPRE_SIGN       0x10  /* +- (sign for floats) */
64 #define CPRE_QUOTE      0x20  /* " and ' */
65 #define CPRE_HSPACE     0x40  /* space, tab, carriage return */
66 #define CPRE_VSPACE     0x80  /* newline, vertical tab, form feed */
67 #define CPRE_WHITE      0xC0  /* all whitespace characters */
68
69 /** Whitespace types.
70  * WS_NO_EOL treats newline as end-of-line, instead of whitespace.
71  * WS_ALL treats newlines as regular whitespace.
72  * WS_COMMENT does not treat comments as whitespace, allowing
73  * comments blocks to be returned as tokens. */
74 typedef enum _preproc_space_t
75 {
76   WS_NO_EOL = CPRE_HSPACE, /* skip horizontal whitespace only */
77   WS_ALL    = CPRE_WHITE,  /* skip all whitespace */
78   WS_COMMENT = (CPRE_WHITE | 0x100), /* comments as tokens */
79 } preproc_space_t;
80
81 /** Preprocessor tokens. */
82 typedef enum _preproc_token_t
83 {
84   TOK_OTHER = 257,
85   TOK_ID,        /* any id */
86   TOK_CHAR,      /* char literal */
87   TOK_STRING,    /* string literal */
88   TOK_NUMBER,    /* any numeric literal */
89   TOK_COMMENT,   /* C or C++ comment */
90   TOK_DBLHASH,   /* ## */
91   TOK_SCOPE,     /* :: */
92   TOK_INCR,      /* ++ */
93   TOK_DECR,      /* -- */
94   TOK_RSHIFT,    /* >> */
95   TOK_LSHIFT,    /* << */
96   TOK_AND,       /* && */
97   TOK_OR,        /* || */
98   TOK_EQ,        /* == */
99   TOK_NE,        /* != */
100   TOK_GE,        /* >= */
101   TOK_LE,        /* <= */
102   TOK_ADD_EQ,    /* += */
103   TOK_SUB_EQ,    /* -= */
104   TOK_MUL_EQ,    /* *= */
105   TOK_DIV_EQ,    /* /= */
106   TOK_MOD_EQ,    /* %= */
107   TOK_AND_EQ,    /* &= */
108   TOK_OR_EQ,     /* |= */
109   TOK_XOR_EQ,    /* ^= */
110   TOK_ARROW,     /* -> */
111   TOK_DOT_STAR,  /* .* */
112   TOK_ARROW_STAR,/* ->* */
113   TOK_RSHIFT_EQ, /* >>= */
114   TOK_LSHIFT_EQ, /* <<= */
115   TOK_ELLIPSIS,  /* ... */
116 } preproc_token_t;
117
118 /** A struct for going through the input one token at a time. */
119 typedef struct _preproc_tokenizer
120 {
121   int tok;
122   unsigned int hash;
123   const char *text;
124   size_t len;
125 } preproc_tokenizer;
126
127 /** Extend dynamic arrays in a progression of powers of two.
128  * Whenever "n" reaches a power of two, then the array size is
129  * doubled so that "n" can be safely incremented. */
130 static void *preproc_array_check(
131   void *arraymem, size_t size, int n)
132 {
133   /* if empty, alloc for the first time */
134   if (n == 0)
135     {
136     return malloc(size);
137     }
138   /* if count is power of two, reallocate with double size */
139   else if ((n & (n-1)) == 0)
140     {
141     return realloc(arraymem, (n << 1)*size);
142     }
143
144   /* no reallocation, just return the original array */
145   return arraymem;
146 }
147
148 /** Convert string to int. */
149 static preproc_int_t string_to_preproc_int(const char *cp, int base)
150 {
151 #if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
152   return _strtoi64(cp, NULL, base);
153 #else
154   return strtoll(cp, NULL, base);
155 #endif
156 }
157
158 /** Convert string to unsigned int. */
159 static preproc_uint_t string_to_preproc_uint(const char *cp, int base)
160 {
161 #if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
162   return _strtoui64(cp, NULL, base);
163 #else
164   return strtoull(cp, NULL, base);
165 #endif
166 }
167
168 /** Array for quick lookup of char types */
169 static unsigned char preproc_charbits[] = {
170   0, 0, 0, 0, 0, 0, 0, 0, 0,
171   CPRE_HSPACE, /* tab */
172   CPRE_VSPACE, CPRE_VSPACE, CPRE_VSPACE, /* newline, vtab, form feed */
173   CPRE_HSPACE, /* carriage return */
174   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
175   CPRE_HSPACE, /* ' ' */
176   0, CPRE_QUOTE, 0, 0, 0, 0, CPRE_QUOTE, 0, 0, /* !"#$%&'() */
177   0, CPRE_SIGN, 0, CPRE_SIGN, 0, 0, /* *+,-./ */
178   CPRE_DIGIT|CPRE_HEX, /* 0 */
179   CPRE_DIGIT|CPRE_HEX, CPRE_DIGIT|CPRE_HEX,
180   CPRE_DIGIT|CPRE_HEX, CPRE_DIGIT|CPRE_HEX,
181   CPRE_DIGIT|CPRE_HEX, CPRE_DIGIT|CPRE_HEX,
182   CPRE_DIGIT|CPRE_HEX, CPRE_DIGIT|CPRE_HEX,
183   CPRE_DIGIT|CPRE_HEX, /* 9 */
184   0, 0, 0, 0, 0, 0, 0, /* :;<=>?@ */
185   CPRE_ID|CPRE_HEX, /* A */
186   CPRE_ID|CPRE_HEX, CPRE_ID|CPRE_HEX, CPRE_ID|CPRE_HEX, /* BCD */
187   CPRE_ID|CPRE_HEX|CPRE_EXP, /* E */
188   CPRE_ID|CPRE_HEX, CPRE_ID, CPRE_ID, CPRE_ID, /* FGHI */
189   CPRE_ID, CPRE_ID, CPRE_ID, CPRE_ID, /* JKLM */
190   CPRE_ID, CPRE_ID, CPRE_ID|CPRE_EXP, CPRE_ID, /* NOPQ */
191   CPRE_ID, CPRE_ID, CPRE_ID, CPRE_ID, /* RSTU */
192   CPRE_ID, CPRE_ID, CPRE_ID, CPRE_ID, /* VWXY */
193   CPRE_ID, /* Z */
194   0, 0, 0, 0, /* [\\]^ */
195   CPRE_ID, /* _ */
196   0, /* ` */
197   CPRE_ID|CPRE_HEX, /* a */
198   CPRE_ID|CPRE_HEX, CPRE_ID|CPRE_HEX, CPRE_ID|CPRE_HEX, /* bcd */
199   CPRE_ID|CPRE_HEX|CPRE_EXP, /* e */
200   CPRE_ID|CPRE_HEX, CPRE_ID, CPRE_ID, CPRE_ID, /* fghi */
201   CPRE_ID, CPRE_ID, CPRE_ID, CPRE_ID, /* jklm */
202   CPRE_ID, CPRE_ID, CPRE_ID|CPRE_EXP, CPRE_ID, /* nopq */
203   CPRE_ID, CPRE_ID, CPRE_ID, CPRE_ID, /* rstu */
204   CPRE_ID, CPRE_ID, CPRE_ID, CPRE_ID, /* vwxy */
205   CPRE_ID, /* z */
206   0, 0, 0, 0, /* {|}~ */
207   0, /* '\x7f' */
208   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
209   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
210   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
211   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
212 };
213
214 /** Macro to get char type */
215 #define preproc_chartype(c, bits) \
216   ((preproc_charbits[(unsigned char)(c)] & bits) != 0)
217
218 /** Skip over a comment. */
219 static void preproc_skip_comment(const char **cpp)
220 {
221   const char *cp = *cpp;
222
223   if (cp[0] == '/')
224     {
225     if (cp[1] == '/')
226       {
227       cp += 2;
228       while (*cp != '\n' && *cp != '\0')
229         {
230         if (cp[0] == '\\')
231           {
232           if (cp[1] == '\n') { cp++; }
233           else if (cp[1] == '\r' && cp[2] == '\n') { cp += 2; }
234           }
235         cp++;
236         }
237       }
238     else if (cp[1] == '*')
239       {
240       cp += 2;
241       while (*cp != '\0')
242         {
243         if (cp[0] == '*' && cp[1] == '/') { cp += 2; break; }
244         cp++;
245         }
246       }
247     }
248
249   *cpp = cp;
250 }
251
252 /** Skip over whitespace, but not newlines unless preceded by backlash. */
253 static void preproc_skip_whitespace(
254   const char **cpp, preproc_space_t spacetype)
255 {
256   const char *cp = *cpp;
257
258   for (;;)
259     {
260     if (preproc_chartype(*cp, spacetype))
261       {
262       do
263         {
264         cp++;
265         }
266       while (preproc_chartype(*cp, spacetype));
267       }
268     if (cp[0] == '\\')
269       {
270       if (cp[1] == '\n')
271         {
272         cp += 2;
273         }
274       else if (cp[1] == '\r' && cp[2] == '\n')
275         {
276         cp += 3;
277         }
278       else
279         {
280         break;
281         }
282       }
283     else if (cp[0] == '/' && (spacetype & WS_COMMENT) != WS_COMMENT)
284       {
285       if (cp[1] == '/' || cp[1] == '*')
286         {
287         preproc_skip_comment(&cp);
288         }
289       else
290         {
291         break;
292         }
293       }
294     else
295       {
296       break;
297       }
298     }
299
300   *cpp = cp;
301 }
302
303 /** Skip over string and char literals. */
304 static void preproc_skip_quotes(const char **cpp)
305 {
306   const char *cp = *cpp;
307   const char qc = *cp;
308
309   if (preproc_chartype(*cp, CPRE_QUOTE))
310     {
311     cp++;
312     while (*cp != qc && *cp != '\n' && *cp != '\0')
313       {
314       if (*cp++ == '\\')
315         {
316         if (cp[0] == '\r' && cp[1] == '\n') { cp += 2; }
317         else if (*cp != '\0') { cp++; }
318         }
319       }
320     }
321   if (*cp == qc)
322     {
323     cp++;
324     }
325
326   *cpp = cp;
327 }
328
329 /** Skip over a name. */
330 static void preproc_skip_name(const char **cpp)
331 {
332   const char *cp = *cpp;
333
334   if (preproc_chartype(*cp, CPRE_ID))
335     {
336     do
337       {
338       cp++;
339       }
340     while (preproc_chartype(*cp, CPRE_IDGIT));
341     }
342
343   *cpp = cp;
344 }
345
346 /** A simple 32-bit hash function based on "djb2". */
347 static unsigned int preproc_hash_name(const char **cpp)
348 {
349   const char *cp = (*cpp);
350   int h = 5381;
351
352   if (preproc_chartype(*cp, CPRE_ID))
353     {
354     do { h = (h << 5) + h + (unsigned char)*cp++; }
355     while (preproc_chartype(*cp, CPRE_IDGIT));
356     }
357
358   *cpp = cp;
359   return h;
360 }
361
362 /** Skip over a number. */
363 static void preproc_skip_number(const char **cpp)
364 {
365   const char *cp = *cpp;
366
367   if (preproc_chartype(cp[0], CPRE_DIGIT) ||
368       (cp[0] == '.' && preproc_chartype(cp[1], CPRE_DIGIT)))
369     {
370     do
371       {
372       char c = *cp++;
373       if (preproc_chartype(c, CPRE_EXP) &&
374           preproc_chartype(*cp, CPRE_SIGN))
375         {
376         cp++;
377         }
378       }
379     while (preproc_chartype(*cp, CPRE_IDGIT) || *cp == '.');
380     }
381
382   *cpp = cp;
383 }
384
385 /** Return the next preprocessor token, or '0' if none left. */
386 static int preproc_next(preproc_tokenizer *tokens)
387 {
388   const char *cp = tokens->text + tokens->len;
389   preproc_skip_whitespace(&cp, WS_NO_EOL);
390
391   if (preproc_chartype(*cp, CPRE_ID))
392     {
393     const char *ep = cp;
394     unsigned int h = preproc_hash_name(&ep);
395     tokens->tok = TOK_ID;
396     tokens->hash = h;
397     tokens->text = cp;
398     tokens->len = ep - cp;
399     }
400   else if (preproc_chartype(*cp, CPRE_QUOTE))
401     {
402     const char *ep = cp;
403     preproc_skip_quotes(&ep);
404     tokens->tok = (*cp == '\"' ? TOK_STRING : TOK_CHAR);
405     tokens->hash = 0;
406     tokens->text = cp;
407     tokens->len = ep - cp;
408     }
409   else if (preproc_chartype(*cp, CPRE_DIGIT) ||
410            (cp[0] == '.' && preproc_chartype(cp[1], CPRE_DIGIT)))
411     {
412     const char *ep = cp;
413     preproc_skip_number(&ep);
414     tokens->tok = TOK_NUMBER;
415     tokens->hash = 0;
416     tokens->text = cp;
417     tokens->len = ep - cp;
418     }
419   else if (cp[0] == '/' && (cp[1] == '/' || cp[1] == '*'))
420     {
421     const char *ep = cp;
422     preproc_skip_comment(&ep);
423     tokens->tok = TOK_COMMENT;
424     tokens->hash = 0;
425     tokens->text = cp;
426     tokens->len = ep - cp;
427     }
428   else
429     {
430     int t = cp[0];
431     size_t l = 1;
432
433     switch (cp[0])
434       {
435       case ':':
436         if (cp[1] == ':') { l = 2; t = TOK_SCOPE; }
437         break;
438       case '.':
439         if (cp[1] == '.' && cp[2] == '.') { l = 3; t = TOK_ELLIPSIS; }
440         else if (cp[1] == '*') { l = 2; t = TOK_DOT_STAR; }
441         break;
442       case '=':
443         if (cp[1] == '=') { l = 2; t = TOK_EQ; }
444         break;
445       case '!':
446         if (cp[1] == '=') { l = 2; t = TOK_NE; }
447         break;
448       case '<':
449         if (cp[1] == '<' && cp[2] == '=') { l = 3; t = TOK_LSHIFT_EQ; }
450         else if (cp[1] == '<') { l = 2; t = TOK_LSHIFT; }
451         else if (cp[1] == '=') { l = 2; t = TOK_LE; }
452         break;
453       case '>':
454         if (cp[1] == '>' && cp[2] == '=') { l = 3; t = TOK_RSHIFT_EQ; }
455         else if (cp[1] == '>') { l = 2; t = TOK_RSHIFT; }
456         else if (cp[1] == '=') { l = 2; t = TOK_GE; }
457         break;
458       case '&':
459         if (cp[1] == '=') { l = 2; t = TOK_AND_EQ; }
460         else if (cp[1] == '&') { l = 2; t = TOK_AND; }
461         break;
462       case '|':
463         if (cp[1] == '=') { l = 2; t = TOK_OR_EQ; }
464         else if (cp[1] == '|') { l = 2; t = TOK_OR; }
465         break;
466       case '^':
467         if (cp[1] == '=') { l = 2; t = TOK_XOR_EQ; }
468         break;
469       case '*':
470         if (cp[1] == '=') { l = 2; t = TOK_MUL_EQ; }
471         break;
472       case '/':
473         if (cp[1] == '=') { l = 2; t = TOK_DIV_EQ; }
474         break;
475       case '%':
476         if (cp[1] == '=') { l = 2; t = TOK_MOD_EQ; }
477         break;
478       case '+':
479         if (cp[1] == '+') { l = 2; t = TOK_INCR; }
480         else if (cp[1] == '=') { l = 2; t = TOK_ADD_EQ; }
481         break;
482       case '-':
483         if (cp[1] == '>' && cp[2] == '*') { l = 3; t = TOK_ARROW_STAR; }
484         else if (cp[1] == '>') { l = 2; t = TOK_ARROW; }
485         else if (cp[1] == '-') { l = 2; t = TOK_DECR; }
486         else if (cp[1] == '=') { l = 2; t = TOK_SUB_EQ; }
487         break;
488       case '#':
489         if (cp[1] == '#') { l = 2; t = TOK_DBLHASH; }
490         break;
491       case '\n':
492       case '\0':
493         { l = 0; t = 0; }
494         break;
495       }
496
497     tokens->tok = t;
498     tokens->hash = 0;
499     tokens->text = cp;
500     tokens->len = l;
501     }
502
503   return tokens->tok;
504 }
505
506 /** Initialize the tokenizer. */
507 static void preproc_init(preproc_tokenizer *tokens, const char *text)
508 {
509   tokens->tok = 0;
510   tokens->hash = 0;
511   tokens->text = text;
512   tokens->len = 0;
513   preproc_next(tokens);
514 }
515
516 /** Tokenize and compare two strings */
517 static int preproc_identical(const char *text1, const char *text2)
518 {
519   int result = 1;
520
521   if (text1 != text2)
522     {
523     result = 0;
524
525     if (text1 && text2)
526       {
527       preproc_tokenizer t1;
528       preproc_tokenizer t2;
529
530       preproc_init(&t1, text1);
531       preproc_init(&t2, text2);
532
533       do
534         {
535         if (t1.tok != t2.tok ||
536             t1.hash != t2.hash ||
537             t1.len != t2.len ||
538             strncmp(t1.text, t2.text, t1.len) != 0)
539           {
540           break;
541           }
542         preproc_next(&t1);
543         preproc_next(&t2);
544         }
545       while (t1.tok && t2.tok);
546
547       result = (t1.tok == 0 && t2.tok == 0);
548       }
549     }
550
551   return result;
552 }
553
554 /** Duplicate the first n bytes of a string. */
555 static const char *preproc_strndup(const char *in, size_t n)
556 {
557   char *res = NULL;
558
559   res = (char *)malloc(n+1);
560   strncpy(res, in, n);
561   res[n] = '\0';
562
563   return res;
564 }
565
566 /** Create a new preprocessor macro. */
567 static MacroInfo *preproc_new_macro(
568   PreprocessInfo *info, const char *name, const char *definition)
569 {
570   MacroInfo *macro = (MacroInfo *)malloc(sizeof(MacroInfo));
571   vtkParsePreprocess_InitMacro(macro);
572
573   if (name)
574     {
575     size_t n;
576     const char *cp = name;
577     preproc_skip_name(&cp);
578     n = cp - name;
579     macro->Name = preproc_strndup(name, n);
580     }
581
582   if (definition)
583     {
584     size_t n;
585     const char *cp = definition;
586     preproc_tokenizer tokens;
587     preproc_init(&tokens, cp);
588
589     do
590       {
591       cp = tokens.text + tokens.len;
592       }
593     while (preproc_next(&tokens));
594
595     n = cp - definition;
596     macro->Definition = preproc_strndup(definition, n);
597     }
598
599   macro->IsExternal = info->IsExternal;
600
601   return macro;
602 }
603
604 /** Free a preprocessor macro struct. */
605 static void preproc_free_macro(MacroInfo *info)
606 {
607   free(info);
608 }
609
610 /** Find a preprocessor macro, return 0 if not found. */
611 static MacroInfo *preproc_find_macro(
612   PreprocessInfo *info, preproc_tokenizer *token)
613 {
614   unsigned int m = PREPROC_HASH_TABLE_SIZE - 1;
615   unsigned int i = (token->hash & m);
616   const char *name = token->text;
617   size_t l = token->len;
618   MacroInfo ***htable = info->MacroHashTable;
619   MacroInfo **hptr;
620   const char *mname;
621
622   if (htable && ((hptr = htable[i]) != NULL) && *hptr)
623     {
624     do
625       {
626       mname = (*hptr)->Name;
627       if (mname[0] == name[0] &&
628           strncmp(mname, name, l) == 0 &&
629           mname[l] == '\0')
630         {
631         return *hptr;
632         }
633       hptr++;
634       }
635     while (*hptr);
636     }
637
638   return NULL;
639 }
640
641 /** Return the address of the macro within the hash table.
642   * If "insert" is nonzero, add a new location if macro not found. */
643 static MacroInfo **preproc_macro_location(
644   PreprocessInfo *info, preproc_tokenizer *token, int insert)
645 {
646   MacroInfo ***htable = info->MacroHashTable;
647   unsigned int m = PREPROC_HASH_TABLE_SIZE - 1;
648   unsigned int i = (token->hash & m);
649   const char *name = token->text;
650   size_t l = token->len;
651   size_t n;
652   MacroInfo **hptr;
653   const char *mname;
654
655   if (htable == NULL)
656     {
657     if (!insert)
658       {
659       return NULL;
660       }
661
662     m = PREPROC_HASH_TABLE_SIZE;
663     htable = (MacroInfo ***)malloc(m*sizeof(MacroInfo **));
664     info->MacroHashTable = htable;
665     do { *htable++ = NULL; } while (--m);
666     htable = info->MacroHashTable;
667     }
668
669   hptr = htable[i];
670
671   if (hptr == NULL)
672     {
673     if (!insert)
674       {
675       return NULL;
676       }
677
678     hptr = (MacroInfo **)malloc(2*sizeof(MacroInfo *));
679     hptr[0] = NULL;
680     hptr[1] = NULL;
681     htable[i] = hptr;
682     }
683   else if (*hptr)
684     {
685     /* see if macro is already there */
686     n = 0;
687     do
688       {
689       mname = (*hptr)->Name;
690       if (mname[0] == name[0] &&
691           strncmp(mname, name, l) == 0 &&
692           mname[l] == '\0')
693         {
694         break;
695         }
696       n++;
697       hptr++;
698       }
699     while (*hptr);
700
701     if (*hptr == NULL)
702       {
703       if (!insert)
704         {
705         return NULL;
706         }
707
708       /* if n+1 is a power of two, double allocated space */
709       if (n > 0 && (n & (n+1)) == 0)
710         {
711         hptr = htable[i];
712         hptr = (MacroInfo **)realloc(hptr, (2*(n+1))*sizeof(MacroInfo *));
713         htable[i] = hptr;
714         hptr += n;
715         }
716
717       /* add a terminating null */
718       hptr[1] = NULL;
719       }
720     }
721
722   return hptr;
723 }
724
725 /** Remove a preprocessor macro.  Returns 0 if macro not found. */
726 static int preproc_remove_macro(
727   PreprocessInfo *info, preproc_tokenizer *token)
728 {
729   MacroInfo **hptr;
730
731   hptr = preproc_macro_location(info, token, 0);
732
733   if (hptr && *hptr)
734     {
735     preproc_free_macro(*hptr);
736
737     do
738       {
739       hptr[0] = hptr[1];
740       hptr++;
741       }
742     while (*hptr);
743
744     return 1;
745     }
746
747   return 0;
748 }
749
750 /** A simple way to add a preprocessor macro definition. */
751 static MacroInfo *preproc_add_macro_definition(
752   PreprocessInfo *info, const char *name, const char *definition)
753 {
754   preproc_tokenizer token;
755   MacroInfo *macro;
756   MacroInfo **macro_p;
757
758   preproc_init(&token, name);
759
760   macro = preproc_new_macro(info, name, definition);
761   macro_p = preproc_macro_location(info, &token, 1);
762 #if PREPROC_DEBUG
763   if (*macro_p)
764     {
765     fprintf(stderr, "duplicate macro definition %s\n", name);
766     }
767 #endif
768   *macro_p = macro;
769
770   return macro;
771 }
772
773 /** Skip over parentheses, return nonzero if not closed. */
774 static int preproc_skip_parentheses(preproc_tokenizer *tokens)
775 {
776   int depth = 0;
777
778   if (tokens->tok == '(')
779     {
780     depth = 1;
781
782     while (depth > 0 && preproc_next(tokens))
783       {
784       if (tokens->tok == '(')
785         {
786         depth++;
787         }
788       else if (tokens->tok == ')')
789         {
790         depth--;
791         }
792       }
793     }
794
795   if (tokens->tok == ')')
796     {
797     preproc_next(tokens);
798     return VTK_PARSE_OK;
799     }
800
801 #if PREPROC_DEBUG
802   fprintf(stderr, "syntax error %d\n", __LINE__);
803 #endif
804   return VTK_PARSE_SYNTAX_ERROR;
805 }
806
807
808 /** Evaluate a char literal to an integer value. */
809 static int preproc_evaluate_char(
810   const char *cp, preproc_int_t *val, int *is_unsigned)
811 {
812   if (cp[0] == '\'')
813     {
814     cp++;
815     if (*cp != '\\')
816       {
817       *val = *cp;
818       }
819     else if (*cp != '\'' && *cp != '\n' && *cp != '\0')
820       {
821       cp++;
822       if (*cp == 'a') { *val = '\a'; }
823       else if (*cp == 'b') { *val = '\b'; }
824       else if (*cp == 'f') { *val = '\f'; }
825       else if (*cp == 'n') { *val = '\n'; }
826       else if (*cp == 'r') { *val = '\r'; }
827       else if (*cp == 'b') { *val = '\b'; }
828       else if (*cp == 't') { *val = '\t'; }
829       else if (*cp == 'v') { *val = '\v'; }
830       else if (*cp == '\'') { *val = '\''; }
831       else if (*cp == '\"') { *val = '\"'; }
832       else if (*cp == '\\') { *val = '\\'; }
833       else if (*cp == '\?') { *val = '\?'; }
834       else if (*cp == '0')
835         {
836         *val = string_to_preproc_int(cp, 8);
837         do { cp++; } while (*cp >= '0' && *cp <= '7');
838         }
839       else if (*cp == 'x')
840         {
841         *val = string_to_preproc_int(cp+1, 16);
842         do { cp++; } while (preproc_chartype(*cp, CPRE_HEX));
843         }
844       }
845     if (*cp != '\'')
846       {
847 #if PREPROC_DEBUG
848       fprintf(stderr, "syntax error %d\n", __LINE__);
849 #endif
850       return VTK_PARSE_SYNTAX_ERROR;
851       }
852     cp++;
853     *is_unsigned = 0;
854     return VTK_PARSE_OK;
855     }
856
857 #if PREPROC_DEBUG
858   fprintf(stderr, "syntax error %d\n", __LINE__);
859 #endif
860   return VTK_PARSE_SYNTAX_ERROR;
861 }
862
863 /* Evaluate an integer, ignoring any suffixes except 'u'. */
864 static int preproc_evaluate_integer(
865   const char *cp, preproc_int_t *val, int *is_unsigned)
866 {
867   const char *ep;
868   int base = 0;
869   ep = cp;
870
871   if (cp[0] == '0' && (cp[1] == 'x' || cp[1] == 'X'))
872     {
873     cp += 2;
874     base = 16;
875     *is_unsigned = 1;
876     ep = cp;
877     while (preproc_chartype(*ep, CPRE_HEX))
878       {
879       ep++;
880       }
881     }
882   else if (cp[0] == '0' && preproc_chartype(cp[1], CPRE_DIGIT))
883     {
884     cp += 1;
885     base = 8;
886     *is_unsigned = 1;
887     ep = cp;
888     while (*ep >= '0' && *ep <= '7')
889       {
890       ep++;
891       }
892     }
893   else
894     {
895     base = 10;
896     *is_unsigned = 0;
897     while (preproc_chartype(*ep, CPRE_DIGIT))
898       {
899       ep++;
900       }
901     }
902
903   for (;;)
904     {
905     if (ep[0] == 'i' && ep[1] == '6' && ep[2] == '4') { ep += 3; }
906     else if (*ep == 'u') { *is_unsigned = 1; ep++; }
907     else if (*ep == 'l' || *ep == 'L') { ep++; }
908     else { break; }
909     }
910
911   if (*is_unsigned)
912     {
913     *val = (preproc_int_t)string_to_preproc_uint(cp, base);
914     }
915   else
916     {
917     *val = string_to_preproc_int(cp, base);
918     }
919
920   if (*ep == '.' || *ep == 'e' || *ep == 'E')
921     {
922     return VTK_PARSE_PREPROC_DOUBLE;
923     }
924
925   return VTK_PARSE_OK;
926 }
927
928 /* forward declaration */
929 static int preproc_evaluate_expression(
930   PreprocessInfo *info, preproc_tokenizer *tokens,
931   preproc_int_t *val, int *is_unsigned);
932
933 /** Evaluate a single item in an expression. */
934 static int preproc_evaluate_single(
935   PreprocessInfo *info, preproc_tokenizer *tokens,
936   preproc_int_t *val, int *is_unsigned)
937 {
938   int result = VTK_PARSE_OK;
939
940   while (tokens->tok == TOK_ID)
941     {
942     /* handle the "defined" keyword */
943     if (tokens->hash == HASH_DEFINED && tokens->len == 7 &&
944         strncmp("defined", tokens->text, tokens->len) == 0)
945       {
946       int paren = 0;
947       preproc_next(tokens);
948
949       if (tokens->tok == '(')
950         {
951         paren = 1;
952         preproc_next(tokens);
953         }
954       if (tokens->tok != TOK_ID)
955         {
956         *val = 0;
957         *is_unsigned = 0;
958 #if PREPROC_DEBUG
959         fprintf(stderr, "syntax error %d\n", __LINE__);
960 #endif
961         return VTK_PARSE_SYNTAX_ERROR;
962         }
963
964       /* do the name lookup */
965       *is_unsigned = 0;
966       *val = (preproc_find_macro(info, tokens) != 0);
967
968       preproc_next(tokens);
969       if (paren)
970         {
971         if (tokens->tok != ')')
972           {
973 #if PREPROC_DEBUG
974           fprintf(stderr, "syntax error %d\n", __LINE__);
975 #endif
976           return VTK_PARSE_SYNTAX_ERROR;
977           }
978         preproc_next(tokens);
979         }
980
981       return result;
982       }
983     else
984       {
985       /* look up and evaluate the macro */
986       MacroInfo *macro = preproc_find_macro(info, tokens);
987       const char *args = NULL;
988       const char *expansion = NULL;
989       const char *cp;
990       preproc_next(tokens);
991       *val = 0;
992       *is_unsigned = 0;
993
994       if (macro == NULL || macro->IsExcluded)
995         {
996         return VTK_PARSE_MACRO_UNDEFINED;
997         }
998       else if (macro->IsFunction)
999         {
1000         /* expand function macros using the arguments */
1001         args = tokens->text;
1002         if (tokens->tok != '(' ||
1003             preproc_skip_parentheses(tokens) != VTK_PARSE_OK)
1004           {
1005 #if PREPROC_DEBUG
1006           fprintf(stderr, "syntax error %d\n", __LINE__);
1007 #endif
1008           return VTK_PARSE_SYNTAX_ERROR;
1009           }
1010         }
1011       expansion = vtkParsePreprocess_ExpandMacro(info, macro, args);
1012       if (expansion == NULL)
1013         {
1014         free((char *)args);
1015 #if PREPROC_DEBUG
1016         fprintf(stderr, "syntax error %d\n", __LINE__);
1017 #endif
1018         return (args ? VTK_PARSE_MACRO_NUMARGS : VTK_PARSE_SYNTAX_ERROR);
1019         }
1020       cp = expansion;
1021       preproc_skip_whitespace(&cp, WS_NO_EOL);
1022       if (*cp != '\0')
1023         {
1024         macro->IsExcluded = 1;
1025         result = vtkParsePreprocess_EvaluateExpression(
1026           info, expansion, val, is_unsigned);
1027         macro->IsExcluded = 0;
1028         vtkParsePreprocess_FreeMacroExpansion(
1029           info, macro, expansion);
1030         return result;
1031         }
1032       vtkParsePreprocess_FreeMacroExpansion(info, macro, expansion);
1033       }
1034     /* if macro expansion was empty, continue */
1035     }
1036
1037   if (tokens->tok == '(')
1038     {
1039     preproc_next(tokens);
1040     result = preproc_evaluate_expression(info, tokens, val, is_unsigned);
1041     if ((result & VTK_PARSE_FATAL_ERROR) == 0)
1042       {
1043       if (tokens->tok == ')')
1044         {
1045         preproc_next(tokens);
1046         return result;
1047         }
1048 #if PREPROC_DEBUG
1049       fprintf(stderr, "syntax error %d\n", __LINE__);
1050 #endif
1051       return VTK_PARSE_SYNTAX_ERROR;
1052       }
1053     return result;
1054     }
1055   else if (tokens->tok == TOK_NUMBER)
1056     {
1057     result = preproc_evaluate_integer(tokens->text, val, is_unsigned);
1058     if (tokens->text[tokens->len-1] == 'f' ||
1059         tokens->text[tokens->len-1] == 'F')
1060       {
1061       result = VTK_PARSE_PREPROC_FLOAT;
1062       }
1063     preproc_next(tokens);
1064     return result;
1065     }
1066   else if (tokens->tok == TOK_CHAR)
1067     {
1068     result = preproc_evaluate_char(tokens->text, val, is_unsigned);
1069     preproc_next(tokens);
1070     return result;
1071     }
1072   else if (tokens->tok == TOK_STRING)
1073     {
1074     *val = 0;
1075     *is_unsigned = 0;
1076     preproc_next(tokens);
1077     while (tokens->tok == TOK_STRING)
1078       {
1079       preproc_next(tokens);
1080       }
1081     return VTK_PARSE_PREPROC_STRING;
1082     }
1083
1084   *val = 0;
1085   *is_unsigned = 0;
1086 #if PREPROC_DEBUG
1087   fprintf(stderr, "syntax error %d \"%*.*s\"\n", __LINE__,
1088           (int)tokens->len, (int)tokens->len, tokens->text);
1089 #endif
1090   return VTK_PARSE_SYNTAX_ERROR;
1091 }
1092
1093 static int preproc_evaluate_unary(
1094   PreprocessInfo *info, preproc_tokenizer *tokens,
1095   preproc_int_t *val, int *is_unsigned)
1096 {
1097   int op = tokens->tok;
1098   int result = VTK_PARSE_OK;
1099
1100   if (op != '+' && op != '-' && op != '~' && op != '!')
1101     {
1102     return preproc_evaluate_single(info, tokens, val, is_unsigned);
1103     }
1104
1105   preproc_next(tokens);
1106
1107   result = preproc_evaluate_unary(info, tokens, val, is_unsigned);
1108   if ((result & VTK_PARSE_FATAL_ERROR) == 0)
1109     {
1110     if (op == '~') { *val = ~(*val); }
1111     else if (op == '!') { *val = !(*val); *is_unsigned = 0; }
1112     else if (op == '-') { *val = -(*val); }
1113     return result;
1114     }
1115
1116   return result;
1117 }
1118
1119 static int preproc_evaluate_multiply(
1120   PreprocessInfo *info, preproc_tokenizer *tokens,
1121   preproc_int_t *val, int *is_unsigned)
1122 {
1123   int op;
1124   preproc_int_t rval;
1125   int rtype;
1126   int result;
1127
1128   result = preproc_evaluate_unary(info, tokens, val, is_unsigned);
1129   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
1130     {
1131     op = tokens->tok;
1132     if (op != '*' && op != '/' && op != '%')
1133       {
1134       return result;
1135       }
1136
1137     preproc_next(tokens);
1138
1139     result = preproc_evaluate_unary(info, tokens, &rval, &rtype);
1140
1141     *is_unsigned = (*is_unsigned || rtype);
1142
1143     if (*is_unsigned)
1144       {
1145       if (op == '*')
1146         {
1147         *val = (preproc_int_t)((preproc_uint_t)*val *
1148                                 (preproc_uint_t)rval);
1149         }
1150       else if (op == '/')
1151         {
1152         if (rval != 0)
1153           {
1154           *val = (preproc_int_t)((preproc_uint_t)*val /
1155                                  (preproc_uint_t)rval);
1156           }
1157         else
1158           {
1159           *val = 2147483647;
1160           }
1161         }
1162       else if (op == '%')
1163         {
1164         if (rval != 0)
1165           {
1166           *val = (preproc_int_t)((preproc_uint_t)*val %
1167                                   (preproc_uint_t)rval);
1168           }
1169         else
1170           {
1171           *val = 2147483647;
1172           }
1173         }
1174       }
1175     else
1176       {
1177       if (op == '*')
1178         {
1179         *val = *val * rval;
1180         }
1181       else if (op == '/')
1182         {
1183         if (rval != 0)
1184           {
1185           *val = *val / rval;
1186           }
1187         else if (*val < 0)
1188           {
1189           *val = -2147483647;
1190           }
1191         else
1192           {
1193           *val = 2147483647;
1194           }
1195         }
1196       else if (op == '%')
1197         {
1198         if (rval != 0)
1199           {
1200           *val = *val % rval;
1201           }
1202         else if (*val < 0)
1203           {
1204           *val = -2147483647;
1205           }
1206         else
1207           {
1208           *val = 2147483647;
1209           }
1210         }
1211       }
1212     }
1213
1214   return result;
1215 }
1216
1217 static int preproc_evaluate_add(
1218   PreprocessInfo *info, preproc_tokenizer *tokens,
1219   preproc_int_t *val, int *is_unsigned)
1220 {
1221   int op;
1222   preproc_int_t rval;
1223   int rtype;
1224   int result;
1225
1226   result = preproc_evaluate_multiply(info, tokens, val, is_unsigned);
1227   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
1228     {
1229     op = tokens->tok;
1230     if (op != '+' && op != '-')
1231       {
1232       return result;
1233       }
1234
1235     preproc_next(tokens);
1236
1237     result = preproc_evaluate_multiply(info, tokens, &rval, &rtype);
1238
1239     *is_unsigned = (*is_unsigned || rtype);
1240
1241     if (op == '+')
1242       {
1243       *val = *val + rval;
1244       }
1245     else if (op == '-')
1246       {
1247       *val = *val - rval;
1248       }
1249     }
1250
1251   return result;
1252 }
1253
1254 static int preproc_evaluate_bitshift(
1255   PreprocessInfo *info, preproc_tokenizer *tokens,
1256   preproc_int_t *val, int *is_unsigned)
1257 {
1258   int op;
1259   preproc_int_t rval;
1260   int rtype;
1261   int result;
1262
1263   result = preproc_evaluate_add(info, tokens, val, is_unsigned);
1264   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
1265     {
1266     op = tokens->tok;
1267
1268     if (op != TOK_LSHIFT && op != TOK_RSHIFT)
1269       {
1270       return result;
1271       }
1272
1273     preproc_next(tokens);
1274
1275     result = preproc_evaluate_add(info, tokens, &rval, &rtype);
1276
1277     if (*is_unsigned)
1278       {
1279       if (op == TOK_LSHIFT)
1280         {
1281         *val = (preproc_int_t)((preproc_uint_t)*val << rval);
1282         }
1283       else if (op == TOK_RSHIFT)
1284         {
1285         *val = (preproc_int_t)((preproc_uint_t)*val >> rval);
1286         }
1287       }
1288     else
1289       {
1290       if (op == TOK_LSHIFT)
1291         {
1292         *val = *val << rval;
1293         }
1294       else if (op == TOK_RSHIFT)
1295         {
1296         *val = *val >> rval;
1297         }
1298       }
1299     }
1300
1301   return result;
1302 }
1303
1304 static int preproc_evaluate_compare(
1305   PreprocessInfo *info, preproc_tokenizer *tokens,
1306   preproc_int_t *val, int *is_unsigned)
1307 {
1308   int op;
1309   preproc_int_t rval;
1310   int rtype;
1311   int result;
1312
1313   result = preproc_evaluate_bitshift(info, tokens, val, is_unsigned);
1314   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
1315     {
1316     op = tokens->tok;
1317     if (op != '<' && op != '>' && op != TOK_LE && op != TOK_GE)
1318       {
1319       return result;
1320       }
1321
1322     preproc_next(tokens);
1323
1324     result = preproc_evaluate_bitshift(info, tokens, &rval, &rtype);
1325
1326     *is_unsigned = (*is_unsigned || rtype);
1327
1328     if (*is_unsigned)
1329       {
1330       if (op == TOK_LE)
1331         {
1332         *val = ((preproc_uint_t)*val <= (preproc_uint_t)rval);
1333         }
1334       else if (op == '<')
1335         {
1336         *val = ((preproc_uint_t)*val < (preproc_uint_t)rval);
1337         }
1338       else if (op == TOK_GE)
1339         {
1340         *val = ((preproc_uint_t)*val >= (preproc_uint_t)rval);
1341         }
1342       else if (op == '>')
1343         {
1344         *val = ((preproc_uint_t)*val > (preproc_uint_t)rval);
1345         }
1346       }
1347     else
1348       {
1349       if (op == TOK_LE)
1350         {
1351         *val = (*val <= rval);
1352         }
1353       else if (op == '<')
1354         {
1355         *val = (*val < rval);
1356         }
1357       else if (op == TOK_GE)
1358         {
1359         *val = (*val >= rval);
1360         }
1361       else if (op == '>')
1362         {
1363         *val = (*val > rval);
1364         }
1365       }
1366     *is_unsigned = 0;
1367     }
1368
1369   return result;
1370 }
1371
1372 static int preproc_evaluate_equal(
1373   PreprocessInfo *info, preproc_tokenizer *tokens,
1374   preproc_int_t *val, int *is_unsigned)
1375 {
1376   int op;
1377   preproc_int_t rval;
1378   int rtype;
1379   int result;
1380
1381   result = preproc_evaluate_compare(info, tokens, val, is_unsigned);
1382   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
1383     {
1384     op = tokens->tok;
1385     if (op != TOK_EQ && op != TOK_NE)
1386       {
1387       return result;
1388       }
1389
1390     preproc_next(tokens);
1391
1392     result = preproc_evaluate_compare(info, tokens, &rval, &rtype);
1393
1394     if (op == TOK_EQ)
1395       {
1396       *val = (*val == rval);
1397       }
1398     else if (op == TOK_NE)
1399       {
1400       *val = (*val != rval);
1401       }
1402     *is_unsigned = 0;
1403     }
1404
1405   return result;
1406 }
1407
1408 static int preproc_evaluate_and(
1409   PreprocessInfo *info, preproc_tokenizer *tokens,
1410   preproc_int_t *val, int *is_unsigned)
1411 {
1412   preproc_int_t rval;
1413   int rtype;
1414   int result;
1415
1416   result = preproc_evaluate_equal(info, tokens, val, is_unsigned);
1417   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
1418     {
1419     if (tokens->tok != '&')
1420       {
1421       return result;
1422       }
1423
1424     preproc_next(tokens);
1425
1426     result = preproc_evaluate_equal(info, tokens, &rval, &rtype);
1427
1428     *is_unsigned = (*is_unsigned || rtype);
1429     *val = (*val & rval);
1430     }
1431
1432   return result;
1433 }
1434
1435 static int preproc_evaluate_xor(
1436   PreprocessInfo *info, preproc_tokenizer *tokens,
1437   preproc_int_t *val, int *is_unsigned)
1438 {
1439   preproc_int_t rval;
1440   int rtype;
1441   int result;
1442
1443   result = preproc_evaluate_and(info, tokens, val, is_unsigned);
1444   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
1445     {
1446     if (tokens->tok != '^')
1447       {
1448       return result;
1449       }
1450
1451     preproc_next(tokens);
1452
1453     result = preproc_evaluate_and(info, tokens, &rval, &rtype);
1454
1455     *is_unsigned = (*is_unsigned || rtype);
1456     *val = (*val ^ rval);
1457     }
1458
1459   return result;
1460 }
1461
1462 static int preproc_evaluate_or(
1463   PreprocessInfo *info, preproc_tokenizer *tokens,
1464   preproc_int_t *val, int *is_unsigned)
1465 {
1466   preproc_int_t rval;
1467   int rtype;
1468   int result;
1469
1470   result = preproc_evaluate_xor(info, tokens, val, is_unsigned);
1471   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
1472     {
1473     if (tokens->tok != '|')
1474       {
1475       return result;
1476       }
1477
1478     preproc_next(tokens);
1479
1480     result = preproc_evaluate_xor(info, tokens, &rval, &rtype);
1481
1482     *is_unsigned = (*is_unsigned || rtype);
1483     *val = (*val | rval);
1484     }
1485
1486   return result;
1487 }
1488
1489 static int preproc_evaluate_logic_and(
1490   PreprocessInfo *info, preproc_tokenizer *tokens,
1491   preproc_int_t *val, int *is_unsigned)
1492 {
1493   preproc_int_t rval;
1494   int rtype;
1495   int result;
1496
1497   result = preproc_evaluate_or(info, tokens, val, is_unsigned);
1498   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
1499     {
1500     if (tokens->tok != TOK_AND)
1501       {
1502       return result;
1503       }
1504
1505     preproc_next(tokens);
1506
1507     if (*val == 0)
1508       {
1509       /* short circuit */
1510       while (tokens->tok != 0 && tokens->tok != ')' &&
1511              tokens->tok != ':' && tokens->tok != '?' &&
1512              tokens->tok != ',' && tokens->tok != TOK_OR)
1513         {
1514         if (tokens->tok == '(')
1515           {
1516           if (preproc_skip_parentheses(tokens) != VTK_PARSE_OK)
1517             {
1518 #if PREPROC_DEBUG
1519             fprintf(stderr, "syntax error %d\n", __LINE__);
1520 #endif
1521             result = VTK_PARSE_SYNTAX_ERROR;
1522             }
1523           }
1524         else
1525           {
1526           preproc_next(tokens);
1527           }
1528         }
1529
1530       *is_unsigned = 0;
1531
1532       return result;
1533       }
1534
1535     result = preproc_evaluate_or(info, tokens, &rval, &rtype);
1536
1537     *is_unsigned = 0;
1538     *val = (rval != 0);
1539     }
1540
1541   return result;
1542 }
1543
1544 static int preproc_evaluate_logic_or(
1545   PreprocessInfo *info, preproc_tokenizer *tokens,
1546   preproc_int_t *val, int *is_unsigned)
1547 {
1548   preproc_int_t rval;
1549   int rtype;
1550   int result;
1551
1552   result = preproc_evaluate_logic_and(info, tokens, val, is_unsigned);
1553   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
1554     {
1555     if (tokens->tok != TOK_OR)
1556       {
1557       return result;
1558       }
1559
1560     preproc_next(tokens);
1561
1562     if (*val != 0)
1563       {
1564       /* short circuit */
1565       while (tokens->tok != 0 && tokens->tok != ')' &&
1566              tokens->tok != ':' && tokens->tok != '?' &&
1567              tokens->tok != ',')
1568         {
1569         if (tokens->tok == '(')
1570           {
1571           if (preproc_skip_parentheses(tokens) != VTK_PARSE_OK)
1572             {
1573 #if PREPROC_DEBUG
1574             fprintf(stderr, "syntax error %d\n", __LINE__);
1575 #endif
1576             result = VTK_PARSE_SYNTAX_ERROR;
1577             }
1578           }
1579         else
1580           {
1581           preproc_next(tokens);
1582           }
1583         }
1584
1585       *is_unsigned = 0;
1586
1587       return result;
1588       }
1589
1590     result = preproc_evaluate_logic_and(info, tokens, &rval, &rtype);
1591
1592     *is_unsigned = 0;
1593     *val = (rval != 0);
1594     }
1595
1596   return result;
1597 }
1598
1599 /** Evaluate an arimetic *expression.  */
1600 int preproc_evaluate_expression(
1601   PreprocessInfo *info, preproc_tokenizer *tokens,
1602   preproc_int_t *val, int *is_unsigned)
1603 {
1604   preproc_int_t rval, sval;
1605   int rtype, stype;
1606   int result;
1607
1608   result = preproc_evaluate_logic_or(info, tokens, val, is_unsigned);
1609   if ((result & VTK_PARSE_FATAL_ERROR) == 0)
1610     {
1611     if (tokens->tok != '?')
1612       {
1613       return result;
1614       }
1615
1616     preproc_next(tokens);
1617
1618     result = preproc_evaluate_expression(info, tokens, &rval, &rtype);
1619     if ((result & VTK_PARSE_FATAL_ERROR) != 0)
1620       {
1621       return result;
1622       }
1623
1624     if (tokens->tok != ':')
1625       {
1626 #if PREPROC_DEBUG
1627       fprintf(stderr, "syntax error %d\n", __LINE__);
1628 #endif
1629       return VTK_PARSE_SYNTAX_ERROR;
1630       }
1631
1632     preproc_next(tokens);
1633
1634     result = preproc_evaluate_expression(info, tokens, &sval, &stype);
1635     if ((result & VTK_PARSE_FATAL_ERROR) != 0)
1636       {
1637       return result;
1638       }
1639
1640     if (*val != 0)
1641       {
1642       *val = rval;
1643       *is_unsigned = rtype;
1644       }
1645     else
1646       {
1647       *val = sval;
1648       *is_unsigned = stype;
1649       }
1650     }
1651
1652   return result;
1653 }
1654
1655 /** Evaluate a conditional *expression.
1656  * Returns VTK_PARSE_OK if the expression is true,
1657  * or VTK_PARSE_SKIP of the expression is false. */
1658 int preproc_evaluate_conditional(
1659   PreprocessInfo *info, preproc_tokenizer *tokens)
1660 {
1661   preproc_int_t rval;
1662   int rtype;
1663   int result;
1664
1665   result = preproc_evaluate_expression(info, tokens, &rval, &rtype);
1666   if ((result & VTK_PARSE_FATAL_ERROR) == 0)
1667     {
1668     if (tokens->tok != 0)
1669       {
1670 #if PREPROC_DEBUG
1671       fprintf(stderr, "syntax error %d\n", __LINE__);
1672 #endif
1673       return VTK_PARSE_SYNTAX_ERROR;
1674       }
1675     return (rval == 0 ? VTK_PARSE_SKIP : VTK_PARSE_OK);
1676     }
1677
1678   return result;
1679 }
1680
1681 /**
1682  * Handle any of the following directives:
1683  * #if, #ifdef, #ifndef, #elif, #else, #endif
1684  * A return value of VTK_PARSE_SKIP means that
1685  * the following code block should be skipped.
1686  */
1687 static int preproc_evaluate_if(
1688   PreprocessInfo *info, preproc_tokenizer *tokens)
1689 {
1690   MacroInfo *macro;
1691   int v1, v2;
1692   int result = VTK_PARSE_OK;
1693
1694   if (tokens->hash == HASH_IF ||
1695       tokens->hash == HASH_IFDEF ||
1696       tokens->hash == HASH_IFNDEF)
1697     {
1698     if (info->ConditionalDepth == 0)
1699       {
1700       if (tokens->hash == HASH_IF)
1701         {
1702         preproc_next(tokens);
1703         result = preproc_evaluate_conditional(info, tokens);
1704         }
1705       else
1706         {
1707         v1 = (tokens->hash != HASH_IFNDEF);
1708         preproc_next(tokens);
1709         if (tokens->tok != TOK_ID)
1710           {
1711 #if PREPROC_DEBUG
1712           fprintf(stderr, "syntax error %d\n", __LINE__);
1713 #endif
1714           return VTK_PARSE_SYNTAX_ERROR;
1715           }
1716         macro = preproc_find_macro(info, tokens);
1717         v2 = (macro && !macro->IsExcluded);
1718         preproc_next(tokens);
1719         result = ( (v1 ^ v2) ? VTK_PARSE_SKIP : VTK_PARSE_OK);
1720         }
1721
1722       if (result != VTK_PARSE_SKIP)
1723         {
1724         /* mark as done, so that the "else" clause is skipped */
1725         info->ConditionalDone = 1;
1726         }
1727       else
1728         {
1729         /* mark as not done, so that "else" clause is not skipped */
1730         info->ConditionalDone = 0;
1731         /* skip the "if" clause */
1732         info->ConditionalDepth = 1;
1733         }
1734       }
1735     else
1736       {
1737       /* increase the skip depth */
1738       info->ConditionalDepth++;
1739       }
1740     }
1741   else if (tokens->hash == HASH_ELIF ||
1742            tokens->hash == HASH_ELSE)
1743     {
1744     if (info->ConditionalDepth == 0)
1745       {
1746       /* preceding clause was not skipped, so must skip this one */
1747       info->ConditionalDepth = 1;
1748       }
1749     else if (info->ConditionalDepth == 1 &&
1750              info->ConditionalDone == 0)
1751       {
1752       if (tokens->hash == HASH_ELIF)
1753         {
1754         preproc_next(tokens);
1755         result = preproc_evaluate_conditional(info, tokens);
1756         }
1757       else
1758         {
1759         preproc_next(tokens);
1760         }
1761       if (result != VTK_PARSE_SKIP)
1762         {
1763         /* do not skip this clause */
1764         info->ConditionalDepth = 0;
1765         /* make sure remaining else/elif clauses are skipped */
1766         info->ConditionalDone = 1;
1767         }
1768       }
1769     }
1770   else if (tokens->hash == HASH_ENDIF)
1771     {
1772     preproc_next(tokens);
1773     if (info->ConditionalDepth > 0)
1774       {
1775       /* decrease the skip depth */
1776       info->ConditionalDepth--;
1777       }
1778     if (info->ConditionalDepth == 0)
1779       {
1780       /* set "done" flag for the context that is being returned to */
1781       info->ConditionalDone = 1;
1782       }
1783     }
1784
1785   return result;
1786 }
1787
1788 /**
1789  * Handle the #define and #undef directives.
1790  */
1791 static int preproc_evaluate_define(
1792   PreprocessInfo *info, preproc_tokenizer *tokens)
1793 {
1794   MacroInfo **macro_p;
1795   MacroInfo *macro;
1796   int is_function;
1797   const char *name;
1798   size_t namelen;
1799   const char *definition = 0;
1800   int n = 0;
1801   const char **params = NULL;
1802
1803   if (tokens->hash == HASH_DEFINE)
1804     {
1805     preproc_next(tokens);
1806     if (tokens->tok != TOK_ID)
1807       {
1808 #if PREPROC_DEBUG
1809       fprintf(stderr, "syntax error %d\n", __LINE__);
1810 #endif
1811       return VTK_PARSE_SYNTAX_ERROR;
1812       }
1813
1814     macro_p = preproc_macro_location(info, tokens, 1);
1815     name = tokens->text;
1816     namelen = tokens->len;
1817     preproc_next(tokens);
1818
1819     is_function = 0;
1820     if (name[namelen] == '(')
1821       {
1822       is_function = 1;
1823       preproc_next(tokens);
1824       while (tokens->tok != 0 && tokens->tok != ')')
1825         {
1826         if (tokens->tok != TOK_ID && tokens->tok != TOK_ELLIPSIS)
1827           {
1828           if (params) { free((char **)params); }
1829 #if PREPROC_DEBUG
1830           fprintf(stderr, "syntax error %d\n", __LINE__);
1831 #endif
1832           return VTK_PARSE_SYNTAX_ERROR;
1833           }
1834
1835         /* add to the arg list */
1836         params = (const char **)preproc_array_check(
1837           (char **)params, sizeof(char *), n);
1838         params[n++] = preproc_strndup(tokens->text, tokens->len);
1839
1840         preproc_next(tokens);
1841         if (tokens->tok == ',')
1842           {
1843           preproc_next(tokens);
1844           }
1845         else if (tokens->tok != ')')
1846           {
1847           if (params) { free((char **)params); }
1848 #if PREPROC_DEBUG
1849           fprintf(stderr, "syntax error %d\n", __LINE__);
1850 #endif
1851           return VTK_PARSE_SYNTAX_ERROR;
1852           }
1853         }
1854       preproc_next(tokens);
1855       }
1856
1857     if (tokens->tok)
1858       {
1859       definition = tokens->text;
1860       }
1861
1862     macro = *macro_p;
1863     if (macro)
1864       {
1865       if (preproc_identical(macro->Definition, definition))
1866         {
1867         return VTK_PARSE_OK;
1868         }
1869       if (params) { free((char **)params); }
1870 #if PREPROC_DEBUG
1871       fprintf(stderr, "macro redefined %d\n", __LINE__);
1872 #endif
1873       return VTK_PARSE_MACRO_REDEFINED;
1874       }
1875
1876     macro = preproc_new_macro(info, name, definition);
1877     macro->IsFunction = is_function;
1878     macro->NumberOfParameters = n;
1879     macro->Parameters = params;
1880     *macro_p = macro;
1881
1882     return VTK_PARSE_OK;
1883     }
1884   else if (tokens->hash == HASH_UNDEF)
1885     {
1886     preproc_next(tokens);
1887     if (tokens->tok != TOK_ID)
1888       {
1889 #if PREPROC_DEBUG
1890       fprintf(stderr, "syntax error %d\n", __LINE__);
1891 #endif
1892       return VTK_PARSE_SYNTAX_ERROR;
1893       }
1894     preproc_remove_macro(info, tokens);
1895     return VTK_PARSE_OK;
1896     }
1897
1898   return VTK_PARSE_OK;
1899 }
1900
1901 /**
1902  * Add an include file to the list.  Return 0 if it is already there.
1903  */
1904 static int preproc_add_include_file(PreprocessInfo *info, const char *name)
1905 {
1906   int i, n;
1907   char *dp;
1908
1909   n = info->NumberOfIncludeFiles;
1910   for (i = 0; i < n; i++)
1911     {
1912     if (strcmp(info->IncludeFiles[i], name) == 0)
1913       {
1914       return 0;
1915       }
1916     }
1917
1918   dp = (char *)malloc(strlen(name)+1);
1919   strcpy(dp, name);
1920
1921   info->IncludeFiles = (const char **)preproc_array_check(
1922     (char **)info->IncludeFiles, sizeof(char *), info->NumberOfIncludeFiles);
1923   info->IncludeFiles[info->NumberOfIncludeFiles++] = dp;
1924
1925   return 1;
1926 }
1927
1928 /**
1929  * Find an include file.  If "cache_only" is set, then do a check to
1930  * see if the file was previously found without going to the filesystem.
1931  */
1932 const char *preproc_find_include_file(
1933   PreprocessInfo *info, const char *filename, int system_first,
1934   int cache_only)
1935 {
1936   int i, n, ii, nn;
1937   size_t j, m;
1938   struct stat fs;
1939   const char *directory;
1940   char *output;
1941   size_t outputsize = 16;
1942   int count;
1943
1944   /* allow filename to be terminated by quote or bracket */
1945   m = 0;
1946   while (filename[m] != '\"' && filename[m] != '>' &&
1947          filename[m] != '\n' && filename[m] != '\0') { m++; }
1948
1949   /* search file system for the file */
1950   output = (char *)malloc(outputsize);
1951
1952   if (system_first != 0)
1953     {
1954     system_first = 1;
1955     }
1956
1957   if (cache_only != 0)
1958     {
1959     cache_only = 1;
1960     }
1961
1962   /* check for absolute path of form DRIVE: or /path/to/file */
1963   j = 0;
1964   while (preproc_chartype(filename[j], CPRE_IDGIT)) { j++; }
1965
1966   if (filename[j] == ':' || filename[0] == '/' || filename[0] == '\\')
1967     {
1968     if (m+1 > outputsize)
1969       {
1970       outputsize += m+1;
1971       output = (char *)realloc(output, outputsize);
1972       }
1973     strncpy(output, filename, m);
1974     output[m] = '\0';
1975
1976     nn = info->NumberOfIncludeFiles;
1977     for (ii = 0; ii < nn; ii++)
1978       {
1979       if (strcmp(output, info->IncludeFiles[ii]) == 0)
1980         {
1981         free(output);
1982         return info->IncludeFiles[ii];
1983         }
1984       }
1985
1986     if (cache_only)
1987       {
1988       free(output);
1989       return NULL;
1990       }
1991
1992     info->IncludeFiles = (const char **)preproc_array_check(
1993       (char **)info->IncludeFiles, sizeof(char *),
1994       info->NumberOfIncludeFiles);
1995     info->IncludeFiles[info->NumberOfIncludeFiles++] = output;
1996
1997     return output;
1998     }
1999
2000   /* Make sure the current filename is already added */
2001   if (info->FileName)
2002     {
2003     preproc_add_include_file(info, info->FileName);
2004     }
2005
2006   /* Check twice. First check the cache, then stat the files. */
2007   for (count = 0; count < (2-cache_only); count++)
2008     {
2009     n = info->NumberOfIncludeDirectories;
2010     for (i = 0; i < (n+1-system_first); i++)
2011       {
2012       /* search the directory of the file being processed */
2013       if (i == 0 && system_first == 0)
2014         {
2015         if (info->FileName)
2016           {
2017           j = strlen(info->FileName);
2018           while (j > 0)
2019             {
2020             if (info->FileName[j-1] == '/') { break; }
2021             j--;
2022             }
2023           if (m+j+1 > outputsize)
2024             {
2025             outputsize += m+j+1;
2026             output = (char *)realloc(output, outputsize);
2027             }
2028           if (j > 0)
2029             {
2030             strncpy(output, info->FileName, j);
2031             }
2032           strncpy(&output[j], filename, m);
2033           output[j+m] = '\0';
2034           }
2035         else
2036           {
2037           if (m+1 > outputsize)
2038             {
2039             outputsize += m+1;
2040             output = (char *)realloc(output, outputsize);
2041             }
2042           strncpy(output, filename, m);
2043           output[m] = '\0';
2044           }
2045         }
2046       /* check all the search paths */
2047       else
2048         {
2049         directory = info->IncludeDirectories[i-1+system_first];
2050         j = strlen(directory);
2051         if (j + m + 2 > outputsize)
2052           {
2053           outputsize += j+m+2;
2054           output = (char *)realloc(output, outputsize);
2055           }
2056
2057         strncpy(output, directory, j);
2058         if (directory[j-1] != '/') { output[j++] = '/'; }
2059         strncpy(&output[j], filename, m);
2060         output[j+m] = '\0';
2061         }
2062
2063       if (count == 0)
2064         {
2065         nn = info->NumberOfIncludeFiles;
2066         for (ii = 0; ii < nn; ii++)
2067           {
2068           if (strcmp(output, info->IncludeFiles[ii]) == 0)
2069             {
2070             free(output);
2071             return info->IncludeFiles[ii];
2072             }
2073           }
2074         }
2075       else if (stat(output, &fs) == 0)
2076         {
2077         info->IncludeFiles = (const char **)preproc_array_check(
2078           (char **)info->IncludeFiles, sizeof(char *),
2079           info->NumberOfIncludeFiles);
2080         info->IncludeFiles[info->NumberOfIncludeFiles++] = output;
2081
2082         return output;
2083         }
2084       }
2085     }
2086
2087   free(output);
2088   return NULL;
2089 }
2090
2091 /**
2092  * Include a file.  All macros defined in the included file
2093  * will have their IsExternal flag set.
2094  */
2095 static int preproc_include_file(
2096   PreprocessInfo *info, const char *filename, int system_first)
2097 {
2098   char *tbuf;
2099   size_t tbuflen = FILE_BUFFER_SIZE;
2100   char *line;
2101   size_t linelen = 80;
2102   size_t i, j, n, r;
2103   int in_comment = 0;
2104   int in_quote = 0;
2105   int result = VTK_PARSE_OK;
2106   FILE *fp = NULL;
2107   const char *path = NULL;
2108   const char *save_filename;
2109   int save_external;
2110
2111   /* check to see if the file has aleady been included */
2112   path = preproc_find_include_file(info, filename, system_first, 1);
2113   if (path != 0)
2114     {
2115 #if PREPROC_DEBUG
2116     int k = 0;
2117     while (filename[k] != '>' && filename[k] != '\"' &&
2118            filename[k] != '\n' && filename[k] != '\0') { k++; }
2119     if (filename[k] == '>')
2120       fprintf(stderr, "already loaded file <%*.*s>\n", k, k, filename);
2121     else
2122       fprintf(stderr, "already loaded file \"%*.*s\"\n", k, k, filename);
2123 #endif
2124
2125     return VTK_PARSE_OK;
2126     }
2127   /* go to the filesystem */
2128   path = preproc_find_include_file(info, filename, system_first, 0);
2129   if (path == NULL)
2130     {
2131 #if PREPROC_DEBUG
2132     int k = 0;
2133     while (filename[k] != '>' && filename[k] != '\"' &&
2134            filename[k] != '\n' && filename[k] != '\0') { k++; }
2135     if (filename[k] == '>')
2136       fprintf(stderr, "couldn't find file <%*.*s>\n", k, k, filename);
2137     else
2138       fprintf(stderr, "couldn't find file \"%*.*s\"\n", k, k, filename);
2139 #endif
2140     return VTK_PARSE_FILE_NOT_FOUND;
2141     }
2142
2143 #if PREPROC_DEBUG
2144   fprintf(stderr, "including file %s\n", path);
2145 #endif
2146   fp = fopen(path, "r");
2147
2148   if (fp == NULL)
2149     {
2150 #if PREPROC_DEBUG
2151     fprintf(stderr, "couldn't open file %s\n", path);
2152 #endif
2153     return VTK_PARSE_FILE_OPEN_ERROR;
2154     }
2155
2156   save_external = info->IsExternal;
2157   save_filename = info->FileName;
2158   info->IsExternal = 1;
2159   info->FileName = path;
2160
2161   tbuf = (char *)malloc(tbuflen+4);
2162   line = (char *)malloc(linelen);
2163
2164   /* the buffer must hold a whole line for it to be processed */
2165   j = 0;
2166   i = 0;
2167   n = 0;
2168   r = 0;
2169
2170   do
2171     {
2172     if (i >= n)
2173       {
2174       /* recycle unused lookahead chars */
2175       if (r)
2176         {
2177         r = n + 2 - i;
2178         if (r == 2)
2179           {
2180           tbuf[0] = tbuf[tbuflen-2];
2181           tbuf[1] = tbuf[tbuflen-1];
2182           }
2183         else if (r == 1)
2184           {
2185           tbuf[0] = tbuf[tbuflen-1];
2186           }
2187         }
2188
2189       /* read the next chunk of the file */
2190       i = 0;
2191       if (feof(fp))
2192         {
2193         /* still have the lookahead chars left */
2194         n = r;
2195         r = 0;
2196         }
2197       else
2198         {
2199         /* fill the remainder of the buffer */
2200         errno = 0;
2201         tbuflen = r + FILE_BUFFER_SIZE;
2202         while ((n = fread(&tbuf[r], 1, tbuflen-r, fp)) == 0 && ferror(fp))
2203           {
2204           if (errno != EINTR)
2205             {
2206             fclose(fp);
2207             free(tbuf);
2208             free(line);
2209             info->IsExternal = save_external;
2210             return VTK_PARSE_FILE_READ_ERROR;
2211             }
2212           errno = 0;
2213           clearerr(fp);
2214           }
2215
2216         if (n + r < tbuflen)
2217           {
2218           /* this only occurs if the final fread does not fill the buffer */
2219           n += r;
2220           r = 0;
2221           }
2222         else
2223           {
2224           /* set a lookahead reserve of two chars */
2225           n -= (2 - r);
2226           r = 2;
2227           }
2228
2229         /* guard against lookahead past last char in file */
2230         tbuf[n + r] = '\0';
2231         }
2232       }
2233
2234     /* copy the characters until end of line is found */
2235     while (i < n)
2236       {
2237       /* expand line buffer as necessary */
2238       while (j+4 > linelen)
2239         {
2240         linelen *= 2;
2241         line = (char *)realloc(line, linelen);
2242         }
2243
2244       if (in_comment)
2245         {
2246         if (tbuf[i] == '*' && tbuf[i+1] == '/')
2247           {
2248           line[j++] = tbuf[i++];
2249           line[j++] = tbuf[i++];
2250           in_comment = 0;
2251           }
2252         else
2253           {
2254           line[j++] = tbuf[i++];
2255           }
2256         }
2257       else if (in_quote)
2258         {
2259         if (tbuf[i] == '\"')
2260           {
2261           line[j++] = tbuf[i++];
2262           in_quote = 0;
2263           }
2264         else if (tbuf[i] == '\\' && tbuf[i+1] != '\0')
2265           {
2266           line[j++] = tbuf[i++];
2267           line[j++] = tbuf[i++];
2268           }
2269         else
2270           {
2271           line[j++] = tbuf[i++];
2272           }
2273         }
2274       else if (tbuf[i] == '/' && tbuf[i+1] == '*')
2275         {
2276         line[j++] = tbuf[i++];
2277         line[j++] = tbuf[i++];
2278         in_comment = 1;
2279         }
2280       else if (tbuf[i] == '\"')
2281         {
2282         line[j++] = tbuf[i++];
2283         in_quote = 1;
2284         }
2285       else if (tbuf[i] == '\\' && tbuf[i+1] == '\n')
2286         {
2287         line[j++] = tbuf[i++];
2288         line[j++] = tbuf[i++];
2289         }
2290       else if (tbuf[i] == '\\' && tbuf[i+1] == '\r' && tbuf[i+2] == '\n')
2291         {
2292         line[j++] = tbuf[i++];
2293         line[j++] = tbuf[i++];
2294         line[j++] = tbuf[i++];
2295         }
2296       else if (tbuf[i] != '\n' && tbuf[i] != '\0')
2297         {
2298         line[j++] = tbuf[i++];
2299         }
2300       else
2301         {
2302         line[j++] = tbuf[i++];
2303         break;
2304         }
2305       }
2306
2307     if (i < n || n == 0)
2308       {
2309       const char *cp = line;
2310       line[j] = '\0';
2311       j = 0;
2312       preproc_skip_whitespace(&cp, WS_NO_EOL);
2313       if (*cp == '#')
2314         {
2315         vtkParsePreprocess_HandleDirective(info, line);
2316         }
2317       }
2318     }
2319   while (n > 0);
2320
2321   free(tbuf);
2322   free(line);
2323   fclose(fp);
2324
2325   info->IsExternal = save_external;
2326   info->FileName = save_filename;
2327
2328   return result;
2329 }
2330
2331 /**
2332  * Handle the #include directive.  The header file will
2333  * only go through the preprocessor.
2334  */
2335 static int preproc_evaluate_include(
2336   PreprocessInfo *info, preproc_tokenizer *tokens)
2337 {
2338   const char *cp;
2339   const char *filename;
2340
2341   if (tokens->hash == HASH_INCLUDE)
2342     {
2343     preproc_next(tokens);
2344
2345     cp = tokens->text;
2346
2347     if (tokens->tok == TOK_ID)
2348       {
2349       MacroInfo *macro = preproc_find_macro(info, tokens);
2350       if (macro && !macro->IsExcluded && macro->Definition)
2351         {
2352         cp = macro->Definition;
2353         }
2354       else
2355         {
2356 #if PREPROC_DEBUG
2357         fprintf(stderr, "couldn't find macro %*.*s.\n",
2358                 (int)tokens->len, (int)tokens->len, tokens->text);
2359 #endif
2360         return VTK_PARSE_MACRO_UNDEFINED;
2361         }
2362       }
2363
2364     if (*cp == '\"')
2365       {
2366       filename = cp + 1;
2367       preproc_skip_quotes(&cp);
2368       if (cp <= filename + 1 || *(cp-1) != '\"')
2369         {
2370         return VTK_PARSE_SYNTAX_ERROR;
2371         }
2372
2373       return preproc_include_file(info, filename, 0);
2374       }
2375     else if (*cp == '<')
2376       {
2377       cp++;
2378       filename = cp;
2379       while (*cp != '>' && *cp != '\n' && *cp != '\0') { cp++; }
2380       if (*cp != '>')
2381         {
2382         return VTK_PARSE_SYNTAX_ERROR;
2383         }
2384
2385       return preproc_include_file(info, filename, 1);
2386       }
2387     }
2388
2389   return VTK_PARSE_OK;
2390 }
2391
2392 /**
2393  * Handle any recognized directive.
2394  * Unrecognized directives are ignored.
2395  */
2396 int vtkParsePreprocess_HandleDirective(
2397   PreprocessInfo *info, const char *directive)
2398 {
2399   int result = VTK_PARSE_OK;
2400   preproc_tokenizer tokens;
2401
2402   preproc_init(&tokens, directive);
2403
2404   if (tokens.tok != '#')
2405     {
2406     return VTK_PARSE_SYNTAX_ERROR;
2407     }
2408
2409   preproc_next(&tokens);
2410
2411   if (tokens.tok == TOK_ID)
2412     {
2413     if ((tokens.hash == HASH_IFDEF && tokens.len == 5 &&
2414          strncmp("ifdef", tokens.text, tokens.len) == 0) ||
2415         (tokens.hash == HASH_IFNDEF && tokens.len == 6 &&
2416          strncmp("ifndef", tokens.text, tokens.len) == 0) ||
2417         (tokens.hash == HASH_IF && tokens.len == 2 &&
2418          strncmp("if", tokens.text, tokens.len) == 0) ||
2419         (tokens.hash == HASH_ELIF && tokens.len == 4 &&
2420          strncmp("elif", tokens.text, tokens.len) == 0) ||
2421         (tokens.hash == HASH_ELSE && tokens.len == 4 &&
2422          strncmp("else", tokens.text, tokens.len) == 0) ||
2423         (tokens.hash == HASH_ENDIF && tokens.len == 5 &&
2424          strncmp("endif", tokens.text, tokens.len) == 0))
2425       {
2426       result = preproc_evaluate_if(info, &tokens);
2427       while (tokens.tok) { preproc_next(&tokens); }
2428 #if PREPROC_DEBUG
2429         {
2430         size_t n = tokens.text - directive;
2431
2432         if (result == VTK_PARSE_SKIP)
2433           {
2434           fprintf(stderr, "SKIP: ");
2435           }
2436         else if (result == VTK_PARSE_OK)
2437           {
2438           fprintf(stderr, "READ: ");
2439           }
2440         else
2441           {
2442           fprintf(stderr, "ERR%-2.2d ", result);
2443           }
2444         fprintf(stderr, "%*.*s\n", (int)n, (int)n, directive);
2445         }
2446 #endif
2447       }
2448     else if (info->ConditionalDepth == 0)
2449       {
2450       if ((tokens.hash == HASH_DEFINE && tokens.len == 6 &&
2451            strncmp("define", tokens.text, tokens.len) == 0) ||
2452           (tokens.hash == HASH_UNDEF && tokens.len == 5 &&
2453            strncmp("undef", tokens.text, tokens.len) == 0))
2454         {
2455         result = preproc_evaluate_define(info, &tokens);
2456         }
2457       else if (tokens.hash == HASH_INCLUDE && tokens.len == 7 &&
2458                strncmp("include", tokens.text, tokens.len) == 0)
2459         {
2460         result = preproc_evaluate_include(info, &tokens);
2461         }
2462       }
2463     }
2464
2465   if (info->ConditionalDepth > 0)
2466     {
2467     return VTK_PARSE_SKIP;
2468     }
2469
2470   return result;
2471 }
2472
2473 /**
2474  * Evaluate a preprocessor expression.
2475  * If no errors occurred, the result will be VTK_PARSE_OK.
2476  */
2477 int vtkParsePreprocess_EvaluateExpression(
2478   PreprocessInfo *info, const char *text,
2479   preproc_int_t *val, int *is_unsigned)
2480 {
2481   preproc_tokenizer tokens;
2482   preproc_init(&tokens, text);
2483
2484   return preproc_evaluate_expression(info, &tokens, val, is_unsigned);
2485 }
2486
2487 /** Add a macro for defining a macro */
2488 #define PREPROC_MACRO_TO_STRING2(x) #x
2489 #define PREPROC_MACRO_TO_STRING(x) PREPROC_MACRO_TO_STRING2(x)
2490 #define PREPROC_ADD_MACRO(info, x) \
2491 preproc_add_macro_definition(info, #x, PREPROC_MACRO_TO_STRING2(x))
2492
2493 /**
2494  * Add all standard preprocessory macros.  Specify the platform.
2495  */
2496 void vtkParsePreprocess_AddStandardMacros(
2497   PreprocessInfo *info, int platform)
2498 {
2499   int save_external = info->IsExternal;
2500   info->IsExternal = 1;
2501
2502   /* a special macro to indicate that this is the wrapper */
2503   preproc_add_macro_definition(info, "__WRAP__", "1");
2504
2505   /* language macros - assume that we are wrapping C++ code */
2506   preproc_add_macro_definition(info, "__cplusplus", "1");
2507
2508   /* stdc version macros */
2509 #ifdef __STDC__
2510   PREPROC_ADD_MACRO(info, __STDC__);
2511 #endif
2512 #ifdef __STDC_VERSION__
2513   PREPROC_ADD_MACRO(info, __STDC_VERSION__);
2514 #endif
2515 #ifdef __STDC_HOSTED__
2516   PREPROC_ADD_MACRO(info, __STDC_HOSTED__);
2517 #endif
2518
2519   if (platform == VTK_PARSE_NATIVE)
2520     {
2521 #ifdef WIN32
2522     PREPROC_ADD_MACRO(info, WIN32);
2523 #endif
2524 #ifdef _WIN32
2525     PREPROC_ADD_MACRO(info, _WIN32);
2526 #endif
2527 #ifdef _MSC_VER
2528     PREPROC_ADD_MACRO(info, _MSC_VER);
2529 #endif
2530
2531 #ifdef __BORLAND__
2532     PREPROC_ADD_MACRO(info, __BORLAND__);
2533 #endif
2534
2535 #ifdef __CYGWIN__
2536     PREPROC_ADD_MACRO(info, __CYGWIN__);
2537 #endif
2538 #ifdef MINGW
2539     PREPROC_ADD_MACRO(info, MINGW);
2540 #endif
2541 #ifdef __MINGW32__
2542     PREPROC_ADD_MACRO(info, __MINGW32__);
2543 #endif
2544
2545 #ifdef __linux__
2546     PREPROC_ADD_MACRO(info, __linux__);
2547 #endif
2548 #ifdef __LINUX__
2549     PREPROC_ADD_MACRO(info, __LINUX__);
2550 #endif
2551
2552 #ifdef __APPLE__
2553     PREPROC_ADD_MACRO(info, __APPLE__);
2554 #endif
2555 #ifdef __MACH__
2556     PREPROC_ADD_MACRO(info, __MACH__);
2557 #endif
2558 #ifdef __DARWIN__
2559     PREPROC_ADD_MACRO(info, __DARWIN__);
2560 #endif
2561
2562 #ifdef __GNUC__
2563     PREPROC_ADD_MACRO(info, __GNUC__);
2564 #endif
2565 #ifdef __LP64__
2566     PREPROC_ADD_MACRO(info, __LP64__);
2567 #endif
2568 #ifdef __BIG_ENDIAN__
2569     PREPROC_ADD_MACRO(info, __BIG_ENDIAN__);
2570 #endif
2571 #ifdef __LITTLE_ENDIAN__
2572     PREPROC_ADD_MACRO(info, __LITTLE_ENDIAN__);
2573 #endif
2574     }
2575
2576   info->IsExternal = save_external;
2577 }
2578
2579 /**
2580  * Add a preprocessor macro, including a definition.
2581  */
2582 int vtkParsePreprocess_AddMacro(
2583   PreprocessInfo *info, const char *name, const char *definition)
2584 {
2585   preproc_tokenizer token;
2586   MacroInfo **macro_p;
2587   MacroInfo *macro;
2588
2589   preproc_init(&token, name);
2590   macro_p = preproc_macro_location(info, &token, 1);
2591   if (*macro_p)
2592     {
2593     macro = *macro_p;
2594     if (preproc_identical(macro->Definition, definition))
2595       {
2596       return VTK_PARSE_OK;
2597       }
2598     else
2599       {
2600       return VTK_PARSE_MACRO_REDEFINED;
2601       }
2602     }
2603
2604   macro = preproc_new_macro(info, name, definition);
2605   macro->IsExternal = 1;
2606   *macro_p = macro;
2607
2608   return VTK_PARSE_OK;
2609 }
2610
2611 /**
2612  * Return a preprocessor macro struct, or NULL if not found.
2613  */
2614 MacroInfo *vtkParsePreprocess_GetMacro(
2615   PreprocessInfo *info, const char *name)
2616 {
2617   preproc_tokenizer token;
2618   MacroInfo *macro;
2619
2620   preproc_init(&token, name);
2621   macro = preproc_find_macro(info, &token);
2622
2623   if (macro && !macro->IsExcluded)
2624     {
2625     return macro;
2626     }
2627
2628   return NULL;
2629 }
2630
2631 /**
2632  * Remove a preprocessor macro.
2633  */
2634 int vtkParsePreprocess_RemoveMacro(
2635   PreprocessInfo *info, const char *name)
2636 {
2637   preproc_tokenizer token;
2638
2639   preproc_init(&token, name);
2640
2641   if (preproc_remove_macro(info, &token))
2642     {
2643     return VTK_PARSE_OK;
2644     }
2645
2646   return VTK_PARSE_MACRO_UNDEFINED;
2647 }
2648
2649 /**
2650  * Expand a macro, argstring is ignored if not a function macro
2651  */
2652 const char *vtkParsePreprocess_ExpandMacro(
2653   PreprocessInfo *info, MacroInfo *macro, const char *argstring)
2654 {
2655   const char *cp = argstring;
2656   int n = 0;
2657   int j = 0;
2658   const char *stack_values[8];
2659   const char **values = NULL;
2660   const char *pp = NULL;
2661   const char *dp = NULL;
2662   const char *wp = NULL;
2663   char stack_rp[128];
2664   char *rp = NULL;
2665   size_t rs = 0;
2666   size_t i = 0;
2667   size_t l = 0;
2668   size_t k = 0;
2669   int stringify = 0;
2670   int noexpand = 0;
2671   int depth = 1;
2672   int c;
2673
2674   if (macro->IsFunction)
2675     {
2676     if (argstring == NULL || *cp != '(')
2677       {
2678       return NULL;
2679       }
2680
2681     /* break the string into individual argument values */
2682     values = stack_values;
2683
2684     cp++;
2685     values[n++] = cp;
2686     while (depth > 0 && *cp != '\0')
2687       {
2688       while (*cp != '\0')
2689         {
2690         if (*cp == '\"' || *cp == '\'')
2691           {
2692           preproc_skip_quotes(&cp);
2693           }
2694         else if (cp[0] == '/' && (cp[1] == '*' || cp[1] == '/'))
2695           {
2696           preproc_skip_comment(&cp);
2697           }
2698         else if (*cp == '(')
2699           {
2700           cp++;
2701           depth++;
2702           }
2703         else if (*cp == ')')
2704           {
2705           cp++;
2706           if (--depth == 0)
2707             {
2708             break;
2709             }
2710           }
2711         else if (*cp == ',')
2712           {
2713           cp++;
2714           if (depth == 1)
2715             {
2716             break;
2717             }
2718           }
2719         else if (*cp != '\0')
2720           {
2721           cp++;
2722           }
2723         }
2724       if (n >= 8 && (n & (n-1)) == 0)
2725         {
2726         if (values != stack_values)
2727           {
2728           values = (const char **)realloc(
2729             (char **)values, 2*n*sizeof(const char **));
2730           }
2731         else
2732           {
2733           values = (const char **)malloc(2*n*sizeof(const char **));
2734           memcpy((char **)values, stack_values, 8*sizeof(const char **));
2735           }
2736         }
2737
2738       values[n++] = cp;
2739       }
2740     --n;
2741
2742     /* diagnostic: print out the values */
2743 #if PREPROC_DEBUG
2744     for (j = 0; j < n; j++)
2745       {
2746       size_t m = values[j+1] - values[j] - 1;
2747       fprintf(stderr, "arg %i: %*.*s\n",
2748               (int)j, (int)m, (int)m, values[j]);
2749       }
2750 #endif
2751
2752     if (macro->NumberOfParameters == 0 && n == 1)
2753       {
2754       const char *tp = values[0];
2755       preproc_skip_whitespace(&tp, WS_NO_EOL);
2756       if (tp + 1 >= values[1])
2757         {
2758         n = 0;
2759         }
2760       }
2761
2762     if (n != macro->NumberOfParameters)
2763       {
2764       if (values != stack_values) { free((char **)values); }
2765 #if PREPROC_DEBUG
2766       fprintf(stderr, "wrong number of macro args to %s, %lu != %lu\n",
2767               macro->Name, n, macro->NumberOfParameters);
2768 #endif
2769       return NULL;
2770       }
2771     }
2772
2773   cp = macro->Definition;
2774   cp = (cp ? cp : "");
2775   dp = cp;
2776   rp = stack_rp;
2777   rp[0] = '\0';
2778   rs = 128;
2779
2780   while (*cp != '\0')
2781     {
2782     pp = cp;
2783     wp = cp;
2784     stringify = 0;
2785     noexpand = 0;
2786     /* skip all chars that aren't part of a name */
2787     while (!preproc_chartype(*cp, CPRE_ID) && *cp != '\0')
2788       {
2789       dp = cp;
2790       preproc_skip_whitespace(&cp, WS_NO_EOL);
2791       if (cp > dp)
2792         {
2793         dp = cp;
2794         }
2795       else if (preproc_chartype(*cp, CPRE_QUOTE))
2796         {
2797         preproc_skip_quotes(&cp);
2798         dp = cp;
2799         wp = cp;
2800         noexpand = 0;
2801         }
2802       else if (preproc_chartype(*cp, CPRE_DIGIT))
2803         {
2804         preproc_skip_number(&cp);
2805         dp = cp;
2806         wp = cp;
2807         noexpand = 0;
2808         }
2809       else if (cp[0] == '#' && cp[1] == '#')
2810         {
2811         noexpand = 1;
2812         dp = wp;
2813         cp += 2;
2814         wp = cp;
2815         preproc_skip_whitespace(&cp, WS_NO_EOL);
2816         break;
2817         }
2818       else if (*cp == '#')
2819         {
2820         stringify = 1;
2821         dp = cp;
2822         wp = cp;
2823         cp++;
2824         preproc_skip_whitespace(&cp, WS_NO_EOL);
2825         break;
2826         }
2827       else
2828         {
2829         cp++;
2830         dp = cp;
2831         wp = cp;
2832         }
2833       }
2834     l = dp - pp;
2835     if (l > 0)
2836       {
2837       if (i + l + 1 >= rs)
2838         {
2839         rs += rs + i + l + 1;
2840         if (rp != stack_rp)
2841           {
2842           rp = (char *)realloc(rp, rs);
2843           }
2844         else
2845           {
2846           rp = (char *)malloc(rs);
2847           memcpy(rp, stack_rp, i);
2848           }
2849         }
2850       strncpy(&rp[i], pp, l);
2851       i += l;
2852       rp[i] = '\0';
2853       }
2854
2855     /* get the name */
2856     pp = cp;
2857     preproc_skip_name(&cp);
2858     l = cp - pp;
2859     if (l > 0)
2860       {
2861       for (j = 0; j < n; j++)
2862         {
2863         /* check whether the name matches a parameter */
2864         if (strncmp(pp, macro->Parameters[j], l) == 0 &&
2865             macro->Parameters[j][l] == '\0')
2866           {
2867           /* substitute the argument value */
2868           l = values[j+1] - values[j] - 1;
2869           pp = values[j];
2870           /* remove leading whitespace from argument */
2871           c = *pp;
2872           while (preproc_chartype(c, CPRE_WHITE))
2873             {
2874             c = *(++pp);
2875             l--;
2876             }
2877           /* remove trailing whitespace from argument */
2878           if (l > 0)
2879             {
2880             c = pp[l - 1];
2881             while (preproc_chartype(c, CPRE_WHITE))
2882               {
2883               if (--l == 0)
2884                 {
2885                 break;
2886                 }
2887               c = pp[l-1];
2888               }
2889             }
2890           /* check if followed by "##" */
2891           wp = cp;
2892           preproc_skip_whitespace(&wp, WS_NO_EOL);
2893           if (wp[0] == '#' && wp[1] == '#')
2894             {
2895             noexpand = 1;
2896             }
2897           break;
2898           }
2899         }
2900       if (stringify)
2901         {
2902         /* compute number of chars that will be added */
2903         stringify = 2;
2904         for (k = 0; k < l; k++)
2905           {
2906           c = pp[k];
2907           if (c == '\\' || c == '\"')
2908             {
2909             stringify++;
2910             }
2911           }
2912         }
2913       if (i + l + stringify + 1 >= rs)
2914         {
2915         rs += rs + i + l + 1;
2916         if (rp != stack_rp)
2917           {
2918           rp = (char *)realloc(rp, rs);
2919           }
2920         else
2921           {
2922           rp = (char *)malloc(rs);
2923           memcpy(rp, stack_rp, i);
2924           }
2925         }
2926       if (stringify)
2927         {
2928         rp[i++] = '\"';
2929         for (k = 0; k < l; k++)
2930           {
2931           c = pp[k];
2932           if (c == '\\' || c == '\"')
2933             {
2934             rp[i++] = '\\';
2935             }
2936           rp[i++] = c;
2937           }
2938         rp[i++] = '\"';
2939         }
2940       else if (noexpand)
2941         {
2942         strncpy(&rp[i], pp, l);
2943         i += l;
2944         }
2945       else
2946         {
2947         /* process the arguments before substituting them */
2948         const char *text;
2949         int is_excluded = macro->IsExcluded;
2950         macro->IsExcluded = 1;
2951         strncpy(&rp[i], pp, l);
2952         rp[i + l] = '\0';
2953         text = vtkParsePreprocess_ProcessString(info, &rp[i]);
2954         if (text)
2955           {
2956           l = strlen(text);
2957           if (text != &rp[i])
2958             {
2959             char *tp = NULL;
2960             if (i + l + 1 >= rs)
2961               {
2962               rs += rs + i + l + 1;
2963               tp = rp;
2964               rp = (char *)malloc(rs);
2965               memcpy(rp, tp, i);
2966               }
2967             strncpy(&rp[i], text, l);
2968             vtkParsePreprocess_FreeProcessedString(info, text);
2969             if (tp && tp != stack_rp)
2970               {
2971               free(tp);
2972               }
2973             }
2974           }
2975         macro->IsExcluded = is_excluded;
2976         i += l;
2977         }
2978       rp[i] = '\0';
2979       }
2980     }
2981
2982   if (values != stack_values) { free((char **)values); }
2983
2984   if (!macro->IsFunction && macro->Definition &&
2985       strcmp(rp, macro->Definition) == 0)
2986     {
2987     if (rp != stack_rp) { free(rp); }
2988     return macro->Definition;
2989     }
2990
2991   if (rp == stack_rp)
2992     {
2993     rp = (char *)malloc(strlen(stack_rp) + 1);
2994     strcpy(rp, stack_rp);
2995     }
2996
2997   return rp;
2998 }
2999
3000 /**
3001  * Process a string
3002  */
3003 const char *vtkParsePreprocess_ProcessString(
3004   PreprocessInfo *info, const char *text)
3005 {
3006   char stack_rp[128];
3007   char *rp;
3008   char *ep;
3009   size_t i = 0;
3010   size_t rs = 128;
3011   int last_tok = 0;
3012   preproc_tokenizer tokens;
3013   preproc_init(&tokens, text);
3014
3015   rp = stack_rp;
3016   rp[0] = '\0';
3017
3018   while (tokens.tok)
3019     {
3020     size_t l = tokens.len;
3021     size_t j;
3022     const char *cp = tokens.text;
3023     const char *dp;
3024
3025     if (tokens.tok == TOK_STRING && last_tok == TOK_STRING)
3026       {
3027       if (i > 0)
3028         {
3029         do { --i; } while (i > 0 && rp[i] != '\"');
3030         }
3031       cp++;
3032       }
3033
3034     if (i + l + 2 >= rs)
3035       {
3036       rs += rs + i + l + 2;
3037       if (rp == stack_rp)
3038         {
3039         rp = (char *)malloc(rs);
3040         memcpy(rp, stack_rp, i);
3041         }
3042       else
3043         {
3044         rp = (char *)realloc(rp, rs);
3045         }
3046       }
3047
3048     /* copy the token, removing backslash-newline */
3049     dp = cp;
3050     ep = &rp[i];
3051     for (j = 0; j < l; j++)
3052       {
3053       if (*dp == '\\')
3054         {
3055         if (dp[1] == '\n') { dp += 2; }
3056         else if (dp[1] == '\r' && dp[2] == '\n') { dp += 3; }
3057         else { *ep++ = *dp++; }
3058         }
3059       else
3060         {
3061         *ep++ = *dp++;
3062         }
3063       }
3064     l = ep - &rp[i];
3065
3066     if (tokens.tok == TOK_ID)
3067       {
3068       MacroInfo *macro = preproc_find_macro(info, &tokens);
3069       if (macro && !macro->IsExcluded)
3070         {
3071         const char *args = NULL;
3072         int expand = 1;
3073
3074         if (macro->IsFunction)
3075           {
3076           /* expand function macros using the arguments */
3077           preproc_next(&tokens);
3078           if (tokens.tok == '(')
3079             {
3080             int depth = 1;
3081             args = tokens.text;
3082             while (depth > 0 && preproc_next(&tokens))
3083               {
3084               if (tokens.tok == '(')
3085                 {
3086                 depth++;
3087                 }
3088               else if (tokens.tok == ')')
3089                 {
3090                 depth--;
3091                 }
3092               }
3093             if (tokens.tok != ')')
3094               {
3095               if (rp != stack_rp) { free(rp); }
3096               return NULL;
3097               }
3098             }
3099           else
3100             {
3101             /* unput the last token if it isn't "(" */
3102             tokens.len = l;
3103             tokens.text = cp;
3104             expand = 0;
3105             }
3106           }
3107         if (expand)
3108           {
3109           const char *expansion;
3110           const char *processed;
3111           expansion = vtkParsePreprocess_ExpandMacro(info, macro, args);
3112           if (expansion == NULL)
3113             {
3114             if (rp != stack_rp) { free(rp); }
3115             return NULL;
3116             }
3117           macro->IsExcluded = 1;
3118           processed = vtkParsePreprocess_ProcessString(info, expansion);
3119           macro->IsExcluded = 0;
3120           if (processed == NULL)
3121             {
3122             vtkParsePreprocess_FreeMacroExpansion(info, macro, expansion);
3123             if (rp != stack_rp) { free(rp); }
3124             return NULL;
3125             }
3126           l = strlen(processed);
3127           if (l > 0)
3128             {
3129             if (i + l + 2 >= rs)
3130               {
3131               rs += rs + i + l + 2;
3132               if (rp == stack_rp)
3133                 {
3134                 rp = (char *)malloc(rs);
3135                 memcpy(rp, stack_rp, i);
3136                 }
3137               else
3138                 {
3139                 rp = (char *)realloc(rp, rs);
3140                 }
3141               }
3142             strncpy(&rp[i], processed, l);
3143             }
3144           if (processed != expansion)
3145             {
3146             vtkParsePreprocess_FreeProcessedString(info, processed);
3147             }
3148           vtkParsePreprocess_FreeMacroExpansion(info, macro, expansion);
3149           }
3150         }
3151       }
3152
3153     i += l;
3154
3155     last_tok = tokens.tok;
3156     l = tokens.len;
3157     cp = tokens.text;
3158     if (preproc_next(&tokens) && tokens.text > cp + l)
3159       {
3160       rp[i++] = ' ';
3161       }
3162     }
3163   rp[i] = '\0';
3164
3165   if (strcmp(rp, text) == 0)
3166     {
3167     /* no change, return */
3168     if (rp != stack_rp) { free(rp); }
3169     return text;
3170     }
3171   else
3172     {
3173     /* string changed, recursively reprocess */
3174     const char *tp = vtkParsePreprocess_ProcessString(info, rp);
3175     if (rp != tp)
3176       {
3177       if (rp != stack_rp) { free(rp); }
3178       return tp;
3179       }
3180     if (rp == stack_rp)
3181       {
3182       rp = (char *)malloc(strlen(stack_rp) + 1);
3183       strcpy(rp, stack_rp);
3184       }
3185     }
3186
3187   return rp;
3188 }
3189
3190 /**
3191  * Free a string returned by ExpandMacro
3192  */
3193 void vtkParsePreprocess_FreeMacroExpansion(
3194   PreprocessInfo *info, MacroInfo *macro, const char *text)
3195 {
3196   /* only free expansion if it is different from definition */
3197   if (info && text != macro->Definition)
3198     {
3199     free((char *)text);
3200     }
3201 }
3202
3203 /**
3204  * Free a string returned by ProcessString
3205  */
3206 void vtkParsePreprocess_FreeProcessedString(
3207   PreprocessInfo *info, const char *text)
3208 {
3209   if (info)
3210     {
3211     free((char *)text);
3212     }
3213 }
3214
3215 /**
3216  * Add an include directory.
3217  */
3218 void vtkParsePreprocess_IncludeDirectory(
3219   PreprocessInfo *info, const char *name)
3220 {
3221   int i, n;
3222
3223   n = info->NumberOfIncludeDirectories;
3224   for (i = 0; i < n; i++)
3225     {
3226     if (strcmp(name, info->IncludeDirectories[i]) == 0)
3227       {
3228       return;
3229       }
3230     }
3231
3232   info->IncludeDirectories = (const char **)preproc_array_check(
3233     (char **)info->IncludeDirectories, sizeof(char *),
3234     info->NumberOfIncludeDirectories);
3235   info->IncludeDirectories[info->NumberOfIncludeDirectories++] =
3236     preproc_strndup(name, strlen(name));
3237 }
3238
3239 /**
3240  * Find an include file in the path.  If system_first is set,
3241  * then the current directory is not searched.
3242  */
3243 const char *vtkParsePreprocess_FindIncludeFile(
3244   PreprocessInfo *info, const char *filename, int system_first,
3245   int *already_loaded)
3246 {
3247   const char *cp;
3248   cp = preproc_find_include_file(info, filename, system_first, 1);
3249   if (cp)
3250     {
3251     *already_loaded = 1;
3252     return cp;
3253     }
3254
3255   *already_loaded = 0;
3256   return preproc_find_include_file(info, filename, system_first, 0);
3257 }
3258
3259 /**
3260  * Initialize a preprocessor macro struct
3261  */
3262 void vtkParsePreprocess_InitMacro(MacroInfo *macro)
3263 {
3264   macro->Name = NULL;
3265   macro->Definition = NULL;
3266   macro->Comment = NULL;
3267   macro->NumberOfParameters = 0;
3268   macro->Parameters = NULL;
3269   macro->IsFunction = 0;
3270   macro->IsExternal = 0;
3271   macro->IsExcluded = 0;
3272 }
3273
3274 /**
3275  * Free a preprocessor macro struct
3276  */
3277 void vtkParsePreprocess_FreeMacro(MacroInfo *macro)
3278 {
3279   int i, n;
3280
3281   free((char *)macro->Name);
3282   free((char *)macro->Definition);
3283   free((char *)macro->Comment);
3284
3285   n = macro->NumberOfParameters;
3286   for (i = 0; i < n; i++)
3287     {
3288     free((char *)macro->Parameters[i]);
3289     }
3290   free((char **)macro->Parameters);
3291
3292   free(macro);
3293 }
3294
3295 /**
3296  * Initialize a preprocessor struct
3297  */
3298 void vtkParsePreprocess_Init(
3299   PreprocessInfo *info, const char *filename)
3300 {
3301   info->FileName = NULL;
3302   info->MacroHashTable = NULL;
3303   info->NumberOfIncludeDirectories = 0;
3304   info->IncludeDirectories = NULL;
3305   info->NumberOfIncludeFiles = 0;
3306   info->IncludeFiles = NULL;
3307   info->IsExternal = 0;
3308   info->ConditionalDepth = 0;
3309   info->ConditionalDone = 0;
3310
3311   if (filename)
3312     {
3313     info->FileName = preproc_strndup(filename, strlen(filename));
3314     }
3315 }
3316
3317 /**
3318  * Free a preprocessor struct and its contents
3319  */
3320 void vtkParsePreprocess_Free(PreprocessInfo *info)
3321 {
3322   int i, n;
3323   MacroInfo **mptr;
3324
3325   free((char *)info->FileName);
3326
3327   if (info->MacroHashTable)
3328     {
3329     n = PREPROC_HASH_TABLE_SIZE;
3330     for (i = 0; i < n; i++)
3331       {
3332       mptr = info->MacroHashTable[i];
3333       if (mptr)
3334         {
3335         while (*mptr)
3336           {
3337           vtkParsePreprocess_FreeMacro(*mptr++);
3338           }
3339         }
3340       free(info->MacroHashTable[i]);
3341       }
3342     free(info->MacroHashTable);
3343     }
3344
3345   n = info->NumberOfIncludeDirectories;
3346   for (i = 0; i < n; i++)
3347     {
3348     free((char *)info->IncludeDirectories[i]);
3349     }
3350   free((char **)info->IncludeDirectories);
3351
3352   n = info->NumberOfIncludeFiles;
3353   for (i = 0; i < n; i++)
3354     {
3355     free((char *)info->IncludeFiles[i]);
3356     }
3357   free((char **)info->IncludeFiles);
3358
3359   free(info);
3360 }