root/libparser/C.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. yacc
  2. C
  3. C_family
  4. process_attribute
  5. function_definition
  6. condition_macro
  7. enumerator_list

   1 /*
   2  * Copyright (c) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008,
   3  *      2010
   4  *      Tama Communications Corporation
   5  *
   6  * This file is part of GNU GLOBAL.
   7  *
   8  * This program is free software: you can redistribute it and/or modify
   9  * it under the terms of the GNU General Public License as published by
  10  * the Free Software Foundation, either version 3 of the License, or
  11  * (at your option) any later version.
  12  * 
  13  * This program is distributed in the hope that it will be useful,
  14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16  * GNU General Public License for more details.
  17  * 
  18  * You should have received a copy of the GNU General Public License
  19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20  */
  21 
  22 #ifdef HAVE_CONFIG_H
  23 #include <config.h>
  24 #endif
  25 #ifdef HAVE_STRING_H
  26 #include <string.h>
  27 #else
  28 #include <strings.h>
  29 #endif
  30 
  31 #include "internal.h"
  32 #include "die.h"
  33 #include "strbuf.h"
  34 #include "strlimcpy.h"
  35 #include "token.h"
  36 #include "c_res.h"
  37 
  38 static void C_family(const struct parser_param *, int);
  39 static void process_attribute(const struct parser_param *);
  40 static int function_definition(const struct parser_param *, char *);
  41 static void condition_macro(const struct parser_param *, int);
  42 static int enumerator_list(const struct parser_param *);
  43 
  44 #define IS_TYPE_QUALIFIER(c)    ((c) == C_CONST || (c) == C_RESTRICT || (c) == C_VOLATILE)
  45 
  46 #define DECLARATIONS    0
  47 #define RULES           1
  48 #define PROGRAMS        2
  49 
  50 #define TYPE_C          0
  51 #define TYPE_LEX        1
  52 #define TYPE_YACC       2
  53 
  54 #define MAXPIFSTACK     100
  55 
  56 /**
  57  * @name #ifdef stack.
  58  */
  59 static struct {
  60         short start;            /**< level when @CODE{\#if} block started */
  61         short end;              /**< level when @CODE{\#if} block end */
  62         short if0only;          /**< @CODE{\#if 0} or notdef only */
  63 } stack[MAXPIFSTACK], *cur;
  64 static int piflevel;            /**< condition macro level */
  65 static int level;               /**< brace level */
  66 static int externclevel;        /**< @CODE{extern "C"} block level */
  67 
  68 /**
  69  * yacc: read yacc file and pickup tag entries.
  70  */
  71 void
  72 yacc(const struct parser_param *param)
  73 {
  74         C_family(param, TYPE_YACC);
  75 }
  76 /**
  77  * C: read C file and pickup tag entries.
  78  */
  79 void
  80 C(const struct parser_param *param)
  81 {
  82         C_family(param, TYPE_C);
  83 }
  84 /**
  85  *      @param[in]      param   source file
  86  *      @param[in]      type    #TYPE_C, #TYPE_YACC, #TYPE_LEX
  87  */
  88 static void
  89 C_family(const struct parser_param *param, int type)
  90 {
  91         int c, cc;
  92         int savelevel;
  93         int startmacro, startsharp;
  94         const char *interested = "{}=;";
  95         STRBUF *sb = strbuf_open(0);
  96         /*
  97          * yacc file format is like the following.
  98          *
  99          * declarations
 100          * %%
 101          * rules
 102          * %%
 103          * programs
 104          *
 105          */
 106         int yaccstatus = (type == TYPE_YACC) ? DECLARATIONS : PROGRAMS;
 107         int inC = (type == TYPE_YACC) ? 0 : 1;  /* 1 while C source */
 108 
 109         level = piflevel = externclevel = 0;
 110         savelevel = -1;
 111         startmacro = startsharp = 0;
 112 
 113         if (!opentoken(param->file))
 114                 die("'%s' cannot open.", param->file);
 115         cmode = 1;                      /* allow token like '#xxx' */
 116         crflag = 1;                     /* require '\n' as a token */
 117         if (type == TYPE_YACC)
 118                 ymode = 1;              /* allow token like '%xxx' */
 119 
 120         while ((cc = nexttoken(interested, c_reserved_word)) != EOF) {
 121                 switch (cc) {
 122                 case SYMBOL:            /* symbol       */
 123                         if (inC && peekc(0) == '('/* ) */) {
 124                                 if (param->isnotfunction(token)) {
 125                                         PUT(PARSER_REF_SYM, token, lineno, sp);
 126                                 } else if (level > 0 || startmacro) {
 127                                         PUT(PARSER_REF_SYM, token, lineno, sp);
 128                                 } else if (level == 0 && !startmacro && !startsharp) {
 129                                         char arg1[MAXTOKEN], savetok[MAXTOKEN], *saveline;
 130                                         int savelineno = lineno;
 131 
 132                                         strlimcpy(savetok, token, sizeof(savetok));
 133                                         strbuf_reset(sb);
 134                                         strbuf_puts(sb, sp);
 135                                         saveline = strbuf_value(sb);
 136                                         arg1[0] = '\0';
 137                                         /*
 138                                          * Guile function entry using guile-snarf is like follows:
 139                                          *
 140                                          * SCM_DEFINE (scm_list, "list", 0, 0, 1, 
 141                                          *           (SCM objs),
 142                                          *            "Return a list containing OBJS, the arguments to `list'.")
 143                                          * #define FUNC_NAME s_scm_list
 144                                          * {
 145                                          *   return objs;
 146                                          * }
 147                                          * #undef FUNC_NAME
 148                                          *
 149                                          * We should assume the first argument as a function name instead of 'SCM_DEFINE'.
 150                                          */
 151                                         if (function_definition(param, arg1)) {
 152                                                 if (!strcmp(savetok, "SCM_DEFINE") && *arg1)
 153                                                         strlimcpy(savetok, arg1, sizeof(savetok));
 154                                                 PUT(PARSER_DEF, savetok, savelineno, saveline);
 155                                         } else {
 156                                                 PUT(PARSER_REF_SYM, savetok, savelineno, saveline);
 157                                         }
 158                                 }
 159                         } else {
 160                                 PUT(PARSER_REF_SYM, token, lineno, sp);
 161                         }
 162                         break;
 163                 case '{':  /* } */
 164                         DBG_PRINT(level, "{"); /* } */
 165                         if (yaccstatus == RULES && level == 0)
 166                                 inC = 1;
 167                         ++level;
 168                         if ((param->flags & PARSER_BEGIN_BLOCK) && atfirst) {
 169                                 if ((param->flags & PARSER_WARNING) && level != 1)
 170                                         warning("forced level 1 block start by '{' at column 0 [+%d %s].", lineno, curfile); /* } */
 171                                 level = 1;
 172                         }
 173                         break;
 174                         /* { */
 175                 case '}':
 176                         if (--level < 0) {
 177                                 if (externclevel > 0)
 178                                         externclevel--;
 179                                 else if (param->flags & PARSER_WARNING)
 180                                         warning("missing left '{' [+%d %s].", lineno, curfile); /* } */
 181                                 level = 0;
 182                         }
 183                         if ((param->flags & PARSER_END_BLOCK) && atfirst) {
 184                                 if ((param->flags & PARSER_WARNING) && level != 0) /* { */
 185                                         warning("forced level 0 block end by '}' at column 0 [+%d %s].", lineno, curfile);
 186                                 level = 0;
 187                         }
 188                         if (yaccstatus == RULES && level == 0)
 189                                 inC = 0;
 190                         /* { */
 191                         DBG_PRINT(level, "}");
 192                         break;
 193                 case '\n':
 194                         if (startmacro && level != savelevel) {
 195                                 if (param->flags & PARSER_WARNING)
 196                                         warning("different level before and after #define macro. reseted. [+%d %s].", lineno, curfile);
 197                                 level = savelevel;
 198                         }
 199                         startmacro = startsharp = 0;
 200                         break;
 201                 case YACC_SEP:          /* %% */
 202                         if (level != 0) {
 203                                 if (param->flags & PARSER_WARNING)
 204                                         warning("forced level 0 block end by '%%' [+%d %s].", lineno, curfile);
 205                                 level = 0;
 206                         }
 207                         if (yaccstatus == DECLARATIONS) {
 208                                 PUT(PARSER_DEF, "yyparse", lineno, sp);
 209                                 yaccstatus = RULES;
 210                         } else if (yaccstatus == RULES)
 211                                 yaccstatus = PROGRAMS;
 212                         inC = (yaccstatus == PROGRAMS) ? 1 : 0;
 213                         break;
 214                 case YACC_BEGIN:        /* %{ */
 215                         if (level != 0) {
 216                                 if (param->flags & PARSER_WARNING)
 217                                         warning("forced level 0 block end by '%%{' [+%d %s].", lineno, curfile);
 218                                 level = 0;
 219                         }
 220                         if (inC == 1 && (param->flags & PARSER_WARNING))
 221                                 warning("'%%{' appeared in C mode. [+%d %s].", lineno, curfile);
 222                         inC = 1;
 223                         break;
 224                 case YACC_END:          /* %} */
 225                         if (level != 0) {
 226                                 if (param->flags & PARSER_WARNING)
 227                                         warning("forced level 0 block end by '%%}' [+%d %s].", lineno, curfile);
 228                                 level = 0;
 229                         }
 230                         if (inC == 0 && (param->flags & PARSER_WARNING))
 231                                 warning("'%%}' appeared in Yacc mode. [+%d %s].", lineno, curfile);
 232                         inC = 0;
 233                         break;
 234                 case YACC_UNION:        /* %union {...} */
 235                         if (yaccstatus == DECLARATIONS)
 236                                 PUT(PARSER_DEF, "YYSTYPE", lineno, sp);
 237                         break;
 238                 /*
 239                  * #xxx
 240                  */
 241                 case SHARP_DEFINE:
 242                 case SHARP_UNDEF:
 243                         startmacro = 1;
 244                         savelevel = level;
 245                         if ((c = nexttoken(interested, c_reserved_word)) != SYMBOL) {
 246                                 pushbacktoken();
 247                                 break;
 248                         }
 249                         if (peekc(1) == '('/* ) */) {
 250                                 PUT(PARSER_DEF, token, lineno, sp);
 251                                 while ((c = nexttoken("()", c_reserved_word)) != EOF && c != '\n' && c != /* ( */ ')')
 252                                         if (c == SYMBOL)
 253                                                 PUT(PARSER_REF_SYM, token, lineno, sp);
 254                                 if (c == '\n')
 255                                         pushbacktoken();
 256                         } else {
 257                                 PUT(PARSER_DEF, token, lineno, sp);
 258                         }
 259                         break;
 260                 case SHARP_IMPORT:
 261                 case SHARP_INCLUDE:
 262                 case SHARP_INCLUDE_NEXT:
 263                 case SHARP_ERROR:
 264                 case SHARP_LINE:
 265                 case SHARP_PRAGMA:
 266                 case SHARP_WARNING:
 267                 case SHARP_IDENT:
 268                 case SHARP_SCCS:
 269                         while ((c = nexttoken(interested, c_reserved_word)) != EOF && c != '\n')
 270                                 ;
 271                         break;
 272                 case SHARP_IFDEF:
 273                 case SHARP_IFNDEF:
 274                 case SHARP_IF:
 275                 case SHARP_ELIF:
 276                 case SHARP_ELSE:
 277                 case SHARP_ENDIF:
 278                         condition_macro(param, cc);
 279                         break;
 280                 case SHARP_SHARP:               /* ## */
 281                         (void)nexttoken(interested, c_reserved_word);
 282                         break;
 283                 case C_EXTERN: /* for 'extern "C"/"C++"' */
 284                         if (peekc(0) != '"') /* " */
 285                                 continue; /* If does not start with '"', continue. */
 286                         while ((c = nexttoken(interested, c_reserved_word)) == '\n')
 287                                 ;
 288                         /*
 289                          * 'extern "C"/"C++"' block is a kind of namespace block.
 290                          * (It doesn't have any influence on level.)
 291                          */
 292                         if (c == '{') /* } */
 293                                 externclevel++;
 294                         else
 295                                 pushbacktoken();
 296                         break;
 297                 case C_STRUCT:
 298                 case C_ENUM:
 299                 case C_UNION:
 300                         while ((c = nexttoken(interested, c_reserved_word)) == C___ATTRIBUTE__)
 301                                 process_attribute(param);
 302                         if (c == SYMBOL) {
 303                                 if (peekc(0) == '{') /* } */ {
 304                                         PUT(PARSER_DEF, token, lineno, sp);
 305                                 } else {
 306                                         PUT(PARSER_REF_SYM, token, lineno, sp);
 307                                 }
 308                                 c = nexttoken(interested, c_reserved_word);
 309                         }
 310                         if (c == '{' /* } */ && cc == C_ENUM) {
 311                                 enumerator_list(param);
 312                         } else {
 313                                 pushbacktoken();
 314                         }
 315                         break;
 316                 /* control statement check */
 317                 case C_BREAK:
 318                 case C_CASE:
 319                 case C_CONTINUE:
 320                 case C_DEFAULT:
 321                 case C_DO:
 322                 case C_ELSE:
 323                 case C_FOR:
 324                 case C_GOTO:
 325                 case C_IF:
 326                 case C_RETURN:
 327                 case C_SWITCH:
 328                 case C_WHILE:
 329                         if ((param->flags & PARSER_WARNING) && !startmacro && level == 0)
 330                                 warning("Out of function. %8s [+%d %s]", token, lineno, curfile);
 331                         break;
 332                 case C_TYPEDEF:
 333                         {
 334                                 /*
 335                                  * This parser is too complex to maintain.
 336                                  * We should rewrite the whole.
 337                                  */
 338                                 char savetok[MAXTOKEN];
 339                                 int savelineno = 0;
 340                                 int typedef_savelevel = level;
 341 
 342                                 savetok[0] = 0;
 343 
 344                                 /* skip type qualifiers */
 345                                 do {
 346                                         c = nexttoken("{}(),;", c_reserved_word);
 347                                 } while (IS_TYPE_QUALIFIER(c) || c == '\n');
 348 
 349                                 if ((param->flags & PARSER_WARNING) && c == EOF) {
 350                                         warning("unexpected eof. [+%d %s]", lineno, curfile);
 351                                         break;
 352                                 } else if (c == C_ENUM || c == C_STRUCT || c == C_UNION) {
 353                                         char *interest_enum = "{},;";
 354                                         int c_ = c;
 355 
 356                                         while ((c = nexttoken(interest_enum, c_reserved_word)) == C___ATTRIBUTE__)
 357                                                 process_attribute(param);
 358                                         /* read tag name if exist */
 359                                         if (c == SYMBOL) {
 360                                                 if (peekc(0) == '{') /* } */ {
 361                                                         PUT(PARSER_DEF, token, lineno, sp);
 362                                                 } else {
 363                                                         PUT(PARSER_REF_SYM, token, lineno, sp);
 364                                                 }
 365                                                 c = nexttoken(interest_enum, c_reserved_word);
 366                                         }
 367                                 
 368                                         if (c_ == C_ENUM) {
 369                                                 if (c == '{') /* } */
 370                                                         c = enumerator_list(param);
 371                                                 else
 372                                                         pushbacktoken();
 373                                         } else {
 374                                                 for (; c != EOF; c = nexttoken(interest_enum, c_reserved_word)) {
 375                                                         switch (c) {
 376                                                         case SHARP_IFDEF:
 377                                                         case SHARP_IFNDEF:
 378                                                         case SHARP_IF:
 379                                                         case SHARP_ELIF:
 380                                                         case SHARP_ELSE:
 381                                                         case SHARP_ENDIF:
 382                                                                 condition_macro(param, c);
 383                                                                 continue;
 384                                                         default:
 385                                                                 break;
 386                                                         }
 387                                                         if (c == ';' && level == typedef_savelevel) {
 388                                                                 if (savetok[0])
 389                                                                         PUT(PARSER_DEF, savetok, savelineno, sp);
 390                                                                 break;
 391                                                         } else if (c == '{')
 392                                                                 level++;
 393                                                         else if (c == '}') {
 394                                                                 if (--level == typedef_savelevel)
 395                                                                         break;
 396                                                         } else if (c == SYMBOL) {
 397                                                                 PUT(PARSER_REF_SYM, token, lineno, sp);
 398                                                                 /* save lastest token */
 399                                                                 strlimcpy(savetok, token, sizeof(savetok));
 400                                                                 savelineno = lineno;
 401                                                         }
 402                                                 }
 403                                                 if (c == ';')
 404                                                         break;
 405                                         }
 406                                         if ((param->flags & PARSER_WARNING) && c == EOF) {
 407                                                 warning("unexpected eof. [+%d %s]", lineno, curfile);
 408                                                 break;
 409                                         }
 410                                 } else if (c == SYMBOL) {
 411                                         PUT(PARSER_REF_SYM, token, lineno, sp);
 412                                 }
 413                                 savetok[0] = 0;
 414                                 while ((c = nexttoken("(),;", c_reserved_word)) != EOF) {
 415                                         switch (c) {
 416                                         case SHARP_IFDEF:
 417                                         case SHARP_IFNDEF:
 418                                         case SHARP_IF:
 419                                         case SHARP_ELIF:
 420                                         case SHARP_ELSE:
 421                                         case SHARP_ENDIF:
 422                                                 condition_macro(param, c);
 423                                                 continue;
 424                                         default:
 425                                                 break;
 426                                         }
 427                                         if (c == '(')
 428                                                 level++;
 429                                         else if (c == ')')
 430                                                 level--;
 431                                         else if (c == SYMBOL) {
 432                                                 if (level > typedef_savelevel) {
 433                                                         PUT(PARSER_REF_SYM, token, lineno, sp);
 434                                                 } else {
 435                                                         /* put latest token if any */
 436                                                         if (savetok[0]) {
 437                                                                 PUT(PARSER_REF_SYM, savetok, savelineno, sp);
 438                                                         }
 439                                                         /* save lastest token */
 440                                                         strlimcpy(savetok, token, sizeof(savetok));
 441                                                         savelineno = lineno;
 442                                                 }
 443                                         } else if (c == ',' || c == ';') {
 444                                                 if (savetok[0]) {
 445                                                         PUT(PARSER_DEF, savetok, lineno, sp);
 446                                                         savetok[0] = 0;
 447                                                 }
 448                                         }
 449                                         if (level == typedef_savelevel && c == ';')
 450                                                 break;
 451                                 }
 452                                 if (param->flags & PARSER_WARNING) {
 453                                         if (c == EOF)
 454                                                 warning("unexpected eof. [+%d %s]", lineno, curfile);
 455                                         else if (level != typedef_savelevel)
 456                                                 warning("unmatched () block. (last at level %d.)[+%d %s]", level, lineno, curfile);
 457                                 }
 458                         }
 459                         break;
 460                 case C___ATTRIBUTE__:
 461                         process_attribute(param);
 462                         break;
 463                 default:
 464                         break;
 465                 }
 466         }
 467         strbuf_close(sb);
 468         if (param->flags & PARSER_WARNING) {
 469                 if (level != 0)
 470                         warning("unmatched {} block. (last at level %d.)[+%d %s]", level, lineno, curfile);
 471                 if (piflevel != 0)
 472                         warning("unmatched #if block. (last at level %d.)[+%d %s]", piflevel, lineno, curfile);
 473         }
 474         closetoken();
 475 }
 476 /**
 477  * process_attribute: skip attributes in @CODE{__attribute__((...))}.
 478  */
 479 static void
 480 process_attribute(const struct parser_param *param)
 481 {
 482         int brace = 0;
 483         int c;
 484         /*
 485          * Skip '...' in __attribute__((...))
 486          * but pick up symbols in it.
 487          */
 488         while ((c = nexttoken("()", c_reserved_word)) != EOF) {
 489                 if (c == '(')
 490                         brace++;
 491                 else if (c == ')')
 492                         brace--;
 493                 else if (c == SYMBOL) {
 494                         PUT(PARSER_REF_SYM, token, lineno, sp);
 495                 }
 496                 if (brace == 0)
 497                         break;
 498         }
 499 }
 500 /**
 501  * function_definition: return if function definition or not.
 502  *
 503  *      @param  param   
 504  *      @param[out]     arg1    the first argument
 505  *      @return target type
 506  */
 507 static int
 508 function_definition(const struct parser_param *param, char arg1[MAXTOKEN])
 509 {
 510         int c;
 511         int brace_level, isdefine;
 512         int accept_arg1 = 0;
 513 
 514         brace_level = isdefine = 0;
 515         while ((c = nexttoken("()", c_reserved_word)) != EOF) {
 516                 switch (c) {
 517                 case SHARP_IFDEF:
 518                 case SHARP_IFNDEF:
 519                 case SHARP_IF:
 520                 case SHARP_ELIF:
 521                 case SHARP_ELSE:
 522                 case SHARP_ENDIF:
 523                         condition_macro(param, c);
 524                         continue;
 525                 default:
 526                         break;
 527                 }
 528                 if (c == '('/* ) */)
 529                         brace_level++;
 530                 else if (c == /* ( */')') {
 531                         if (--brace_level == 0)
 532                                 break;
 533                 }
 534                 /* pick up symbol */
 535                 if (c == SYMBOL) {
 536                         if (accept_arg1 == 0) {
 537                                 accept_arg1 = 1;
 538                                 strlimcpy(arg1, token, MAXTOKEN);
 539                         }
 540                         PUT(PARSER_REF_SYM, token, lineno, sp);
 541                 }
 542         }
 543         if (c == EOF)
 544                 return 0;
 545         brace_level = 0;
 546         while ((c = nexttoken(",;[](){}=", c_reserved_word)) != EOF) {
 547                 switch (c) {
 548                 case SHARP_IFDEF:
 549                 case SHARP_IFNDEF:
 550                 case SHARP_IF:
 551                 case SHARP_ELIF:
 552                 case SHARP_ELSE:
 553                 case SHARP_ENDIF:
 554                         condition_macro(param, c);
 555                         continue;
 556                 case C___ATTRIBUTE__:
 557                         process_attribute(param);
 558                         continue;
 559                 default:
 560                         break;
 561                 }
 562                 if (c == '('/* ) */ || c == '[')
 563                         brace_level++;
 564                 else if (c == /* ( */')' || c == ']')
 565                         brace_level--;
 566                 else if (brace_level == 0
 567                     && ((c == SYMBOL && strcmp(token, "__THROW")) || IS_RESERVED_WORD(c)))
 568                         isdefine = 1;
 569                 else if (c == ';' || c == ',') {
 570                         if (!isdefine)
 571                                 break;
 572                 } else if (c == '{' /* } */) {
 573                         pushbacktoken();
 574                         return 1;
 575                 } else if (c == /* { */'}')
 576                         break;
 577                 else if (c == '=')
 578                         break;
 579 
 580                 /* pick up symbol */
 581                 if (c == SYMBOL)
 582                         PUT(PARSER_REF_SYM, token, lineno, sp);
 583         }
 584         return 0;
 585 }
 586 
 587 /**
 588  * condition_macro: 
 589  *
 590  *      @param  param   
 591  *      @param[in]      cc      token
 592  */
 593 static void
 594 condition_macro(const struct parser_param *param, int cc)
 595 {
 596         cur = &stack[piflevel];
 597         if (cc == SHARP_IFDEF || cc == SHARP_IFNDEF || cc == SHARP_IF) {
 598                 DBG_PRINT(piflevel, "#if");
 599                 if (++piflevel >= MAXPIFSTACK)
 600                         die("#if stack over flow. [%s]", curfile);
 601                 ++cur;
 602                 cur->start = level;
 603                 cur->end = -1;
 604                 cur->if0only = 0;
 605                 if (peekc(0) == '0')
 606                         cur->if0only = 1;
 607                 else if ((cc = nexttoken(NULL, c_reserved_word)) == SYMBOL && !strcmp(token, "notdef"))
 608                         cur->if0only = 1;
 609                 else
 610                         pushbacktoken();
 611         } else if (cc == SHARP_ELIF || cc == SHARP_ELSE) {
 612                 DBG_PRINT(piflevel - 1, "#else");
 613                 if (cur->end == -1)
 614                         cur->end = level;
 615                 else if (cur->end != level && (param->flags & PARSER_WARNING))
 616                         warning("uneven level. [+%d %s]", lineno, curfile);
 617                 level = cur->start;
 618                 cur->if0only = 0;
 619         } else if (cc == SHARP_ENDIF) {
 620                 int minus = 0;
 621 
 622                 --piflevel;
 623                 if (piflevel < 0) {
 624                         minus = 1;
 625                         piflevel = 0;
 626                 }
 627                 DBG_PRINT(piflevel, "#endif");
 628                 if (minus) {
 629                         if (param->flags & PARSER_WARNING)
 630                                 warning("unmatched #if block. reseted. [+%d %s]", lineno, curfile);
 631                 } else {
 632                         if (cur->if0only)
 633                                 level = cur->start;
 634                         else if (cur->end != -1) {
 635                                 if (cur->end != level && (param->flags & PARSER_WARNING))
 636                                         warning("uneven level. [+%d %s]", lineno, curfile);
 637                                 level = cur->end;
 638                         }
 639                 }
 640         }
 641         while ((cc = nexttoken(NULL, c_reserved_word)) != EOF && cc != '\n') {
 642                 if (cc == SYMBOL && strcmp(token, "defined") != 0)
 643                         PUT(PARSER_REF_SYM, token, lineno, sp);
 644         }
 645 }
 646 
 647 /**
 648  * enumerator_list: process @CODE{"symbol (= expression), ... \}"}
 649  */
 650 static int
 651 enumerator_list(const struct parser_param *param)
 652 {
 653         int savelevel = level;
 654         int in_expression = 0;
 655         int c = '{';
 656 
 657         for (; c != EOF; c = nexttoken("{}(),=", c_reserved_word)) {
 658                 switch (c) {
 659                 case SHARP_IFDEF:
 660                 case SHARP_IFNDEF:
 661                 case SHARP_IF:
 662                 case SHARP_ELIF:
 663                 case SHARP_ELSE:
 664                 case SHARP_ENDIF:
 665                         condition_macro(param, c);
 666                         break;
 667                 case SYMBOL:
 668                         if (in_expression)
 669                                 PUT(PARSER_REF_SYM, token, lineno, sp);
 670                         else
 671                                 PUT(PARSER_DEF, token, lineno, sp);
 672                         break;
 673                 case '{':
 674                 case '(':
 675                         level++;
 676                         break;
 677                 case '}':
 678                 case ')':
 679                         if (--level == savelevel)
 680                                 return c;
 681                         break;
 682                 case ',':
 683                         if (level == savelevel + 1)
 684                                 in_expression = 0;
 685                         break;
 686                 case '=':
 687                         in_expression = 1;
 688                         break;
 689                 default:
 690                         break;
 691                 }
 692         }
 693 
 694         return c;
 695 }

/* [previous][next][first][last][top][bottom][index][help] */