home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Guide / c-cplusplus-interactive-guide.iso / c_ref / csource4 / 243_01 / cpp2.c < prev    next >
C/C++ Source or Header  |  1990-05-14  |  21KB  |  644 lines

  1.  
  2. /*
  3.  *                              C P P 2 . C
  4.  *
  5.  *                         Process #control lines
  6.  *
  7.  * Edit history
  8.  * 13-Nov-84    MM      Split from cpp1.c
  9.  * 06-Jun-85    KR      fixed #include bug in doinclude()
  10.  */
  11.  
  12. #include        "cppdef.h"
  13. #include        "cpp.h"
  14.  
  15. FILE_LOCAL int    openinclude();
  16. FILE_LOCAL void    doinclude();
  17. FILE_LOCAL void    doif();
  18.  
  19.  
  20. #if HOST == SYS_VMS
  21. /*
  22.  * Include the rms stuff.  (We can't just include rms.h as it uses the
  23.  * VaxC-specific library include syntax that Decus CPP doesn't support.
  24.  * By including things by hand, we can CPP ourself.)
  25.  */
  26. #include        <nam.h>
  27. #include        <fab.h>
  28. #include        <rab.h>
  29. #include        <rmsdef.h>
  30. #endif
  31.  
  32. /*
  33.  * Generate (by hand-inspection) a set of unique values for each control
  34.  * operator.  Note that this is not guaranteed to work for non-Ascii
  35.  * machines.  CPP won't compile if there are hash conflicts.
  36.  */
  37.  
  38. #define L_assert        ('a' + ('s' << 1))
  39. #define L_define        ('d' + ('f' << 1))
  40. #define L_elif          ('e' + ('i' << 1))
  41. #define L_else          ('e' + ('s' << 1))
  42. #define L_endif         ('e' + ('d' << 1))
  43. #define L_if            ('i' + (EOS << 1))
  44. #define L_ifdef         ('i' + ('d' << 1))
  45. #define L_ifndef        ('i' + ('n' << 1))
  46. #define L_include       ('i' + ('c' << 1))
  47. #define L_line          ('l' + ('n' << 1))
  48. #define L_nogood        (EOS + (EOS << 1))      /* To catch #i          */
  49. #define L_pragma        ('p' + ('a' << 1))
  50. #define L_undef         ('u' + ('d' << 1))
  51. #if DEBUG
  52. #define L_debug         ('d' + ('b' << 1))      /* #debug               */
  53. #endif
  54.  
  55. int
  56. control(counter)
  57. int             counter;        /* Pending newline counter              */
  58. /*
  59.  * Process #control lines.  Simple commands are processed inline,
  60.  * while complex commands have their own subroutines.
  61.  *
  62.  * The counter is used to force out a newline before #line, and
  63.  * #pragma commands.  This prevents these commands from ending up at
  64.  * the end of the previous line if cpp is invoked with the -C option.
  65.  */
  66. {
  67.         register int            c;
  68.         register char           *tp;
  69.         register int            hash;
  70.         char                    *ep;
  71.  
  72.         c = skipws();
  73.         if (c == '\n' || c == EOF_CHAR)
  74.             return (counter + 1);
  75.         if (!isdigit(c))
  76.             scanid(c);                  /* Get #word to token[]         */
  77.         else {
  78.             unget();                    /* Hack -- allow #123 as a      */
  79.             strcpy(token, "line");      /* synonym for #line 123        */
  80.         }
  81.         hash = (token[1] == EOS) ? L_nogood : (token[0] + (token[2] << 1));
  82.         switch (hash) {
  83.         case L_assert:  tp = "assert";          break;
  84.         case L_define:  tp = "define";          break;
  85.         case L_elif:    tp = "elif";            break;
  86.         case L_else:    tp = "else";            break;
  87.         case L_endif:   tp = "endif";           break;
  88.         case L_if:      tp = "if";              break;
  89.         case L_ifdef:   tp = "ifdef";           break;
  90.         case L_ifndef:  tp = "ifndef";          break;
  91.         case L_include: tp = "include";         break;
  92.         case L_line:    tp = "line";            break;
  93.         case L_pragma:  tp = "pragma";          break;
  94.         case L_undef:   tp = "undef";           break;
  95. #if DEBUG
  96.         case L_debug:   tp = "debug";           break;
  97. #endif
  98.         default:        hash = L_nogood;
  99.         case L_nogood:  tp = "";                break;
  100.         }
  101.         if (!streq(tp, token))
  102.             hash = L_nogood;
  103.         /*
  104.          * hash is set to a unique value corresponding to the
  105.          * control keyword (or L_nogood if we think it's nonsense).
  106.          */
  107.         if (infile->fp == NULL)
  108.             cwarn("Control line \"%s\" within macro expansion", token);
  109.         if (!compiling) {                       /* Not compiling now    */
  110.             switch (hash) {
  111.             case L_if:                          /* These can't turn     */
  112.             case L_ifdef:                       /*  compilation on, but */
  113.             case L_ifndef:                      /*   we must nest #if's */
  114.                 if (++ifptr >= &ifstack[BLK_NEST])
  115.                     goto if_nest_err;
  116.                 *ifptr = 0;                     /* !WAS_COMPILING       */
  117.             case L_line:                        /* Many                 */
  118.             /*
  119.              * Are pragma's always processed?
  120.              */
  121.             case L_pragma:                      /*  options             */
  122.             case L_include:                     /*   are uninteresting  */
  123.             case L_define:                      /*    if we             */
  124.             case L_undef:                       /*     aren't           */
  125.             case L_assert:                      /*      compiling.      */
  126. dump_line:      skipnl();                       /* Ignore rest of line  */
  127.                 return (counter + 1);
  128.             }
  129.         }
  130.         /*
  131.          * Make sure that #line and #pragma are output on a fresh line.
  132.          */
  133.         if (counter > 0 && (hash == L_line || hash == L_pragma)) {
  134.             putchar('\n');
  135.             counter--;
  136.         }
  137.         switch (hash) {
  138.         case L_line:
  139.             /*
  140.              * Parse the line to update the line number and "progname"
  141.              * field and line number for the next input line.
  142.              * Set wrongline to force it out later.
  143.              */
  144.             c = skipws();
  145.             workp = work;                       /* Save name in work    */
  146.             while (c != '\n' && c != EOF_CHAR) {
  147.                 save(c);
  148.                 c = get();
  149.             }
  150.             unget();
  151.             save(EOS);
  152.             /*
  153.              * Split #line argument into <line-number> and <name>
  154.              * We subtract 1 as we want the number of the next line.
  155.              */
  156.             line = atoi(work) - 1;              /* Reset line number    */
  157.             for (tp = work; isdigit(*tp) || type[*tp] == SPA; tp++)
  158.                 ;                               /* Skip over digits     */
  159.             if (*tp != EOS) {                   /* Got a filename, so:  */
  160.                 if (*tp == '"' && (ep = strrchr(tp + 1, '"')) != NULL) {
  161.                     tp++;                       /* Skip over left quote */
  162.                     *ep = EOS;                  /* And ignore right one */
  163.                 }
  164.                 if (infile->progname != NULL)   /* Give up the old name */
  165.                     free(infile->progname);     /* if it's allocated.   */
  166.                 infile->progname = savestring(tp);
  167.             }
  168.             wrongline = TRUE;                   /* Force output later   */
  169.             break;
  170.  
  171.         case L_include:
  172.             doinclude();
  173.             break;
  174.  
  175.         case L_define:
  176.             dodefine();
  177.             break;
  178.  
  179.         case L_undef:
  180.             doundef();
  181.             break;
  182.  
  183.         case L_else:
  184.             if (ifptr == &ifstack[0])
  185.                 goto nest_err;
  186.             else if ((*ifptr & ELSE_SEEN) != 0)
  187.                 goto else_seen_err;
  188.             *ifptr |= ELSE_SEEN;
  189.             if ((*ifptr & WAS_COMPILING) != 0) {
  190.                 if (compiling || (*ifptr & TRUE_SEEN) != 0)
  191.                     compiling = FALSE;
  192.                 else {
  193.                     compiling = TRUE;
  194.                 }
  195.             }
  196.             break;
  197.  
  198.         case L_elif:
  199.             if (ifptr == &ifstack[0])
  200.                 goto nest_err;
  201.             else if ((*ifptr & ELSE_SEEN) != 0) {
  202. else_seen_err:  cerror("#%s may not follow #else", token);
  203.                 goto dump_line;
  204.             }
  205.             if ((*ifptr & (WAS_COMPILING | TRUE_SEEN)) != WAS_COMPILING) {
  206.                 compiling = FALSE;              /* Done compiling stuff */
  207.                 goto dump_line;                 /* Skip this clause     */
  208.             }
  209.             doif(L_if);
  210.             break;
  211.  
  212.         case L_if:
  213.         case L_ifdef:
  214.         case L_ifndef:
  215.             if (