root/libparser/Cpp.c

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

DEFINITIONS

This source file includes following definitions.
  1. Cpp
  2. process_attribute
  3. function_definition
  4. condition_macro
  5. enumerator_list

   1 /*
   2  * Copyright (c) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009,
   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 "cpp_res.h"
  37 
  38 static void process_attribute(const struct parser_param *);
  39 static int function_definition(const struct parser_param *);
  40 static void condition_macro(const struct parser_param *, int);
  41 static int enumerator_list(const struct parser_param *);
  42 
  43                 /** max size of complete name of class */
  44 #define MAXCOMPLETENAME 1024
  45                 /** max size of class stack */
  46 #define MAXCLASSSTACK   100
  47 #define IS_CV_QUALIFIER(c)      ((c) == CPP_CONST || (c) == CPP_VOLATILE)
  48 
  49 #define MAXPIFSTACK     100
  50 
  51 /**
  52  * @name #ifdef stack.
  53  */
  54 
  55 static struct {
  56         short start;            /**< level when @CODE{\#if} block started */
  57         short end;              /**< level when @CODE{\#if} block end */
  58         short if0only;          /**< @CODE{\#if 0} or notdef only */
  59 } pifstack[MAXPIFSTACK], *cur;
  60 static int piflevel;            /**< condition macro level */
  61 static int level;               /**< brace level */
  62 static int namespacelevel;      /**< namespace block level */
  63 
  64 /**
  65  * Cpp: read C++ file and pickup tag entries.
  66  */
  67 void
  68 Cpp(const struct parser_param *param)
  69 {
  70         int c, cc;
  71         int savelevel;
  72         int startclass, startthrow, startmacro, startsharp, startequal;
  73         char classname[MAXTOKEN];
  74         char completename[MAXCOMPLETENAME];
  75         char *completename_limit = &completename[sizeof(completename)];
  76         int classlevel;
  77         struct {
  78                 char *classname;
  79                 char *terminate;
  80                 int level;
  81         } stack[MAXCLASSSTACK];
  82         const char *interested = "{}=;~";
  83         STRBUF *sb = strbuf_open(0);
  84 
  85         *classname = *completename = 0;
  86         stack[0].classname = completename;
  87         stack[0].terminate = completename;
  88         stack[0].level = 0;
  89         level = classlevel = piflevel = namespacelevel = 0;
  90         savelevel = -1;
  91         startclass = startthrow = startmacro = startsharp = startequal = 0;
  92 
  93         if (!opentoken(param->file))
  94                 die("'%s' cannot open.", param->file);
  95         cmode = 1;                      /* allow token like '#xxx' */
  96         crflag = 1;                     /* require '\n' as a token */
  97         cppmode = 1;                    /* treat '::' as a token */
  98 
  99         while ((cc = nexttoken(interested, cpp_reserved_word)) != EOF) {
 100                 if (cc == '~' && level == stack[classlevel].level)
 101                         continue;
 102                 switch (cc) {
 103                 case SYMBOL:            /* symbol       */
 104                         if (startclass || startthrow) {
 105                                 PUT(PARSER_REF_SYM, token, lineno, sp);
 106                         } else if (peekc(0) == '('/* ) */) {
 107                                 if (param->isnotfunction(token)) {
 108                                         PUT(PARSER_REF_SYM, token, lineno, sp);
 109                                 } else if (level > stack[classlevel].level || startequal || startmacro) {
 110                                         PUT(PARSER_REF_SYM, token, lineno, sp);
 111                                 } else if (level == stack[classlevel].level && !startmacro && !startsharp && !startequal) {
 112                                         char savetok[MAXTOKEN], *saveline;
 113                                         int savelineno = lineno;
 114 
 115                                         strlimcpy(savetok, token, sizeof(savetok));
 116                                         strbuf_reset(sb);
 117                                         strbuf_puts(sb, sp);
 118                                         saveline = strbuf_value(sb);
 119                                         if (function_definition(param)) {
 120                                                 /* ignore constructor */
 121                                                 if (strcmp(stack[classlevel].classname, savetok))
 122                                                         PUT(PARSER_DEF, savetok, savelineno, saveline);
 123                                         } else {
 124                                                 PUT(PARSER_REF_SYM, savetok, savelineno, saveline);
 125                                         }
 126                                 }
 127                         } else {
 128                                 PUT(PARSER_REF_SYM, token, lineno, sp);
 129                         }
 130                         break;
 131                 case CPP_USING:
 132                         /*
 133                          * using namespace name;
 134                          * using ...;
 135                          */
 136                         if ((c = nexttoken(interested, cpp_reserved_word)) == CPP_NAMESPACE) {
 137                                 if ((c = nexttoken(interested, cpp_reserved_word)) == SYMBOL) {
 138                                         PUT(PARSER_REF_SYM, token, lineno, sp);
 139                                 } else {
 140                                         if (param->flags & PARSER_WARNING)
 141                                                 warning("missing namespace name. [+%d %s].", lineno, curfile);
 142                                         pushbacktoken();
 143                                 }
 144                         } else
 145                                 pushbacktoken();
 146                         break;
 147                 case CPP_NAMESPACE:
 148                         crflag = 0;
 149                         /*
 150                          * namespace name = ...;
 151                          * namespace [name] { ... }
 152                          */
 153                         if ((c = nexttoken(interested, cpp_reserved_word)) == SYMBOL) {
 154                                 PUT(PARSER_DEF, token, lineno, sp);
 155                                 if ((c = nexttoken(interested, cpp_reserved_word)) == '=') {
 156                                         crflag = 1;
 157                                         break;
 158                                 }
 159                         }
 160                         /*
 161                          * Namespace block doesn't have any influence on level.
 162                          */
 163                         if (c == '{') /* } */ {
 164                                 namespacelevel++;
 165                         } else {
 166                                 if (param->flags & PARSER_WARNING)
 167                                         warning("missing namespace block. [+%d %s](0x%x).", lineno, curfile, c);
 168                         }
 169                         crflag = 1;
 170                         break;
 171                 case CPP_EXTERN: /* for 'extern "C"/"C++"' */
 172                         if (peekc(0) != '"') /* " */
 173                                 continue; /* If does not start with '"', continue. */
 174                         while ((c = nexttoken(interested, cpp_reserved_word)) == '\n')
 175                                 ;
 176                         /*
 177                          * 'extern "C"/"C++"' block is a kind of namespace block.
 178                          * (It doesn't have any influence on level.)
 179                          */
 180                         if (c == '{') /* } */
 181                                 namespacelevel++;
 182                         else
 183                                 pushbacktoken();
 184                         break;
 185                 case CPP_CLASS:
 186                         DBG_PRINT(level, "class");
 187                         if ((c = nexttoken(interested, cpp_reserved_word)) == SYMBOL) {
 188                                 strlimcpy(classname, token, sizeof(classname));
 189                                 /*
 190                                  * Ignore forward definitions.
 191                                  * "class name;"
 192                                  */
 193                                 if (peekc(0) != ';') {
 194                                         startclass = 1;
 195                                         PUT(PARSER_DEF, token, lineno, sp);
 196                                 }
 197                         }
 198                         break;
 199                 case '{':  /* } */
 200                         DBG_PRINT(level, "{"); /* } */
 201                         ++level;
 202                         if ((param->flags & PARSER_BEGIN_BLOCK) && atfirst) {
 203                                 if ((param->flags & PARSER_WARNING) && level != 1)
 204                                         warning("forced level 1 block start by '{' at column 0 [+%d %s].", lineno, curfile); /* } */
 205                                 level = 1;
 206                         }
 207                         if (startclass) {
 208                                 char *p = stack[classlevel].terminate;
 209                                 char *q = classname;
 210 
 211                                 if (++classlevel >= MAXCLASSSTACK)
 212                                         die("class stack over flow.[%s]", curfile);
 213                                 if (classlevel > 1 && p < completename_limit)
 214                                         *p++ = '.';
 215                                 stack[classlevel].classname = p;
 216                                 while (*q && p < completename_limit)
 217                                         *p++ = *q++;
 218                                 stack[classlevel].terminate = p;
 219                                 stack[classlevel].level = level;
 220                                 *p++ = 0;
 221                         }
 222                         startclass = startthrow = 0;
 223                         break;
 224                         /* { */
 225                 case '}':
 226                         if (--level < 0) {
 227                                 if (namespacelevel > 0)
 228                                         namespacelevel--;
 229                                 else if (param->flags & PARSER_WARNING)
 230                                         warning("missing left '{' [+%d %s].", lineno, curfile); /* } */
 231                                 level = 0;
 232                         }
 233                         if ((param->flags & PARSER_END_BLOCK) && atfirst) {
 234                                 if ((param->flags & PARSER_WARNING) && level != 0)
 235                                         /* { */
 236                                         warning("forced level 0 block end by '}' at column 0 [+%d %s].", lineno, curfile);
 237                                 level = 0;
 238                         }
 239                         if (level < stack[classlevel].level)
 240                                 *(stack[--classlevel].terminate) = 0;
 241                         /* { */
 242                         DBG_PRINT(level, "}");
 243                         break;
 244                 case '=':
 245                         /* dirty hack. Don't mimic this. */
 246                         if (peekc(0) == '=') {
 247                                 throwaway_nextchar();
 248                         } else {
 249                                 startequal = 1;
 250                         }
 251                         break;
 252                 case ';':
 253                         startthrow = startequal = 0;
 254                         break;
 255                 case '\n':
 256                         if (startmacro && level != savelevel) {
 257                                 if (param->flags & PARSER_WARNING)
 258                                         warning("different level before and after #define macro. reseted. [+%d %s].", lineno, curfile);
 259                                 level = savelevel;
 260                         }
 261                         startmacro = startsharp = 0;
 262                         break;
 263                 /*
 264                  * #xxx
 265                  */
 266                 case SHARP_DEFINE:
 267                 case SHARP_UNDEF:
 268                         startmacro = 1;
 269                         savelevel = level;
 270                         if ((c = nexttoken(interested, cpp_reserved_word)) != SYMBOL) {
 271                                 pushbacktoken();
 272                                 break;
 273                         }
 274                         if (peekc(1) == '('/* ) */) {
 275                                 PUT(PARSER_DEF, token, lineno, sp);
 276                                 while ((c = nexttoken("()", cpp_reserved_word)) != EOF && c != '\n' && c != /* ( */ ')')
 277                                         if (c == SYMBOL)
 278                                                 PUT(PARSER_REF_SYM, token, lineno, sp);
 279                                 if (c == '\n')
 280                                         pushbacktoken();
 281                         }  else {
 282                                 PUT(PARSER_DEF, token, lineno, sp);
 283                         }
 284                         break;
 285                 case SHARP_IMPORT:
 286                 case SHARP_INCLUDE:
 287                 case SHARP_INCLUDE_NEXT:
 288                 case SHARP_ERROR:
 289                 case SHARP_LINE:
 290                 case SHARP_PRAGMA:
 291                 case SHARP_WARNING:
 292                 case SHARP_IDENT:
 293                 case SHARP_SCCS:
 294                         while ((c = nexttoken(interested, cpp_reserved_word)) != EOF && c != '\n')
 295                                 ;
 296                         break;
 297                 case SHARP_IFDEF:
 298                 case SHARP_IFNDEF:
 299                 case SHARP_IF:
 300                 case SHARP_ELIF:
 301                 case SHARP_ELSE:
 302                 case SHARP_ENDIF:
 303                         condition_macro(param, cc);
 304                         break;
 305                 case SHARP_SHARP:               /* ## */
 306                         (void)nexttoken(interested, cpp_reserved_word);
 307                         break;
 308                 case CPP_NEW:
 309                         if ((c = nexttoken(interested, cpp_reserved_word)) == SYMBOL)
 310                                 PUT(PARSER_REF_SYM, token, lineno, sp);
 311                         break;
 312                 case CPP_STRUCT:
 313                 case CPP_ENUM:
 314                 case CPP_UNION:
 315                         while ((c = nexttoken(interested, cpp_reserved_word)) == CPP___ATTRIBUTE__)
 316                                 process_attribute(param);
 317                         if (c == SYMBOL) {
 318                                 if (peekc(0) == '{') /* } */ {
 319                                         PUT(PARSER_DEF, token, lineno, sp);
 320                                 } else {
 321                                         PUT(PARSER_REF_SYM, token, lineno, sp);
 322                                 }
 323                                 c = nexttoken(interested, cpp_reserved_word);
 324                         }
 325                         if (c == '{' /* } */ && cc == CPP_ENUM) {
 326                                 enumerator_list(param);
 327                         } else {
 328                                 pushbacktoken();
 329                         }
 330                         break;
 331                 case CPP_TEMPLATE:
 332                         {
 333                                 int level = 0;
 334 
 335                                 while ((c = nexttoken("<>", cpp_reserved_word)) != EOF) {
 336                                         if (c == '<')
 337                                                 ++level;
 338                                         else if (c == '>') {
 339                                                 if (--level == 0)
 340                                                         break;
 341                                         } else if (c == SYMBOL) {
 342                                                 PUT(PARSER_REF_SYM, token, lineno, sp);
 343                                         }
 344                                 }
 345                                 if (c == EOF && (param->flags & PARSER_WARNING))
 346                                         warning("template <...> isn't closed. [+%d %s].", lineno, curfile);
 347                         }
 348                         break;
 349                 case CPP_OPERATOR:
 350                         while ((c = nexttoken(";{", /* } */ cpp_reserved_word)) != EOF) {
 351                                 if (c == '{') /* } */ {
 352                                         pushbacktoken();
 353                                         break;
 354                                 } else if (c == ';') {
 355                                         break;
 356                                 } else if (c == SYMBOL) {
 357                                         PUT(PARSER_REF_SYM, token, lineno, sp);
 358                                 }
 359                         }
 360                         if (c == EOF && (param->flags & PARSER_WARNING))
 361                                 warning("'{' doesn't exist after 'operator'. [+%d %s].", lineno, curfile); /* } */
 362                         break;
 363                 /* control statement check */
 364                 case CPP_THROW:
 365                         startthrow = 1;
 366                 case CPP_BREAK:
 367                 case CPP_CASE:
 368                 case CPP_CATCH:
 369                 case CPP_CONTINUE:
 370                 case CPP_DEFAULT:
 371                 case CPP_DELETE:
 372                 case CPP_DO:
 373                 case CPP_ELSE:
 374                 case CPP_FOR:
 375                 case CPP_GOTO:
 376                 case CPP_IF:
 377                 case CPP_RETURN:
 378                 case CPP_SWITCH:
 379                 case CPP_TRY:
 380                 case CPP_WHILE:
 381                         if ((param->flags & PARSER_WARNING) && !startmacro && level == 0)
 382                                 warning("Out of function. %8s [+%d %s]", token, lineno, curfile);
 383                         break;
 384                 case CPP_TYPEDEF:
 385                         {
 386                                 /*
 387                                  * This parser is too complex to maintain.
 388                                  * We should rewrite the whole.
 389                                  */
 390                                 char savetok[MAXTOKEN];
 391                                 int savelineno = 0;
 392                                 int typedef_savelevel = level;
 393 
 394                                 savetok[0] = 0;
 395 
 396                                 /* skip CV qualifiers */
 397                                 do {
 398                                         c = nexttoken("{}(),;", cpp_reserved_word);
 399                                 } while (IS_CV_QUALIFIER(c) || c == '\n');
 400 
 401                                 if ((param->flags & PARSER_WARNING) && c == EOF) {
 402                                         warning("unexpected eof. [+%d %s]", lineno, curfile);
 403                                         break;
 404                                 } else if (c == CPP_ENUM || c == CPP_STRUCT || c == CPP_UNION) {
 405                                         char *interest_enum = "{},;";
 406                                         int c_ = c;
 407 
 408                                         while ((c = nexttoken(interest_enum, cpp_reserved_word)) == CPP___ATTRIBUTE__)
 409                                                 process_attribute(param);
 410                                         /* read tag name if exist */
 411                                         if (c == SYMBOL) {
 412                                                 if (peekc(0) == '{') /* } */ {
 413                                                         PUT(PARSER_DEF, token, lineno, sp);
 414                                                 } else {
 415                                                         PUT(PARSER_REF_SYM, token, lineno, sp);
 416                                                 }
 417                                                 c = nexttoken(interest_enum, cpp_reserved_word);
 418                                         }
 419                                         if (c_ == CPP_ENUM) {
 420                                                 if (c == '{') /* } */
 421                                                         c = enumerator_list(param);
 422                                                 else
 423                                                         pushbacktoken();
 424                                         } else {
 425                                                 for (; c != EOF; c = nexttoken(interest_enum, cpp_reserved_word)) {
 426                                                         switch (c) {
 427                                                         case SHARP_IFDEF:
 428                                                         case SHARP_IFNDEF:
 429                                                         case SHARP_IF:
 430                                                         case SHARP_ELIF:
 431                                                         case SHARP_ELSE:
 432                                                         case SHARP_ENDIF:
 433                                                                 condition_macro(param, c);
 434                                                                 continue;
 435                                                         default:
 436                                                                 break;
 437                                                         }
 438                                                         if (c == ';' && level == typedef_savelevel) {
 439                                                                 if (savetok[0])
 440                                                                         PUT(PARSER_DEF, savetok, savelineno, sp);
 441                                                                 break;
 442                                                         } else if (c == '{')
 443                                                                 level++;
 444                                                         else if (c == '}') {
 445                                                                 if (--level == typedef_savelevel)
 446                                                                         break;
 447                                                         } else if (c == SYMBOL) {
 448                                                                 PUT(PARSER_REF_SYM, token, lineno, sp);
 449                                                                 /* save lastest token */
 450                                                                 strlimcpy(savetok, token, sizeof(savetok));
 451                                                                 savelineno = lineno;
 452                                                         }
 453                                                 }
 454                                                 if (c == ';')
 455                                                         break;
 456                                         }
 457                                         if ((param->flags & PARSER_WARNING) && c == EOF) {
 458                                                 warning("unexpected eof. [+%d %s]", lineno, curfile);
 459                                                 break;
 460                                         }
 461                                 } else if (c == SYMBOL) {
 462                                         PUT(PARSER_REF_SYM, token, lineno, sp);
 463                                 }
 464                                 savetok[0] = 0;
 465                                 while ((c = nexttoken("(),;", cpp_reserved_word)) != EOF) {
 466                                         switch (c) {
 467                                         case SHARP_IFDEF:
 468                                         case SHARP_IFNDEF:
 469                                         case SHARP_IF:
 470                                         case SHARP_ELIF:
 471                                         case SHARP_ELSE:
 472                                         case SHARP_ENDIF:
 473                                                 condition_macro(param, c);
 474                                                 continue;
 475                                         default:
 476                                                 break;
 477                                         }
 478                                         if (c == '(')
 479                                                 level++;
 480                                         else if (c == ')')
 481                                                 level--;
 482                                         else if (c == SYMBOL) {
 483                                                 if (level > typedef_savelevel) {
 484                                                         PUT(PARSER_REF_SYM, token, lineno, sp);
 485                                                 } else {
 486                                                         /* put latest token if any */
 487                                                         if (savetok[0]) {
 488                                                                 PUT(PARSER_REF_SYM, savetok, savelineno, sp);
 489                                                         }
 490                                                         /* save lastest token */
 491                                                         strlimcpy(savetok, token, sizeof(savetok));
 492                                                         savelineno = lineno;
 493                                                 }
 494                                         } else if (c == ',' || c == ';') {
 495                                                 if (savetok[0]) {
 496                                                         PUT(PARSER_DEF, savetok, lineno, sp);
 497                                                         savetok[0] = 0;
 498                                                 }
 499                                         }
 500                                         if (level == typedef_savelevel && c == ';')
 501                                                 break;
 502                                 }
 503                                 if (param->flags & PARSER_WARNING) {
 504                                         if (c == EOF)
 505                                                 warning("unexpected eof. [+%d %s]", lineno, curfile);
 506                                         else if (level != typedef_savelevel)
 507                                                 warning("unmatched () block. (last at level %d.)[+%d %s]", level, lineno, curfile);
 508                                 }
 509                         }
 510                         break;
 511                 case CPP___ATTRIBUTE__:
 512                         process_attribute(param);
 513                         break;
 514                 default:
 515                         break;
 516                 }
 517         }
 518         strbuf_close(sb);
 519         if (param->flags & PARSER_WARNING) {
 520                 if (level != 0)
 521                         warning("unmatched {} block. (last at level %d.)[+%d %s]", level, lineno, curfile);
 522                 if (piflevel != 0)
 523                         warning("unmatched #if block. (last at level %d.)[+%d %s]", piflevel, lineno, curfile);
 524         }
 525         closetoken();
 526 }
 527 /**
 528  * process_attribute: skip attributes in @CODE{__attribute__((...))}.
 529  */
 530 static void
 531 process_attribute(const struct parser_param *param)
 532 {
 533         int brace = 0;
 534         int c;
 535         /*
 536          * Skip '...' in __attribute__((...))
 537          * but pick up symbols in it.
 538          */
 539         while ((c = nexttoken("()", cpp_reserved_word)) != EOF) {
 540                 if (c == '(')
 541                         brace++;
 542                 else if (c == ')')
 543                         brace--;
 544                 else if (c == SYMBOL) {
 545                         PUT(PARSER_REF_SYM, token, lineno, sp);
 546                 }
 547                 if (brace == 0)
 548                         break;
 549         }
 550 }
 551 /**
 552  * function_definition: return if function definition or not.
 553  *
 554  *      @return target type
 555  */
 556 static int
 557 function_definition(const struct parser_param *param)
 558 {
 559         int c;
 560         int brace_level;
 561 
 562         brace_level = 0;
 563         while ((c = nexttoken("()", cpp_reserved_word)) != EOF) {
 564                 switch (c) {
 565                 case SHARP_IFDEF:
 566                 case SHARP_IFNDEF:
 567                 case SHARP_IF:
 568                 case SHARP_ELIF:
 569                 case SHARP_ELSE:
 570                 case SHARP_ENDIF:
 571                         condition_macro(param, c);
 572                         continue;
 573                 default:
 574                         break;
 575                 }
 576                 if (c == '('/* ) */)
 577                         brace_level++;
 578                 else if (c == /* ( */')') {
 579                         if (--brace_level == 0)
 580                                 break;
 581                 }
 582                 /* pick up symbol */
 583                 if (c == SYMBOL)
 584                         PUT(PARSER_REF_SYM, token, lineno, sp);
 585         }
 586         if (c == EOF)
 587                 return 0;
 588         if (peekc(0) == ';') {
 589                 (void)nexttoken(";", NULL);
 590                 return 0;
 591         }
 592         brace_level = 0;
 593         while ((c = nexttoken(",;[](){}=", cpp_reserved_word)) != EOF) {
 594                 switch (c) {
 595                 case SHARP_IFDEF:
 596                 case SHARP_IFNDEF:
 597                 case SHARP_IF:
 598                 case SHARP_ELIF:
 599                 case SHARP_ELSE:
 600                 case SHARP_ENDIF:
 601                         condition_macro(param, c);
 602                         continue;
 603                 case CPP___ATTRIBUTE__:
 604                         process_attribute(param);
 605                         continue;
 606                 default:
 607                         break;
 608                 }
 609                 if (c == '('/* ) */ || c == '[')
 610                         brace_level++;
 611                 else if (c == /* ( */')' || c == ']')
 612                         brace_level--;
 613                 else if (brace_level == 0 && (c == ';' || c == ','))
 614                         break;
 615                 else if (c == '{' /* } */) {
 616                         pushbacktoken();
 617                         return 1;
 618                 } else if (c == /* { */'}') {
 619                         pushbacktoken();
 620                         break;
 621                 } else if (c == '=')
 622                         break;
 623                 /* pick up symbol */
 624                 if (c == SYMBOL)
 625                         PUT(PARSER_REF_SYM, token, lineno, sp);
 626         }
 627         return 0;
 628 }
 629 
 630 /**
 631  * condition_macro: 
 632  *
 633  *      @param[in]      param
 634  *      @param[in]      cc      token
 635  */
 636 static void
 637 condition_macro(const struct parser_param *param, int cc)
 638 {
 639         cur = &pifstack[piflevel];
 640         if (cc == SHARP_IFDEF || cc == SHARP_IFNDEF || cc == SHARP_IF) {
 641                 DBG_PRINT(piflevel, "#if");
 642                 if (++piflevel >= MAXPIFSTACK)
 643                         die("#if pifstack over flow. [%s]", curfile);
 644                 ++cur;
 645                 cur->start = level;
 646                 cur->end = -1;
 647                 cur->if0only = 0;
 648                 if (peekc(0) == '0')
 649                         cur->if0only = 1;
 650                 else if ((cc = nexttoken(NULL, cpp_reserved_word)) == SYMBOL && !strcmp(token, "notdef"))
 651                         cur->if0only = 1;
 652                 else
 653                         pushbacktoken();
 654         } else if (cc == SHARP_ELIF || cc == SHARP_ELSE) {
 655                 DBG_PRINT(piflevel - 1, "#else");
 656                 if (cur->end == -1)
 657                         cur->end = level;
 658                 else if (cur->end != level && (param->flags & PARSER_WARNING))
 659                         warning("uneven level. [+%d %s]", lineno, curfile);
 660                 level = cur->start;
 661                 cur->if0only = 0;
 662         } else if (cc == SHARP_ENDIF) {
 663                 int minus = 0;
 664 
 665                 --piflevel;
 666                 if (piflevel < 0) {
 667                         minus = 1;
 668                         piflevel = 0;
 669                 }
 670                 DBG_PRINT(piflevel, "#endif");
 671                 if (minus) {
 672                         if (param->flags & PARSER_WARNING)
 673                                 warning("unmatched #if block. reseted. [+%d %s]", lineno, curfile);
 674                 } else {
 675                         if (cur->if0only)
 676                                 level = cur->start;
 677                         else if (cur->end != -1) {
 678                                 if (cur->end != level && (param->flags & PARSER_WARNING))
 679                                         warning("uneven level. [+%d %s]", lineno, curfile);
 680                                 level = cur->end;
 681                         }
 682                 }
 683         }
 684         while ((cc = nexttoken(NULL, cpp_reserved_word)) != EOF && cc != '\n') {
 685                 if (cc == SYMBOL && strcmp(token, "defined") != 0) {
 686                         PUT(PARSER_REF_SYM, token, lineno, sp);
 687                 }
 688         }
 689 }
 690 
 691 /**
 692  * enumerator_list: process @CODE{"symbol (= expression), ... \}"}
 693  */
 694 static int
 695 enumerator_list(const struct parser_param *param)
 696 {
 697         int savelevel = level;
 698         int in_expression = 0;
 699         int c = '{';
 700 
 701         for (; c != EOF; c = nexttoken("{}(),=", cpp_reserved_word)) {
 702                 switch (c) {
 703                 case SHARP_IFDEF:
 704                 case SHARP_IFNDEF:
 705                 case SHARP_IF:
 706                 case SHARP_ELIF:
 707                 case SHARP_ELSE:
 708                 case SHARP_ENDIF:
 709                         condition_macro(param, c);
 710                         break;
 711                 case SYMBOL:
 712                         if (in_expression)
 713                                 PUT(PARSER_REF_SYM, token, lineno, sp);
 714                         else
 715                                 PUT(PARSER_DEF, token, lineno, sp);
 716                         break;
 717                 case '{':
 718                 case '(':
 719                         level++;
 720                         break;
 721                 case '}':
 722                 case ')':
 723                         if (--level == savelevel)
 724                                 return c;
 725                         break;
 726                 case ',':
 727                         if (level == savelevel + 1)
 728                                 in_expression = 0;
 729                         break;
 730                 case '=':
 731                         in_expression = 1;
 732                         break;
 733                 default:
 734                         break;
 735                 }
 736         }
 737 
 738         return c;
 739 }

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