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