LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/ucpp - macro.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 921 0.0 %
Date: 2012-12-17 Functions: 0 23 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * (c) Thomas Pornin 1999 - 2002
       3             :  *
       4             :  * Redistribution and use in source and binary forms, with or without
       5             :  * modification, are permitted provided that the following conditions
       6             :  * are met:
       7             :  * 1. Redistributions of source code must retain the above copyright
       8             :  *    notice, this list of conditions and the following disclaimer.
       9             :  * 2. Redistributions in binary form must reproduce the above copyright
      10             :  *    notice, this list of conditions and the following disclaimer in the
      11             :  *    documentation and/or other materials provided with the distribution.
      12             :  * 4. The name of the authors may not be used to endorse or promote
      13             :  *    products derived from this software without specific prior written
      14             :  *    permission.
      15             :  *
      16             :  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
      17             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
      18             :  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      19             :  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
      20             :  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      21             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
      22             :  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
      23             :  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      24             :  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
      25             :  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
      26             :  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      27             :  *
      28             :  */
      29             : 
      30             : #include "tune.h"
      31             : #include <stdio.h>
      32             : #include <string.h>
      33             : #include <stddef.h>
      34             : #include <limits.h>
      35             : #include "ucppi.h"
      36             : #include "mem.h"
      37             : #include "nhash.h"
      38             : 
      39             : /*
      40             :  * we store macros in a hash table, and retrieve them using their name
      41             :  * as identifier.
      42             :  */
      43             : static HTT macros;
      44             : static int macros_init_done = 0;
      45             : 
      46           0 : static void del_macro(void *m)
      47             : {
      48           0 :         struct macro *n = m;
      49             :         size_t i;
      50             : 
      51           0 :         for (i = 0; (int)i < n->narg; i ++) freemem(n->arg[i]);
      52           0 :         if (n->narg > 0) freemem(n->arg);
      53             : #ifdef LOW_MEM
      54           0 :         if (n->cval.length) freemem(n->cval.t);
      55             : #else
      56             :         if (n->val.nt) {
      57             :                 for (i = 0; i < n->val.nt; i ++)
      58             :                         if (S_TOKEN(n->val.t[i].type))
      59             :                                 freemem(n->val.t[i].name);
      60             :                 freemem(n->val.t);
      61             :         }
      62             : #endif
      63           0 :         freemem(n);
      64           0 : }
      65             : 
      66           0 : static inline struct macro *new_macro(void)
      67             : {
      68           0 :         struct macro *m = getmem(sizeof(struct macro));
      69             : 
      70           0 :         m->narg = -1;
      71           0 :         m->nest = 0;
      72             : #ifdef LOW_MEM
      73           0 :         m->cval.length = 0;
      74             : #else
      75             :         m->val.nt = m->val.art = 0;
      76             : #endif
      77           0 :         m->vaarg = 0;
      78           0 :         return m;
      79             : }
      80             : 
      81             : /*
      82             :  * for special macros, and the "defined" operator
      83             :  */
      84             : enum {
      85             :         MAC_NONE, MAC_DEFINED,
      86             :         MAC_LINE, MAC_FILE, MAC_DATE, MAC_TIME, MAC_STDC, MAC_PRAGMA
      87             : };
      88             : #define MAC_SPECIAL     MAC_LINE
      89             : 
      90             : /*
      91             :  * returns 1 for "defined"
      92             :  * returns x > 1 for a special macro such as __FILE__
      93             :  * returns 0 otherwise
      94             :  */
      95           0 : static inline int check_special_macro(char *name)
      96             : {
      97           0 :         if (!strcmp(name, "defined")) return MAC_DEFINED;
      98           0 :         if (*name != '_') return MAC_NONE;
      99           0 :         if (*(name + 1) == 'P') {
     100           0 :                 if (!strcmp(name, "_Pragma")) return MAC_PRAGMA;
     101           0 :                 return MAC_NONE;
     102           0 :         } else if (*(name + 1) != '_') return MAC_NONE;
     103           0 :         if (no_special_macros) return MAC_NONE;
     104           0 :         if (!strcmp(name, "__LINE__")) return MAC_LINE;
     105           0 :         else if (!strcmp(name, "__FILE__")) return MAC_FILE;
     106           0 :         else if (!strcmp(name, "__DATE__")) return MAC_DATE;
     107           0 :         else if (!strcmp(name, "__TIME__")) return MAC_TIME;
     108           0 :         else if (!strcmp(name, "__STDC__")) return MAC_STDC;
     109           0 :         return MAC_NONE;
     110             : }
     111             : 
     112             : int c99_compliant = 1;
     113             : int c99_hosted = 1;
     114             : 
     115             : /*
     116             :  * add the special macros to the macro table
     117             :  */
     118           0 : static void add_special_macros(void)
     119             : {
     120             :         struct macro *m;
     121             : 
     122           0 :         HTT_put(&macros, new_macro(), "__LINE__");
     123           0 :         HTT_put(&macros, new_macro(), "__FILE__");
     124           0 :         HTT_put(&macros, new_macro(), "__DATE__");
     125           0 :         HTT_put(&macros, new_macro(), "__TIME__");
     126           0 :         HTT_put(&macros, new_macro(), "__STDC__");
     127           0 :         m = new_macro(); m->narg = 1;
     128           0 :         m->arg = getmem(sizeof(char *)); m->arg[0] = sdup("foo");
     129           0 :         HTT_put(&macros, m, "_Pragma");
     130           0 :         if (c99_compliant) {
     131             : #ifndef LOW_MEM
     132             :                 struct token t;
     133             : #endif
     134             : 
     135           0 :                 m = new_macro();
     136             : #ifdef LOW_MEM
     137           0 :                 m->cval.t = getmem(9);
     138           0 :                 m->cval.t[0] = NUMBER;
     139           0 :                 mmv(m->cval.t + 1, "199901L", 8);
     140           0 :                 m->cval.length = 9;
     141             : #else
     142             :                 t.type = NUMBER;
     143             :                 t.line = 0;
     144             :                 t.name = sdup("199901L");
     145             :                 aol(m->val.t, m->val.nt, t, TOKEN_LIST_MEMG);
     146             : #endif
     147           0 :                 HTT_put(&macros, m, "__STDC_VERSION__");
     148             :         }
     149           0 :         if (c99_hosted) {
     150             : #ifndef LOW_MEM
     151             :                 struct token t;
     152             : #endif
     153             : 
     154           0 :                 m = new_macro();
     155             : #ifdef LOW_MEM
     156           0 :                 m->cval.t = getmem(3);
     157           0 :                 m->cval.t[0] = NUMBER;
     158           0 :                 mmv(m->cval.t + 1, "1", 2);
     159           0 :                 m->cval.length = 3;
     160             : #else
     161             :                 t.type = NUMBER;
     162             :                 t.line = 0;
     163             :                 t.name = sdup("1");
     164             :                 aol(m->val.t, m->val.nt, t, TOKEN_LIST_MEMG);
     165             : #endif
     166           0 :                 HTT_put(&macros, m, "__STDC_HOSTED__");
     167             :         }
     168           0 : }
     169             : 
     170             : #ifdef LOW_MEM
     171             : /*
     172             :  * We store macro arguments as a single-byte token MACROARG, followed
     173             :  * by the argument number as a one or two-byte value. If the argument
     174             :  * number is between 0 and 127 (inclusive), it is stored as such in
     175             :  * a single byte. Otherwise, it is supposed to be a 14-bit number, with
     176             :  * the 7 upper bits stored in the first byte (with the high bit set to 1)
     177             :  * and the 7 lower bits in the second byte.
     178             :  */
     179             : #endif
     180             : 
     181             : /*
     182             :  * print the content of a macro, in #define form
     183             :  */
     184           0 : static void print_macro(void *vm)
     185             : {
     186           0 :         struct macro *m = vm;
     187           0 :         char *mname = HASH_ITEM_NAME(m);
     188           0 :         int x = check_special_macro(mname);
     189             :         size_t i;
     190             : 
     191           0 :         if (x != MAC_NONE) {
     192           0 :                 fprintf(emit_output, "/* #define %s */ /* special */\n",
     193             :                         mname);
     194           0 :                 return;
     195             :         }
     196           0 :         fprintf(emit_output, "#define %s", mname);
     197           0 :         if (m->narg >= 0) {
     198           0 :                 fprintf(emit_output, "(");
     199           0 :                 for (i = 0; i < (size_t)(m->narg); i ++) {
     200           0 :                         fprintf(emit_output, i ? ", %s" : "%s", m->arg[i]);
     201             :                 }
     202           0 :                 if (m->vaarg) {
     203           0 :                         fputs(m->narg ? ", ..." : "...", emit_output);
     204             :                 }
     205           0 :                 fprintf(emit_output, ")");
     206             :         }
     207             : #ifdef LOW_MEM
     208           0 :         if (m->cval.length == 0) {
     209           0 :                 fputc('\n', emit_output);
     210           0 :                 return;
     211             :         }
     212           0 :         fputc(' ', emit_output);
     213           0 :         for (i = 0; i < m->cval.length;) {
     214           0 :                 int tt = m->cval.t[i ++];
     215             : 
     216           0 :                 if (tt == MACROARG) {
     217           0 :                         unsigned anum = m->cval.t[i];
     218             : 
     219           0 :                         if (anum >= 128) anum = ((anum & 127U) << 8)
     220           0 :                                 | m->cval.t[++ i];
     221           0 :                         if (anum == (unsigned)m->narg)
     222           0 :                                 fputs("__VA_ARGS__", emit_output);
     223             :                         else
     224           0 :                                 fputs(m->arg[anum], emit_output);
     225           0 :                         i ++;
     226             :                 }
     227           0 :                 else if (S_TOKEN(tt)) {
     228           0 :                         fputs((char *)(m->cval.t + i), emit_output);
     229           0 :                         i += 1 + strlen((char *)(m->cval.t + i));
     230           0 :                 } else fputs(operators_name[tt], emit_output);
     231             :         }
     232             : #else
     233             :         if (m->val.nt == 0) {
     234             :                 fputc('\n', emit_output);
     235             :                 return;
     236             :         }
     237             :         fputc(' ', emit_output);
     238             :         for (i = 0; i < m->val.nt; i ++) {
     239             :                 if (m->val.t[i].type == MACROARG) {
     240             :                         if (m->val.t[i].line == m->narg)
     241             :                                 fputs("__VA_ARGS__", emit_output);
     242             :                         else
     243             :                                 fputs(m->arg[(size_t)(m->val.t[i].line)],
     244             :                                         emit_output);
     245             :                 } else fputs(token_name(m->val.t + i), emit_output);
     246             :         }
     247             : #endif
     248           0 :         fputc('\n', emit_output);
     249             : }
     250             : 
     251             : /*
     252             :  * Send a token to the output (a token_fifo in lexer mode, the output
     253             :  * buffer in stand alone mode).
     254             :  */
     255           0 : void print_token(struct lexer_state *ls, struct token *t, long uz_line)
     256             : {
     257           0 :         char *x = t->name;
     258             : 
     259           0 :         if (uz_line && t->line < 0) t->line = uz_line;
     260           0 :         if (ls->flags & LEXER) {
     261             :                 struct token at;
     262             : 
     263           0 :                 at = *t;
     264           0 :                 if (S_TOKEN(t->type)) {
     265           0 :                         at.name = sdup(at.name);
     266           0 :                         throw_away(ls->gf, at.name);
     267             :                 }
     268           0 :                 aol(ls->output_fifo->t, ls->output_fifo->nt, at,
     269             :                         TOKEN_LIST_MEMG);
     270           0 :                 return;
     271             :         }
     272           0 :         if (ls->flags & KEEP_OUTPUT) {
     273           0 :                 for (; ls->oline < ls->line;) put_char(ls, '\n');
     274             :         }
     275           0 :         if (!S_TOKEN(t->type)) x = operators_name[t->type];
     276           0 :         for (; *x; x ++) put_char(ls, *x);
     277             : }
     278             : 
     279             : /*
     280             :  * Send a token to the output at a given line (this is for text output
     281             :  * and unreplaced macros due to lack of arguments).
     282             :  */
     283           0 : static void print_token_nailed(struct lexer_state *ls, struct token *t,
     284             :         long nail_line)
     285             : {
     286           0 :         char *x = t->name;
     287             : 
     288           0 :         if (ls->flags & LEXER) {
     289           0 :                 print_token(ls, t, 0);
     290           0 :                 return;
     291             :         }
     292           0 :         if (ls->flags & KEEP_OUTPUT) {
     293           0 :                 for (; ls->oline < nail_line;) put_char(ls, '\n');
     294             :         }
     295           0 :         if (!S_TOKEN(t->type)) x = operators_name[t->type];
     296           0 :         for (; *x; x ++) put_char(ls, *x);
     297             : }
     298             : 
     299             : /*
     300             :  * send a reduced whitespace token to the output
     301             :  */
     302             : #define print_space(ls) do { \
     303             :                 struct token lt; \
     304             :                 lt.type = OPT_NONE; \
     305             :                 lt.line = (ls)->line; \
     306             :                 print_token((ls), &lt, 0); \
     307             :         } while (0)
     308             : 
     309             : /*
     310             :  * We found a #define directive; parse the end of the line, perform
     311             :  * sanity checks, store the new macro into the "macros" hash table.
     312             :  *
     313             :  * In case of a redefinition of a macro: we enforce the rule that a
     314             :  * macro should be redefined identically, including the spelling of
     315             :  * parameters. We emit an error on offending code; dura lex, sed lex.
     316             :  * After all, it is easy to avoid such problems, with a #undef directive.
     317             :  */
     318           0 : int handle_define(struct lexer_state *ls)
     319             : {
     320           0 :         struct macro *m = 0, *n;
     321             : #ifdef LOW_MEM
     322             :         struct token_fifo mv;
     323             : #endif
     324           0 :         int ltwws = 1, redef = 0;
     325           0 :         char *mname = 0;
     326             :         int narg;
     327             :         size_t nt;
     328           0 :         long l = ls->line;
     329             :         
     330             : #ifdef LOW_MEM
     331           0 :         mv.art = mv.nt = 0;
     332             : #endif
     333             :         /* find the next non-white token on the line, this should be
     334             :            the macro name */
     335           0 :         while (!next_token(ls) && ls->ctok->type != NEWLINE) {
     336           0 :                 if (ttMWS(ls->ctok->type)) continue;
     337           0 :                 if (ls->ctok->type == NAME) mname = sdup(ls->ctok->name);
     338           0 :                 break;
     339             :         }
     340           0 :         if (mname == 0) {
     341           0 :                 error(l, "missing macro name");
     342           0 :                 return 1;
     343             :         }
     344           0 :         if (check_special_macro(mname)) {
     345           0 :                 error(l, "trying to redefine the special macro %s", mname);
     346           0 :                 goto warp_error;
     347             :         }
     348             :         /*
     349             :          * If a macro with this name was already defined: the K&R
     350             :          * states that the new macro should be identical to the old one
     351             :          * (with some arcane rule of equivalence of whitespace); otherwise,
     352             :          * redefining the macro is an error. Most preprocessors would
     353             :          * only emit a warning (or nothing at all) on an unidentical
     354             :          * redefinition.
     355             :          *
     356             :          * Since it is easy to avoid this error (with a #undef directive),
     357             :          * we choose to enforce the rule and emit an error.
     358             :          */
     359           0 :         if ((n = HTT_get(&macros, mname)) != 0) {
     360             :                 /* redefinition of a macro: we must check that we define
     361             :                    it identical */
     362           0 :                 redef = 1;
     363             : #ifdef LOW_MEM
     364           0 :                 n->cval.rp = 0;
     365             : #endif
     366           0 :                 freemem(mname);
     367           0 :                 mname = 0;
     368             :         }
     369           0 :         if (!redef) {
     370           0 :                 m = new_macro();
     371           0 :                 m->narg = -1;
     372             : #ifdef LOW_MEM
     373             : #define mval    mv
     374             : #else
     375             : #define mval    (m->val)
     376             : #endif
     377             :         }
     378           0 :         if (next_token(ls)) goto define_end;
     379             :         /*
     380             :          * Check if the token immediately following the macro name is
     381             :          * a left parenthesis; if so, then this is a macro with arguments.
     382             :          * Collect their names and try to match the next parenthesis.
     383             :          */
     384           0 :         if (ls->ctok->type == LPAR) {
     385             :                 int i, j;
     386           0 :                 int need_comma = 0, saw_mdots = 0;
     387             : 
     388           0 :                 narg = 0;
     389           0 :                 while (!next_token(ls)) {
     390           0 :                         if (ls->ctok->type == NEWLINE) {
     391           0 :                                 error(l, "truncated macro definition");
     392           0 :                                 goto define_error;
     393             :                         }
     394           0 :                         if (ls->ctok->type == COMMA) {
     395           0 :                                 if (saw_mdots) {
     396           0 :                                         error(l, "'...' must end the macro "
     397             :                                                 "argument list");
     398           0 :                                         goto warp_error;
     399             :                                 }
     400           0 :                                 if (!need_comma) {
     401           0 :                                         error(l, "void macro argument");
     402           0 :                                         goto warp_error;
     403             :                                 }
     404           0 :                                 need_comma = 0;
     405           0 :                                 continue;
     406           0 :                         } else if (ls->ctok->type == NAME) {
     407           0 :                                 if (saw_mdots) {
     408           0 :                                         error(l, "'...' must end the macro "
     409             :                                                 "argument list");
     410           0 :                                         goto warp_error;
     411             :                                 }
     412           0 :                                 if (need_comma) {
     413           0 :                                         error(l, "missing comma in "
     414             :                                                 "macro argument list");
     415           0 :                                         goto warp_error;
     416             :                                 }
     417           0 :                                 if (!redef) {
     418           0 :                                         aol(m->arg, narg,
     419             :                                                 sdup(ls->ctok->name), 8);
     420             :                                         /* we must keep track of m->narg
     421             :                                            so that cleanup in case of
     422             :                                            error works. */
     423           0 :                                         m->narg = narg;
     424           0 :                                         if (narg == 128
     425           0 :                                                 && (ls->flags & WARN_STANDARD))
     426           0 :                                                 warning(l, "more arguments to "
     427             :                                                         "macro than the ISO "
     428             :                                                         "limit (127)");
     429             : #ifdef LOW_MEM
     430           0 :                                         if (narg == 32767) {
     431           0 :                                                 error(l, "too many arguments "
     432             :                                                         "in macro definition "
     433             :                                                         "(max 32766)");
     434           0 :                                                 goto warp_error;
     435             :                                         }
     436             : #endif
     437             :                                 } else {
     438             :                                         /* this is a redefinition of the
     439             :                                            macro; check equality between
     440             :                                            old and new definitions */
     441           0 :                                         if (narg >= n->narg) goto redef_error;
     442           0 :                                         if (strcmp(ls->ctok->name,
     443           0 :                                                 n->arg[narg ++]))
     444           0 :                                                 goto redef_error;
     445             :                                 }
     446           0 :                                 need_comma = 1;
     447           0 :                                 continue;
     448           0 :                         } else if ((ls->flags & MACRO_VAARG)
     449           0 :                                 && ls->ctok->type == MDOTS) {
     450           0 :                                 if (need_comma) {
     451           0 :                                         error(l, "missing comma before '...'");
     452           0 :                                         goto warp_error;
     453             :                                 }
     454           0 :                                 if (redef && !n->vaarg) goto redef_error;
     455           0 :                                 if (!redef) m->vaarg = 1;
     456           0 :                                 saw_mdots = 1;
     457           0 :                                 need_comma = 1;
     458           0 :                                 continue;
     459           0 :                         } else if (ls->ctok->type == RPAR) {
     460           0 :                                 if (narg > 0 && !need_comma) {
     461           0 :                                         error(l, "void macro argument");
     462           0 :                                         goto warp_error;
     463             :                                 }
     464           0 :                                 if (redef && n->vaarg && !saw_mdots)
     465           0 :                                         goto redef_error;
     466           0 :                                 break;
     467           0 :                         } else if (ttMWS(ls->ctok->type)) {
     468           0 :                                 continue;
     469             :                         }
     470           0 :                         error(l, "invalid macro argument");
     471           0 :                         goto warp_error;
     472             :                 }
     473           0 :                 if (!redef) {
     474           0 :                         for (i = 1; i < narg; i ++) for (j = 0; j < i; j ++)
     475           0 :                                 if (!strcmp(m->arg[i], m->arg[j])) {
     476           0 :                                         error(l, "duplicate macro "
     477             :                                                 "argument");
     478           0 :                                         goto warp_error;
     479             :                                 }
     480             :                 }
     481           0 :                 if (!redef) m->narg = narg;
     482             :         } else {
     483           0 :                 if (!ttWHI(ls->ctok->type) && (ls->flags & WARN_STANDARD))
     484           0 :                         warning(ls->line, "identifier not followed by "
     485             :                                 "whitespace in #define");
     486           0 :                 ls->flags |= READ_AGAIN;
     487           0 :                 narg = 0;
     488             :         }
     489           0 :         if (redef) nt = 0;
     490             : 
     491             :         /* now, we have the arguments. Let's get the macro contents. */
     492           0 :         while (!next_token(ls) && ls->ctok->type != NEWLINE) {
     493             :                 struct token t;
     494             : 
     495           0 :                 t.type = ls->ctok->type;
     496           0 :                 if (ltwws && ttMWS(t.type)) continue;
     497           0 :                 t.line = 0;
     498           0 :                 if (t.type == NAME) {
     499             :                         int i;
     500             : 
     501           0 :                         if ((ls->flags & MACRO_VAARG)
     502           0 :                                 && !strcmp(ls->ctok->name, "__VA_ARGS__")) {
     503           0 :                                 if (redef) {
     504           0 :                                         if (!n->vaarg) goto redef_error;
     505           0 :                                 } else if (!m->vaarg) {
     506           0 :                                         error(l, "'__VA_ARGS__' is forbidden "
     507             :                                                 "in macros with a fixed "
     508             :                                                 "number of arguments");
     509             :                                         goto warp_error;
     510             :                                 }
     511           0 :                                 t.type = MACROARG;
     512           0 :                                 t.line = redef ? n->narg : m->narg;
     513             :                         }
     514           0 :                         for (i = 0; i < narg; i ++)
     515           0 :                                 if (!strcmp(redef ? n->arg[i] : m->arg[i],
     516           0 :                                         ls->ctok->name)) {
     517           0 :                                         t.type = MACROARG;
     518             :                                         /* this is a hack: we store the
     519             :                                            argument number in the line field */
     520           0 :                                         t.line = i;
     521           0 :                                         break;
     522             :                                 }
     523             :                 }
     524           0 :                 if (!redef && S_TOKEN(t.type)) t.name = sdup(ls->ctok->name);
     525           0 :                 if (ttMWS(t.type)) {
     526           0 :                         if (ltwws) continue;
     527             : #ifdef SEMPER_FIDELIS
     528             :                         t.type = OPT_NONE;
     529             : #else
     530           0 :                         t.type = NONE;
     531             : #endif
     532           0 :                         ltwws = 1;
     533           0 :                 } else ltwws = 0;
     534           0 :                 if (!redef) {
     535             :                         /* we ensure that each macro token has a correct
     536             :                            line number */
     537           0 :                         if (t.type != MACROARG) t.line = 1;
     538           0 :                         aol(mval.t, mval.nt, t, TOKEN_LIST_MEMG);
     539             :                 } else {
     540             : #ifdef LOW_MEM
     541             :                         int tt;
     542             : 
     543           0 :                         if (n->cval.rp >= n->cval.length) {
     544             : #ifdef SEMPER_FIDELIS
     545             :                                 if (t.type != OPT_NONE) goto redef_error;
     546             : #else
     547           0 :                                 if (t.type != NONE) goto redef_error;
     548             : #endif
     549           0 :                         } else if (t.type != n->cval.t[n->cval.rp]) {
     550             :                                 goto redef_error;
     551           0 :                         } else if (t.type == MACROARG) {
     552           0 :                                 unsigned anum = n->cval.t[n->cval.rp + 1];
     553             : 
     554           0 :                                 if (anum >= 128U) anum = ((anum & 127U) << 8)
     555           0 :                                         | m->cval.t[n->cval.rp + 2];
     556           0 :                                 if (anum != (unsigned)t.line) goto redef_error;
     557           0 :                         } else if (S_TOKEN(t.type) && strcmp(ls->ctok->name,
     558           0 :                                    (char *)(n->cval.t + n->cval.rp + 1))) {
     559             :                                 goto redef_error;
     560             :                         }
     561           0 :                         tt = n->cval.t[n->cval.rp ++];
     562           0 :                         if (S_TOKEN(tt)) n->cval.rp += 1
     563           0 :                                 + strlen((char *)(n->cval.t + n->cval.rp));
     564           0 :                         else if (tt == MACROARG) {
     565           0 :                                 if (n->cval.t[++ n->cval.rp] >= 128)
     566           0 :                                         n->cval.rp ++;
     567             :                         }
     568             : #else
     569             :                         if (nt >= n->val.nt) {
     570             : #ifdef SEMPER_FIDELIS
     571             :                                 if (t.type != OPT_NONE) goto redef_error;
     572             : #else
     573             :                                 if (t.type != NONE) goto redef_error;
     574             : #endif
     575             :                         } else if (t.type != n->val.t[nt].type
     576             :                                 || (t.type == MACROARG
     577             :                                     && t.line != n->val.t[nt].line)
     578             :                                 || (S_TOKEN(t.type) && strcmp(ls->ctok->name,
     579             :                                    n->val.t[nt].name))) {
     580             :                                 goto redef_error;
     581             :                         }
     582             : #endif
     583           0 :                         nt ++;
     584             :                 }
     585             :         }
     586             : 
     587           0 :         if (redef) {
     588             : #ifdef LOW_MEM
     589           0 :                 if (n->cval.rp < n->cval.length) goto redef_error_2;
     590             : #else
     591             :                 if (nt < n->val.nt) goto redef_error_2;
     592             : #endif
     593           0 :                 return 0;
     594             :         }
     595             : 
     596             :         /* now we have the complete macro; perform some checks about
     597             :            the operators # and ##, and, if everything is ok,
     598             :            store the macro into the hash table */
     599             : define_end:
     600             : #ifdef SEMPER_FIDELIS
     601             :         if (mval.nt && mval.t[mval.nt - 1].type == OPT_NONE) {
     602             : #else
     603           0 :         if (mval.nt && mval.t[mval.nt - 1].type == NONE) {
     604             : #endif
     605           0 :                 mval.nt --;
     606           0 :                 if (mval.nt == 0) freemem(mval.t);
     607             :         }
     608           0 :         if (mval.nt != 0) {
     609             :                 size_t i;
     610             : 
     611             :                 /* some checks about the macro */
     612           0 :                 if (mval.t[0].type == DSHARP
     613           0 :                         || mval.t[0].type == DIG_DSHARP
     614           0 :                         || mval.t[mval.nt - 1].type == DSHARP
     615           0 :                         || mval.t[mval.nt - 1].type == DIG_DSHARP) {
     616           0 :                         error(l, "operator '##' may neither begin "
     617             :                                 "nor end a macro");
     618           0 :                         goto define_error;
     619             :                 }
     620           0 :                 if (m->narg >= 0) for (i = 0; i < mval.nt; i ++)
     621           0 :                         if ((mval.t[i].type == SHARP
     622           0 :                                 || mval.t[i].type == DIG_SHARP) &&
     623           0 :                                 (i == (mval.nt - 1)
     624           0 :                                 || (ttMWS(mval.t[i + 1].type) &&
     625           0 :                                     (i == mval.nt - 2
     626           0 :                                      || mval.t[i + 2].type != MACROARG))
     627           0 :                                 || (!ttMWS(mval.t[i + 1].type)
     628           0 :                                      && mval.t[i + 1].type != MACROARG))) {
     629           0 :                                 error(l, "operator '#' not followed "
     630             :                                         "by a macro argument");
     631           0 :                                 goto define_error;
     632             :                         }
     633             :         }
     634             : #ifdef LOW_MEM
     635             :         {
     636             :                 size_t i, l;
     637             : 
     638           0 :                 for (i = 0, l = 0; i < mval.nt; i ++) {
     639           0 :                         l ++;
     640           0 :                         if (S_TOKEN(mval.t[i].type))
     641           0 :                                 l += 1 + strlen(mval.t[i].name);
     642           0 :                         else if (mval.t[i].type == MACROARG) {
     643           0 :                                 l ++;
     644           0 :                                 if (mval.t[i].line >= 128) l ++;
     645             :                         }
     646             :                 }
     647           0 :                 m->cval.length = l;
     648           0 :                 if (l) m->cval.t = getmem(l);
     649           0 :                 for (i = 0, l = 0; i < mval.nt; i ++) {
     650           0 :                         m->cval.t[l ++] = mval.t[i].type;
     651           0 :                         if (S_TOKEN(mval.t[i].type)) {
     652           0 :                                 size_t x = 1 + strlen(mval.t[i].name);
     653             : 
     654           0 :                                 mmv(m->cval.t + l, mval.t[i].name, x);
     655           0 :                                 l += x;
     656           0 :                                 freemem(mval.t[i].name);
     657             :                         }
     658           0 :                         else if (mval.t[i].type == MACROARG) {
     659           0 :                                 unsigned anum = mval.t[i].line;
     660             : 
     661           0 :                                 if (anum >= 128) {
     662           0 :                                         m->cval.t[l ++] = 128 | (anum >> 8);
     663           0 :                                         m->cval.t[l ++] = anum & 0xFF;
     664             :                                 } else {
     665           0 :                                         m->cval.t[l ++] = anum;
     666             :                                 }
     667             :                         }
     668             :                 }
     669           0 :                 if (mval.nt) freemem(mval.t);
     670             :         }
     671             : #endif
     672           0 :         HTT_put(&macros, m, mname);
     673           0 :         freemem(mname);
     674           0 :         if (emit_defines) print_macro(m);
     675           0 :         return 0;
     676             : 
     677             : redef_error:
     678           0 :         while (ls->ctok->type != NEWLINE && !next_token(ls));
     679             : redef_error_2:
     680           0 :         error(l, "macro '%s' redefined unidentically", HASH_ITEM_NAME(n));
     681           0 :         return 1;
     682             : warp_error:
     683           0 :         while (ls->ctok->type != NEWLINE && !next_token(ls));
     684             : define_error:
     685           0 :         if (m) del_macro(m);
     686           0 :         if (mname) freemem(mname);
     687             : #ifdef LOW_MEM
     688           0 :         if (mv.nt) {
     689             :                 size_t i;
     690             : 
     691           0 :                 for (i = 0; i < mv.nt; i ++)
     692           0 :                         if (S_TOKEN(mv.t[i].type)) freemem(mv.t[i].name);
     693           0 :                 freemem(mv.t);
     694             :         }
     695             : #endif
     696           0 :         return 1;
     697             : #undef mval
     698             : }
     699             : 
     700             : /*
     701             :  * Get the arguments for a macro. This code is tricky because there can
     702             :  * be multiple sources for these arguments, if we are in the middle of
     703             :  * a macro replacement; arguments are macro-replaced before inclusion
     704             :  * into the macro replacement.
     705             :  *
     706             :  * return value:
     707             :  * 1    no argument (last token read from next_token())
     708             :  * 2    no argument (last token read from tfi)
     709             :  * 3    no argument (nothing read)
     710             :  * 4    error
     711             :  *
     712             :  * Void arguments are allowed in C99.
     713             :  */
     714           0 : static int collect_arguments(struct lexer_state *ls, struct token_fifo *tfi,
     715             :         int penury, struct token_fifo *atl, int narg, int vaarg, int *wr)
     716             : {
     717           0 :         int ltwws = 1, npar = 0, i;
     718           0 :         struct token *ct = 0;
     719           0 :         int read_from_fifo = 0;
     720           0 :         long begin_line = ls->line;
     721             : 
     722             : #define unravel(ls)     (read_from_fifo = 0, !((tfi && tfi->art < tfi->nt \
     723             :         && (read_from_fifo = 1) != 0 && (ct = tfi->t + (tfi->art ++))) \
     724             :         || ((!tfi || penury) && !next_token(ls) && (ct = (ls)->ctok))))
     725             : 
     726             :         /*
     727             :          * collect_arguments() is assumed to setup correctly atl
     728             :          * (this is not elegant, but it works)
     729             :          */
     730           0 :         for (i = 0; i < narg; i ++) atl[i].art = atl[i].nt = 0;
     731           0 :         if (vaarg) atl[narg].art = atl[narg].nt = 0;
     732           0 :         *wr = 0;
     733           0 :         while (!unravel(ls)) {
     734           0 :                 if (!read_from_fifo && ct->type == NEWLINE) ls->ltwnl = 1;
     735           0 :                 if (ttWHI(ct->type)) {
     736           0 :                         *wr = 1;
     737           0 :                         continue;
     738             :                 }
     739           0 :                 if (ct->type == LPAR) {
     740           0 :                         npar = 1;
     741             :                 }
     742           0 :                 break;
     743             :         }
     744           0 :         if (!npar) {
     745           0 :                 if (ct == ls->ctok) return 1;
     746           0 :                 if (read_from_fifo) return 2;
     747           0 :                 return 3;
     748             :         }
     749           0 :         if (!read_from_fifo && ct == ls->ctok) ls->ltwnl = 0;
     750           0 :         i = 0;
     751           0 :         if ((narg + vaarg) == 0) {
     752           0 :                 while(!unravel(ls)) {
     753           0 :                         if (ttWHI(ct->type)) continue;
     754           0 :                         if (ct->type == RPAR) goto harvested;
     755           0 :                         npar = 1;
     756           0 :                         goto too_many_args;
     757             :                 }
     758             :         }
     759           0 :         while (!unravel(ls)) {
     760             :                 struct token t;
     761             : 
     762           0 :                 if (ct->type == LPAR) npar ++;
     763           0 :                 else if (ct->type == RPAR && (-- npar) == 0) {
     764           0 :                         if (atl[i].nt != 0
     765           0 :                                 && ttMWS(atl[i].t[atl[i].nt - 1].type))
     766           0 :                                         atl[i].nt --;
     767           0 :                         i ++;
     768             :                         /*
     769             :                          * C99 standard states that at least one argument
     770             :                          * should be present for the ... part; to relax
     771             :                          * this behaviour, change 'narg + vaarg' to 'narg'.
     772             :                          */
     773           0 :                         if (i < (narg + vaarg)) {
     774           0 :                                 error(begin_line, "not enough arguments "
     775             :                                         "to macro");
     776           0 :                                 return 4;
     777             :                         }
     778           0 :                         if (i > narg) {
     779           0 :                                 if (!(ls->flags & MACRO_VAARG) || !vaarg)
     780             :                                         goto too_many_args;
     781             :                         }
     782             :                         goto harvested;
     783           0 :                 } else if (ct->type == COMMA && npar <= 1 && i < narg) {
     784           0 :                         if (atl[i].nt != 0
     785           0 :                                 && ttMWS(atl[i].t[atl[i].nt - 1].type))
     786           0 :                                         atl[i].nt --;
     787           0 :                         if (++ i == narg) {
     788           0 :                                 if (!(ls->flags & MACRO_VAARG) || !vaarg)
     789             :                                         goto too_many_args;
     790             :                         }
     791           0 :                         if (i > 30000) goto too_many_args;
     792           0 :                         ltwws = 1;
     793           0 :                         continue;
     794           0 :                 } else if (ltwws && ttWHI(ct->type)) continue;
     795             : 
     796           0 :                 t.type = ct->type;
     797           0 :                 if (!read_from_fifo) t.line = ls->line; else t.line = ct->line;
     798             :                 /*
     799             :                  * Stringification applies only to macro arguments;
     800             :                  * so we handle here OPT_NONE.
     801             :                  * OPT_NONE is kept, but does not count as whitespace,
     802             :                  * and merges with other whitespace to give a fully
     803             :                  * qualified NONE token. Two OPT_NONE tokens merge.
     804             :                  * Initial and final OPT_NONE are discarded (initial
     805             :                  * is already done, as OPT_NONE is matched by ttWHI).
     806             :                  */
     807           0 :                 if (ttWHI(t.type)) {
     808           0 :                         if (t.type != OPT_NONE) {
     809           0 :                                 t.type = NONE;
     810             : #ifdef SEMPER_FIDELIS
     811             :                                 t.name = sdup(" ");
     812             :                                 throw_away(ls->gf, t.name);
     813             : #endif
     814           0 :                                 ltwws = 1;
     815             :                         }
     816           0 :                         if (atl[i].nt > 0
     817           0 :                                 && atl[i].t[atl[i].nt - 1].type == OPT_NONE)
     818           0 :                                         atl[i].nt --;
     819             :                 } else { 
     820           0 :                         ltwws = 0;
     821           0 :                         if (S_TOKEN(t.type)) {
     822           0 :                                 t.name = ct->name;
     823           0 :                                 if (ct == (ls)->ctok) {
     824           0 :                                         t.name = sdup(t.name);
     825           0 :                                         throw_away(ls->gf, t.name);
     826             :                                 }
     827             :                         }
     828             :                 }
     829           0 :                 aol(atl[i].t, atl[i].nt, t, TOKEN_LIST_MEMG);
     830             :         }
     831           0 :         error(begin_line, "unfinished macro call");
     832           0 :         return 4;
     833             : too_many_args:
     834           0 :         error(begin_line, "too many arguments to macro");
     835           0 :         while (npar && !unravel(ls)) {
     836           0 :                 if (ct->type == LPAR) npar ++;
     837           0 :                 else if (ct->type == RPAR) npar --;
     838             :         }
     839           0 :         return 4;
     840             : harvested:
     841           0 :         if (i > 127 && (ls->flags & WARN_STANDARD))
     842           0 :                 warning(begin_line, "macro call with %d arguments (ISO "
     843             :                         "specifies 127 max)", i);
     844           0 :         return 0;
     845             : #undef unravel
     846             : }
     847             : 
     848             : /*
     849             :  * concat_token() is called when the ## operator is used. It uses
     850             :  * the struct lexer_state dsharp_lexer to parse the result of the
     851             :  * concatenation.
     852             :  *
     853             :  * Law enforcement: if the whole string does not produce a valid
     854             :  * single token, an error (non-zero result) is returned.
     855             :  */
     856             : struct lexer_state dsharp_lexer;
     857             : 
     858           0 : static inline int concat_token(struct token *t1, struct token *t2)
     859             : {
     860           0 :         char *n1 = token_name(t1), *n2 = token_name(t2);
     861           0 :         size_t l1 = strlen(n1), l2 = strlen(n2);
     862           0 :         unsigned char *x = getmem(l1 + l2 + 1);
     863             :         int r;
     864             : 
     865           0 :         mmv(x, n1, l1);
     866           0 :         mmv(x + l1, n2, l2);
     867           0 :         x[l1 + l2] = 0;
     868           0 :         dsharp_lexer.input = 0;
     869           0 :         dsharp_lexer.input_string = x;
     870           0 :         dsharp_lexer.pbuf = 0;
     871           0 :         dsharp_lexer.ebuf = l1 + l2;
     872           0 :         dsharp_lexer.discard = 1;
     873           0 :         dsharp_lexer.flags = DEFAULT_LEXER_FLAGS;
     874           0 :         dsharp_lexer.pending_token = 0;
     875           0 :         r = next_token(&dsharp_lexer);
     876           0 :         freemem(x);
     877           0 :         return (r == 1 || dsharp_lexer.pbuf < (l1 + l2)
     878           0 :                 || dsharp_lexer.pending_token
     879           0 :                 || (dsharp_lexer.pbuf == (l1 + l2) && !dsharp_lexer.discard));
     880             : }
     881             : 
     882             : #ifdef PRAGMA_TOKENIZE
     883             : /*
     884             :  * tokenize_string() takes a string as input, and split it into tokens,
     885             :  * reassembling the tokens into a single compressed string generated by
     886             :  * compress_token_list(); this function is used for _Pragma processing.
     887             :  */
     888             : struct lexer_state tokenize_lexer;
     889             : 
     890           0 : static char *tokenize_string(struct lexer_state *ls, char *buf)
     891             : {
     892             :         struct token_fifo tf;
     893           0 :         size_t bl = strlen(buf);
     894             :         int r;
     895             : 
     896           0 :         tokenize_lexer.input = 0;
     897           0 :         tokenize_lexer.input_string = (unsigned char *)buf;
     898           0 :         tokenize_lexer.pbuf = 0;
     899           0 :         tokenize_lexer.ebuf = bl;
     900           0 :         tokenize_lexer.discard = 1;
     901           0 :         tokenize_lexer.flags = ls->flags | LEXER;
     902           0 :         tokenize_lexer.pending_token = 0;
     903           0 :         tf.art = tf.nt = 0;
     904           0 :         while (!(r = next_token(&tokenize_lexer))) {
     905           0 :                 struct token t, *ct = tokenize_lexer.ctok;
     906             : 
     907           0 :                 if (ttWHI(ct->type)) continue;
     908           0 :                 t = *ct;
     909           0 :                 if (S_TOKEN(t.type)) t.name = sdup(t.name);
     910           0 :                 aol(tf.t, tf.nt, t, TOKEN_LIST_MEMG);
     911             :         }
     912           0 :         if (tokenize_lexer.pbuf < bl) goto tokenize_error;
     913           0 :         return (char *)((compress_token_list(&tf)).t);
     914             : 
     915             : tokenize_error:
     916           0 :         if (tf.nt) {
     917           0 :                 for (tf.art = 0; tf.art < tf.nt; tf.art ++)
     918           0 :                         if (S_TOKEN(tf.t[tf.art].type))
     919           0 :                                 freemem(tf.t[tf.art].name);
     920           0 :                 freemem(tf.t);
     921             :         }
     922           0 :         return 0;
     923             : }
     924             : #endif
     925             : 
     926             : /*
     927             :  * stringify_string() has a self-explanatory name. It is called when
     928             :  * the # operator is used in a macro and a string constant must be
     929             :  * stringified.
     930             :  */
     931           0 : static inline char *stringify_string(char *x)
     932             : {
     933             :         size_t l;
     934           0 :         int i, inside_str = 0, inside_cc = 0, must_quote, has_quoted = 0;
     935             :         char *y, *d;
     936             : 
     937           0 :         for (i = 0; i < 2; i ++) {
     938           0 :                 if (i) d[0] = '"';
     939           0 :                 for (l = 1, y = x; *y; y ++, l ++) {
     940           0 :                         must_quote = 0;
     941           0 :                         if (inside_cc) {
     942           0 :                                 if (*y == '\\') {
     943           0 :                                         must_quote = 1;
     944           0 :                                         has_quoted = 1;
     945           0 :                                 } else if (!has_quoted && *y == '\'')
     946           0 :                                         inside_cc = 0;
     947           0 :                         } else if (inside_str) {
     948           0 :                                 if (*y == '"' || *y == '\\') must_quote = 1;
     949           0 :                                 if (*y == '\\') has_quoted = 1;
     950           0 :                                 else if (!has_quoted && *y == '"')
     951           0 :                                         inside_str = 0;
     952           0 :                         } else if (*y == '"') {
     953           0 :                                 inside_str = 1;
     954           0 :                                 must_quote = 1;
     955           0 :                         } else if (*y == '\'') {
     956           0 :                                 inside_cc = 1;
     957             :                         }
     958           0 :                         if (must_quote) {
     959           0 :                                 if (i) d[l] = '\\';
     960           0 :                                 l ++;
     961             :                         }
     962           0 :                         if (i) d[l] = *y;
     963             :                 }
     964           0 :                 if (!i) d = getmem(l + 2);
     965           0 :                 if (i) {
     966           0 :                         d[l] = '"';
     967           0 :                         d[l + 1] = 0;
     968             :                 }
     969             :         }
     970           0 :         return d;
     971             : }
     972             : 
     973             : /*
     974             :  * stringify() produces a constant string, result of the # operator
     975             :  * on a list of tokens.
     976             :  */
     977           0 : static char *stringify(struct token_fifo *tf)
     978             : {
     979             :         size_t tlen;
     980             :         size_t i;
     981             :         char *x, *y;
     982             : 
     983           0 :         for (tlen = 0, i = 0; i < tf->nt; i ++)
     984           0 :                 if (tf->t[i].type < CPPERR && tf->t[i].type != OPT_NONE)
     985           0 :                         tlen += strlen(token_name(tf->t + i));
     986           0 :         if (tlen == 0) return sdup("\"\"");
     987           0 :         x = getmem(tlen + 1);
     988           0 :         for (tlen = 0, i = 0; i < tf->nt; i ++) {
     989           0 :                 if (tf->t[i].type >= CPPERR || tf->t[i].type == OPT_NONE)
     990           0 :                         continue;
     991           0 :                 strcpy(x + tlen, token_name(tf->t + i));
     992           0 :                 tlen += strlen(token_name(tf->t + i));
     993             :         }
     994             :         /* no need to add a trailing 0: strcpy() did that (and the string
     995             :            is not empty) */
     996           0 :         y = stringify_string(x);
     997           0 :         freemem(x);
     998           0 :         return y;
     999             : }
    1000             : 
    1001             : /*
    1002             :  * Two strings evaluated at initialization time, to handle the __TIME__
    1003             :  * and __DATE__ special macros.
    1004             :  *
    1005             :  * C99 specifies that these macros should remain constant throughout
    1006             :  * the whole preprocessing.
    1007             :  */
    1008             : char compile_time[12], compile_date[24];
    1009             : 
    1010             : /*
    1011             :  * substitute_macro() performs the macro substitution. It is called when
    1012             :  * an identifier recognized as a macro name has been found; this function
    1013             :  * tries to collect the arguments (if needed), applies # and ## operators
    1014             :  * and perform recursive and nested macro expansions.
    1015             :  *
    1016             :  * In the substitution of a macro, we remove all newlines that were in the
    1017             :  * arguments. This might confuse error reporting (which could report
    1018             :  * erroneous line numbers) or have worse effect is the preprocessor is
    1019             :  * used for another language pickier than C. Since the interface between
    1020             :  * the preprocessor and the compiler is not fully specified, I believe
    1021             :  * that this is no violation of the standard. Comments welcome.
    1022             :  *
    1023             :  * We take tokens from tfi. If tfi has no more tokens to give: we may
    1024             :  * take some tokens from ls to complete a call (fetch arguments) if
    1025             :  * and only if penury is non zero.
    1026             :  */
    1027           0 : int substitute_macro(struct lexer_state *ls, struct macro *m,
    1028             :         struct token_fifo *tfi, int penury, int reject_nested, long l)
    1029             : {
    1030           0 :         char *mname = HASH_ITEM_NAME(m);
    1031             :         struct token_fifo *atl, etl;
    1032             :         struct token t, *ct;
    1033           0 :         int i, save_nest = m->nest;
    1034             :         size_t save_art, save_tfi, etl_limit;
    1035             :         int ltwds, ntwds, ltwws;
    1036           0 :         int pragma_op = 0;
    1037             : 
    1038             :         /*
    1039             :          * Reject the replacement, if we are already inside the macro.
    1040             :          */
    1041           0 :         if (m->nest > reject_nested) {
    1042           0 :                 t.type = NAME;
    1043           0 :                 t.line = ls->line;
    1044           0 :                 t.name = mname;
    1045           0 :                 print_token(ls, &t, 0);
    1046           0 :                 return 0;
    1047             :         }
    1048             : 
    1049             :         /*
    1050             :          * put a separation from preceeding tokens
    1051             :          */
    1052           0 :         print_space(ls);
    1053             : 
    1054             :         /*
    1055             :          * Check if the macro is a special one.
    1056             :          */
    1057           0 :         if ((i = check_special_macro(mname)) >= MAC_SPECIAL) {
    1058             :                 /* we have a special macro */
    1059           0 :                 switch (i) {
    1060             :                         char buf[30], *bbuf, *cfn;
    1061             : 
    1062             :                 case MAC_LINE:
    1063           0 :                         t.type = NUMBER;
    1064           0 :                         t.line = l;
    1065           0 :                         sprintf(buf, "%ld", l);
    1066           0 :                         t.name = buf;
    1067           0 :                         print_space(ls);
    1068           0 :                         print_token(ls, &t, 0);
    1069             :                         break;
    1070             :                 case MAC_FILE:
    1071           0 :                         t.type = STRING;
    1072           0 :                         t.line = l;
    1073           0 :                         cfn = current_long_filename ?
    1074           0 :                                 current_long_filename : current_filename;
    1075           0 :                         bbuf = getmem(2 * strlen(cfn) + 3);
    1076             :                         {
    1077             :                                 char *c, *d;
    1078           0 :                                 int lcwb = 0;
    1079             : 
    1080           0 :                                 bbuf[0] = '"';
    1081           0 :                                 for (c = cfn, d = bbuf + 1; *c; c ++) {
    1082           0 :                                         if (*c == '\\') {
    1083           0 :                                                 if (lcwb) continue;
    1084           0 :                                                 *(d ++) = '\\';
    1085           0 :                                                 lcwb = 1;
    1086           0 :                                         } else lcwb = 0;
    1087           0 :                                         *(d ++) = *c;
    1088             :                                 }
    1089           0 :                                 *(d ++) = '"';
    1090           0 :                                 *(d ++) = 0;
    1091             :                         }
    1092           0 :                         t.name = bbuf;
    1093           0 :                         print_space(ls);
    1094           0 :                         print_token(ls, &t, 0);
    1095           0 :                         freemem(bbuf);
    1096             :                         break;
    1097             :                 case MAC_DATE:
    1098           0 :                         t.type = STRING;
    1099           0 :                         t.line = l;
    1100           0 :                         t.name = compile_date;
    1101           0 :                         print_space(ls);
    1102           0 :                         print_token(ls, &t, 0);
    1103             :                         break;
    1104             :                 case MAC_TIME:
    1105           0 :                         t.type = STRING;
    1106           0 :                         t.line = l;
    1107           0 :                         t.name = compile_time;
    1108           0 :                         print_space(ls);
    1109           0 :                         print_token(ls, &t, 0);
    1110             :                         break;
    1111             :                 case MAC_STDC:
    1112           0 :                         t.type = NUMBER;
    1113           0 :                         t.line = l;
    1114           0 :                         t.name = "1";
    1115           0 :                         print_space(ls);
    1116           0 :                         print_token(ls, &t, 0);
    1117             :                         break;
    1118             :                 case MAC_PRAGMA:
    1119           0 :                         if (reject_nested > 0) {
    1120             :                                 /* do not replace _Pragma() unless toplevel */
    1121           0 :                                 t.type = NAME;
    1122           0 :                                 t.line = ls->line;
    1123           0 :                                 t.name = mname;
    1124           0 :                                 print_token(ls, &t, 0);
    1125           0 :                                 return 0;
    1126             :                         }
    1127           0 :                         pragma_op = 1;
    1128             :                         goto collect_args;
    1129             : #ifdef AUDIT
    1130             :                 default:
    1131             :                         ouch("unbekanntes fliegendes macro");
    1132             : #endif
    1133             :                 }
    1134           0 :                 return 0;
    1135             :         }
    1136             : 
    1137             :         /*
    1138             :          * If the macro has arguments, collect them.
    1139             :          */
    1140             : collect_args:
    1141           0 :         if (m->narg >= 0) {
    1142           0 :                 unsigned long save_flags = ls->flags;
    1143           0 :                 int wr = 0;
    1144             : 
    1145           0 :                 ls->flags |= LEXER;
    1146           0 :                 if (m->narg > 0 || m->vaarg)
    1147           0 :                         atl = getmem((m->narg + m->vaarg)
    1148             :                                 * sizeof(struct token_fifo));
    1149           0 :                 switch (collect_arguments(ls, tfi, penury, atl,
    1150             :                         m->narg, m->vaarg, &wr)) {
    1151             :                 case 1:
    1152             :                         /* the macro expected arguments, but we did not
    1153             :                            find any; the last read token should be read
    1154             :                            again. */
    1155           0 :                         ls->flags = save_flags | READ_AGAIN;
    1156           0 :                         goto no_argument_next;
    1157             :                 case 2:
    1158           0 :                         tfi->art --;
    1159             :                         /* fall through */
    1160             :                 case 3:
    1161           0 :                         ls->flags = save_flags;
    1162             :                 no_argument_next:
    1163           0 :                         t.type = NAME;
    1164           0 :                         t.line = l;
    1165           0 :                         t.name = mname;
    1166           0 :                         print_token_nailed(ls, &t, l);
    1167           0 :                         if (wr) {
    1168           0 :                                 t.type = NONE;
    1169           0 :                                 t.line = l;
    1170             : #ifdef SEMPER_FIDELIS
    1171             :                                 t.name = " ";
    1172             : #endif
    1173           0 :                                 print_token(ls, &t, 0);
    1174             :                                 goto exit_macro_2;
    1175             :                         }
    1176             :                         goto exit_macro_1;
    1177             :                 case 4:
    1178           0 :                         ls->flags = save_flags;
    1179             :                         goto exit_error_1;
    1180             :                 }
    1181           0 :                 ls->flags = save_flags;
    1182             :         }
    1183             : 
    1184             :         /*
    1185             :          * If the macro is _Pragma, and we got here, then we have
    1186             :          * exactly one argument. We check it, unstringize it, and
    1187             :          * emit a PRAGMA token.
    1188             :          */
    1189           0 :         if (pragma_op) {
    1190             :                 char *pn;
    1191             : 
    1192           0 :                 if (atl[0].nt != 1 || atl[0].t[0].type != STRING) {
    1193           0 :                         error(ls->line, "invalid argument to _Pragma");
    1194           0 :                         if (atl[0].nt) freemem(atl[0].t);
    1195           0 :                         freemem(atl);
    1196           0 :                         goto exit_error;
    1197             :                 }
    1198           0 :                 pn = atl[0].t[0].name;
    1199           0 :                 if ((pn[0] == '"' && pn[1] == '"') || (pn[0] == 'L'
    1200           0 :                         && pn[1] == '"' && pn[2] == '"')) {
    1201             :                         /* void pragma -- just ignore it */
    1202           0 :                         freemem(atl[0].t);
    1203           0 :                         freemem(atl);
    1204           0 :                         return 0;
    1205             :                 }
    1206           0 :                 if (ls->flags & TEXT_OUTPUT) {
    1207             : #ifdef PRAGMA_DUMP
    1208             :         /*
    1209             :          * This code works because we actually evaluate arguments in a
    1210             :          * lazy way: we scan a macro argument only if it appears in the
    1211             :          * output, and exactly as many times as it appears. Therefore,
    1212             :          * _Pragma() will get evaluated just like they should.
    1213             :          */
    1214           0 :                         char *c = atl[0].t[0].name, *d;
    1215             : 
    1216           0 :                         for (d = "\n#pragma "; *d; d ++) put_char(ls, *d);
    1217           0 :                         d = (*c == 'L') ? c + 2 : c + 1;
    1218           0 :                         for (; *d != '"'; d ++) {
    1219           0 :                                 if (*d == '\\' && (*(d + 1) == '\\'
    1220           0 :                                         || *(d + 1) == '"')) {
    1221           0 :                                         d ++;
    1222             :                                 }
    1223           0 :                                 put_char(ls, *d);
    1224             :                         }
    1225           0 :                         put_char(ls, '\n');
    1226           0 :                         ls->oline = ls->line;
    1227           0 :                         enter_file(ls, ls->flags);
    1228             : #else
    1229             :                         if (ls->flags & WARN_PRAGMA)
    1230             :                                 warning(ls->line,
    1231             :                                         "_Pragma() ignored and not dumped");
    1232             : #endif
    1233           0 :                 } else if (ls->flags & HANDLE_PRAGMA) {
    1234           0 :                         char *c = atl[0].t[0].name, *d, *buf;
    1235             :                         struct token t;
    1236             : 
    1237             :                         /* a wide string is a string */
    1238           0 :                         if (*c == 'L') c ++;
    1239           0 :                         c ++;
    1240           0 :                         for (buf = d = getmem(strlen(c)); *c != '"'; c ++) {
    1241           0 :                                 if (*c == '\\' && (*(c + 1) == '\\'
    1242           0 :                                         || *(c + 1) == '"')) {
    1243           0 :                                         *(d ++) = *(++ c);
    1244           0 :                                 } else *(d ++) = *c;
    1245             :                         }
    1246           0 :                         *d = 0;
    1247           0 :                         t.type = PRAGMA;
    1248           0 :                         t.line = ls->line;
    1249             : #ifdef PRAGMA_TOKENIZE
    1250           0 :                         t.name = tokenize_string(ls, buf);
    1251           0 :                         freemem(buf);
    1252           0 :                         buf = t.name;
    1253           0 :                         if (!buf) {
    1254           0 :                                 freemem(atl[0].t);
    1255           0 :                                 freemem(atl);
    1256             :                                 goto exit_error;
    1257             :                         }
    1258             : #else
    1259             :                         t.name = buf;
    1260             : #endif
    1261           0 :                         aol(ls->toplevel_of->t, ls->toplevel_of->nt,
    1262             :                                 t, TOKEN_LIST_MEMG);
    1263           0 :                         throw_away(ls->gf, buf);
    1264             :                 }
    1265           0 :                 freemem(atl[0].t);
    1266           0 :                 freemem(atl);
    1267           0 :                 return 0;
    1268             :         }
    1269             : 
    1270             :         /*
    1271             :          * Now we expand and replace the arguments in the macro; we
    1272             :          * also handle '#' and '##'. If we find an argument, that has
    1273             :          * to be replaced, we expand it in its own token list, then paste
    1274             :          * it. Tricky point: when we paste an argument, we must scan
    1275             :          * again the resulting list for further replacements. This
    1276             :          * implies problems with regards to nesting self-referencing
    1277             :          * macros.
    1278             :          *
    1279             :          * We do then YAUH (yet another ugly hack): if a macro is replaced,
    1280             :          * and nested replacement exhibit the same macro, we mark it with
    1281             :          * a negative line number. All produced negative line numbers
    1282             :          * must be cleaned in the end.
    1283             :          */
    1284             : 
    1285             : #define ZAP_LINE(t)     do { \
    1286             :                 if ((t).type == NAME) { \
    1287             :                         struct macro *zlm = HTT_get(&macros, (t).name); \
    1288             :                         if (zlm && zlm->nest > reject_nested) \
    1289             :                                 (t).line = -1 - (t).line; \
    1290             :                 } \
    1291             :         } while (0)
    1292             : 
    1293             : #ifdef LOW_MEM
    1294           0 :         save_art = m->cval.rp;
    1295           0 :         m->cval.rp = 0;
    1296             : #else
    1297             :         save_art = m->val.art;
    1298             :         m->val.art = 0;
    1299             : #endif
    1300           0 :         etl.art = etl.nt = 0;
    1301           0 :         m->nest = reject_nested + 1;
    1302           0 :         ltwds = ntwds = 0;
    1303             : #ifdef LOW_MEM
    1304           0 :         while (m->cval.rp < m->cval.length) {
    1305             : #else
    1306             :         while (m->val.art < m->val.nt) {
    1307             : #endif
    1308             :                 size_t next, z;
    1309             : #ifdef LOW_MEM
    1310             :                 struct token uu;
    1311             : 
    1312           0 :                 ct = &uu;
    1313           0 :                 ct->line = 1;
    1314           0 :                 t.type = ct->type = m->cval.t[m->cval.rp ++];
    1315           0 :                 if (ct->type == MACROARG) {
    1316           0 :                         unsigned anum = m->cval.t[m->cval.rp ++];
    1317             : 
    1318           0 :                         if (anum >= 128U) anum = ((anum & 127U) << 8)
    1319           0 :                                 | (unsigned)m->cval.t[m->cval.rp ++];
    1320           0 :                         ct->line = anum;
    1321           0 :                 } else if (S_TOKEN(ct->type)) {
    1322           0 :                         t.name = ct->name = (char *)(m->cval.t + m->cval.rp);
    1323           0 :                         m->cval.rp += 1 + strlen(ct->name);
    1324             :                 }
    1325             : #ifdef SEMPER_FIDELIS
    1326             :                 else if (ct->type == OPT_NONE) {
    1327             :                         t.type = ct->type = NONE;
    1328             :                         t.name = ct->name = " ";
    1329             :                 }
    1330             : #endif
    1331           0 :                 t.line = ls->line;
    1332           0 :                 next = m->cval.rp;
    1333           0 :                 if ((next < m->cval.length && (m->cval.t[z = next] == DSHARP
    1334           0 :                         || m->cval.t[z = next] == DIG_DSHARP))
    1335           0 :                         || ((next + 1) < m->cval.length
    1336           0 :                            && ttWHI(m->cval.t[next])
    1337           0 :                            && (m->cval.t[z = next + 1] == DSHARP
    1338           0 :                             || m->cval.t[z = next + 1] == DIG_DSHARP))) {
    1339           0 :                         ntwds = 1;
    1340           0 :                         m->cval.rp = z;
    1341           0 :                 } else ntwds = 0;
    1342             : #else
    1343             :                 ct = m->val.t + (m->val.art ++);
    1344             :                 next = m->val.art;
    1345             :                 t.type = ct->type;
    1346             :                 t.line = ls->line;
    1347             : #ifdef SEMPER_FIDELIS
    1348             :                 if (t.type == OPT_NONE) {
    1349             :                         t.type = NONE;
    1350             :                         t.name = " ";
    1351             :                 } else
    1352             : #endif
    1353             :                 t.name = ct->name;
    1354             :                 if ((next < m->val.nt && (m->val.t[z = next].type == DSHARP
    1355             :                         || m->val.t[z = next].type == DIG_DSHARP))
    1356             :                         || ((next + 1) < m->val.nt
    1357             :                            && ttWHI(m->val.t[next].type)
    1358             :                            && (m->val.t[z = next + 1].type == DSHARP
    1359             :                             || m->val.t[z = next + 1].type == DIG_DSHARP))) {
    1360             :                         ntwds = 1;
    1361             :                         m->val.art = z;
    1362             :                 } else ntwds = 0;
    1363             : #endif
    1364           0 :                 if (ct->type == MACROARG) {
    1365             : #ifdef DSHARP_TOKEN_MERGE
    1366             :                         int need_opt_space = 1;
    1367             : #endif
    1368           0 :                         z = ct->line;        /* the argument number is there */
    1369           0 :                         if (ltwds && atl[z].nt != 0 && etl.nt) {
    1370           0 :                                 if (concat_token(etl.t + (-- etl.nt),
    1371           0 :                                         atl[z].t)) {
    1372           0 :                                         warning(ls->line, "operator '##' "
    1373             :                                                 "produced the invalid token "
    1374             :                                                 "'%s%s'",
    1375           0 :                                                 token_name(etl.t + etl.nt),
    1376           0 :                                                 token_name(atl[z].t));
    1377             : #if 0
    1378             : /* obsolete */
    1379             : #ifdef LOW_MEM
    1380             :                                         m->cval.rp = save_art;
    1381             : #else
    1382             :                                         m->val.art = save_art;
    1383             : #endif
    1384             :                                         etl.nt ++;
    1385             :                                         goto exit_error_2;
    1386             : #endif
    1387           0 :                                         etl.nt ++;
    1388           0 :                                         atl[z].art = 0;
    1389             : #ifdef DSHARP_TOKEN_MERGE
    1390             :                                         need_opt_space = 0;
    1391             : #endif
    1392             :                                 } else {
    1393           0 :                                         if (etl.nt == 0) freemem(etl.t);
    1394           0 :                                         else if (!ttWHI(etl.t[etl.nt - 1]
    1395             :                                                 .type)) {
    1396           0 :                                                 t.type = OPT_NONE;
    1397           0 :                                                 t.line = ls->line;
    1398           0 :                                                 aol(etl.t, etl.nt, t,
    1399             :                                                         TOKEN_LIST_MEMG);
    1400             :                                         }
    1401           0 :                                         t.type = dsharp_lexer.ctok->type;
    1402           0 :                                         t.line = ls->line;
    1403           0 :                                         if (S_TOKEN(t.type)) {
    1404           0 :                                                 t.name = sdup(dsharp_lexer
    1405           0 :                                                         .ctok->name);
    1406           0 :                                                 throw_away(ls->gf, t.name);
    1407             :                                         }
    1408           0 :                                         ZAP_LINE(t);
    1409           0 :                                         aol(etl.t, etl.nt, t, TOKEN_LIST_MEMG);
    1410           0 :                                         atl[z].art = 1;
    1411             :                                 }
    1412           0 :                         } else atl[z].art = 0;
    1413           0 :                         if (
    1414             : #ifdef DSHARP_TOKEN_MERGE
    1415             :                                 need_opt_space &&
    1416             : #endif
    1417           0 :                                 atl[z].art < atl[z].nt && (!etl.nt
    1418           0 :                                         || !ttWHI(etl.t[etl.nt - 1].type))) {
    1419           0 :                                 t.type = OPT_NONE;
    1420           0 :                                 t.line = ls->line;
    1421           0 :                                 aol(etl.t, etl.nt, t, TOKEN_LIST_MEMG);
    1422             :                         }
    1423           0 :                         if (ltwds || ntwds) {
    1424           0 :                                 while (atl[z].art < atl[z].nt) {
    1425           0 :                                         t = atl[z].t[atl[z].art ++];
    1426           0 :                                         t.line = ls->line;
    1427           0 :                                         ZAP_LINE(t);
    1428           0 :                                         aol(etl.t, etl.nt, t, TOKEN_LIST_MEMG);
    1429             :                                 }
    1430             :                         } else {
    1431             :                                 struct token_fifo *save_tf;
    1432             :                                 unsigned long save_flags;
    1433           0 :                                 int ret = 0;
    1434             : 
    1435           0 :                                 atl[z].art = 0;
    1436           0 :                                 save_tf = ls->output_fifo;
    1437           0 :                                 ls->output_fifo = &etl;
    1438           0 :                                 save_flags = ls->flags;
    1439           0 :                                 ls->flags |= LEXER;
    1440           0 :                                 while (atl[z].art < atl[z].nt) {
    1441             :                                         struct macro *nm;
    1442             :                                         struct token *cct;
    1443             : 
    1444           0 :                                         cct = atl[z].t + (atl[z].art ++);
    1445           0 :                                         if (cct->type == NAME
    1446           0 :                                                 && cct->line >= 0
    1447           0 :                                                 && (nm = HTT_get(&macros,
    1448             :                                                     cct->name))
    1449           0 :                                                 && nm->nest <=
    1450           0 :                                                     (reject_nested + 1)) {
    1451           0 :                                                 ret |= substitute_macro(ls,
    1452           0 :                                                         nm, atl + z, 0,
    1453             :                                                         reject_nested + 1, l);
    1454           0 :                                                 continue;
    1455             :                                         }
    1456           0 :                                         t = *cct;
    1457           0 :                                         ZAP_LINE(t);
    1458           0 :                                         aol(etl.t, etl.nt, t, TOKEN_LIST_MEMG);
    1459             :                                 }
    1460           0 :                                 ls->output_fifo = save_tf;
    1461           0 :                                 ls->flags = save_flags;
    1462           0 :                                 if (ret) {
    1463             : #ifdef LOW_MEM
    1464           0 :                                         m->cval.rp = save_art;
    1465             : #else
    1466             :                                         m->val.art = save_art;
    1467             : #endif
    1468             :                                         goto exit_error_2;
    1469             :                                 }
    1470             :                         }
    1471           0 :                         if (!ntwds && (!etl.nt
    1472           0 :                                 || !ttWHI(etl.t[etl.nt - 1].type))) {
    1473           0 :                                 t.type = OPT_NONE;
    1474           0 :                                 t.line = ls->line;
    1475           0 :                                 aol(etl.t, etl.nt, t, TOKEN_LIST_MEMG);
    1476             :                         }
    1477           0 :                         ltwds = 0;
    1478           0 :                         continue;
    1479             :                 }
    1480             :                 /*
    1481             :                  * This code is definitely cursed.
    1482             :                  *
    1483             :                  * For the extremely brave reader who tries to understand
    1484             :                  * what is happening: ltwds is a flag meaning "last token
    1485             :                  * was double-sharp" and ntwds means "next token will be
    1486             :                  * double-sharp". The tokens are from the macro definition,
    1487             :                  * and scanned from left to right. Arguments that are
    1488             :                  * not implied into a #/## construction are macro-expanded
    1489             :                  * seperately, then included into the token stream.
    1490             :                  */
    1491           0 :                 if (ct->type == DSHARP || ct->type == DIG_DSHARP) {
    1492           0 :                         if (ltwds) {
    1493           0 :                                 error(ls->line, "quad sharp");
    1494             : #ifdef LOW_MEM
    1495           0 :                                 m->cval.rp = save_art;
    1496             : #else
    1497             :                                 m->val.art = save_art;
    1498             : #endif
    1499             :                                 goto exit_error_2;
    1500             :                         }
    1501             : #ifdef LOW_MEM
    1502           0 :                         if (m->cval.rp < m->cval.length
    1503           0 :                                 && ttMWS(m->cval.t[m->cval.rp]))
    1504           0 :                                         m->cval.rp ++;
    1505             : #else
    1506             :                         if (m->val.art < m->val.nt
    1507             :                                 && ttMWS(m->val.t[m->val.art].type))
    1508             :                                         m->val.art ++;
    1509             : #endif
    1510           0 :                         ltwds = 1;
    1511           0 :                         continue;
    1512           0 :                 } else if (ltwds && etl.nt != 0) {
    1513           0 :                         if (concat_token(etl.t + (-- etl.nt), ct)) {
    1514           0 :                                 warning(ls->line, "operator '##' produced "
    1515             :                                         "the invalid token '%s%s'",
    1516           0 :                                         token_name(etl.t + etl.nt),
    1517             :                                         token_name(ct));
    1518             : #if 0
    1519             : /* obsolete */
    1520             : #ifdef LOW_MEM
    1521             :                                 m->cval.rp = save_art;
    1522             : #else
    1523             :                                 m->val.art = save_art;
    1524             : #endif
    1525             :                                 etl.nt ++;
    1526             :                                 goto exit_error_2;
    1527             : #endif
    1528           0 :                                 etl.nt ++;
    1529             :                         } else {
    1530           0 :                                 if (etl.nt == 0) freemem(etl.t);
    1531           0 :                                 t.type = dsharp_lexer.ctok->type;
    1532           0 :                                 t.line = ls->line;
    1533           0 :                                 if (S_TOKEN(t.type)) {
    1534           0 :                                         t.name = sdup(dsharp_lexer.ctok->name);
    1535           0 :                                         throw_away(ls->gf, t.name);
    1536             :                                 }
    1537           0 :                                 ct = &t;
    1538             :                         }
    1539             :                 }
    1540           0 :                 ltwds = 0;
    1541             : #ifdef LOW_MEM
    1542           0 :                 if ((ct->type == SHARP || ct->type == DIG_SHARP)
    1543           0 :                         && next < m->cval.length
    1544           0 :                         && (m->cval.t[next] == MACROARG
    1545           0 :                         || (ttMWS(m->cval.t[next])
    1546           0 :                         && (next + 1) < m->cval.length
    1547           0 :                         && m->cval.t[next + 1] == MACROARG))) {
    1548             : 
    1549             :                         unsigned anum;
    1550             : #else
    1551             :                 if ((ct->type == SHARP || ct->type == DIG_SHARP)
    1552             :                         && next < m->val.nt
    1553             :                         && (m->val.t[next].type == MACROARG
    1554             :                         || (ttMWS(m->val.t[next].type)
    1555             :                         && (next + 1) < m->val.nt
    1556             :                         && m->val.t[next + 1].type == MACROARG))) {
    1557             : #endif
    1558             :                         /*
    1559             :                          * We have a # operator followed by (an optional
    1560             :                          * whitespace and) a macro argument; this means
    1561             :                          * stringification. So be it.
    1562             :                          */
    1563             : #ifdef LOW_MEM
    1564           0 :                         if (ttMWS(m->cval.t[next])) m->cval.rp ++;
    1565             : #else
    1566             :                         if (ttMWS(m->val.t[next].type)) m->val.art ++;
    1567             : #endif
    1568           0 :                         t.type = STRING;
    1569             : #ifdef LOW_MEM
    1570           0 :                         anum = m->cval.t[++ m->cval.rp];
    1571           0 :                         if (anum >= 128U) anum = ((anum & 127U) << 8)
    1572           0 :                                 | (unsigned)m->cval.t[++ m->cval.rp];
    1573           0 :                         t.name = stringify(atl + anum);
    1574           0 :                         m->cval.rp ++;
    1575             : #else
    1576             :                         t.name = stringify(atl +
    1577             :                                 (size_t)(m->val.t[m->val.art ++].line));
    1578             : #endif
    1579           0 :                         throw_away(ls->gf, t.name);
    1580           0 :                         ct = &t;
    1581             :                         /*
    1582             :                          * There is no need for extra spaces here.
    1583             :                          */
    1584             :                 }
    1585           0 :                 t = *ct;
    1586           0 :                 ZAP_LINE(t);
    1587           0 :                 aol(etl.t, etl.nt, t, TOKEN_LIST_MEMG);
    1588             :         }
    1589             : #ifdef LOW_MEM
    1590           0 :         m->cval.rp = save_art;
    1591             : #else
    1592             :         m->val.art = save_art;
    1593             : #endif
    1594             : 
    1595             :         /*
    1596             :          * Now etl contains the expanded macro, to be parsed again for
    1597             :          * further expansions -- much easier, since '#' and '##' have
    1598             :          * already been handled.
    1599             :          * However, we might need some input from tfi. So, we paste
    1600             :          * the contents of tfi after etl, and we put back what was
    1601             :          * not used.
    1602             :          *
    1603             :          * Some adjacent spaces are merged; only unique NONE, or sequences
    1604             :          * OPT_NONE NONE are emitted.
    1605             :          */
    1606           0 :         etl_limit = etl.nt;
    1607           0 :         if (tfi) {
    1608           0 :                 save_tfi = tfi->art;
    1609           0 :                 while (tfi->art < tfi->nt) aol(etl.t, etl.nt,
    1610             :                         tfi->t[tfi->art ++], TOKEN_LIST_MEMG);
    1611             :         }
    1612           0 :         ltwws = 0;
    1613           0 :         while (etl.art < etl_limit) {
    1614             :                 struct macro *nm;
    1615             : 
    1616           0 :                 ct = etl.t + (etl.art ++);
    1617           0 :                 if (ct->type == NAME && ct->line >= 0
    1618           0 :                         && (nm = HTT_get(&macros, ct->name))) {
    1619           0 :                         if (substitute_macro(ls, nm, &etl,
    1620             :                                 penury, reject_nested, l)) {
    1621           0 :                                 m->nest = save_nest;
    1622           0 :                                 goto exit_error_2;
    1623             :                         }
    1624           0 :                         ltwws = 0;
    1625           0 :                         continue;
    1626             :                 }
    1627           0 :                 if (ttMWS(ct->type)) {
    1628           0 :                         if (ltwws == 1) {
    1629           0 :                                 if (ct->type == OPT_NONE) continue;
    1630           0 :                                 ltwws = 2;
    1631           0 :                         } else if (ltwws == 2) continue;
    1632           0 :                         else if (ct->type == OPT_NONE) ltwws = 1;
    1633           0 :                         else ltwws = 2;
    1634           0 :                 } else ltwws = 0;
    1635           0 :                 if (ct->line >= 0) ct->line = l;
    1636           0 :                 print_token(ls, ct, reject_nested ? 0 : l);
    1637             :         }
    1638           0 :         if (etl.nt) freemem(etl.t);
    1639           0 :         if (tfi) {
    1640           0 :                 tfi->art = save_tfi + (etl.art - etl_limit);
    1641             :         }
    1642             : 
    1643             : exit_macro_1:
    1644           0 :         print_space(ls);
    1645             : exit_macro_2:
    1646           0 :         for (i = 0; i < (m->narg + m->vaarg); i ++)
    1647           0 :                 if (atl[i].nt) freemem(atl[i].t);
    1648           0 :         if (m->narg > 0 || m->vaarg) freemem(atl);
    1649           0 :         m->nest = save_nest;
    1650           0 :         return 0;
    1651             : 
    1652             : exit_error_2:
    1653           0 :         if (etl.nt) freemem(etl.t);
    1654             : exit_error_1:
    1655           0 :         for (i = 0; i < (m->narg + m->vaarg); i ++)
    1656           0 :                 if (atl[i].nt) freemem(atl[i].t);
    1657           0 :         if (m->narg > 0 || m->vaarg) freemem(atl);
    1658           0 :         m->nest = save_nest;
    1659             : exit_error:
    1660           0 :         return 1;
    1661             : }
    1662             : 
    1663             : /*
    1664             :  * print already defined macros
    1665             :  */
    1666           0 : void print_defines(void)
    1667             : {
    1668           0 :         HTT_scan(&macros, print_macro);
    1669           0 : }
    1670             : 
    1671             : /*
    1672             :  * define_macro() defines a new macro, whom definition is given in
    1673             :  * the command-line syntax: macro=def
    1674             :  * The '=def' part is optional.
    1675             :  *
    1676             :  * It returns non-zero on error.
    1677             :  */
    1678           0 : int define_macro(struct lexer_state *ls, char *def)
    1679             : {
    1680           0 :         char *c = sdup(def), *d;
    1681           0 :         int with_def = 0;
    1682           0 :         int ret = 0;
    1683             : 
    1684           0 :         for (d = c; *d && *d != '='; d ++);
    1685           0 :         if (*d) {
    1686           0 :                 *d = ' ';
    1687           0 :                 with_def = 1;
    1688             :         }
    1689           0 :         if (with_def) {
    1690             :                 struct lexer_state lls;
    1691           0 :                 size_t n = strlen(c) + 1;
    1692             : 
    1693           0 :                 if (c == d) {
    1694           0 :                         error(-1, "void macro name");
    1695           0 :                         ret = 1;
    1696             :                 } else {
    1697           0 :                         *(c + n - 1) = '\n';
    1698           0 :                         init_buf_lexer_state(&lls, 0);
    1699           0 :                         lls.flags = ls->flags | LEXER;
    1700           0 :                         lls.input = 0;
    1701           0 :                         lls.input_string = (unsigned char *)c;
    1702           0 :                         lls.pbuf = 0;
    1703           0 :                         lls.ebuf = n;
    1704           0 :                         lls.line = -1;
    1705           0 :                         ret = handle_define(&lls);
    1706           0 :                         free_lexer_state(&lls);
    1707             :                 }
    1708             :         } else {
    1709             :                 struct macro *m;
    1710             : 
    1711           0 :                 if (!*c) {
    1712           0 :                         error(-1, "void macro name");
    1713           0 :                         ret = 1;
    1714           0 :                 } else if ((m = HTT_get(&macros, c))
    1715             : #ifdef LOW_MEM
    1716           0 :                         && (m->cval.length != 3
    1717           0 :                         || m->cval.t[0] != NUMBER
    1718           0 :                         || strcmp((char *)(m->cval.t + 1), "1"))) {
    1719             : #else
    1720             :                         && (m->val.nt != 1
    1721             :                         || m->val.t[0].type != NUMBER
    1722             :                         || strcmp(m->val.t[0].name, "1"))) {
    1723             : #endif
    1724           0 :                         error(-1, "macro %s already defined", c);
    1725           0 :                         ret = 1;
    1726             :                 } else {
    1727             : #ifndef LOW_MEM
    1728             :                         struct token t;
    1729             : #endif
    1730             : 
    1731           0 :                         m = new_macro();
    1732             : #ifdef LOW_MEM
    1733           0 :                         m->cval.length = 3;
    1734           0 :                         m->cval.t = getmem(3);
    1735           0 :                         m->cval.t[0] = NUMBER;
    1736           0 :                         m->cval.t[1] = '1';
    1737           0 :                         m->cval.t[2] = 0;
    1738             : #else
    1739             :                         t.type = NUMBER;
    1740             :                         t.name = sdup("1");
    1741             :                         aol(m->val.t, m->val.nt, t, TOKEN_LIST_MEMG);
    1742             : #endif
    1743           0 :                         HTT_put(&macros, m, c);
    1744             :                 }
    1745             :         }
    1746           0 :         freemem(c);
    1747           0 :         return ret;
    1748             : }
    1749             : 
    1750             : /*
    1751             :  * undef_macro() undefines the macro whom name is given as "def";
    1752             :  * it is not an error to try to undef a macro that does not exist.
    1753             :  *
    1754             :  * It returns non-zero on error (undefinition of a special macro,
    1755             :  * void macro name).
    1756             :  */
    1757           0 : int undef_macro(struct lexer_state *ls, char *def)
    1758             : {
    1759           0 :         char *c = def;
    1760             : 
    1761           0 :         if (!*c) {
    1762           0 :                 error(-1, "void macro name");
    1763           0 :                 return 1;
    1764             :         }
    1765           0 :         if (HTT_get(&macros, c)) {
    1766           0 :                 if (check_special_macro(c)) {
    1767           0 :                         error(-1, "trying to undef special macro %s", c);
    1768           0 :                         return 1;
    1769           0 :                 } else HTT_del(&macros, c);
    1770             :         }
    1771           0 :         return 0;
    1772             : }
    1773             : 
    1774             : /*
    1775             :  * We saw a #ifdef directive. Parse the line.
    1776             :  * return value: 1 if the macro is defined, 0 if it is not, -1 on error
    1777             :  */
    1778           0 : int handle_ifdef(struct lexer_state *ls)
    1779             : {
    1780           0 :         while (!next_token(ls)) {
    1781           0 :                 int tgd = 1;
    1782             : 
    1783           0 :                 if (ls->ctok->type == NEWLINE) break;
    1784           0 :                 if (ttMWS(ls->ctok->type)) continue;
    1785           0 :                 if (ls->ctok->type == NAME) {
    1786           0 :                         int x = (HTT_get(&macros, ls->ctok->name) != 0);
    1787           0 :                         while (!next_token(ls) && ls->ctok->type != NEWLINE)
    1788           0 :                                 if (tgd && !ttWHI(ls->ctok->type)
    1789           0 :                                         && (ls->flags & WARN_STANDARD)) {
    1790           0 :                                         warning(ls->line, "trailing garbage "
    1791             :                                                 "in #ifdef");
    1792           0 :                                         tgd = 0;
    1793             :                                 }
    1794           0 :                         return x;
    1795             :                 }
    1796           0 :                 error(ls->line, "illegal macro name for #ifdef");
    1797           0 :                 while (!next_token(ls) && ls->ctok->type != NEWLINE)
    1798           0 :                         if (tgd && !ttWHI(ls->ctok->type)
    1799           0 :                                 && (ls->flags & WARN_STANDARD)) {
    1800           0 :                                 warning(ls->line, "trailing garbage in "
    1801             :                                         "#ifdef");
    1802           0 :                                 tgd = 0;
    1803             :                         }
    1804           0 :                 return -1;
    1805             :         }
    1806           0 :         error(ls->line, "unfinished #ifdef");
    1807           0 :         return -1;
    1808             : }
    1809             : 
    1810             : /*
    1811             :  * for #undef
    1812             :  * return value: 1 on error, 0 on success. Undefining a macro that was
    1813             :  * already not defined is not an error.
    1814             :  */
    1815           0 : int handle_undef(struct lexer_state *ls)
    1816             : {
    1817           0 :         while (!next_token(ls)) {
    1818           0 :                 if (ls->ctok->type == NEWLINE) break;
    1819           0 :                 if (ttMWS(ls->ctok->type)) continue;
    1820           0 :                 if (ls->ctok->type == NAME) {
    1821           0 :                         struct macro *m = HTT_get(&macros, ls->ctok->name);
    1822           0 :                         int tgd = 1;
    1823             : 
    1824           0 :                         if (m != 0) {
    1825           0 :                                 if (check_special_macro(ls->ctok->name)) {
    1826           0 :                                         error(ls->line, "trying to undef "
    1827             :                                                 "special macro %s",
    1828           0 :                                                 ls->ctok->name);
    1829           0 :                                         goto undef_error;
    1830             :                                 }
    1831           0 :                                 if (emit_defines)
    1832           0 :                                         fprintf(emit_output, "#undef %s\n",
    1833           0 :                                                 ls->ctok->name);
    1834           0 :                                 HTT_del(&macros, ls->ctok->name);
    1835             :                         }
    1836           0 :                         while (!next_token(ls) && ls->ctok->type != NEWLINE)
    1837           0 :                                 if (tgd && !ttWHI(ls->ctok->type)
    1838           0 :                                         && (ls->flags & WARN_STANDARD)) {
    1839           0 :                                         warning(ls->line, "trailing garbage "
    1840             :                                                 "in #undef");
    1841           0 :                                         tgd = 0;
    1842             :                                 }
    1843           0 :                         return 0;
    1844             :                 }
    1845           0 :                 error(ls->line, "illegal macro name for #undef");
    1846             :         undef_error:
    1847           0 :                 while (!next_token(ls) && ls->ctok->type != NEWLINE);
    1848           0 :                 return 1;
    1849             :         }
    1850           0 :         error(ls->line, "unfinished #undef");
    1851           0 :         return 1;
    1852             : }
    1853             : 
    1854             : /*
    1855             :  * for #ifndef
    1856             :  * return value: 0 if the macro is defined, 1 if it is not, -1 on error.
    1857             :  */
    1858           0 : int handle_ifndef(struct lexer_state *ls)
    1859             : {
    1860           0 :         while (!next_token(ls)) {
    1861           0 :                 int tgd = 1;
    1862             : 
    1863           0 :                 if (ls->ctok->type == NEWLINE) break;
    1864           0 :                 if (ttMWS(ls->ctok->type)) continue;
    1865           0 :                 if (ls->ctok->type == NAME) {
    1866           0 :                         int x = (HTT_get(&macros, ls->ctok->name) == 0);
    1867             : 
    1868           0 :                         while (!next_token(ls) && ls->ctok->type != NEWLINE)
    1869           0 :                                 if (tgd && !ttWHI(ls->ctok->type)
    1870           0 :                                         && (ls->flags & WARN_STANDARD)) {
    1871           0 :                                         warning(ls->line, "trailing garbage "
    1872             :                                                 "in #ifndef");
    1873           0 :                                         tgd = 0;
    1874             :                                 }
    1875           0 :                         if (protect_detect.state == 1) {
    1876           0 :                                 protect_detect.state = 2;
    1877           0 :                                 protect_detect.macro = sdup(ls->ctok->name);
    1878             :                         }
    1879           0 :                         return x;
    1880             :                 }
    1881           0 :                 error(ls->line, "illegal macro name for #ifndef");
    1882           0 :                 while (!next_token(ls) && ls->ctok->type != NEWLINE)
    1883           0 :                         if (tgd && !ttWHI(ls->ctok->type)
    1884           0 :                                 && (ls->flags & WARN_STANDARD)) {
    1885           0 :                                 warning(ls->line, "trailing garbage in "
    1886             :                                         "#ifndef");
    1887           0 :                                 tgd = 0;
    1888             :                         }
    1889           0 :                 return -1;
    1890             :         }
    1891           0 :         error(ls->line, "unfinished #ifndef");
    1892           0 :         return -1;
    1893             : }
    1894             : 
    1895             : /*
    1896             :  * erase the macro table.
    1897             :  */
    1898           0 : void wipe_macros(void)
    1899             : {
    1900           0 :         if (macros_init_done) HTT_kill(&macros);
    1901           0 :         macros_init_done = 0;
    1902           0 : }
    1903             : 
    1904             : /*
    1905             :  * initialize the macro table
    1906             :  */
    1907           0 : void init_macros(void)
    1908             : {
    1909           0 :         wipe_macros();
    1910           0 :         HTT_init(&macros, del_macro);
    1911           0 :         macros_init_done = 1;
    1912           0 :         if (!no_special_macros) add_special_macros();
    1913           0 : }
    1914             : 
    1915             : /*
    1916             :  * find a macro from its name
    1917             :  */
    1918           0 : struct macro *get_macro(char *name)
    1919             : {
    1920           0 :         return HTT_get(&macros, name);
    1921             : }

Generated by: LCOV version 1.10