Back to index

salome-paravis  6.5.0
vtkParsePreprocess.c
Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Program:   Visualization Toolkit
00004   Module:    vtkParsePreprocess.c
00005 
00006   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
00007   All rights reserved.
00008   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
00009 
00010      This software is distributed WITHOUT ANY WARRANTY; without even
00011      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00012      PURPOSE.  See the above copyright notice for more information.
00013 
00014 =========================================================================*/
00015 /*-------------------------------------------------------------------------
00016   Copyright (c) 2010 David Gobbi.
00017 
00018   Contributed to the VisualizationToolkit by the author in June 2010
00019   under the terms of the Visualization Toolkit 2008 copyright.
00020 -------------------------------------------------------------------------*/
00021 
00022 #include "vtkParsePreprocess.h"
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #include <stdio.h>
00026 #include <errno.h>
00027 #include <sys/stat.h>
00028 
00034 #define PREPROC_DEBUG 0
00035 
00037 enum _preproc_token_t
00038 {
00039   TOK_ID = 258,
00040   TOK_CHAR,
00041   TOK_STRING,
00042   TOK_NUMBER,
00043   TOK_AND,
00044   TOK_OR,
00045   TOK_NE,
00046   TOK_EQ,
00047   TOK_GE,
00048   TOK_LE,
00049   TOK_LSHIFT,
00050   TOK_RSHIFT,
00051   TOK_DBLHASH,
00052   TOK_ELLIPSIS,
00053   TOK_OTHER
00054 };
00055 
00057 typedef struct _preproc_tokenizer
00058 {
00059   int tok;
00060   size_t len;
00061   const char *text;
00062 } preproc_tokenizer;
00063 
00067 static void *preproc_array_check(
00068   void *arraymem, size_t size, int n)
00069 {
00070   /* if empty, alloc for the first time */
00071   if (n == 0)
00072     {
00073     return malloc(size);
00074     }
00075   /* if count is power of two, reallocate with double size */
00076   else if ((n & (n-1)) == 0)
00077     {
00078     return realloc(arraymem, (n << 1)*size);
00079     }
00080 
00081   /* no reallocation, just return the original array */
00082   return arraymem;
00083 }
00084 
00086 static preproc_int_t string_to_preproc_int(const char *cp, int base)
00087 {
00088 #if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
00089   return _strtoi64(cp, NULL, base);
00090 #else
00091   return strtoll(cp, NULL, base);
00092 #endif
00093 }
00094 
00096 static preproc_uint_t string_to_preproc_uint(const char *cp, int base)
00097 {
00098 #if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
00099   return _strtoui64(cp, NULL, base);
00100 #else
00101   return strtoull(cp, NULL, base);
00102 #endif
00103 }
00104 
00105 
00107 static void preproc_skip_comment(const char **cpp)
00108 {
00109   const char *cp = *cpp;
00110 
00111   if (cp[0] == '/')
00112     {
00113     if (cp[1] == '/')
00114       {
00115       cp += 2;
00116       while (*cp != '\n' && *cp != '\0')
00117         {
00118         if (cp[0] == '\\')
00119           {
00120           if (cp[1] == '\n') { cp++; }
00121           else if (cp[1] == '\r' && cp[2] == '\n') { cp += 2; }
00122           }
00123         cp++;
00124         }
00125       }
00126     else if (cp[1] == '*')
00127       {
00128       cp += 2;
00129       while (*cp != '\0')
00130         {
00131         if (cp[0] == '*' && cp[1] == '/') { cp += 2; break; }
00132         cp++;
00133         }
00134       }
00135     }
00136 
00137   *cpp = cp;
00138 }
00139 
00141 static void preproc_skip_whitespace(const char **cpp)
00142 {
00143   const char *cp = *cpp;
00144 
00145   for (;;)
00146     {
00147     while (*cp == ' ' || *cp == '\t' || *cp == '\r') { cp++; }
00148 
00149     if (cp[0] == '\\' && cp[1] == '\n')
00150       {
00151       cp += 2;
00152       }
00153     else if (cp[0] == '\\' && cp[1] == '\r' && cp[2] == '\n')
00154       {
00155       cp += 3;
00156       }
00157     else if (cp[0] == '/' && (cp[1] == '/' || cp[1] == '*'))
00158       {
00159       preproc_skip_comment(&cp);
00160       }
00161     else
00162       {
00163       break;
00164       }
00165     }
00166 
00167   *cpp = cp;
00168 }
00169 
00171 static void preproc_skip_quotes(const char **cpp)
00172 {
00173   const char *cp = *cpp;
00174   const char qc = *cp;
00175 
00176   if (*cp == '\'' || *cp == '\"')
00177     {
00178     cp++;
00179     while (*cp != qc && *cp != '\n' && *cp != '\0')
00180       {
00181       if (cp[0] == '\\' && cp[1] == qc) { cp++; }
00182       cp++;
00183       }
00184     }
00185   if (*cp == qc)
00186     {
00187     cp++;
00188     }
00189 
00190   *cpp = cp;
00191 }
00192 
00194 static void preproc_skip_name(const char **cpp)
00195 {
00196   const char *cp = *cpp;
00197 
00198   if ((*cp >= 'a' && *cp <= 'z') ||
00199       (*cp >= 'A' && *cp <= 'Z') ||
00200       (*cp == '_'))
00201     {
00202     cp++;
00203     while ((*cp >= '0' && *cp <= '9') ||
00204            (*cp >= 'a' && *cp <= 'z') ||
00205            (*cp >= 'A' && *cp <= 'Z') ||
00206            (*cp == '_'))
00207       {
00208       cp++;
00209       }
00210     }
00211 
00212   *cpp = cp;
00213 }
00214 
00216 static void preproc_skip_number(const char **cpp)
00217 {
00218   const char *cp = *cpp;
00219 
00220   if ((cp[0] >= '0' && cp[0] <= '9') ||
00221       (cp[0] == '.' && (cp[1] >= '0' && cp[1] <= '9')))
00222     {
00223     cp++;
00224     while ((*cp >= '0' && *cp <= '9') ||
00225            (*cp >= 'a' && *cp <= 'z') ||
00226            (*cp >= 'A' && *cp <= 'Z') ||
00227            *cp == '_' || *cp == '.')
00228       {
00229       char c = *cp++;
00230       if (c == 'e' || c == 'E' ||
00231           c == 'p' || c == 'P')
00232         {
00233         if (*cp == '-' || *cp == '+') { cp++; }
00234         }
00235       }
00236     }
00237 
00238   *cpp = cp;
00239 }
00240 
00242 static int preproc_next(preproc_tokenizer *tokens)
00243 {
00244   const char *cp = tokens->text + tokens->len;
00245   preproc_skip_whitespace(&cp);
00246   tokens->text = cp;
00247 
00248   if (cp[0] == '_' ||
00249       (cp[0] >= 'a' && cp[0] <= 'z') ||
00250       (cp[0] >= 'A' && cp[0] <= 'Z'))
00251     {
00252     const char *ep = cp;
00253     preproc_skip_name(&ep);
00254     tokens->len = ep - cp;
00255     tokens->tok = TOK_ID;
00256     }
00257   else if ((cp[0] >= '0' && cp[0] <= '9') ||
00258            (cp[0] == '.' && (cp[1] >= '0' && cp[1] <= '9')))
00259     {
00260     const char *ep = cp;
00261     preproc_skip_number(&ep);
00262     tokens->len = ep - cp;
00263     tokens->tok = TOK_NUMBER;
00264     }
00265   else if (cp[0] == '\'')
00266     {
00267     const char *ep = cp;
00268     preproc_skip_quotes(&ep);
00269     tokens->len = ep - cp;
00270     tokens->tok = TOK_CHAR;
00271     }
00272   else if (cp[0] == '\"')
00273     {
00274     const char *ep = cp;
00275     preproc_skip_quotes(&ep);
00276     tokens->len = ep - cp;
00277     tokens->tok = TOK_STRING;
00278     }
00279   else
00280     {
00281     switch (cp[0])
00282       {
00283       case ':':
00284         if (cp[1] == ':') { tokens->len = 2; tokens->tok = TOK_OTHER; }
00285         else { tokens->len = 1; tokens->tok = cp[0]; }
00286         break;
00287       case '.':
00288         if (cp[1] == '.' && cp[2] == '.')
00289           { tokens->len = 3; tokens->tok = TOK_ELLIPSIS; }
00290         else if (cp[1] == '*') { tokens->len = 2; tokens->tok = TOK_OTHER; }
00291         else { tokens->len = 1; tokens->tok = cp[0]; }
00292         break;
00293       case '=':
00294         if (cp[1] == '=') { tokens->len = 2; tokens->tok = TOK_EQ; }
00295         else { tokens->len = 1; tokens->tok = cp[0]; }
00296         break;
00297       case '!':
00298         if (cp[1] == '=') { tokens->len = 2; tokens->tok = TOK_NE; }
00299         else { tokens->len = 1; tokens->tok = cp[0]; }
00300         break;
00301       case '<':
00302         if (cp[1] == '<' && cp[2] == '=')
00303           { tokens->len = 3; tokens->tok = TOK_OTHER; }
00304         else if (cp[1] == '<') { tokens->len = 2; tokens->tok = TOK_RSHIFT; }
00305         else if (cp[1] == '=') { tokens->len = 2; tokens->tok = TOK_LE; }
00306         else { tokens->len = 1; tokens->tok = cp[0]; }
00307         break;
00308       case '>':
00309         if (cp[1] == '>' && cp[2] == '=')
00310           { tokens->len = 3; tokens->tok = TOK_OTHER; }
00311         else if (cp[1] == '>') { tokens->len = 2; tokens->tok = TOK_LSHIFT; }
00312         else if (cp[1] == '=') { tokens->len = 2; tokens->tok = TOK_GE; }
00313         else { tokens->len = 1; tokens->tok = cp[0]; }
00314         break;
00315       case '&':
00316         if (cp[1] == '&' && cp[2] == '=')
00317           { tokens->len = 3; tokens->tok = TOK_OTHER; }
00318         else if (cp[1] == '=') { tokens->len = 2; tokens->tok = TOK_OTHER; }
00319         else if (cp[1] == '&') { tokens->len = 2; tokens->tok = TOK_AND; }
00320         else { tokens->len = 1; tokens->tok = cp[0]; }
00321         break;
00322       case '|':
00323         if (cp[1] == '|' && cp[2] == '=')
00324           { tokens->len = 3; tokens->tok = TOK_OTHER; }
00325         else if (cp[1] == '=') { tokens->len = 2; tokens->tok = TOK_OTHER; }
00326         else if (cp[1] == '|') { tokens->len = 2; tokens->tok = TOK_OR; }
00327         else { tokens->len = 1; tokens->tok = cp[0]; }
00328         break;
00329       case '^': case '*': case '/': case '%':
00330         if (cp[1] == '=') { tokens->len = 2; tokens->tok = TOK_OTHER; }
00331         else { tokens->len = 1; tokens->tok = cp[0]; }
00332         break;
00333       case '+':
00334         if (cp[1] == '+') { tokens->len = 2; tokens->tok = TOK_OTHER; }
00335         else if (cp[1] == '=') { tokens->len = 2; tokens->tok = TOK_OTHER; }
00336         else { tokens->len = 1; tokens->tok = cp[0]; }
00337         break;
00338       case '-':
00339         if (cp[1] == '>' && cp[2] == '*')
00340           { tokens->len = 3; tokens->tok = TOK_OTHER; }
00341         else if (cp[1] == '>') { tokens->len = 2; tokens->tok = TOK_OTHER; }
00342         else if (cp[1] == '-') { tokens->len = 2; tokens->tok = TOK_OTHER; }
00343         else if (cp[1] == '=') { tokens->len = 2; tokens->tok = TOK_OTHER; }
00344         else { tokens->len = 1; tokens->tok = cp[0]; }
00345         break;
00346       case '#':
00347         if (cp[1] == '#') { tokens->len = 2; tokens->tok = TOK_DBLHASH; }
00348         else { tokens->len = 1; tokens->tok = cp[0]; }
00349         break;
00350       case '\n':
00351       case '\0':
00352         { tokens->len = 0; tokens->tok = 0; }
00353         break;
00354       default:
00355         { tokens->len = 1; tokens->tok = cp[0]; }
00356         break;
00357       }
00358     }
00359 
00360   return tokens->tok;
00361 }
00362 
00364 static void preproc_init(preproc_tokenizer *tokens, const char *text)
00365 {
00366   tokens->tok = 0;
00367   tokens->len = 0;
00368   tokens->text = text;
00369   preproc_next(tokens);
00370 }
00371 
00373 static const char *preproc_strndup(const char *in, size_t n)
00374 {
00375   char *res = NULL;
00376 
00377   res = (char *)malloc(n+1);
00378   strncpy(res, in, n);
00379   res[n] = '\0';
00380 
00381   return res;
00382 }
00383 
00385 static void preproc_free_macro(MacroInfo *info)
00386 {
00387   free(info);
00388 }
00389 
00391 static void preproc_add_macro(
00392   PreprocessInfo *info, MacroInfo *macro)
00393 {
00394   info->Macros = (MacroInfo **)preproc_array_check(
00395     info->Macros, sizeof(MacroInfo *), info->NumberOfMacros);
00396   info->Macros[info->NumberOfMacros++] = macro;
00397 }
00398 
00400 static MacroInfo *preproc_add_macro_definition(
00401   PreprocessInfo *info, const char *name, const char *definition)
00402 {
00403   MacroInfo *macro = (MacroInfo *)malloc(sizeof(MacroInfo));
00404   vtkParsePreprocess_InitMacro(macro);
00405 
00406   if (name)
00407     {
00408     size_t n;
00409     const char *cp = name;
00410     preproc_skip_name(&cp);
00411     n = cp - name;
00412     macro->Name = preproc_strndup(name, n);
00413     }
00414 
00415   if (definition)
00416     {
00417     size_t n;
00418     const char *cp = definition;
00419     preproc_tokenizer tokens;
00420     preproc_init(&tokens, cp);
00421 
00422     do
00423       {
00424       cp = tokens.text + tokens.len;
00425       }
00426     while (preproc_next(&tokens));
00427 
00428     n = cp - definition;
00429     macro->Definition = preproc_strndup(definition, n);
00430     }
00431 
00432   macro->IsExternal = info->IsExternal;
00433   preproc_add_macro(info, macro);
00434 
00435   return macro;
00436 }
00437 
00439 static int preproc_find_macro(
00440   PreprocessInfo *info, const char *name, int *idx)
00441 {
00442   int i, n;
00443   size_t m;
00444   const char *cp = name;
00445 
00446   preproc_skip_name(&cp);
00447   m = cp - name;
00448 
00449   n = info->NumberOfMacros;
00450   for (i = 0; i < n; i++)
00451     {
00452     if (strncmp(name, info->Macros[i]->Name, m) == 0 &&
00453         info->Macros[i]->Name[m] == '\0')
00454       {
00455       *idx = i;
00456       return 1;
00457       }
00458     }
00459 
00460   *idx = 0;
00461   return 0;
00462 }
00463 
00465 static int preproc_remove_macro(
00466   PreprocessInfo *info, const char *name)
00467 {
00468   int i, n;
00469 
00470   if (preproc_find_macro(info, name, &i))
00471     {
00472     preproc_free_macro(info->Macros[i]);
00473     n = info->NumberOfMacros-1;
00474     for (; i < n; i++)
00475       {
00476       info->Macros[i] = info->Macros[i+1];
00477       }
00478     info->NumberOfMacros = n;
00479     return 1;
00480     }
00481 
00482   return 0;
00483 }
00484 
00486 static int preproc_skip_parentheses(preproc_tokenizer *tokens)
00487 {
00488   int depth = 0;
00489 
00490   if (tokens->tok == '(')
00491     {
00492     depth = 1;
00493 
00494     while (depth > 0 && preproc_next(tokens))
00495       {
00496       if (tokens->tok == '(')
00497         {
00498         depth++;
00499         }
00500       else if (tokens->tok == ')')
00501         {
00502         depth--;
00503         }
00504       }
00505     }
00506 
00507   if (tokens->tok == ')')
00508     {
00509     preproc_next(tokens);
00510     return VTK_PARSE_OK;
00511     }
00512 
00513   return VTK_PARSE_SYNTAX_ERROR;
00514 }
00515 
00516 
00518 static int preproc_evaluate_char(
00519   const char *cp, preproc_int_t *val, int *is_unsigned)
00520 {
00521   if (cp[0] == '\'')
00522     {
00523     cp++;
00524     if (*cp != '\\')
00525       {
00526       *val = *cp;
00527       }
00528     else if (*cp != '\'' && *cp != '\n' && *cp != '\0')
00529       {
00530       cp++;
00531       if (*cp == 'a') { *val = '\a'; }
00532       else if (*cp == 'b') { *val = '\b'; }
00533       else if (*cp == 'f') { *val = '\f'; }
00534       else if (*cp == 'n') { *val = '\n'; }
00535       else if (*cp == 'r') { *val = '\r'; }
00536       else if (*cp == 'b') { *val = '\b'; }
00537       else if (*cp == 't') { *val = '\t'; }
00538       else if (*cp == 'v') { *val = '\v'; }
00539       else if (*cp == '\'') { *val = '\''; }
00540       else if (*cp == '\"') { *val = '\"'; }
00541       else if (*cp == '\\') { *val = '\\'; }
00542       else if (*cp == '\?') { *val = '\?'; }
00543       else if (*cp == '0')
00544         {
00545         *val = string_to_preproc_int(cp, 8);
00546         while (*cp >= '0' && *cp <= '7') { cp++; }
00547         }
00548       else if (*cp == 'x')
00549         {
00550         cp++;
00551         *val = string_to_preproc_int(cp, 16);
00552         while ((*cp >= '0' && *cp <= '9') ||
00553                (*cp >= 'a' && *cp <= 'z') ||
00554                (*cp >= 'A' && *cp <= 'Z')) { cp++; }
00555         }
00556       }
00557     if (*cp != '\'')
00558       {
00559 #if PREPROC_DEBUG
00560       fprintf(stderr, "syntax error %d\n", __LINE__);
00561 #endif
00562       return VTK_PARSE_SYNTAX_ERROR;
00563       }
00564     cp++;
00565     *is_unsigned = 0;
00566     return VTK_PARSE_OK;
00567     }
00568 
00569 #if PREPROC_DEBUG
00570   fprintf(stderr, "syntax error %d\n", __LINE__);
00571 #endif
00572   return VTK_PARSE_SYNTAX_ERROR;
00573 }
00574 
00575 /* Evaluate an integer, ignoring any suffixes except 'u'. */
00576 static int preproc_evaluate_integer(
00577   const char *cp, preproc_int_t *val, int *is_unsigned)
00578 {
00579   const char *ep;
00580   int base = 0;
00581   ep = cp;
00582 
00583   if (cp[0] == '0' && (cp[1] == 'x' || cp[1] == 'X'))
00584     {
00585     cp += 2;
00586     base = 16;
00587     *is_unsigned = 1;
00588     ep = cp;
00589     while ((*ep >= '0' && *ep <= '9') ||
00590            (*ep >= 'a' && *ep <= 'f') ||
00591            (*ep >= 'A' && *ep <= 'F'))
00592       {
00593       ep++;
00594       }
00595     }
00596   else if (cp[0] == '0' && (cp[1] >= '0' && cp[1] <= '9'))
00597     {
00598     cp += 1;
00599     base = 8;
00600     *is_unsigned = 1;
00601     ep = cp;
00602     while (*ep >= '0' && *ep <= '7')
00603       {
00604       ep++;
00605       }
00606     }
00607   else
00608     {
00609     base = 10;
00610     *is_unsigned = 0;
00611     while (*ep >= '0' && *ep <= '9')
00612       {
00613       ep++;
00614       }
00615     }
00616 
00617   for (;;)
00618     {
00619     if (ep[0] == 'i' && ep[1] == '6' && ep[2] == '4') { ep += 3; }
00620     else if (*ep == 'u') { *is_unsigned = 1; ep++; }
00621     else if (*ep == 'l' || *ep == 'L') { ep++; }
00622     else { break; }
00623     }
00624 
00625   if (*is_unsigned)
00626     {
00627     *val = (preproc_int_t)string_to_preproc_uint(cp, base);
00628     }
00629   else
00630     {
00631     *val = string_to_preproc_int(cp, base);
00632     }
00633 
00634   if (*ep == '.' || *ep == 'e' || *ep == 'E')
00635     {
00636     return VTK_PARSE_PREPROC_DOUBLE;
00637     }
00638 
00639   return VTK_PARSE_OK;
00640 }
00641 
00642 /* forward declaration */
00643 static int preproc_evaluate_expression(
00644   PreprocessInfo *info, preproc_tokenizer *tokens,
00645   preproc_int_t *val, int *is_unsigned);
00646 
00648 static int preproc_evaluate_single(
00649   PreprocessInfo *info, preproc_tokenizer *tokens,
00650   preproc_int_t *val, int *is_unsigned)
00651 {
00652   int result = VTK_PARSE_OK;
00653 
00654   if (tokens->tok == '(')
00655     {
00656     preproc_next(tokens);
00657     result = preproc_evaluate_expression(info, tokens, val, is_unsigned);
00658     if ((result & VTK_PARSE_FATAL_ERROR) == 0)
00659       {
00660       if (tokens->tok == ')')
00661         {
00662         preproc_next(tokens);
00663         return result;
00664         }
00665 #if PREPROC_DEBUG
00666       fprintf(stderr, "syntax error %d\n", __LINE__);
00667 #endif
00668       return VTK_PARSE_SYNTAX_ERROR;
00669       }
00670     return result;
00671     }
00672   else if (tokens->tok == TOK_ID)
00673     {
00674     if (strncmp("defined", tokens->text, tokens->len) == 0)
00675       {
00676       const char *name;
00677       int paren = 0;
00678       preproc_next(tokens);
00679 
00680       if (tokens->tok == '(')
00681         {
00682         paren = 1;
00683         preproc_next(tokens);
00684         }
00685       if (tokens->tok != TOK_ID)
00686         {
00687 #if PREPROC_DEBUG
00688         fprintf(stderr, "syntax error %d\n", __LINE__);
00689 #endif
00690         return VTK_PARSE_SYNTAX_ERROR;
00691         }
00692       name = tokens->text;
00693       preproc_next(tokens);
00694       if (paren)
00695         {
00696         if (tokens->tok != ')')
00697           {
00698 #if PREPROC_DEBUG
00699           fprintf(stderr, "syntax error %d\n", __LINE__);
00700 #endif
00701           return VTK_PARSE_SYNTAX_ERROR;
00702           }
00703         preproc_next(tokens);
00704         }
00705 
00706       /* do the name lookup */
00707       *is_unsigned = 0;
00708       *val = (vtkParsePreprocess_GetMacro(info, name) != NULL);
00709 
00710       return result;
00711       }
00712     else
00713       {
00714       /* look up and evaluate the macro */
00715       const char *name = tokens->text;
00716       MacroInfo *macro = vtkParsePreprocess_GetMacro(info, name);
00717       preproc_next(tokens);
00718 
00719       if (macro == NULL)
00720         {
00721         *val = 0;
00722         *is_unsigned = 0;
00723         return VTK_PARSE_MACRO_UNDEFINED;
00724         }
00725       else if (macro->IsFunction)
00726         {
00727         /* expand function macros using the arguments */
00728         if (tokens->tok == '(')
00729           {
00730           const char *args = tokens->text;
00731           *val = 0;
00732           *is_unsigned = 0;
00733           if (preproc_skip_parentheses(tokens) == VTK_PARSE_OK)
00734             {
00735             const char *expansion;
00736             expansion = vtkParsePreprocess_ExpandMacro(macro, args);
00737             if (expansion)
00738               {
00739               result = vtkParsePreprocess_EvaluateExpression(
00740                 info, expansion, val, is_unsigned);
00741               vtkParsePreprocess_FreeExpandedMacro(expansion);
00742               return result;
00743               }
00744 #if PREPROC_DEBUG
00745             fprintf(stderr, "wrong number of macro args %d\n", __LINE__);
00746 #endif
00747             }
00748 #if PREPROC_DEBUG
00749           fprintf(stderr, "syntax error %d\n", __LINE__);
00750 #endif
00751           return VTK_PARSE_SYNTAX_ERROR;
00752           }
00753         else
00754           {
00755 #if PREPROC_DEBUG
00756           fprintf(stderr, "syntax error %d\n", __LINE__);
00757 #endif
00758           return VTK_PARSE_SYNTAX_ERROR;
00759           }
00760         }
00761 
00762       return vtkParsePreprocess_EvaluateExpression(
00763         info, macro->Definition, val, is_unsigned);
00764       }
00765     }
00766   else if (tokens->tok == TOK_NUMBER)
00767     {
00768     result = preproc_evaluate_integer(tokens->text, val, is_unsigned);
00769     if (tokens->text[tokens->len-1] == 'f' ||
00770         tokens->text[tokens->len-1] == 'F')
00771       {
00772       result = VTK_PARSE_PREPROC_FLOAT;
00773       }
00774     preproc_next(tokens);
00775     return result;
00776     }
00777   else if (tokens->tok == TOK_CHAR)
00778     {
00779     result = preproc_evaluate_char(tokens->text, val, is_unsigned);
00780     preproc_next(tokens);
00781     return result;
00782     }
00783   else if (tokens->tok == TOK_STRING)
00784     {
00785     *val = 0;
00786     *is_unsigned = 0;
00787     preproc_next(tokens);
00788     return VTK_PARSE_PREPROC_STRING;
00789     }
00790 
00791 #if PREPROC_DEBUG
00792   fprintf(stderr, "syntax error %d \"%*.*s\"\n", __LINE__,
00793           (int)tokens->len, (int)tokens->len, tokens->text);
00794 #endif
00795   return VTK_PARSE_SYNTAX_ERROR;
00796 }
00797 
00798 static int preproc_evaluate_unary(
00799   PreprocessInfo *info, preproc_tokenizer *tokens,
00800   preproc_int_t *val, int *is_unsigned)
00801 {
00802   int op = tokens->tok;
00803   int result = VTK_PARSE_OK;
00804 
00805   if (op != '+' && op != '-' && op != '~' && op != '!')
00806     {
00807     return preproc_evaluate_single(info, tokens, val, is_unsigned);
00808     }
00809 
00810   preproc_next(tokens);
00811 
00812   result = preproc_evaluate_unary(info, tokens, val, is_unsigned);
00813   if ((result & VTK_PARSE_FATAL_ERROR) == 0)
00814     {
00815     if (op == '~') { *val = ~(*val); }
00816     else if (op == '!') { *val = !(*val); *is_unsigned = 0; }
00817     else if (op == '-') { *val = -(*val); }
00818     return result;
00819     }
00820 
00821   return result;
00822 }
00823 
00824 static int preproc_evaluate_multiply(
00825   PreprocessInfo *info, preproc_tokenizer *tokens,
00826   preproc_int_t *val, int *is_unsigned)
00827 {
00828   int op;
00829   preproc_int_t rval;
00830   int rtype;
00831   int result;
00832 
00833   result = preproc_evaluate_unary(info, tokens, val, is_unsigned);
00834   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
00835     {
00836     op = tokens->tok;
00837     if (op != '*' && op != '/' && op != '%')
00838       {
00839       return result;
00840       }
00841 
00842     preproc_next(tokens);
00843 
00844     result = preproc_evaluate_unary(info, tokens, &rval, &rtype);
00845 
00846     *is_unsigned = (*is_unsigned || rtype);
00847 
00848     if (*is_unsigned)
00849       {
00850       if (op == '*')
00851         {
00852         *val = (preproc_int_t)((preproc_uint_t)*val *
00853                                 (preproc_uint_t)rval);
00854         }
00855       else if (op == '/')
00856         {
00857         if (rval != 0)
00858           {
00859           *val = (preproc_int_t)((preproc_uint_t)*val /
00860                                  (preproc_uint_t)rval);
00861           }
00862         else
00863           {
00864           *val = 2147483647;
00865           }
00866         }
00867       else if (op == '%')
00868         {
00869         if (rval != 0)
00870           {
00871           *val = (preproc_int_t)((preproc_uint_t)*val %
00872                                   (preproc_uint_t)rval);
00873           }
00874         else
00875           {
00876           *val = 2147483647;
00877           }
00878         }
00879       }
00880     else
00881       {
00882       if (op == '*')
00883         {
00884         *val = *val * rval;
00885         }
00886       else if (op == '/')
00887         {
00888         if (rval != 0)
00889           {
00890           *val = *val / rval;
00891           }
00892         else if (*val < 0)
00893           {
00894           *val = -2147483647;
00895           }
00896         else
00897           {
00898           *val = 2147483647;
00899           }
00900         }
00901       else if (op == '%')
00902         {
00903         if (rval != 0)
00904           {
00905           *val = *val % rval;
00906           }
00907         else if (*val < 0)
00908           {
00909           *val = -2147483647;
00910           }
00911         else
00912           {
00913           *val = 2147483647;
00914           }
00915         }
00916       }
00917     }
00918 
00919   return result;
00920 }
00921 
00922 static int preproc_evaluate_add(
00923   PreprocessInfo *info, preproc_tokenizer *tokens,
00924   preproc_int_t *val, int *is_unsigned)
00925 {
00926   int op;
00927   preproc_int_t rval;
00928   int rtype;
00929   int result;
00930 
00931   result = preproc_evaluate_multiply(info, tokens, val, is_unsigned);
00932   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
00933     {
00934     op = tokens->tok;
00935     if (op != '+' && op != '-')
00936       {
00937       return result;
00938       }
00939 
00940     preproc_next(tokens);
00941 
00942     result = preproc_evaluate_multiply(info, tokens, &rval, &rtype);
00943 
00944     *is_unsigned = (*is_unsigned || rtype);
00945 
00946     if (op == '+')
00947       {
00948       *val = *val + rval;
00949       }
00950     else if (op == '-')
00951       {
00952       *val = *val - rval;
00953       }
00954     }
00955 
00956   return result;
00957 }
00958 
00959 static int preproc_evaluate_bitshift(
00960   PreprocessInfo *info, preproc_tokenizer *tokens,
00961   preproc_int_t *val, int *is_unsigned)
00962 {
00963   int op;
00964   preproc_int_t rval;
00965   int rtype;
00966   int result;
00967 
00968   result = preproc_evaluate_add(info, tokens, val, is_unsigned);
00969   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
00970     {
00971     op = tokens->tok;
00972 
00973     if (op != TOK_RSHIFT && op != TOK_LSHIFT)
00974       {
00975       return result;
00976       }
00977 
00978     preproc_next(tokens);
00979 
00980     result = preproc_evaluate_add(info, tokens, &rval, &rtype);
00981 
00982     if (*is_unsigned)
00983       {
00984       if (op == TOK_RSHIFT)
00985         {
00986         *val = (preproc_int_t)((preproc_uint_t)*val << rval);
00987         }
00988       else if (op == TOK_LSHIFT)
00989         {
00990         *val = (preproc_int_t)((preproc_uint_t)*val >> rval);
00991         }
00992       }
00993     else
00994       {
00995       if (op == TOK_RSHIFT)
00996         {
00997         *val = *val << rval;
00998         }
00999       else if (op == TOK_LSHIFT)
01000         {
01001         *val = *val >> rval;
01002         }
01003       }
01004     }
01005 
01006   return result;
01007 }
01008 
01009 static int preproc_evaluate_compare(
01010   PreprocessInfo *info, preproc_tokenizer *tokens,
01011   preproc_int_t *val, int *is_unsigned)
01012 {
01013   int op;
01014   preproc_int_t rval;
01015   int rtype;
01016   int result;
01017 
01018   result = preproc_evaluate_bitshift(info, tokens, val, is_unsigned);
01019   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
01020     {
01021     op = tokens->tok;
01022     if (op != '<' && op != '>' && op != TOK_LE && op != TOK_GE)
01023       {
01024       return result;
01025       }
01026 
01027     preproc_next(tokens);
01028 
01029     result = preproc_evaluate_bitshift(info, tokens, &rval, &rtype);
01030 
01031     *is_unsigned = (*is_unsigned || rtype);
01032 
01033     if (*is_unsigned)
01034       {
01035       if (op == TOK_LE)
01036         {
01037         *val = ((preproc_uint_t)*val <= (preproc_uint_t)rval);
01038         }
01039       else if (op == '<')
01040         {
01041         *val = ((preproc_uint_t)*val < (preproc_uint_t)rval);
01042         }
01043       else if (op == TOK_GE)
01044         {
01045         *val = ((preproc_uint_t)*val >= (preproc_uint_t)rval);
01046         }
01047       else if (op == '>')
01048         {
01049         *val = ((preproc_uint_t)*val > (preproc_uint_t)rval);
01050         }
01051       }
01052     else
01053       {
01054       if (op == TOK_LE)
01055         {
01056         *val = (*val <= rval);
01057         }
01058       else if (op == '<')
01059         {
01060         *val = (*val < rval);
01061         }
01062       else if (op == TOK_GE)
01063         {
01064         *val = (*val >= rval);
01065         }
01066       else if (op == '>')
01067         {
01068         *val = (*val > rval);
01069         }
01070       }
01071     *is_unsigned = 0;
01072     }
01073 
01074   return result;
01075 }
01076 
01077 static int preproc_evaluate_equal(
01078   PreprocessInfo *info, preproc_tokenizer *tokens,
01079   preproc_int_t *val, int *is_unsigned)
01080 {
01081   int op;
01082   preproc_int_t rval;
01083   int rtype;
01084   int result;
01085 
01086   result = preproc_evaluate_compare(info, tokens, val, is_unsigned);
01087   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
01088     {
01089     op = tokens->tok;
01090     if (op != TOK_EQ && op != TOK_NE)
01091       {
01092       return result;
01093       }
01094 
01095     preproc_next(tokens);
01096 
01097     result = preproc_evaluate_compare(info, tokens, &rval, &rtype);
01098 
01099     if (op == TOK_EQ)
01100       {
01101       *val = (*val == rval);
01102       }
01103     else if (op == TOK_NE)
01104       {
01105       *val = (*val != rval);
01106       }
01107     *is_unsigned = 0;
01108     }
01109 
01110   return result;
01111 }
01112 
01113 static int preproc_evaluate_and(
01114   PreprocessInfo *info, preproc_tokenizer *tokens,
01115   preproc_int_t *val, int *is_unsigned)
01116 {
01117   preproc_int_t rval;
01118   int rtype;
01119   int result;
01120 
01121   result = preproc_evaluate_equal(info, tokens, val, is_unsigned);
01122   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
01123     {
01124     if (tokens->tok != '&')
01125       {
01126       return result;
01127       }
01128 
01129     preproc_next(tokens);
01130 
01131     result = preproc_evaluate_equal(info, tokens, &rval, &rtype);
01132 
01133     *is_unsigned = (*is_unsigned || rtype);
01134     *val = (*val & rval);
01135     }
01136 
01137   return result;
01138 }
01139 
01140 static int preproc_evaluate_xor(
01141   PreprocessInfo *info, preproc_tokenizer *tokens,
01142   preproc_int_t *val, int *is_unsigned)
01143 {
01144   preproc_int_t rval;
01145   int rtype;
01146   int result;
01147 
01148   result = preproc_evaluate_and(info, tokens, val, is_unsigned);
01149   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
01150     {
01151     if (tokens->tok != '^')
01152       {
01153       return result;
01154       }
01155 
01156     preproc_next(tokens);
01157 
01158     result = preproc_evaluate_and(info, tokens, &rval, &rtype);
01159 
01160     *is_unsigned = (*is_unsigned || rtype);
01161     *val = (*val ^ rval);
01162     }
01163 
01164   return result;
01165 }
01166 
01167 static int preproc_evaluate_or(
01168   PreprocessInfo *info, preproc_tokenizer *tokens,
01169   preproc_int_t *val, int *is_unsigned)
01170 {
01171   preproc_int_t rval;
01172   int rtype;
01173   int result;
01174 
01175   result = preproc_evaluate_xor(info, tokens, val, is_unsigned);
01176   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
01177     {
01178     if (tokens->tok != '|')
01179       {
01180       return result;
01181       }
01182 
01183     preproc_next(tokens);
01184 
01185     result = preproc_evaluate_xor(info, tokens, &rval, &rtype);
01186 
01187     *is_unsigned = (*is_unsigned || rtype);
01188     *val = (*val | rval);
01189     }
01190 
01191   return result;
01192 }
01193 
01194 static int preproc_evaluate_logic_and(
01195   PreprocessInfo *info, preproc_tokenizer *tokens,
01196   preproc_int_t *val, int *is_unsigned)
01197 {
01198   preproc_int_t rval;
01199   int rtype;
01200   int result;
01201 
01202   result = preproc_evaluate_or(info, tokens, val, is_unsigned);
01203   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
01204     {
01205     if (tokens->tok != TOK_AND)
01206       {
01207       return result;
01208       }
01209 
01210     preproc_next(tokens);
01211 
01212     if (*val == 0)
01213       {
01214       /* short circuit */
01215       while (tokens->tok != 0 && tokens->tok != ')' &&
01216              tokens->tok != ':' && tokens->tok != '?' &&
01217              tokens->tok != TOK_OR && tokens->tok != TOK_OTHER)
01218         {
01219         if (tokens->tok == '(')
01220           {
01221           if (preproc_skip_parentheses(tokens) != VTK_PARSE_OK)
01222             {
01223 #if PREPROC_DEBUG
01224             fprintf(stderr, "syntax error %d\n", __LINE__);
01225 #endif
01226             result = VTK_PARSE_SYNTAX_ERROR;
01227             }
01228           }
01229         else
01230           {
01231           preproc_next(tokens);
01232           }
01233         }
01234 
01235       *is_unsigned = 0;
01236 
01237       return result;
01238       }
01239 
01240     result = preproc_evaluate_or(info, tokens, &rval, &rtype);
01241 
01242     *is_unsigned = 0;
01243     *val = (rval != 0);
01244     }
01245 
01246   return result;
01247 }
01248 
01249 static int preproc_evaluate_logic_or(
01250   PreprocessInfo *info, preproc_tokenizer *tokens,
01251   preproc_int_t *val, int *is_unsigned)
01252 {
01253   preproc_int_t rval;
01254   int rtype;
01255   int result;
01256 
01257   result = preproc_evaluate_logic_and(info, tokens, val, is_unsigned);
01258   while ((result & VTK_PARSE_FATAL_ERROR) == 0)
01259     {
01260     if (tokens->tok != TOK_OR)
01261       {
01262       return result;
01263       }
01264 
01265     preproc_next(tokens);
01266 
01267     if (*val != 0)
01268       {
01269       /* short circuit */
01270       while (tokens->tok != 0 && tokens->tok != ')' &&
01271              tokens->tok != ':' && tokens->tok != '?' &&
01272              tokens->tok != TOK_OTHER)
01273         {
01274         if (tokens->tok == '(')
01275           {
01276           if (preproc_skip_parentheses(tokens) != VTK_PARSE_OK)
01277             {
01278 #if PREPROC_DEBUG
01279             fprintf(stderr, "syntax error %d\n", __LINE__);
01280 #endif
01281             result = VTK_PARSE_SYNTAX_ERROR;
01282             }
01283           }
01284         else
01285           {
01286           preproc_next(tokens);
01287           }
01288         }
01289 
01290       *is_unsigned = 0;
01291 
01292       return result;
01293       }
01294 
01295     result = preproc_evaluate_logic_and(info, tokens, &rval, &rtype);
01296 
01297     *is_unsigned = 0;
01298     *val = (rval != 0);
01299     }
01300 
01301   return result;
01302 }
01303 
01305 int preproc_evaluate_expression(
01306   PreprocessInfo *info, preproc_tokenizer *tokens,
01307   preproc_int_t *val, int *is_unsigned)
01308 {
01309   preproc_int_t rval, sval;
01310   int rtype, stype;
01311   int result;
01312 
01313   result = preproc_evaluate_logic_or(info, tokens, val, is_unsigned);
01314   if ((result & VTK_PARSE_FATAL_ERROR) == 0)
01315     {
01316     if (tokens->tok != '?')
01317       {
01318       return result;
01319       }
01320 
01321     preproc_next(tokens);
01322 
01323     result = preproc_evaluate_expression(info, tokens, &rval, &rtype);
01324     if ((result & VTK_PARSE_FATAL_ERROR) != 0)
01325       {
01326       return result;
01327       }
01328 
01329     if (tokens->tok != ':')
01330       {
01331 #if PREPROC_DEBUG
01332       fprintf(stderr, "syntax error %d\n", __LINE__);
01333 #endif
01334       return VTK_PARSE_SYNTAX_ERROR;
01335       }
01336 
01337     preproc_next(tokens);
01338 
01339     result = preproc_evaluate_expression(info, tokens, &sval, &stype);
01340     if ((result & VTK_PARSE_FATAL_ERROR) != 0)
01341       {
01342       return result;
01343       }
01344 
01345     if (*val != 0)
01346       {
01347       *val = rval;
01348       *is_unsigned = rtype;
01349       }
01350     else
01351       {
01352       *val = sval;
01353       *is_unsigned = stype;
01354       }
01355     }
01356 
01357   return result;
01358 }
01359 
01363 int preproc_evaluate_conditional(
01364   PreprocessInfo *info, preproc_tokenizer *tokens)
01365 {
01366   preproc_int_t rval;
01367   int rtype;
01368   int result;
01369 
01370   result = preproc_evaluate_expression(info, tokens, &rval, &rtype);
01371   if ((result & VTK_PARSE_FATAL_ERROR) == 0)
01372     {
01373     if (tokens->tok != 0)
01374       {
01375       return VTK_PARSE_SYNTAX_ERROR;
01376       }
01377     return (rval == 0 ? VTK_PARSE_SKIP : VTK_PARSE_OK);
01378     }
01379 
01380   return result;
01381 }
01382 
01389 static int preproc_evaluate_if(
01390   PreprocessInfo *info, preproc_tokenizer *tokens)
01391 {
01392   int v1, v2;
01393   int result = VTK_PARSE_OK;
01394 
01395   if (strncmp("if", tokens->text, tokens->len) == 0 ||
01396       strncmp("ifdef", tokens->text, tokens->len) == 0 ||
01397       strncmp("ifndef", tokens->text, tokens->len) == 0)
01398     {
01399     if (info->ConditionalDepth == 0)
01400       {
01401       if (strncmp("if", tokens->text, tokens->len) == 0)
01402         {
01403         preproc_next(tokens);
01404         result = preproc_evaluate_conditional(info, tokens);
01405         }
01406       else
01407         {
01408         v1 = (strncmp("ifndef", tokens->text, tokens->len) != 0);
01409         preproc_next(tokens);
01410         if (tokens->tok != TOK_ID)
01411           {
01412 #if PREPROC_DEBUG
01413           fprintf(stderr, "syntax error %d\n", __LINE__);
01414 #endif
01415           return VTK_PARSE_SYNTAX_ERROR;
01416           }
01417         v2 = (vtkParsePreprocess_GetMacro(info, tokens->text) != 0);
01418         preproc_next(tokens);
01419         result = ( (v1 ^ v2) ? VTK_PARSE_SKIP : VTK_PARSE_OK);
01420         }
01421 
01422       if (result != VTK_PARSE_SKIP)
01423         {
01424         /* mark as done, so that the "else" clause is skipped */
01425         info->ConditionalDone = 1;
01426         }
01427       else
01428         {
01429         /* mark as not done, so that "else" clause is not skipped */
01430         info->ConditionalDone = 0;
01431         /* skip the "if" clause */
01432         info->ConditionalDepth = 1;
01433         }
01434       }
01435     else
01436       {
01437       /* increase the skip depth */
01438       info->ConditionalDepth++;
01439       }
01440     }
01441   else if (strncmp("elif", tokens->text, tokens->len) == 0 ||
01442            strncmp("else", tokens->text, tokens->len) == 0)
01443     {
01444     if (info->ConditionalDepth == 0)
01445       {
01446       /* preceeding clause was not skipped, so must skip this one */
01447       info->ConditionalDepth = 1;
01448       }
01449     else if (info->ConditionalDepth == 1 &&
01450              info->ConditionalDone == 0)
01451       {
01452       if (strncmp("elif", tokens->text, tokens->len) == 0)
01453         {
01454         preproc_next(tokens);
01455         result = preproc_evaluate_conditional(info, tokens);
01456         }
01457       else
01458         {
01459         preproc_next(tokens);
01460         }
01461       if (result != VTK_PARSE_SKIP)
01462         {
01463         /* do not skip this clause */
01464         info->ConditionalDepth = 0;
01465         /* make sure remaining else/elif clauses are skipped */
01466         info->ConditionalDone = 1;
01467         }
01468       }
01469     }
01470   else if (strncmp("endif", tokens->text, tokens->len) == 0)
01471     {
01472     preproc_next(tokens);
01473     if (info->ConditionalDepth > 0)
01474       {
01475       /* decrease the skip depth */
01476       info->ConditionalDepth--;
01477       }
01478     if (info->ConditionalDepth == 0)
01479       {
01480       /* set "done" flag for the context that is being returned to */
01481       info->ConditionalDone = 1;
01482       }
01483     }
01484 
01485   return result;
01486 }
01487 
01491 static int preproc_evaluate_define(
01492   PreprocessInfo *info, preproc_tokenizer *tokens)
01493 {
01494   MacroInfo *macro;
01495   int is_function;
01496   const char *name;
01497   size_t namelen;
01498   const char *definition = "";
01499   int i;
01500   int n = 0;
01501   const char **args = NULL;
01502 
01503   if (strncmp("define", tokens->text, tokens->len) == 0)
01504     {
01505     preproc_next(tokens);
01506     if (tokens->tok != TOK_ID)
01507       {
01508 #if PREPROC_DEBUG
01509       fprintf(stderr, "syntax error %d\n", __LINE__);
01510 #endif
01511       return VTK_PARSE_SYNTAX_ERROR;
01512       }
01513 
01514     name = tokens->text;
01515     namelen = tokens->len;
01516     preproc_next(tokens);
01517 
01518     is_function = 0;
01519     if (name[namelen] == '(')
01520       {
01521       is_function = 1;
01522       preproc_next(tokens);
01523       while (tokens->tok != 0 && tokens->tok != ')')
01524         {
01525         if (tokens->tok != TOK_ID && tokens->tok != TOK_ELLIPSIS)
01526           {
01527           if (args) { free((char **)args); }
01528 #if PREPROC_DEBUG
01529           fprintf(stderr, "syntax error %d\n", __LINE__);
01530 #endif
01531           return VTK_PARSE_SYNTAX_ERROR;
01532           }
01533 
01534         /* add to the arg list */
01535         args = (const char **)preproc_array_check(
01536           (char **)args, sizeof(char *), n);
01537         args[n++] = preproc_strndup(tokens->text, tokens->len);
01538 
01539         preproc_next(tokens);
01540         if (tokens->tok == ',')
01541           {
01542           preproc_next(tokens);
01543           }
01544         else if (tokens->tok != ')')
01545           {
01546           if (args) { free((char **)args); }
01547 #if PREPROC_DEBUG
01548           fprintf(stderr, "syntax error %d\n", __LINE__);
01549 #endif
01550           return VTK_PARSE_SYNTAX_ERROR;
01551           }
01552         }
01553       preproc_next(tokens);
01554       }
01555 
01556     if (tokens->tok)
01557       {
01558       definition = tokens->text;
01559       }
01560     if (preproc_find_macro(info, name, &i))
01561       {
01562       if (args) { free((char **)args); }
01563 #if PREPROC_DEBUG
01564       fprintf(stderr, "macro redefined %d\n", __LINE__);
01565 #endif
01566       return VTK_PARSE_MACRO_REDEFINED;
01567       }
01568 
01569     macro = preproc_add_macro_definition(info, name, definition);
01570     macro->IsFunction = is_function;
01571     macro->NumberOfArguments = n;
01572     macro->Arguments = args;
01573     return VTK_PARSE_OK;
01574     }
01575   else if (strncmp("undef", tokens->text, tokens->len) == 0)
01576     {
01577     preproc_next(tokens);
01578     if (tokens->tok != TOK_ID)
01579       {
01580 #if PREPROC_DEBUG
01581       fprintf(stderr, "syntax error %d\n", __LINE__);
01582 #endif
01583       return VTK_PARSE_SYNTAX_ERROR;
01584       }
01585     name = tokens->text;
01586     preproc_remove_macro(info, name);
01587     return VTK_PARSE_OK;
01588     }
01589 
01590   return VTK_PARSE_OK;
01591 }
01592 
01596 static int preproc_add_include_file(PreprocessInfo *info, const char *name)
01597 {
01598   int i, n;
01599 
01600   n = info->NumberOfIncludeFiles;
01601   for (i = 0; i < n; i++)
01602     {
01603     if (strcmp(info->IncludeFiles[i], name) == 0)
01604       {
01605       return 0;
01606       }
01607     }
01608 
01609   info->IncludeFiles = (const char **)preproc_array_check(
01610     (char **)info->IncludeFiles, sizeof(char *), info->NumberOfIncludeFiles);
01611   info->IncludeFiles[info->NumberOfIncludeFiles++] = name;
01612 
01613   return 1;
01614 }
01615 
01620 const char *preproc_find_include_file(
01621   PreprocessInfo *info, const char *filename, int system_first,
01622   int cache_only)
01623 {
01624   int i, n, ii, nn;
01625   size_t j, m;
01626   struct stat fs;
01627   const char *directory;
01628   char *output;
01629   size_t outputsize = 16;
01630   int count;
01631 
01632   /* allow filename to be terminated by quote or bracket */
01633   m = 0;
01634   while (filename[m] != '\"' && filename[m] != '>' &&
01635          filename[m] != '\n' && filename[m] != '\0') { m++; }
01636 
01637   /* search file system for the file */
01638   output = (char *)malloc(outputsize);
01639 
01640   if (system_first != 0)
01641     {
01642     system_first = 1;
01643     }
01644 
01645   if (cache_only != 0)
01646     {
01647     cache_only = 1;
01648     }
01649 
01650   /* check for absolute path of form DRIVE: or /path/to/file */
01651   j = 0;
01652   while (filename[j] == '_' ||
01653          (filename[j] >= '0' && filename[j] <= '9') ||
01654          (filename[j] >= 'a' && filename[j] <= 'z') ||
01655          (filename[j] >= 'Z' && filename[j] <= 'Z')) { j++; }
01656 
01657   if (filename[j] == ':' || filename[0] == '/' || filename[0] == '\\')
01658     {
01659     if (m+1 > outputsize)
01660       {
01661       outputsize += m+1;
01662       output = (char *)realloc(output, outputsize);
01663       }
01664     strncpy(output, filename, m);
01665     output[m] = '\0';
01666 
01667     nn = info->NumberOfIncludeFiles;
01668     for (ii = 0; ii < nn; ii++)
01669       {
01670       if (strcmp(output, info->IncludeFiles[ii]) == 0)
01671         {
01672         free(output);
01673         return info->IncludeFiles[ii];
01674         }
01675       }
01676 
01677     if (cache_only)
01678       {
01679       free(output);
01680       return NULL;
01681       }
01682 
01683     info->IncludeFiles = (const char **)preproc_array_check(
01684       (char **)info->IncludeFiles, sizeof(char *),
01685       info->NumberOfIncludeFiles);
01686     info->IncludeFiles[info->NumberOfIncludeFiles++] = output;
01687 
01688     return output;
01689     }
01690 
01691   /* Make sure the current filename is already added */
01692   if (info->FileName)
01693     {
01694     preproc_add_include_file(info, info->FileName);
01695     }
01696 
01697   /* Check twice. First check the cache, then stat the files. */
01698   for (count = 0; count < (2-cache_only); count++)
01699     {
01700     n = info->NumberOfIncludeDirectories;
01701     for (i = 0; i < (n+1-system_first); i++)
01702       {
01703       /* search the directory of the file being processed */
01704       if (i == 0 && system_first == 0)
01705         {
01706         if (info->FileName)
01707           {
01708           j = strlen(info->FileName);
01709           while (j > 0)
01710             {
01711             if (info->FileName[j-1] == '/') { break; }
01712             j--;
01713             }
01714           if (m+j+1 > outputsize)
01715             {
01716             outputsize += m+j+1;
01717             output = (char *)realloc(output, outputsize);
01718             }
01719           if (j > 0)
01720             {
01721             strncpy(output, info->FileName, j);
01722             }
01723           strncpy(&output[j], filename, m);
01724           output[j+m] = '\0';
01725           }
01726         else
01727           {
01728           if (m+1 > outputsize)
01729             {
01730             outputsize += m+1;
01731             output = (char *)realloc(output, outputsize);
01732             }
01733           strncpy(output, filename, m);
01734           output[m] = '\0';
01735           }
01736         }
01737       /* check all the search paths */
01738       else
01739         {
01740         directory = info->IncludeDirectories[i-1+system_first];
01741         j = strlen(directory);
01742         if (j + m + 2 > outputsize)
01743           {
01744           outputsize += j+m+2;
01745           output = (char *)realloc(output, outputsize);
01746           }
01747 
01748         strncpy(output, directory, j);
01749         if (directory[j-1] != '/') { output[j++] = '/'; }
01750         strncpy(&output[j], filename, m);
01751         output[j+m] = '\0';
01752         }
01753 
01754       if (count == 0)
01755         {
01756         nn = info->NumberOfIncludeFiles;
01757         for (ii = 0; ii < nn; ii++)
01758           {
01759           if (strcmp(output, info->IncludeFiles[ii]) == 0)
01760             {
01761             free(output);
01762             return info->IncludeFiles[ii];
01763             }
01764           }
01765         }
01766       else if (stat(output, &fs) == 0)
01767         {
01768         info->IncludeFiles = (const char **)preproc_array_check(
01769           (char **)info->IncludeFiles, sizeof(char *),
01770           info->NumberOfIncludeFiles);
01771         info->IncludeFiles[info->NumberOfIncludeFiles++] = output;
01772 
01773         return output;
01774         }
01775       }
01776     }
01777 
01778   free(output);
01779   return NULL;
01780 }
01781 
01786 static int preproc_include_file(
01787   PreprocessInfo *info, const char *filename, int system_first)
01788 {
01789   char *tbuf;
01790   size_t tbuflen = 8192;
01791   char *line;
01792   size_t linelen = 80;
01793   size_t i, j, n;
01794   int in_comment = 0;
01795   int in_quote = 0;
01796   int result = VTK_PARSE_OK;
01797   FILE *fp = NULL;
01798   const char *path = NULL;
01799   const char *save_filename;
01800   int save_external;
01801 
01802   /* check to see if the file has aleady been included */
01803   path = preproc_find_include_file(info, filename, system_first, 1);
01804   if (path != 0)
01805     {
01806 #if PREPROC_DEBUG
01807     int k = 0;
01808     while (filename[k] != '>' && filename[k] != '\"' &&
01809            filename[k] != '\n' && filename[k] != '\0') { k++; }
01810     if (filename[k] == '>')
01811       fprintf(stderr, "already loaded file <%*.*s>\n", k, k, filename);
01812     else
01813       fprintf(stderr, "already loaded file \"%*.*s\"\n", k, k, filename);
01814 #endif
01815 
01816     return VTK_PARSE_OK;
01817     }
01818   /* go to the filesystem */
01819   path = preproc_find_include_file(info, filename, system_first, 0);
01820   if (path == NULL)
01821     {
01822 #if PREPROC_DEBUG
01823     int k = 0;
01824     while (filename[k] != '>' && filename[k] != '\"' &&
01825            filename[k] != '\n' && filename[k] != '\0') { k++; }
01826     if (filename[k] == '>')
01827       fprintf(stderr, "couldn't find file <%*.*s>\n", k, k, filename);
01828     else
01829       fprintf(stderr, "couldn't find file \"%*.*s\"\n", k, k, filename);
01830 #endif
01831     return VTK_PARSE_FILE_NOT_FOUND;
01832     }
01833 
01834 #if PREPROC_DEBUG
01835   fprintf(stderr, "including file %s\n", path);
01836 #endif
01837   fp = fopen(path, "r");
01838 
01839   if (fp == NULL)
01840     {
01841 #if PREPROC_DEBUG
01842     fprintf(stderr, "couldn't open file %s\n", path);
01843 #endif
01844     return VTK_PARSE_FILE_OPEN_ERROR;
01845     }
01846 
01847   save_external = info->IsExternal;
01848   save_filename = info->FileName;
01849   info->IsExternal = 1;
01850   info->FileName = path;
01851 
01852   tbuf = (char *)malloc(tbuflen);
01853   line = (char *)malloc(linelen);
01854 
01855   /* the buffer must hold a whole line for it to be processed */
01856   j = 0;
01857   i = 0;
01858   n = 0;
01859 
01860   do
01861     {
01862     if (i == n)
01863       {
01864       /* read the next chunk of the file */
01865       i = 0;
01866       if (feof(fp))
01867         {
01868         n = 0;
01869         }
01870       else
01871         {
01872         errno = 0;
01873         i = 0;
01874         while ((n = fread(tbuf, 1, tbuflen, fp)) == 0 && ferror(fp))
01875           {
01876           if (errno != EINTR)
01877             {
01878             fclose(fp);
01879             free(tbuf);
01880             free(line);
01881             info->IsExternal = save_external;
01882             return VTK_PARSE_FILE_READ_ERROR;
01883             }
01884           errno = 0;
01885           clearerr(fp);
01886           }
01887         }
01888       }
01889 
01890     /* copy the characters until end of line is found */
01891     while (i < n)
01892       {
01893       /* expand line buffer as necessary */
01894       if (j+4 > linelen)
01895         {
01896         linelen *= 2;
01897         line = (char *)realloc(line, linelen);
01898         }
01899 
01900       if (in_comment)
01901         {
01902         if (tbuf[i] == '*' && tbuf[i+1] == '/')
01903           {
01904           line[j++] = tbuf[i++];
01905           line[j++] = tbuf[i++];
01906           in_comment = 0;
01907           }
01908         else
01909           {
01910           line[j++] = tbuf[i++];
01911           }
01912         }
01913       else if (in_quote)
01914         {
01915         if (tbuf[i] == '\"')
01916           {
01917           line[j++] = tbuf[i++];
01918           in_quote = 0;
01919           }
01920         else if (tbuf[i] == '\\' && tbuf[i] == '\"')
01921           {
01922           line[j++] = tbuf[i++];
01923           line[j++] = tbuf[i++];
01924           }
01925         else
01926           {
01927           line[j++] = tbuf[i++];
01928           }
01929         }
01930       else if (tbuf[i] == '/' && tbuf[i] == '*')
01931         {
01932         line[j++] = tbuf[i++];
01933         line[j++] = tbuf[i++];
01934         in_comment = 1;
01935         }
01936       else if (tbuf[i] == '\"')
01937         {
01938         line[j++] = tbuf[i++];
01939         in_quote = 1;
01940         }
01941       else if (tbuf[i] == '\\' && tbuf[i+1] == '\n')
01942         {
01943         line[j++] = tbuf[i++];
01944         line[j++] = tbuf[i++];
01945         }
01946       else if (tbuf[i] == '\\' && tbuf[i+1] == '\r' && tbuf[i+2] == '\n')
01947         {
01948         line[j++] = tbuf[i++];
01949         line[j++] = tbuf[i++];
01950         line[j++] = tbuf[i++];
01951         }
01952       else if (tbuf[i] != '\n' && tbuf[i] != '\0')
01953         {
01954         line[j++] = tbuf[i++];
01955         }
01956       else
01957         {
01958         line[j++] = tbuf[i++];
01959         break;
01960         }
01961       }
01962 
01963     if (i < n || n == 0)
01964       {
01965       const char *cp = line;
01966       line[j] = '\0';
01967       j = 0;
01968       preproc_skip_whitespace(&cp);
01969       if (*cp == '#')
01970         {
01971         vtkParsePreprocess_HandleDirective(info, line);
01972         }
01973       }
01974     }
01975   while (n > 0);
01976 
01977   free(tbuf);
01978   free(line);
01979   fclose(fp);
01980 
01981   info->IsExternal = save_external;
01982   info->FileName = save_filename;
01983 
01984   return result;
01985 }
01986 
01991 static int preproc_evaluate_include(
01992   PreprocessInfo *info, preproc_tokenizer *tokens)
01993 {
01994   const char *cp;
01995   const char *filename;
01996 
01997   if (strncmp("include", tokens->text, tokens->len) == 0)
01998     {
01999     preproc_next(tokens);
02000 
02001     cp = tokens->text;
02002 
02003     if (tokens->tok == TOK_ID)
02004       {
02005       MacroInfo *macro;
02006       macro = vtkParsePreprocess_GetMacro(info, cp);
02007       if (macro && macro->Definition)
02008         {
02009         cp = macro->Definition;
02010         }
02011       else
02012         {
02013 #if PREPROC_DEBUG
02014         fprintf(stderr, "couldn't find macro %*.*s.\n",
02015                 (int)tokens->len, (int)tokens->len, tokens->text);
02016 #endif
02017         return VTK_PARSE_MACRO_UNDEFINED;
02018         }
02019       }
02020 
02021     if (*cp == '\"')
02022       {
02023       filename = cp + 1;
02024       preproc_skip_quotes(&cp);
02025       if (cp <= filename + 1 || *(cp-1) != '\"')
02026         {
02027         return VTK_PARSE_SYNTAX_ERROR;
02028         }
02029 
02030       return preproc_include_file(info, filename, 0);
02031       }
02032     else if (*cp == '<')
02033       {
02034       cp++;
02035       filename = cp;
02036       while (*cp != '>' && *cp != '\n' && *cp != '\0') { cp++; }
02037       if (*cp != '>')
02038         {
02039         return VTK_PARSE_SYNTAX_ERROR;
02040         }
02041 
02042       return preproc_include_file(info, filename, 1);
02043       }
02044     }
02045 
02046   return VTK_PARSE_OK;
02047 }
02048 
02053 int vtkParsePreprocess_HandleDirective(
02054   PreprocessInfo *info, const char *directive)
02055 {
02056   int result = VTK_PARSE_OK;
02057   preproc_tokenizer tokens;
02058 
02059   preproc_init(&tokens, directive);
02060 
02061   if (tokens.tok != '#')
02062     {
02063     return VTK_PARSE_SYNTAX_ERROR;
02064     }
02065 
02066   preproc_next(&tokens);
02067 
02068   if (tokens.tok == TOK_ID)
02069     {
02070     if (strncmp("ifdef", tokens.text, tokens.len) == 0 ||
02071         strncmp("ifndef", tokens.text, tokens.len) == 0 ||
02072         strncmp("if", tokens.text, tokens.len) == 0 ||
02073         strncmp("elif", tokens.text, tokens.len) == 0 ||
02074         strncmp("else", tokens.text, tokens.len) == 0 ||
02075         strncmp("endif", tokens.text, tokens.len) == 0)
02076       {
02077       result = preproc_evaluate_if(info, &tokens);
02078       while (tokens.tok) { preproc_next(&tokens); }
02079 #if PREPROC_DEBUG
02080         {
02081         size_t n = tokens.text - directive;
02082 
02083         if (result == VTK_PARSE_SKIP)
02084           {
02085           fprintf(stderr, "SKIP: ");
02086           }
02087         else if (result == VTK_PARSE_OK)
02088           {
02089           fprintf(stderr, "READ: ");
02090           }
02091         else
02092           {
02093           fprintf(stderr, "ERR%-2.2d ", result);
02094           }
02095         fprintf(stderr, "%*.*s\n", (int)n, (int)n, directive);
02096         }
02097 #endif
02098       }
02099     else if (info->ConditionalDepth == 0)
02100       {
02101       if (strncmp("define", tokens.text, tokens.len) == 0 ||
02102           strncmp("undef", tokens.text, tokens.len) == 0)
02103         {
02104         result = preproc_evaluate_define(info, &tokens);
02105         }
02106       else if (strncmp("include", tokens.text, tokens.len) == 0)
02107         {
02108         result = preproc_evaluate_include(info, &tokens);
02109         }
02110       }
02111     }
02112 
02113   if (info->ConditionalDepth > 0)
02114     {
02115     return VTK_PARSE_SKIP;
02116     }
02117 
02118   return result;
02119 }
02120 
02125 int vtkParsePreprocess_EvaluateExpression(
02126   PreprocessInfo *info, const char *text,
02127   preproc_int_t *val, int *is_unsigned)
02128 {
02129   preproc_tokenizer tokens;
02130   preproc_init(&tokens, text);
02131 
02132   return preproc_evaluate_expression(info, &tokens, val, is_unsigned);
02133 }
02134 
02136 #define PREPROC_MACRO_TO_STRING2(x) #x
02137 #define PREPROC_MACRO_TO_STRING(x) PREPROC_MACRO_TO_STRING2(x)
02138 #define PREPROC_ADD_MACRO(info, x) \
02139 preproc_add_macro_definition(info, #x, PREPROC_MACRO_TO_STRING2(x))
02140 
02144 void vtkParsePreprocess_AddStandardMacros(
02145   PreprocessInfo *info, int platform)
02146 {
02147   int save_external = info->IsExternal;
02148   info->IsExternal = 1;
02149 
02150   /* a special macro to indicate that this is the wrapper */
02151   preproc_add_macro_definition(info, "__WRAP__", "1");
02152 
02153   /* language macros - assume that we are wrapping C++ code */
02154   preproc_add_macro_definition(info, "__cplusplus", "1");
02155 
02156   /* stdc version macros */
02157 #ifdef __STDC__
02158   PREPROC_ADD_MACRO(info, __STDC__);
02159 #endif
02160 #ifdef __STDC_VERSION__
02161   PREPROC_ADD_MACRO(info, __STDC_VERSION__);
02162 #endif
02163 #ifdef __STDC_HOSTED__
02164   PREPROC_ADD_MACRO(info, __STDC_HOSTED__);
02165 #endif
02166 
02167   if (platform == VTK_PARSE_NATIVE)
02168     {
02169 #ifdef WIN32
02170     PREPROC_ADD_MACRO(info, WIN32);
02171 #endif
02172 #ifdef _WIN32
02173     PREPROC_ADD_MACRO(info, _WIN32);
02174 #endif
02175 #ifdef _MSC_VER
02176     PREPROC_ADD_MACRO(info, _MSC_VER);
02177 #endif
02178 
02179 #ifdef __BORLAND__
02180     PREPROC_ADD_MACRO(info, __BORLAND__);
02181 #endif
02182 
02183 #ifdef __CYGWIN__
02184     PREPROC_ADD_MACRO(info, __CYGWIN__);
02185 #endif
02186 #ifdef MINGW
02187     PREPROC_ADD_MACRO(info, MINGW);
02188 #endif
02189 #ifdef __MINGW32__
02190     PREPROC_ADD_MACRO(info, __MINGW32__);
02191 #endif
02192 
02193 #ifdef __linux__
02194     PREPROC_ADD_MACRO(info, __linux__);
02195 #endif
02196 #ifdef __LINUX__
02197     PREPROC_ADD_MACRO(info, __LINUX__);
02198 #endif
02199 
02200 #ifdef __APPLE__
02201     PREPROC_ADD_MACRO(info, __APPLE__);
02202 #endif
02203 #ifdef __MACH__
02204     PREPROC_ADD_MACRO(info, __MACH__);
02205 #endif
02206 #ifdef __DARWIN__
02207     PREPROC_ADD_MACRO(info, __DARWIN__);
02208 #endif
02209 
02210 #ifdef __GNUC__
02211     PREPROC_ADD_MACRO(info, __GNUC__);
02212 #endif
02213 #ifdef __LP64__
02214     PREPROC_ADD_MACRO(info, __LP64__);
02215 #endif
02216 #ifdef __BIG_ENDIAN__
02217     PREPROC_ADD_MACRO(info, __BIG_ENDIAN__);
02218 #endif
02219 #ifdef __LITTLE_ENDIAN__
02220     PREPROC_ADD_MACRO(info, __LITTLE_ENDIAN__);
02221 #endif
02222     }
02223 
02224   info->IsExternal = save_external;
02225 }
02226 
02230 int vtkParsePreprocess_AddMacro(
02231   PreprocessInfo *info, const char *name, const char *definition)
02232 {
02233   int i;
02234   MacroInfo *macro;
02235 
02236   if (preproc_find_macro(info, name, &i))
02237     {
02238     return VTK_PARSE_MACRO_REDEFINED;
02239     }
02240 
02241   macro = preproc_add_macro_definition(info, name, definition);
02242   macro->IsExternal = 1;
02243 
02244   return VTK_PARSE_OK;
02245 }
02246 
02250 MacroInfo *vtkParsePreprocess_GetMacro(
02251   PreprocessInfo *info, const char *name)
02252 {
02253   int i = 0;
02254 
02255   if (preproc_find_macro(info, name, &i))
02256     {
02257     return info->Macros[i];
02258     }
02259 
02260   return NULL;
02261 }
02262 
02266 int vtkParsePreprocess_RemoveMacro(
02267  PreprocessInfo *info, const char *name)
02268 {
02269   if (preproc_remove_macro(info, name))
02270     {
02271     return VTK_PARSE_OK;
02272     }
02273 
02274   return VTK_PARSE_MACRO_UNDEFINED;
02275 }
02276 
02280 const char *vtkParsePreprocess_ExpandMacro(
02281   MacroInfo *macro, const char *argstring)
02282 {
02283   const char *cp = argstring;
02284   int n = 0;
02285   int j = 0;
02286   const char **values = NULL;
02287   const char *pp = NULL;
02288   const char *dp = NULL;
02289   char *rp = NULL;
02290   size_t rs = 0;
02291   size_t i = 0;
02292   size_t l = 0;
02293   size_t k = 0;
02294   int stringify = 0;
02295   int depth = 1;
02296   int c;
02297 
02298   if (argstring == NULL || *cp != '(')
02299     {
02300     return NULL;
02301     }
02302 
02303   /* break the string into individual argument values */
02304   values = (const char **)malloc(4*sizeof(const char **));
02305 
02306   cp++;
02307   values[n++] = cp;
02308   while (depth > 0 && *cp != '\0')
02309     {
02310     while (*cp != '\0')
02311       {
02312       if (*cp == '\"' || *cp == '\'')
02313         {
02314         preproc_skip_quotes(&cp);
02315         }
02316       else if (cp[0] == '/' && (cp[1] == '*' || cp[1] == '/'))
02317         {
02318         preproc_skip_comment(&cp);
02319         }
02320       else if (*cp == '(')
02321         {
02322         cp++;
02323         depth++;
02324         }
02325       else if (*cp == ')')
02326         {
02327         cp++;
02328         if (--depth == 0)
02329           {
02330           break;
02331           }
02332         }
02333       else if (*cp == ',')
02334         {
02335         cp++;
02336         if (depth == 1)
02337           {
02338           break;
02339           }
02340         }
02341       else if (*cp != '\0')
02342         {
02343         cp++;
02344         }
02345       }
02346     if (n >= 4 && (n & (n-1)) == 0)
02347       {
02348       values = (const char **)realloc(
02349         (char **)values, 2*n*sizeof(const char **));
02350       }
02351 
02352     values[n++] = cp;
02353     }
02354   --n;
02355 
02356   /* diagnostic: print out the values */
02357 #if PREPROC_DEBUG
02358   for (j = 0; j < n; j++)
02359     {
02360     size_t m = values[j+1] - values[j] - 1;
02361     fprintf(stderr, "arg %i: %*.*s\n", (int)j, (int)m, (int)m, values[j]);
02362     }
02363 #endif
02364 
02365   /* allow whitespace as "no argument" */
02366   if (macro->NumberOfArguments == 0 && n == 1)
02367     {
02368     cp = values[0];
02369     c = *cp;
02370     while (c == ' ' || c == '\n' || c == '\t' || c == '\r')
02371       {
02372       c = *(++cp);
02373       }
02374     if (cp + 1 == values[1])
02375       {
02376       n = 0;
02377       }
02378     }
02379 
02380   if (n != macro->NumberOfArguments)
02381     {
02382     free((char **)values);
02383 #if PREPROC_DEBUG
02384     fprintf(stderr, "wrong number of macro args to %s, %d != %d\n",
02385             macro->Name, n, macro->NumberOfArguments);
02386 #endif
02387     return NULL;
02388     }
02389 
02390   cp = macro->Definition;
02391   dp = cp;
02392   if (cp == NULL)
02393     {
02394     free((char **)values);
02395     return NULL;
02396     }
02397 
02398   rp = (char *)malloc(128);
02399   rp[0] = '\0';
02400   rs = 128;
02401 
02402   while (*cp != '\0')
02403     {
02404     pp = cp;
02405     stringify = 0;
02406     /* skip all chars that aren't part of a name */
02407     while ((*cp < 'a' || *cp > 'z') &&
02408            (*cp < 'A' || *cp > 'Z') &&
02409            *cp != '_' && *cp != '\0')
02410       {
02411       if (*cp == '\'' || *cp == '\"')
02412         {
02413         preproc_skip_quotes(&cp);
02414         dp = cp;
02415         }
02416       else if (*cp >= '0' && *cp <= '9')
02417         {
02418         preproc_skip_number(&cp);
02419         dp = cp;
02420         }
02421       else if (*cp == '/' && (cp[1] == '/' || cp[1] == '*'))
02422         {
02423         preproc_skip_comment(&cp);
02424         dp = cp;
02425         }
02426       else if (cp[0] == '#' && cp[1] == '#')
02427         {
02428         dp = cp;
02429         while (dp > pp && (dp[-1] == ' ' || dp[-1] == '\t' ||
02430                            dp[-1] == '\r' || dp[-1] == '\n'))
02431           {
02432           --dp;
02433           }
02434         cp += 2;
02435         while (*cp == ' ' || *cp == '\t' || *cp == '\r' || *cp == '\n')
02436           {
02437           cp++;
02438           }
02439         break;
02440         }
02441       else if (*cp == '#')
02442         {
02443         stringify = 1;
02444         dp = cp;
02445         cp++;
02446         while (*cp == ' ' || *cp == '\t' || *cp == '\r' || *cp == '\n')
02447           {
02448           cp++;
02449           }
02450         break;
02451         }
02452       else
02453         {
02454         cp++;
02455         dp = cp;
02456         }
02457       }
02458     l = dp - pp;
02459     if (l > 0)
02460       {
02461       if (i + l + 1 >= rs)
02462         {
02463         rs += rs + i + l + 1;
02464         rp = (char *)realloc(rp, rs);
02465         }
02466       strncpy(&rp[i], pp, l);
02467       i += l;
02468       rp[i] = '\0';
02469       }
02470 
02471     /* get the name */
02472     pp = cp;
02473     preproc_skip_name(&cp);
02474     l = cp - pp;
02475     if (l > 0)
02476       {
02477       for (j = 0; j < n; j++)
02478         {
02479         /* check whether the name matches an argument */
02480         if (strncmp(pp, macro->Arguments[j], l) == 0 &&
02481             macro->Arguments[j][l] == '\0')
02482           {
02483           /* substitute the argument value */
02484           l = values[j+1] - values[j] - 1;
02485           pp = values[j];
02486           /* remove leading whitespace from argument */
02487           c = *pp;
02488           while (c == ' ' || c == '\n' || c == '\t' || c == '\r')
02489             {
02490             c = *(++pp);
02491             l--;
02492             }
02493           /* remove trailing whitespace from argument */
02494           if (l > 0)
02495             {
02496             c = pp[l - 1];
02497             while (c == ' ' || c == '\n' || c == '\t' || c == '\r')
02498               {
02499               if (--l == 0)
02500                 {
02501                 break;
02502                 }
02503               c = pp[l-1];
02504               }
02505             }
02506           break;
02507           }
02508         }
02509       if (stringify)
02510         {
02511         /* compute number of chars that will be added */
02512         stringify = 2;
02513         for (k = 0; k < l; k++)
02514           {
02515           c = pp[k];
02516           if (c == '\\' || c == '\"')
02517             {
02518             stringify++;
02519             }
02520           }
02521         }
02522       if (i + l + stringify + 1 >= rs)
02523         {
02524         rs += rs + i + l + 1;
02525         rp = (char *)realloc(rp, rs);
02526         }
02527       if (stringify)
02528         {
02529         rp[i++] = '\"';
02530         for (k = 0; k < l; k++)
02531           {
02532           c = pp[k];
02533           if (c == '\\' || c == '\"')
02534             {
02535             rp[i++] = '\\';
02536             }
02537           rp[i++] = c;
02538           }
02539         rp[i++] = '\"';
02540         }
02541       else
02542         {
02543         strncpy(&rp[i], pp, l);
02544         i += l;
02545         }
02546       rp[i] = '\0';
02547       }
02548     }
02549 
02550   free((char **)values);
02551 
02552   return rp;
02553 }
02554 
02558 void vtkParsePreprocess_FreeExpandedMacro(const char *emacro)
02559 {
02560   free((char *)emacro);
02561 }
02562 
02566 void vtkParsePreprocess_IncludeDirectory(
02567   PreprocessInfo *info, const char *name)
02568 {
02569   int i, n;
02570 
02571   n = info->NumberOfIncludeDirectories;
02572   for (i = 0; i < n; i++)
02573     {
02574     if (strcmp(name, info->IncludeDirectories[i]) == 0)
02575       {
02576       return;
02577       }
02578     }
02579 
02580   info->IncludeDirectories = (const char **)preproc_array_check(
02581     (char **)info->IncludeDirectories, sizeof(char *),
02582     info->NumberOfIncludeDirectories);
02583   info->IncludeDirectories[info->NumberOfIncludeDirectories++] =
02584     preproc_strndup(name, strlen(name));
02585 }
02586 
02591 const char *vtkParsePreprocess_FindIncludeFile(
02592   PreprocessInfo *info, const char *filename, int system_first,
02593   int *already_loaded)
02594 {
02595   const char *cp;
02596   cp = preproc_find_include_file(info, filename, system_first, 1);
02597   if (cp)
02598     {
02599     *already_loaded = 1;
02600     }
02601 
02602   *already_loaded = 0;
02603   return preproc_find_include_file(info, filename, system_first, 0);
02604 }
02605 
02609 void vtkParsePreprocess_InitMacro(MacroInfo *macro)
02610 {
02611   macro->Name = NULL;
02612   macro->Definition = NULL;
02613   macro->Comment = NULL;
02614   macro->NumberOfArguments = 0;
02615   macro->Arguments = NULL;
02616   macro->IsFunction = 0;
02617   macro->IsExternal = 0;
02618 }
02619 
02623 void vtkParsePreprocess_InitPreprocess(PreprocessInfo *info)
02624 {
02625   info->FileName = NULL;
02626   info->NumberOfMacros = 0;
02627   info->Macros = NULL;
02628   info->NumberOfIncludeDirectories = 0;
02629   info->IncludeDirectories = NULL;
02630   info->NumberOfIncludeFiles = 0;
02631   info->IncludeFiles = NULL;
02632   info->IsExternal = 0;
02633   info->ConditionalDepth = 0;
02634   info->ConditionalDone = 0;
02635 }