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

  1.  
  2. /*
  3.  *                          C P P 4 . C
  4.  *              M a c r o  D e f i n i t i o n s
  5.  *
  6.  * Edit History
  7.  * 31-Aug-84    MM      USENET net.sources release
  8.  * 04-Oct-84    MM      __LINE__ and __FILE__ must call ungetstring()
  9.  *                      so they work correctly with token concatenation.
  10.  *                      Added string formal recognition.
  11.  * 25-Oct-84    MM      "Short-circuit" evaluate #if's so that we
  12.  *                      don't print unnecessary error messages for
  13.  *                      #if !defined(FOO) && FOO != 0 && 10 / FOO ...
  14.  * 31-Oct-84    ado/MM  Added token concatenation
  15.  *  6-Nov-84    MM      Split off eval stuff
  16.  *  1-Apr-85    ado     Fixed bug in STRING_FORMAL version
  17.  *  2-May-85    MM      Changed the way macro parameters work -- only
  18.  *                      one byte is reserved, 255 param's possible.
  19.  */
  20.  
  21. #include        "cppdef.h"
  22. #include        "cpp.h"
  23.  
  24. FILE_LOCAL void    mtokensave();
  25. FILE_LOCAL void    expstuff();
  26.  
  27.  
  28. #if OK_CONCAT == CON_NOEXPAND
  29. #define SEP     COM_SEP                 /* concat token, don't reexpand */
  30. #endif
  31. #if OK_CONCAT == CON_EXPAND
  32. #define SEP     TOK_SEP                 /* concat token and reexpand    */
  33. #endif
  34.  
  35. /*
  36.  * parm[], parmp, and parlist[] are used to store #define() argument
  37.  * lists.  nargs contains the actual number of parameters stored.
  38.  */
  39. static char     parm[NPARMWORK + 1];    /* define param work buffer     */
  40. static char     *parmp;                 /* Free space in parm           */
  41. static char     *parlist[NMACPARS];     /* -> start of each parameter   */
  42. static int      nargs;                  /* Parameters for this macro    */
  43.  
  44. void
  45. dodefine()
  46. /*
  47.  * Called from control when a #define is scanned.  This module
  48.  * parses formal parameters and the replacement string.  When
  49.  * the formal parameter name is encountered in the replacement
  50.  * string, it is replaced by a character in the range 128 to
  51.  * 128+NPARAM (this allows up to 32 parameters within the
  52.  * Dec Multinational range).  If cpp is ported to an EBCDIC
  53.  * machine, you will have to make other arrangements.
  54.  *
  55.  * There is some special case code to distinguish
  56.  *      #define foo     bar
  57.  * from #define foo()   bar
  58.  *
  59.  * Also, we make sure that
  60.  *      #define foo     foo
  61.  * expands to "foo" but doesn't put cpp into an infinite loop.
  62.  *
  63.  * A warning message is printed if you redefine a symbol to a
  64.  * different text.  I.e,
  65.  *      #define foo     123
  66.  *      #define foo     123
  67.  * is ok, but
  68.  *      #define foo     123
  69.  *      #define foo     +123
  70.  * is not.
  71.  *
  72.  * The following subroutines are called from define():
  73.  * checkparm    called when a token is scanned.  It checks through the
  74.  *              array of formal parameters.  If a match is found, the
  75.  *              token is replaced by a control byte which will be used
  76.  *              to locate the parameter when the macro is expanded.
  77.  * textput      puts a string in the macro work area (parm[]), updating
  78.  *              parmp to point to the first free byte in parm[].
  79.  *              textput() tests for work buffer overflow.
  80.  * charput      puts a single character in the macro work area (parm[])
  81.  *              in a manner analogous to textput().
  82.  */
  83. {
  84.         register int            c;
  85.         register DEFBUF         *dp;            /* -> new definition    */
  86.         int                     isredefine;     /* TRUE if redefined    */
  87.         char                    *old;           /* Remember redefined   */
  88.  
  89.         if (type[(c = skipws())] != LET)
  90.             goto bad_define;
  91.         isredefine = FALSE;                     /* Set if redefining    */
  92.         if ((dp = lookid(c)) == NULL)           /* If not known now     */
  93.             dp = defendel(token, FALSE);        /* Save the name        */
  94.         else {                                  /* It's known:          */
  95.             isredefine = TRUE;                  /* Remember this fact   */
  96.             old = dp->repl;                     /* Remember replacement */
  97.             dp->repl = NULL;                    /* No replacement now   */
  98.         }
  99.         parlist[0] = parmp = parm;              /* Setup parm buffer    */
  100.         if ((c = get()) == '(') {               /* With arguments?      */
  101.             nargs = 0;                          /* Init formals counter */
  102.             do {                                /* Collect formal parms */
  103.                 if (nargs >= NMACPARS)
  104.                     cfatal("Too many arguments for macro", NULLST);
  105.                 else if ((c = skipws()) == ')')
  106.                     break;                      /* Got them all         */
  107.                 else if (type[c] != LET)        /* Bad formal syntax    */
  108.                     goto bad_define;
  109.                 scanid(c);                      /* Get the formal param */
  110.                 parlist[nargs++] = parmp;       /* Save its start       */
  111.                 textput(token);                 /* Save text in parm[]  */
  112.             } while ((c = skipws()) == ',');    /* Get another argument */
  113.             if (c != ')')                       /* Must end at )        */
  114.                 goto bad_define;
  115.             c = ' ';                            /* Will skip to body    */
  116.         }
  117.         else {
  118.             /*
  119.              * DEF_NOARGS is needed to distinguish between
  120.              * "#define foo" and "#define foo()".
  121.              */
  122.             nargs = DEF_NOARGS;                 /* No () parameters     */
  123.         }
  124.         if (type[c] == SPA)                     /* At whitespace?       */
  125.             c = skipws();                       /* Not any more.        */
  126.         workp = work;                           /* Replacement put here */
  127.         inmacro = TRUE;                         /* Keep \<newline> now  */
  128.         for (; c != EOF_CHAR && c != '\n'; c = get()) {
  129. #if OK_CONCAT != CON_FALSE
  130.             if (c == '#') {                     /* String/concat?       */
  131.                 if ((c = get()) == '#') {       /* Concatenate tokens?  */
  132.                     while (workp > work && type[workp[-1]] == SPA)
  133.                         --workp;                /* Erase leading spaces */
  134.                     save(SEP);
  135.                     c = skipws();               /* Eat whitespace       */
  136.                     switch (type[c]) {          /* What flavor of token */
  137.                     case LET:
  138.                         checkparm(c, dp);       /* Save it normally     */
  139.                         break;
  140.  
  141.                     case DIG:
  142.                         do {                    /* Stuff the digits     */
  143.                             save(c);
  144.                             c = get();
  145.                         } while (type[c] == DIG);
  146.                         break;
  147.  
  148.                     default:
  149.                         ciwarn("Strange character after # (%d.)", c);
  150.                         save(c);
  151.                         break;
  152.                     }
  153.                     save(SEP);                  /* Delimit 2nd token    */
  154.                 }
  155.                 else {                          /* Stringize            */
  156.                     unget();                    /* Gotta rescan it      */
  157.                     /*
  158.                      * We store a magic cookie (which becomes " on output)
  159.                      * so the macro expander doesn't block expansion
  160.                      * of the actual parameter.  For example,
  161.                      *          #define abc(a) #a
  162.                      *          abc(__LINE__)
  163.                      * should yield "123", not "__LINE__".
  164.                      * This is a hack, and probably going to cause trouble.
  165.                      */
  166.                     save(ST_QUOTE);
  167.                     if ((c = isformal(skipws())) == 0) {
  168.                         cwarn("Expected formal parameter, got \"%s\"", token);
  169.                         mtokensave(dp);
  170.                     }
  171.                     save(ST_QUOTE);
  172.                 }
  173.                 continue;                       /* Done with this token */
  174.             }
  175. #endif
  176.             switch (ty