LCOV - code coverage report
Current view: top level - workdir/unxlngi6.pro/CustomTarget/ucpp/source - macro.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 138 921 15.0 %
Date: 2012-08-25 Functions: 11 23 47.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 77 1162 6.6 %

           Branch data     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                 :     121938 : static void del_macro(void *m)
      47                 :            : {
      48                 :     121938 :         struct macro *n = m;
      49                 :            :         size_t i;
      50                 :            : 
      51         [ +  + ]:     127916 :         for (i = 0; (int)i < n->narg; i ++) freemem(n->arg[i]);
      52         [ +  + ]:     121938 :         if (n->narg > 0) freemem(n->arg);
      53                 :            : #ifdef LOW_MEM
      54         [ +  + ]:     121938 :         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                 :     121938 :         freemem(n);
      64                 :     121938 : }
      65                 :            : 
      66                 :     121938 : static inline struct macro *new_macro(void)
      67                 :            : {
      68                 :     121938 :         struct macro *m = getmem(sizeof(struct macro));
      69                 :            : 
      70                 :     121938 :         m->narg = -1;
      71                 :     121938 :         m->nest = 0;
      72                 :            : #ifdef LOW_MEM
      73                 :     121938 :         m->cval.length = 0;
      74                 :            : #else
      75                 :            :         m->val.nt = m->val.art = 0;
      76                 :            : #endif
      77                 :     121938 :         m->vaarg = 0;
      78                 :     121938 :         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                 :      68136 : static inline int check_special_macro(char *name)
      96                 :            : {
      97         [ -  + ]:      68136 :         if (!strcmp(name, "defined")) return MAC_DEFINED;
      98         [ +  + ]:      68136 :         if (*name != '_') return MAC_NONE;
      99         [ -  + ]:      66956 :         if (*(name + 1) == 'P') {
     100         [ #  # ]:          0 :                 if (!strcmp(name, "_Pragma")) return MAC_PRAGMA;
     101                 :          0 :                 return MAC_NONE;
     102         [ +  + ]:      66956 :         } else if (*(name + 1) != '_') return MAC_NONE;
     103         [ -  + ]:      66840 :         if (no_special_macros) return MAC_NONE;
     104         [ -  + ]:      66840 :         if (!strcmp(name, "__LINE__")) return MAC_LINE;
     105         [ -  + ]:      66840 :         else if (!strcmp(name, "__FILE__")) return MAC_FILE;
     106         [ -  + ]:      66840 :         else if (!strcmp(name, "__DATE__")) return MAC_DATE;
     107         [ -  + ]:      66840 :         else if (!strcmp(name, "__TIME__")) return MAC_TIME;
     108         [ -  + ]:      66840 :         else if (!strcmp(name, "__STDC__")) return MAC_STDC;
     109                 :      68136 :         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                 :       5978 : static void add_special_macros(void)
     119                 :            : {
     120                 :            :         struct macro *m;
     121                 :            : 
     122                 :       5978 :         HTT_put(&macros, new_macro(), "__LINE__");
     123                 :       5978 :         HTT_put(&macros, new_macro(), "__FILE__");
     124                 :       5978 :         HTT_put(&macros, new_macro(), "__DATE__");
     125                 :       5978 :         HTT_put(&macros, new_macro(), "__TIME__");
     126                 :       5978 :         HTT_put(&macros, new_macro(), "__STDC__");
     127                 :       5978 :         m = new_macro(); m->narg = 1;
     128                 :       5978 :         m->arg = getmem(sizeof(char *)); m->arg[0] = sdup("foo");
     129                 :       5978 :         HTT_put(&macros, m, "_Pragma");
     130         [ +  - ]:       5978 :         if (c99_compliant) {
     131                 :            : #ifndef LOW_MEM
     132                 :            :                 struct token t;
     133                 :            : #endif
     134                 :            : 
     135                 :       5978 :                 m = new_macro();
     136                 :            : #ifdef LOW_MEM
     137                 :       5978 :                 m->cval.t = getmem(9);
     138                 :       5978 :                 m->cval.t[0] = NUMBER;
     139                 :       5978 :                 mmv(m->cval.t + 1, "199901L", 8);
     140                 :       5978 :                 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                 :       5978 :                 HTT_put(&macros, m, "__STDC_VERSION__");
     148                 :            :         }
     149         [ +  - ]:       5978 :         if (c99_hosted) {
     150                 :            : #ifndef LOW_MEM
     151                 :            :                 struct token t;
     152                 :            : #endif
     153                 :            : 
     154                 :       5978 :                 m = new_macro();
     155                 :            : #ifdef LOW_MEM
     156                 :       5978 :                 m->cval.t = getmem(3);
     157                 :       5978 :                 m->cval.t[0] = NUMBER;
     158                 :       5978 :                 mmv(m->cval.t + 1, "1", 2);
     159                 :       5978 :                 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                 :       5978 :                 HTT_put(&macros, m, "__STDC_HOSTED__");
     167                 :            :         }
     168                 :       5978 : }
     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                 :    2415999 : void print_token(struct lexer_state *ls, struct token *t, long uz_line)
     256                 :            : {
     257                 :    2415999 :         char *x = t->name;
     258                 :            : 
     259 [ -  + ][ #  # ]:    2415999 :         if (uz_line && t->line < 0) t->line = uz_line;
     260         [ -  + ]:    2415999 :         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                 :    2415999 :                 return;
     271                 :            :         }
     272         [ +  - ]:    2415999 :         if (ls->flags & KEEP_OUTPUT) {
     273         [ -  + ]:    2415999 :                 for (; ls->oline < ls->line;) put_char(ls, '\n');
     274                 :            :         }
     275 [ +  - ][ -  + ]:    2415999 :         if (!S_TOKEN(t->type)) x = operators_name[t->type];
     276         [ +  + ]:   18439750 :         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                 :      68136 : int handle_define(struct lexer_state *ls)
     319                 :            : {
     320                 :      68136 :         struct macro *m = 0, *n;
     321                 :            : #ifdef LOW_MEM
     322                 :            :         struct token_fifo mv;
     323                 :            : #endif
     324                 :      68136 :         int ltwws = 1, redef = 0;
     325                 :      68136 :         char *mname = 0;
     326                 :            :         int narg;
     327                 :            :         size_t nt;
     328                 :      68136 :         long l = ls->line;
     329                 :            :         
     330                 :            : #ifdef LOW_MEM
     331                 :      68136 :         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 [ +  - ][ +  - ]:     136272 :         while (!next_token(ls) && ls->ctok->type != NEWLINE) {
     336 [ +  + ][ +  - ]:     136272 :                 if (ttMWS(ls->ctok->type)) continue;
                 [ -  + ]
     337         [ +  - ]:      68136 :                 if (ls->ctok->type == NAME) mname = sdup(ls->ctok->name);
     338                 :      68136 :                 break;
     339                 :            :         }
     340         [ -  + ]:      68136 :         if (mname == 0) {
     341                 :          0 :                 error(l, "missing macro name");
     342                 :          0 :                 return 1;
     343                 :            :         }
     344         [ -  + ]:      68136 :         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         [ -  + ]:      68136 :         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         [ +  - ]:      68136 :         if (!redef) {
     370                 :      68136 :                 m = new_macro();
     371                 :      68136 :                 m->narg = -1;
     372                 :            : #ifdef LOW_MEM
     373                 :            : #define mval    mv
     374                 :            : #else
     375                 :            : #define mval    (m->val)
     376                 :            : #endif
     377                 :            :         }
     378         [ -  + ]:      68136 :         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         [ -  + ]:      68136 :         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 [ +  - ][ +  - ]:      68136 :                 if (!ttWHI(ls->ctok->type) && (ls->flags & WARN_STANDARD))
         [ +  - ][ -  + ]
                 [ #  # ]
     484                 :          0 :                         warning(ls->line, "identifier not followed by "
     485                 :            :                                 "whitespace in #define");
     486                 :      68136 :                 ls->flags |= READ_AGAIN;
     487                 :      68136 :                 narg = 0;
     488                 :            :         }
     489         [ -  + ]:      68136 :         if (redef) nt = 0;
     490                 :            : 
     491                 :            :         /* now, we have the arguments. Let's get the macro contents. */
     492 [ +  - ][ -  + ]:      68136 :         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         [ -  + ]:      68136 :         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 [ -  + ][ #  # ]:      68136 :         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         [ -  + ]:      68136 :         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         [ -  + ]:      68136 :                 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                 :      68136 :                 m->cval.length = l;
     648         [ -  + ]:      68136 :                 if (l) m->cval.t = getmem(l);
     649         [ -  + ]:      68136 :                 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         [ -  + ]:      68136 :                 if (mval.nt) freemem(mval.t);
     670                 :            :         }
     671                 :            : #endif
     672                 :      68136 :         HTT_put(&macros, m, mname);
     673                 :      68136 :         freemem(mname);
     674         [ -  + ]:      68136 :         if (emit_defines) print_macro(m);
     675                 :      68136 :         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                 :      68136 :         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                 :       5978 : int define_macro(struct lexer_state *ls, char *def)
    1679                 :            : {
    1680                 :       5978 :         char *c = sdup(def), *d;
    1681                 :       5978 :         int with_def = 0;
    1682                 :       5978 :         int ret = 0;
    1683                 :            : 
    1684 [ +  + ][ +  - ]:      23912 :         for (d = c; *d && *d != '='; d ++);
    1685         [ -  + ]:       5978 :         if (*d) {
    1686                 :          0 :                 *d = ' ';
    1687                 :          0 :                 with_def = 1;
    1688                 :            :         }
    1689         [ -  + ]:       5978 :         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         [ -  + ]:       5978 :                 if (!*c) {
    1712                 :          0 :                         error(-1, "void macro name");
    1713                 :          0 :                         ret = 1;
    1714         [ -  + ]:       5978 :                 } 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                 :       5978 :                         m = new_macro();
    1732                 :            : #ifdef LOW_MEM
    1733                 :       5978 :                         m->cval.length = 3;
    1734                 :       5978 :                         m->cval.t = getmem(3);
    1735                 :       5978 :                         m->cval.t[0] = NUMBER;
    1736                 :       5978 :                         m->cval.t[1] = '1';
    1737                 :       5978 :                         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                 :       5978 :                         HTT_put(&macros, m, c);
    1744                 :            :                 }
    1745                 :            :         }
    1746                 :       5978 :         freemem(c);
    1747                 :       5978 :         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                 :      68340 : int handle_ifndef(struct lexer_state *ls)
    1859                 :            : {
    1860         [ +  - ]:     136680 :         while (!next_token(ls)) {
    1861                 :     136680 :                 int tgd = 1;
    1862                 :            : 
    1863         [ -  + ]:     136680 :                 if (ls->ctok->type == NEWLINE) break;
    1864 [ +  + ][ +  - ]:     136680 :                 if (ttMWS(ls->ctok->type)) continue;
                 [ -  + ]
    1865         [ +  - ]:      68340 :                 if (ls->ctok->type == NAME) {
    1866                 :      68340 :                         int x = (HTT_get(&macros, ls->ctok->name) == 0);
    1867                 :            : 
    1868 [ +  - ][ -  + ]:      68340 :                         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         [ +  + ]:      68340 :                         if (protect_detect.state == 1) {
    1876                 :      68137 :                                 protect_detect.state = 2;
    1877                 :      68137 :                                 protect_detect.macro = sdup(ls->ctok->name);
    1878                 :            :                         }
    1879                 :      68340 :                         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                 :      68340 :         return -1;
    1893                 :            : }
    1894                 :            : 
    1895                 :            : /*
    1896                 :            :  * erase the macro table.
    1897                 :            :  */
    1898                 :      11956 : void wipe_macros(void)
    1899                 :            : {
    1900         [ +  + ]:      11956 :         if (macros_init_done) HTT_kill(&macros);
    1901                 :      11956 :         macros_init_done = 0;
    1902                 :      11956 : }
    1903                 :            : 
    1904                 :            : /*
    1905                 :            :  * initialize the macro table
    1906                 :            :  */
    1907                 :       5978 : void init_macros(void)
    1908                 :            : {
    1909                 :       5978 :         wipe_macros();
    1910                 :       5978 :         HTT_init(&macros, del_macro);
    1911                 :       5978 :         macros_init_done = 1;
    1912         [ +  - ]:       5978 :         if (!no_special_macros) add_special_macros();
    1913                 :       5978 : }
    1914                 :            : 
    1915                 :            : /*
    1916                 :            :  * find a macro from its name
    1917                 :            :  */
    1918                 :    2465597 : struct macro *get_macro(char *name)
    1919                 :            : {
    1920                 :    2465597 :         return HTT_get(&macros, name);
    1921                 :            : }

Generated by: LCOV version 1.10