]> git.saurik.com Git - apple/boot.git/blame - i386/nasm/preproc.c
boot-132.tar.gz
[apple/boot.git] / i386 / nasm / preproc.c
CommitLineData
14c7c974
A
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
4f6e3300
A
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
14c7c974
A
13 *
14 * The Original Code and all software distributed under the License are
4f6e3300 15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14c7c974
A
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
4f6e3300
A
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
14c7c974
A
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24/* preproc.c macro preprocessor for the Netwide Assembler
25 *
26 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
27 * Julian Hall. All rights reserved. The software is
28 * redistributable under the licence given in the file "Licence"
29 * distributed in the NASM archive.
30 *
31 * initial version 18/iii/97 by Simon Tatham
32 */
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <stddef.h>
37#include <string.h>
38#include <ctype.h>
39#include <limits.h>
40
41#include "nasm.h"
42#include "nasmlib.h"
43
44typedef struct SMacro SMacro;
45typedef struct MMacro MMacro;
46typedef struct Context Context;
47typedef struct Token Token;
48typedef struct Line Line;
49typedef struct Include Include;
50typedef struct Cond Cond;
51typedef struct IncPath IncPath;
52
53/*
54 * Store the definition of a single-line macro.
55 */
56struct SMacro {
57 SMacro *next;
58 char *name;
59 int casesense;
60 int nparam;
61 int in_progress;
62 Token *expansion;
63};
64
65/*
66 * Store the definition of a multi-line macro. This is also used to
67 * store the interiors of `%rep...%endrep' blocks, which are
68 * effectively self-re-invoking multi-line macros which simply
69 * don't have a name or bother to appear in the hash tables. %rep
70 * blocks are signified by having a NULL `name' field.
71 *
72 * In a MMacro describing a `%rep' block, the `in_progress' field
73 * isn't merely boolean, but gives the number of repeats left to
74 * run.
75 *
76 * The `next' field is used for storing MMacros in hash tables; the
77 * `next_active' field is for stacking them on istk entries.
78 *
79 * When a MMacro is being expanded, `params', `iline', `nparam',
80 * `paramlen', `rotate' and `unique' are local to the invocation.
81 */
82struct MMacro {
83 MMacro *next;
84 char *name;
85 int casesense;
86 int nparam_min, nparam_max;
87 int plus; /* is the last parameter greedy? */
88 int nolist; /* is this macro listing-inhibited? */
89 int in_progress;
90 Token **defaults, *dlist;
91 int ndefs; /* number of default parameters */
92 Line *expansion;
93
94 MMacro *next_active;
95 Token **params, *iline;
96 int nparam, rotate, *paramlen;
97 unsigned long unique;
98};
99
100/*
101 * The context stack is composed of a linked list of these.
102 */
103struct Context {
104 Context *next;
105 SMacro *localmac;
106 char *name;
107 unsigned long number;
108};
109
110/*
111 * This is the internal form which we break input lines up into.
112 * Typically stored in linked lists.
113 *
114 * TOK_PS_OTHER is a token type used internally within
115 * expand_smacro(), to denote a token which has already been
116 * checked for being a potential macro, but may still be a context-
117 * local label.
118 *
119 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
120 * necessarily used as-is, but is intended to denote the number of
121 * the substituted parameter. So in the definition
122 *
123 * %define a(x,y) ( (x) & ~(y) )
124 *
125 * the token representing `x' will have its type changed to
126 * TOK_SMAC_PARAM, but the one representing `y' will be
127 * TOK_SMAC_PARAM+1.
128 *
129 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
130 * which doesn't need quotes around it. Used in the pre-include
131 * mechanism as an alternative to trying to find a sensible type of
132 * quote to use on the filename we were passed.
133 */
134struct Token {
135 Token *next;
136 char *text;
137 SMacro *mac; /* associated macro for TOK_SMAC_END */
138 int type;
139};
140enum {
141 TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING,
142 TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_PS_OTHER, TOK_SMAC_PARAM,
143 TOK_INTERNAL_STRING
144};
145
146/*
147 * Multi-line macro definitions are stored as a linked list of
148 * these, which is essentially a container to allow several linked
149 * lists of Tokens.
150 *
151 * Note that in this module, linked lists are treated as stacks
152 * wherever possible. For this reason, Lines are _pushed_ on to the
153 * `expansion' field in MMacro structures, so that the linked list,
154 * if walked, would give the macro lines in reverse order; this
155 * means that we can walk the list when expanding a macro, and thus
156 * push the lines on to the `expansion' field in _istk_ in reverse
157 * order (so that when popped back off they are in the right
158 * order). It may seem cockeyed, and it relies on my design having
159 * an even number of steps in, but it works...
160 *
161 * Some of these structures, rather than being actual lines, are
162 * markers delimiting the end of the expansion of a given macro.
163 * This is for use in the cycle-tracking and %rep-handling code.
164 * Such structures have `finishes' non-NULL, and `first' NULL. All
165 * others have `finishes' NULL, but `first' may still be NULL if
166 * the line is blank.
167 */
168struct Line {
169 Line *next;
170 MMacro *finishes;
171 Token *first;
172};
173
174/*
175 * To handle an arbitrary level of file inclusion, we maintain a
176 * stack (ie linked list) of these things.
177 */
178struct Include {
179 Include *next;
180 FILE *fp;
181 Cond *conds;
182 Line *expansion;
183 char *fname;
184 int lineno, lineinc;
185 MMacro *mstk; /* stack of active macros/reps */
186};
187
188/*
189 * Include search path. This is simply a list of strings which get
190 * prepended, in turn, to the name of an include file, in an
191 * attempt to find the file if it's not in the current directory.
192 */
193struct IncPath {
194 IncPath *next;
195 char *path;
196};
197
198/*
199 * Conditional assembly: we maintain a separate stack of these for
200 * each level of file inclusion. (The only reason we keep the
201 * stacks separate is to ensure that a stray `%endif' in a file
202 * included from within the true branch of a `%if' won't terminate
203 * it and cause confusion: instead, rightly, it'll cause an error.)
204 */
205struct Cond {
206 Cond *next;
207 int state;
208};
209enum {
210 /*
211 * These states are for use just after %if or %elif: IF_TRUE
212 * means the condition has evaluated to truth so we are
213 * currently emitting, whereas IF_FALSE means we are not
214 * currently emitting but will start doing so if a %else comes
215 * up. In these states, all directives are admissible: %elif,
216 * %else and %endif. (And of course %if.)
217 */
218 COND_IF_TRUE, COND_IF_FALSE,
219 /*
220 * These states come up after a %else: ELSE_TRUE means we're
221 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
222 * any %elif or %else will cause an error.
223 */
224 COND_ELSE_TRUE, COND_ELSE_FALSE,
225 /*
226 * This state means that we're not emitting now, and also that
227 * nothing until %endif will be emitted at all. It's for use in
228 * two circumstances: (i) when we've had our moment of emission
229 * and have now started seeing %elifs, and (ii) when the
230 * condition construct in question is contained within a
231 * non-emitting branch of a larger condition construct.
232 */
233 COND_NEVER
234};
235#define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
236
237/*
238 * Condition codes. Note that we use c_ prefix not C_ because C_ is
239 * used in nasm.h for the "real" condition codes. At _this_ level,
240 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
241 * ones, so we need a different enum...
242 */
243static char *conditions[] = {
244 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
245 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
246 "np", "ns", "nz", "o", "p", "pe", "po", "s", "z"
247};
248enum {
249 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
250 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
251 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_S, c_Z
252};
253static int inverse_ccs[] = {
254 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
255 c_A, c_AE, c_B, c_BE, c_C, c_E, c_G, c_GE, c_L, c_LE, c_O, c_P, c_S,
256 c_Z, c_NO, c_NP, c_PO, c_PE, c_NS, c_NZ
257};
258
259/*
260 * Directive names.
261 */
262static char *directives[] = {
263 "%assign", "%clear", "%define", "%elif", "%elifctx", "%elifdef",
264 "%elifid", "%elifidn", "%elifidni", "%elifnctx", "%elifndef",
265 "%elifnid", "%elifnidn", "%elifnidni", "%elifnnum", "%elifnstr",
266 "%elifnum", "%elifstr", "%else", "%endif", "%endm", "%endmacro",
267 "%endrep", "%error", "%exitrep", "%iassign", "%idefine", "%if",
268 "%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifnctx",
269 "%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnnum",
270 "%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include", "%line",
271 "%macro", "%pop", "%push", "%rep", "%repl", "%rotate"
272};
273enum {
274 PP_ASSIGN, PP_CLEAR, PP_DEFINE, PP_ELIF, PP_ELIFCTX, PP_ELIFDEF,
275 PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFNCTX, PP_ELIFNDEF,
276 PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNNUM, PP_ELIFNSTR,
277 PP_ELIFNUM, PP_ELIFSTR, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO,
278 PP_ENDREP, PP_ERROR, PP_EXITREP, PP_IASSIGN, PP_IDEFINE, PP_IF,
279 PP_IFCTX, PP_IFDEF, PP_IFID, PP_IFIDN, PP_IFIDNI, PP_IFNCTX,
280 PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNNUM,
281 PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE, PP_LINE,
282 PP_MACRO, PP_POP, PP_PUSH, PP_REP, PP_REPL, PP_ROTATE
283};
284
285
286static Context *cstk;
287static Include *istk;
288static IncPath *ipath = NULL;
289
290static efunc error;
291static evalfunc evaluate;
292
293static int pass;
294
295static unsigned long unique; /* unique identifier numbers */
296
297static char *linesync, *outline;
298
299static Line *predef = NULL;
300
301static ListGen *list;
302
303/*
304 * The number of hash values we use for the macro lookup tables.
305 */
306#define NHASH 31
307
308/*
309 * The current set of multi-line macros we have defined.
310 */
311static MMacro *mmacros[NHASH];
312
313/*
314 * The current set of single-line macros we have defined.
315 */
316static SMacro *smacros[NHASH];
317
318/*
319 * The multi-line macro we are currently defining, or the %rep
320 * block we are currently reading, if any.
321 */
322static MMacro *defining;
323
324/*
325 * The number of macro parameters to allocate space for at a time.
326 */
327#define PARAM_DELTA 16
328
329/*
330 * The standard macro set: defined as `static char *stdmac[]'. Also
331 * gives our position in the macro set, when we're processing it.
332 */
333#include "macros.c"
334static char **stdmacpos;
335
336/*
337 * The extra standard macros that come from the object format, if
338 * any.
339 */
340static char **extrastdmac = NULL;
341int any_extrastdmac;
342
343/*
344 * Forward declarations.
345 */
346static Token *expand_smacro (Token *tline);
347static void update_fileline (int which);
348
349/*
350 * The pre-preprocessing stage... This function translates line
351 * number indications as they emerge from GNU cpp (`# lineno "file"
352 * flags') into NASM preprocessor line number indications (`%line
353 * lineno file').
354 */
355static char *prepreproc(char *line) {
356 int lineno, fnlen;
357 char *fname, *oldline;
358
359 if (line[0] == '#' && line[1] == ' ') {
360 oldline = line;
361 fname = oldline+2;
362 lineno = atoi(fname);
363 fname += strspn(fname, "0123456789 ");
364 if (*fname == '"')
365 fname++;
366 fnlen = strcspn(fname, "\"");
367 line = nasm_malloc(20+fnlen);
368 sprintf(line, "%%line %d %.*s", lineno, fnlen, fname);
369 nasm_free (oldline);
370 }
371 return line;
372}
373
374/*
375 * The hash function for macro lookups. Note that due to some
376 * macros having case-insensitive names, the hash function must be
377 * invariant under case changes. We implement this by applying a
378 * perfectly normal hash function to the uppercase of the string.
379 */
380static int hash(char *s) {
381 /*
382 * Powers of three, mod 31.
383 */
384 static const int multipliers[] = {
385 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10,
386 30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21
387 };
388 int h = 0;
389 int i = 0;
390
391 while (*s) {
392 h += multipliers[i] * (unsigned char) (toupper(*s));
393 s++;
f083c6c3 394 if (++i >= (int)sizeof(multipliers)/(int)sizeof(*multipliers))
14c7c974
A
395 i = 0;
396 }
397 h %= NHASH;
398 return h;
399}
400
401/*
402 * Free a linked list of tokens.
403 */
404static void free_tlist (Token *list) {
405 Token *t;
406 while (list) {
407 t = list;
408 list = list->next;
409 nasm_free (t->text);
410 nasm_free (t);
411 }
412}
413
414/*
415 * Free a linked list of lines.
416 */
417static void free_llist (Line *list) {
418 Line *l;
419 while (list) {
420 l = list;
421 list = list->next;
422 free_tlist (l->first);
423 nasm_free (l);
424 }
425}
426
427/*
428 * Pop the context stack.
429 */
430static void ctx_pop (void) {
431 Context *c = cstk;
432 SMacro *smac, *s;
433
434 cstk = cstk->next;
435 smac = c->localmac;
436 while (smac) {
437 s = smac;
438 smac = smac->next;
439 nasm_free (s->name);
440 free_tlist (s->expansion);
441 nasm_free (s);
442 }
443 nasm_free (c->name);
444 nasm_free (c);
445}
446
447/*
448 * Generate a line synchronisation comment, to ensure the assembler
449 * knows which source file the current output has really come from.
450 */
451static void line_sync (void) {
452 char text[30+FILENAME_MAX];
453 sprintf(text, "%%line %d+%d %s",
454 (istk->expansion ? istk->lineno - istk->lineinc : istk->lineno),
455 (istk->expansion ? 0 : istk->lineinc), istk->fname);
456 nasm_free (linesync);
457 linesync = nasm_strdup(text);
458}
459
460#define BUF_DELTA 512
461/*
462 * Read a line from the top file in istk, handling multiple CR/LFs
463 * at the end of the line read, and handling spurious ^Zs. Will
464 * return lines from the standard macro set if this has not already
465 * been done.
466 */
467static char *read_line (void) {
468 char *buffer, *p, *q;
469 int bufsize;
470
471 if (stdmacpos) {
472 if (*stdmacpos) {
473 char *ret = nasm_strdup(*stdmacpos++);
474 if (!*stdmacpos && any_extrastdmac) {
475 stdmacpos = extrastdmac;
476 any_extrastdmac = FALSE;
477 return ret;
478 }
479 /*
480 * Nasty hack: here we push the contents of `predef' on
481 * to the top-level expansion stack, since this is the
482 * most convenient way to implement the pre-include and
483 * pre-define features.
484 */
485 if (!*stdmacpos) {
486 Line *pd, *l;
487 Token *head, **tail, *t, *tt;
488
489 for (pd = predef; pd; pd = pd->next) {
490 head = NULL;
491 tail = &head;
492 for (t = pd->first; t; t = t->next) {
493 tt = *tail = nasm_malloc(sizeof(Token));
494 tt->next = NULL;
495 tail = &tt->next;
496 tt->type = t->type;
497 tt->text = nasm_strdup(t->text);
498 tt->mac = t->mac; /* always NULL here, in fact */
499 }
500 l = nasm_malloc(sizeof(Line));
501 l->next = istk->expansion;
502 l->first = head;
503 l->finishes = FALSE;
504 istk->expansion = l;
505 }
506 }
507 return ret;
508 } else {
509 stdmacpos = NULL;
510 line_sync();
511 update_fileline(3); /* update __FILE__ and __LINE__ */
512 }
513 }
514
515 bufsize = BUF_DELTA;
516 buffer = nasm_malloc(BUF_DELTA);
517 p = buffer;
518 while (1) {
519 q = fgets(p, bufsize-(p-buffer), istk->fp);
520 if (!q)
521 break;
522 p += strlen(p);
523 if (p > buffer && p[-1] == '\n') {
524 istk->lineno += istk->lineinc;
525 update_fileline(1); /* update __LINE__ only */
526 break;
527 }
528 if (p-buffer > bufsize-10) {
529 bufsize += BUF_DELTA;
530 buffer = nasm_realloc(buffer, bufsize);
531 }
532 }
533
534 if (!q && p == buffer) {
535 nasm_free (buffer);
536 return NULL;
537 }
538
539 /*
540 * Play safe: remove CRs as well as LFs, if any of either are
541 * present at the end of the line.
542 */
543 while (p > buffer && (p[-1] == '\n' || p[-1] == '\r'))
544 *--p = '\0';
545
546 /*
547 * Handle spurious ^Z, which may be inserted into source files
548 * by some file transfer utilities.
549 */
550 buffer[strcspn(buffer, "\032")] = '\0';
551
552 list->line (LIST_READ, buffer);
553
554 return buffer;
555}
556
557/*
558 * Tokenise a line of text. This is a very simple process since we
559 * don't need to parse the value out of e.g. numeric tokens: we
560 * simply split one string into many.
561 */
562static Token *tokenise (char *line) {
563 char *p = line;
564 int type;
565 Token *list = NULL;
566 Token *t, **tail = &list;
567
568 while (*line) {
569 p = line;
570 if (*p == '%' &&
571 (p[1] == '{' || p[1] == '!' || (p[1] == '%' && isidchar(p[2])) ||
572 p[1] == '$' || p[1] == '+' || p[1] == '-' || isidchar(p[1]))) {
573 type = TOK_PREPROC_ID;
574 p++;
575 if (*p == '{') {
576 p++;
577 while (*p && *p != '}') {
578 p[-1] = *p;
579 p++;
580 }
581 p[-1] = '\0';
582 if (*p) p++;
583 } else {
584 if (*p == '!' || *p == '%' || *p == '$' ||
585 *p == '+' || *p == '-') p++;
586 while (*p && isidchar(*p))
587 p++;
588 }
589 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
590 type = TOK_ID;
591 p++;
592 while (*p && isidchar(*p))
593 p++;
594 } else if (*p == '\'' || *p == '"') {
595 /*
596 * A string token.
597 */
598 char c = *p;
599 p++;
600 type = TOK_STRING;
601 while (*p && *p != c)
602 p++;
603 if (*p) p++;
604 } else if (isnumstart(*p)) {
605 /*
606 * A number token.
607 */
608 type = TOK_NUMBER;
609 p++;
610 while (*p && isnumchar(*p))
611 p++;
612 } else if (isspace(*p)) {
613 type = TOK_WHITESPACE;
614 p++;
615 while (*p && isspace(*p))
616 p++;
617 /*
618 * Whitespace just before end-of-line is discarded by
619 * pretending it's a comment; whitespace just before a
620 * comment gets lumped into the comment.
621 */
622 if (!*p || *p == ';') {
623 type = TOK_COMMENT;
624 while (*p) p++;
625 }
626 } else if (*p == ';') {
627 type = TOK_COMMENT;
628 while (*p) p++;
629 } else {
630 /*
631 * Anything else is an operator of some kind. We check
632 * for all the double-character operators (>>, <<, //,
633 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
634 * else is a single-character operator.
635 */
636 type = TOK_OTHER;
637 if ((p[0] == '>' && p[1] == '>') ||
638 (p[0] == '<' && p[1] == '<') ||
639 (p[0] == '/' && p[1] == '/') ||
640 (p[0] == '%' && p[1] == '%') ||
641 (p[0] == '<' && p[1] == '=') ||
642 (p[0] == '>' && p[1] == '=') ||
643 (p[0] == '=' && p[1] == '=') ||
644 (p[0] == '!' && p[1] == '=') ||
645 (p[0] == '<' && p[1] == '>') ||
646 (p[0] == '&' && p[1] == '&') ||
647 (p[0] == '|' && p[1] == '|') ||
648 (p[0] == '^' && p[1] == '^'))
649 p++;
650 p++;
651 }
652 if (type != TOK_COMMENT) {
653 *tail = t = nasm_malloc (sizeof(Token));
654 tail = &t->next;
655 t->next = NULL;
656 t->type = type;
657 t->text = nasm_malloc(1+p-line);
658 strncpy(t->text, line, p-line);
659 t->text[p-line] = '\0';
660 }
661 line = p;
662 }
663
664 return list;
665}
666
667/*
668 * Convert a line of tokens back into text.
669 */
670static char *detoken (Token *tlist) {
671 Token *t;
672 int len;
673 char *line, *p;
674
675 len = 0;
676 for (t = tlist; t; t = t->next) {
677 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
678 char *p = getenv(t->text+2);
679 nasm_free (t->text);
680 if (p)
681 t->text = nasm_strdup(p);
682 else
683 t->text = NULL;
684 }
685 if (t->text)
686 len += strlen(t->text);
687 }
688 p = line = nasm_malloc(len+1);
689 for (t = tlist; t; t = t->next) {
690 if (t->text) {
691 strcpy (p, t->text);
692 p += strlen(p);
693 }
694 }
695 *p = '\0';
696 return line;
697}
698
699/*
700 * A scanner, suitable for use by the expression evaluator, which
701 * operates on a line of Tokens. Expects a pointer to a pointer to
702 * the first token in the line to be passed in as its private_data
703 * field.
704 */
705static int ppscan(void *private_data, struct tokenval *tokval) {
706 Token **tlineptr = private_data;
707 Token *tline;
708
709 do {
710 tline = *tlineptr;
711 *tlineptr = tline ? tline->next : NULL;
712 } while (tline && (tline->type == TOK_WHITESPACE ||
713 tline->type == TOK_COMMENT));
714
715 if (!tline)
716 return tokval->t_type = TOKEN_EOS;
717
718 if (tline->text[0] == '$' && !tline->text[1])
719 return tokval->t_type = TOKEN_HERE;
720 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[1])
721 return tokval->t_type = TOKEN_BASE;
722
723 if (tline->type == TOK_ID) {
724 tokval->t_charptr = tline->text;
725 if (tline->text[0] == '$') {
726 tokval->t_charptr++;
727 return tokval->t_type = TOKEN_ID;
728 }
729
730 /*
731 * This is the only special case we actually need to worry
732 * about in this restricted context.
733 */
734 if (!nasm_stricmp(tline->text, "seg"))
735 return tokval->t_type = TOKEN_SEG;
736
737 return tokval->t_type = TOKEN_ID;
738 }
739
740 if (tline->type == TOK_NUMBER) {
741 int rn_error;
742
743 tokval->t_integer = readnum(tline->text, &rn_error);
744 if (rn_error)
745 return tokval->t_type = TOKEN_ERRNUM;
746 tokval->t_charptr = NULL;
747 return tokval->t_type = TOKEN_NUM;
748 }
749
750 if (tline->type == TOK_OTHER) {
751 if (!strcmp(tline->text, "<<")) return tokval->t_type = TOKEN_SHL;
752 if (!strcmp(tline->text, ">>")) return tokval->t_type = TOKEN_SHR;
753 if (!strcmp(tline->text, "//")) return tokval->t_type = TOKEN_SDIV;
754 if (!strcmp(tline->text, "%%")) return tokval->t_type = TOKEN_SMOD;
755 if (!strcmp(tline->text, "==")) return tokval->t_type = TOKEN_EQ;
756 if (!strcmp(tline->text, "<>")) return tokval->t_type = TOKEN_NE;
757 if (!strcmp(tline->text, "!=")) return tokval->t_type = TOKEN_NE;
758 if (!strcmp(tline->text, "<=")) return tokval->t_type = TOKEN_LE;
759 if (!strcmp(tline->text, ">=")) return tokval->t_type = TOKEN_GE;
760 if (!strcmp(tline->text, "&&")) return tokval->t_type = TOKEN_DBL_AND;
761 if (!strcmp(tline->text, "^^")) return tokval->t_type = TOKEN_DBL_XOR;
762 if (!strcmp(tline->text, "||")) return tokval->t_type = TOKEN_DBL_OR;
763 }
764
765 /*
766 * We have no other options: just return the first character of
767 * the token text.
768 */
769 return tokval->t_type = tline->text[0];
770}
771
772/*
773 * Return the Context structure associated with a %$ token. Return
774 * NULL, having _already_ reported an error condition, if the
775 * context stack isn't deep enough for the supplied number of $
776 * signs.
777 */
778static Context *get_ctx (char *name) {
779 Context *ctx;
780 int i;
781
782 if (!cstk) {
783 error (ERR_NONFATAL|ERR_OFFBY1, "`%s': context stack is empty", name);
784 return NULL;
785 }
786
787 i = 1;
788 ctx = cstk;
789 while (name[i+1] == '$') {
790 i++;
791 ctx = ctx->next;
792 if (!ctx) {
793 error (ERR_NONFATAL|ERR_OFFBY1, "`%s': context stack is only"
794 " %d level%s deep", name, i-1, (i==2 ? "" : "s"));
795 return NULL;
796 }
797 }
798 return ctx;
799}
800
801/*
802 * Compare a string to the name of an existing macro; this is a
803 * simple wrapper which calls either strcmp or nasm_stricmp
804 * depending on the value of the `casesense' parameter.
805 */
806static int mstrcmp(char *p, char *q, int casesense) {
807 return casesense ? strcmp(p,q) : nasm_stricmp(p,q);
808}
809
810/*
811 * Open an include file. This routine must always return a valid
812 * file pointer if it returns - it's responsible for throwing an
813 * ERR_FATAL and bombing out completely if not. It should also try
814 * the include path one by one until it finds the file or reaches
815 * the end of the path.
816 */
817static FILE *inc_fopen(char *file) {
818 FILE *fp;
819 char *prefix = "", *combine;
820 IncPath *ip = ipath;
821 int len = strlen(file);
822
823 do {
824 combine = nasm_malloc(strlen(prefix)+len+1);
825 strcpy(combine, prefix);
826 strcat(combine, file);
827 fp = fopen(combine, "r");
828 nasm_free (combine);
829 if (fp)
830 return fp;
831 prefix = ip ? ip->path : NULL;
832 if (ip)
833 ip = ip->next;
834 } while (prefix);
835
836 error (ERR_FATAL|ERR_OFFBY1,
837 "unable to open include file `%s'", file);
838 return NULL; /* never reached - placate compilers */
839}
840
841/*
842 * Determine if we should warn on defining a single-line macro of
843 * name `name', with `nparam' parameters. If nparam is 0, will
844 * return TRUE if _any_ single-line macro of that name is defined.
845 * Otherwise, will return TRUE if a single-line macro with either
846 * `nparam' or no parameters is defined.
847 *
848 * If a macro with precisely the right number of parameters is
849 * defined, the address of the definition structure will be
850 * returned in `defn'; otherwise NULL will be returned. If `defn'
851 * is NULL, no action will be taken regarding its contents, and no
852 * error will occur.
853 *
854 * Note that this is also called with nparam zero to resolve
855 * `ifdef'.
856 */
857static int smacro_defined (char *name, int nparam, SMacro **defn) {
858 SMacro *m;
859 Context *ctx;
860 char *p;
861
862 if (name[0] == '%' && name[1] == '$') {
863 ctx = get_ctx (name);
864 if (!ctx)
865 return FALSE; /* got to return _something_ */
866 m = ctx->localmac;
867 p = name+1;
868 p += strspn(p, "$");
869 } else {
870 m = smacros[hash(name)];
871 p = name;
872 }
873
874 while (m) {
875 if (!mstrcmp(m->name, p, m->casesense) &&
876 (nparam == 0 || m->nparam == 0 || nparam == m->nparam)) {
877 if (defn) {
878 if (nparam == m->nparam)
879 *defn = m;
880 else
881 *defn = NULL;
882 }
883 return TRUE;
884 }
885 m = m->next;
886 }
887 return FALSE;
888}
889
890/*
891 * Update the __FILE__ and __LINE__ macros. Specifically, update
892 * __FILE__ if bit 1 of our argument is set, and update __LINE__ if
893 * bit 0 is set.
894 *
895 * If the macros don't exist, a `%clear' must have happened, in
896 * which case we should exit quite happily and carry on going. It's
897 * not an error condition.
898 */
899static void update_fileline(int which) {
900 SMacro *sm;
901 char num[20];
902
903 if ((which & 3) && smacro_defined ("__FILE__", 0, &sm) && sm) {
904 free_tlist(sm->expansion);
905 sm->expansion = nasm_malloc(sizeof(Token));
906 sm->expansion->next = NULL;
907 sm->expansion->mac = NULL;
908 sm->expansion->type = TOK_STRING;
909 sm->expansion->text = nasm_malloc(3+strlen(istk->fname));
910 /* FIXME: throw an error if both sorts of quote are present */
911 /* Better still, invent a way for us to cope with that case */
912 sprintf(sm->expansion->text, "\"%s\"", istk->fname);
913 }
914
915 if ((which & 1) && smacro_defined ("__LINE__", 0, &sm) && sm) {
916 free_tlist(sm->expansion);
917 sm->expansion = nasm_malloc(sizeof(Token));
918 sm->expansion->next = NULL;
919 sm->expansion->mac = NULL;
920 sm->expansion->type = TOK_NUMBER;
921 sprintf(num, "%d", istk->lineno - istk->lineinc);
922 sm->expansion->text = nasm_strdup(num);
923 }
924}
925
926/*
927 * Count and mark off the parameters in a multi-line macro call.
928 * This is called both from within the multi-line macro expansion
929 * code, and also to mark off the default parameters when provided
930 * in a %macro definition line.
931 */
932static void count_mmac_params (Token *t, int *nparam, Token ***params) {
933 int paramsize, brace;
934
935 *nparam = paramsize = 0;
936 *params = NULL;
937 while (t) {
938 if (*nparam >= paramsize) {
939 paramsize += PARAM_DELTA;
940 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
941 }
942 if (t && t->type == TOK_WHITESPACE)
943 t = t->next;
944 brace = FALSE;
945 if (t && t->type == TOK_OTHER && !strcmp(t->text, "{"))
946 brace = TRUE;
947 (*params)[(*nparam)++] = t;
948 while (t && (t->type != TOK_OTHER ||
949 strcmp(t->text, brace ? "}" : ",")))
950 t = t->next;
951 if (t) { /* got a comma/brace */
952 t = t->next;
953 if (brace) {
954 /*
955 * Now we've found the closing brace, look further
956 * for the comma.
957 */
958 if (t && t->type == TOK_WHITESPACE)
959 t = t->next;
960 if (t && (t->type != TOK_OTHER || strcmp(t->text, ","))) {
961 error (ERR_NONFATAL|ERR_OFFBY1,
962 "braces do not enclose all of macro parameter");
963 while (t && (t->type != TOK_OTHER ||
964 strcmp(t->text, ",")))
965 t = t->next;
966 }
967 if (t)
968 t = t->next; /* eat the comma */
969 }
970 }
971 else /* got EOL */
972 break;
973 }
974}
975
976/*
977 * Determine whether one of the various `if' conditions is true or
978 * not.
979 *
980 * We must free the tline we get passed.
981 */
982static int if_condition (Token *tline, int i) {
983 int j, casesense;
984 Token *t, *tt, **tptr, *origline;
985 struct tokenval tokval;
986 expr *evalresult;
987
988 origline = tline;
989
990 switch (i) {
991 case PP_IFCTX: case PP_ELIFCTX:
992 case PP_IFNCTX: case PP_ELIFNCTX:
993 j = FALSE; /* have we matched yet? */
994 if (!cstk)
995 error(ERR_FATAL|ERR_OFFBY1,
996 "`%s': context stack is empty", directives[i]);
997 else while (tline) {
998 if (tline->type == TOK_WHITESPACE)
999 tline = tline->next;
1000 if (!tline || tline->type != TOK_ID) {
1001 error(ERR_NONFATAL|ERR_OFFBY1,
1002 "`%s' expects context identifiers", directives[i]);
1003 free_tlist (origline);
1004 return -1;
1005 }
1006 if (!nasm_stricmp(tline->text, cstk->name))
1007 j = TRUE;
1008 tline = tline->next;
1009 }
1010 if (i == PP_IFNCTX || i == PP_ELIFNCTX)
1011 j = !j;
1012 free_tlist (origline);
1013 return j;
1014
1015 case PP_IFDEF: case PP_ELIFDEF:
1016 case PP_IFNDEF: case PP_ELIFNDEF:
1017 j = FALSE; /* have we matched yet? */
1018 while (tline) {
1019 if (tline->type == TOK_WHITESPACE)
1020 tline = tline->next;
1021 if (!tline || (tline->type != TOK_ID &&
1022 (tline->type != TOK_PREPROC_ID ||
1023 tline->text[1] != '$'))) {
1024 error(ERR_NONFATAL|ERR_OFFBY1,
1025 "`%%if%sdef' expects macro identifiers",
1026 (i==PP_ELIFNDEF ? "n" : ""));
1027 free_tlist (origline);
1028 return -1;
1029 }
1030 if (smacro_defined(tline->text, 0, NULL))
1031 j = TRUE;
1032 tline = tline->next;
1033 }
1034 if (i == PP_IFNDEF || i == PP_ELIFNDEF)
1035 j = !j;
1036 free_tlist (origline);
1037 return j;
1038
1039 case PP_IFIDN: case PP_ELIFIDN: case PP_IFNIDN: case PP_ELIFNIDN:
1040 case PP_IFIDNI: case PP_ELIFIDNI: case PP_IFNIDNI: case PP_ELIFNIDNI:
1041 tline = expand_smacro(tline);
1042 t = tt = tline;
1043 while (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
1044 tt = tt->next;
1045 if (!tt) {
1046 error(ERR_NONFATAL, "`%s' expects two comma-separated arguments");
1047 free_tlist (tline);
1048 return -1;
1049 }
1050 tt = tt->next;
1051 casesense = (i == PP_IFIDN || i == PP_ELIFIDN ||
1052 i == PP_IFNIDN || i == PP_ELIFNIDN);
1053 j = TRUE; /* assume equality unless proved not */
1054 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1055 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1056 error(ERR_NONFATAL, "`%s': more than one comma on line",
1057 directives[i]);
1058 free_tlist (tline);
1059 return -1;
1060 }
1061 if (t->type == TOK_WHITESPACE) {
1062 t = t->next;
1063 continue;
1064 } else if (tt->type == TOK_WHITESPACE) {
1065 tt = tt->next;
1066 continue;
1067 } else if (tt->type != t->type ||
1068 (casesense ? strcmp(tt->text, t->text) :
1069 nasm_stricmp(tt->text, t->text))) {
1070 j = FALSE; /* found mismatching tokens */
1071 break;
1072 } else {
1073 t = t->next;
1074 tt = tt->next;
1075 continue;
1076 }
1077 }
1078 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
1079 j = FALSE; /* trailing gunk on one end or other */
1080 if (i == PP_IFNIDN || i == PP_ELIFNIDN)
1081 j = !j;
1082 free_tlist (tline);
1083 return j;
1084
1085 case PP_IFID: case PP_ELIFID: case PP_IFNID: case PP_ELIFNID:
1086 case PP_IFNUM: case PP_ELIFNUM: case PP_IFNNUM: case PP_ELIFNNUM:
1087 case PP_IFSTR: case PP_ELIFSTR: case PP_IFNSTR: case PP_ELIFNSTR:
1088 tline = expand_smacro(tline);
1089 t = tline;
1090 while (t && t->type == TOK_WHITESPACE)
1091 t = t->next;
1092 j = FALSE; /* placate optimiser */
1093 switch (i) {
1094 case PP_IFID: case PP_ELIFID: case PP_IFNID: case PP_ELIFNID:
1095 j = (t->type == TOK_ID);
1096 break;
1097 case PP_IFNUM: case PP_ELIFNUM: case PP_IFNNUM: case PP_ELIFNNUM:
1098 j = (t->type == TOK_NUMBER);
1099 break;
1100 case PP_IFSTR: case PP_ELIFSTR: case PP_IFNSTR: case PP_ELIFNSTR:
1101 j = (t->type == TOK_STRING);
1102 break;
1103 }
1104 if (i == PP_IFNID || i == PP_ELIFNID ||
1105 i == PP_IFNNUM || i == PP_ELIFNNUM ||
1106 i == PP_IFNSTR || i == PP_ELIFNSTR)
1107 j = !j;
1108 free_tlist (tline);
1109 return j;
1110
1111 case PP_IF: case PP_ELIF:
1112 t = tline = expand_smacro(tline);
1113 tptr = &t;
1114 tokval.t_type = TOKEN_INVALID;
1115 evalresult = evaluate (ppscan, tptr, &tokval,
1116 NULL, pass | 0x10, error, NULL);
1117 free_tlist (tline);
1118 if (!evalresult)
1119 return -1;
1120 if (tokval.t_type)
1121 error(ERR_WARNING|ERR_OFFBY1,
1122 "trailing garbage after expression ignored");
1123 if (!is_simple(evalresult)) {
1124 error(ERR_NONFATAL|ERR_OFFBY1,
1125 "non-constant value given to `%s'", directives[i]);
1126 return -1;
1127 }
1128 return reloc_value(evalresult) != 0;
1129
1130 default:
1131 error(ERR_FATAL|ERR_OFFBY1,
1132 "preprocessor directive `%s' not yet implemented",
1133 directives[i]);
1134 free_tlist (origline);
1135 return -1; /* yeah, right */
1136 }
1137}
1138
1139/*
1140 * Find out if a line contains a preprocessor directive, and deal
1141 * with it if so.
1142 *
1143 * If a directive _is_ found, we are expected to free_tlist() the
1144 * line.
1145 *
1146 * Return values go like this:
1147 *
1148 * bit 0 is set if a directive was found (so the line gets freed)
1149 * bit 1 is set if a blank line should be emitted
1150 * bit 2 is set if a re-sync line number comment should be emitted
1151 *
1152 * (bits 1 and 2 are mutually exclusive in that the rest of the
1153 * preprocessor doesn't guarantee to be able to handle the case in
1154 * which both are set)
1155 */
1156static int do_directive (Token *tline) {
1157 int i, j, k, m, nparam, nolist;
1158 char *p, *mname;
1159 Include *inc;
1160 Context *ctx;
1161 Cond *cond;
1162 SMacro *smac, **smhead;
1163 MMacro *mmac;
1164 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
1165 Line *l;
1166 struct tokenval tokval;
1167 expr *evalresult;
1168
1169 origline = tline;
1170
1171 if (tline && tline->type == TOK_WHITESPACE)
1172 tline = tline->next;
1173 if (!tline || tline->type != TOK_PREPROC_ID ||
1174 (tline->text[1]=='%' || tline->text[1]=='$' || tline->text[1]=='!'))
1175 return 0;
1176
1177 i = -1;
1178 j = sizeof(directives)/sizeof(*directives);
1179 while (j-i > 1) {
1180 k = (j+i) / 2;
1181 m = nasm_stricmp(tline->text, directives[k]);
1182 if (m == 0) {
1183 i = k;
1184 j = -2;
1185 break;
1186 } else if (m < 0) {
1187 j = k;
1188 } else
1189 i = k;
1190 }
1191
1192 /*
1193 * If we're in a non-emitting branch of a condition construct,
1194 * or walking to the end of an already terminated %rep block,
1195 * we should ignore all directives except for condition
1196 * directives.
1197 */
1198 if (((istk->conds && !emitting(istk->conds->state)) ||
1199 (istk->mstk && !istk->mstk->in_progress)) &&
1200 i != PP_IF && i != PP_ELIF &&
1201 i != PP_IFCTX && i != PP_ELIFCTX &&
1202 i != PP_IFDEF && i != PP_ELIFDEF &&
1203 i != PP_IFID && i != PP_ELIFID &&
1204 i != PP_IFIDN && i != PP_ELIFIDN &&
1205 i != PP_IFIDNI && i != PP_ELIFIDNI &&
1206 i != PP_IFNCTX && i != PP_ELIFNCTX &&
1207 i != PP_IFNDEF && i != PP_ELIFNDEF &&
1208 i != PP_IFNID && i != PP_ELIFNID &&
1209 i != PP_IFNIDN && i != PP_ELIFNIDN &&
1210 i != PP_IFNIDNI && i != PP_ELIFNIDNI &&
1211 i != PP_IFNNUM && i != PP_ELIFNNUM &&
1212 i != PP_IFNSTR && i != PP_ELIFNSTR &&
1213 i != PP_IFNUM && i != PP_ELIFNUM &&
1214 i != PP_IFSTR && i != PP_ELIFSTR &&
1215 i != PP_ELSE && i != PP_ENDIF)
1216 return 0;
1217
1218 /*
1219 * If we're defining a macro or reading a %rep block, we should
1220 * ignore all directives except for %macro/%imacro (which
1221 * generate an error), %endm/%endmacro, and (only if we're in a
1222 * %rep block) %endrep.
1223 */
1224 if (defining && i != PP_MACRO && i != PP_IMACRO &&
1225 i != PP_ENDMACRO && i != PP_ENDM &&
1226 (defining->name || i != PP_ENDREP))
1227 return 0;
1228
1229 if (j != -2) {
1230 error(ERR_NONFATAL|ERR_OFFBY1, "unknown preprocessor directive `%s'",
1231 tline->text);
1232 return 0; /* didn't get it */
1233 }
1234
1235 switch (i) {
1236
1237 case PP_CLEAR:
1238 if (tline->next)
1239 error(ERR_WARNING|ERR_OFFBY1,
1240 "trailing garbage after `%%clear' ignored");
1241 for (j=0; j<NHASH; j++) {
1242 while (mmacros[j]) {
1243 MMacro *m = mmacros[j];
1244 mmacros[j] = mmacros[j]->next;
1245 nasm_free (m->name);
1246 free_tlist (m->dlist);
1247 free_llist (m->expansion);
1248 nasm_free (m);
1249 }
1250 while (smacros[j]) {
1251 SMacro *s = smacros[j];
1252 smacros[j] = smacros[j]->next;
1253 nasm_free (s->name);
1254 free_tlist (s->expansion);
1255 nasm_free (s);
1256 }
1257 }
1258 free_tlist (origline);
1259 return 3;
1260
1261 case PP_INCLUDE:
1262 tline = tline->next;
1263 if (tline && tline->type == TOK_WHITESPACE)
1264 tline = tline->next;
1265 if (!tline || (tline->type != TOK_STRING &&
1266 tline->type != TOK_INTERNAL_STRING)) {
1267 error(ERR_NONFATAL|ERR_OFFBY1, "`%%include' expects a file name");
1268 free_tlist (origline);
1269 return 3; /* but we did _something_ */
1270 }
1271 if (tline->next)
1272 error(ERR_WARNING|ERR_OFFBY1,
1273 "trailing garbage after `%%include' ignored");
1274 if (tline->type != TOK_INTERNAL_STRING) {
1275 p = tline->text+1; /* point past the quote to the name */
1276 p[strlen(p)-1] = '\0'; /* remove the trailing quote */
1277 } else
1278 p = tline->text; /* internal_string is easier */
1279 inc = nasm_malloc(sizeof(Include));
1280 inc->next = istk;
1281 inc->conds = NULL;
1282 inc->fp = inc_fopen(p);
1283 inc->fname = nasm_strdup(p);
1284 inc->lineno = inc->lineinc = 1;
1285 inc->expansion = NULL;
1286 inc->mstk = NULL;
1287 istk = inc;
1288 list->uplevel (LIST_INCLUDE);
1289 update_fileline(3); /* update __FILE__ and __LINE__ */
1290 free_tlist (origline);
1291 return 5;
1292
1293 case PP_PUSH:
1294 tline = tline->next;
1295 if (tline && tline->type == TOK_WHITESPACE)
1296 tline = tline->next;
1297 if (!tline || tline->type != TOK_ID) {
1298 error(ERR_NONFATAL|ERR_OFFBY1,
1299 "`%%push' expects a context identifier");
1300 free_tlist (origline);
1301 return 3; /* but we did _something_ */
1302 }
1303 if (tline->next)
1304 error(ERR_WARNING|ERR_OFFBY1,
1305 "trailing garbage after `%%push' ignored");
1306 ctx = nasm_malloc(sizeof(Context));
1307 ctx->next = cstk;
1308 ctx->localmac = NULL;
1309 ctx->name = nasm_strdup(tline->text);
1310 ctx->number = unique++;
1311 cstk = ctx;
1312 free_tlist (origline);
1313 break;
1314
1315 case PP_REPL:
1316 tline = tline->next;
1317 if (tline && tline->type == TOK_WHITESPACE)
1318 tline = tline->next;
1319 if (!tline || tline->type != TOK_ID) {
1320 error(ERR_NONFATAL|ERR_OFFBY1,
1321 "`%%repl' expects a context identifier");
1322 free_tlist (origline);
1323 return 3; /* but we did _something_ */
1324 }
1325 if (tline->next)
1326 error(ERR_WARNING|ERR_OFFBY1,
1327 "trailing garbage after `%%repl' ignored");
1328 if (!cstk)
1329 error(ERR_NONFATAL|ERR_OFFBY1,
1330 "`%%repl': context stack is empty");
1331 else {
1332 nasm_free (cstk->name);
1333 cstk->name = nasm_strdup(tline->text);
1334 }
1335 free_tlist (origline);
1336 break;
1337
1338 case PP_POP:
1339 if (tline->next)
1340 error(ERR_WARNING|ERR_OFFBY1,
1341 "trailing garbage after `%%pop' ignored");
1342 if (!cstk)
1343 error(ERR_NONFATAL|ERR_OFFBY1,
1344 "`%%pop': context stack is already empty");
1345 else
1346 ctx_pop();
1347 free_tlist (origline);
1348 break;
1349
1350 case PP_ERROR:
1351 tline = tline->next;
1352 if (tline && tline->type == TOK_WHITESPACE)
1353 tline = tline->next;
1354 if (!tline || tline->type != TOK_STRING) {
1355 error(ERR_NONFATAL|ERR_OFFBY1,
1356 "`%%error' expects an error string");
1357 free_tlist (origline);
1358 return 3; /* but we did _something_ */
1359 }
1360 if (tline->next)
1361 error(ERR_WARNING|ERR_OFFBY1,
1362 "trailing garbage after `%%error' ignored");
1363 p = tline->text+1; /* point past the quote to the name */
1364 p[strlen(p)-1] = '\0'; /* remove the trailing quote */
1365 error(ERR_NONFATAL|ERR_OFFBY1, "user error: %s", p);
1366 free_tlist (origline);
1367 break;
1368
1369 case PP_IF:
1370 case PP_IFCTX:
1371 case PP_IFDEF:
1372 case PP_IFID:
1373 case PP_IFIDN:
1374 case PP_IFIDNI:
1375 case PP_IFNCTX:
1376 case PP_IFNDEF:
1377 case PP_IFNID:
1378 case PP_IFNIDN:
1379 case PP_IFNIDNI:
1380 case PP_IFNNUM:
1381 case PP_IFNSTR:
1382 case PP_IFNUM:
1383 case PP_IFSTR:
1384 if (istk->conds && !emitting(istk->conds->state))
1385 j = COND_NEVER;
1386 else {
1387 j = if_condition(tline->next, i);
1388 tline->next = NULL; /* it got freed */
1389 free_tlist (origline);
1390 if (j < 0)
1391 return 3;
1392 else
1393 j = j ? COND_IF_TRUE : COND_IF_FALSE;
1394 }
1395 cond = nasm_malloc(sizeof(Cond));
1396 cond->next = istk->conds;
1397 cond->state = j;
1398 istk->conds = cond;
1399 return (j == COND_IF_TRUE ? 3 : 1);
1400
1401 case PP_ELIF:
1402 case PP_ELIFCTX:
1403 case PP_ELIFDEF:
1404 case PP_ELIFID:
1405 case PP_ELIFIDN:
1406 case PP_ELIFIDNI:
1407 case PP_ELIFNCTX:
1408 case PP_ELIFNDEF:
1409 case PP_ELIFNID:
1410 case PP_ELIFNIDN:
1411 case PP_ELIFNIDNI:
1412 case PP_ELIFNNUM:
1413 case PP_ELIFNSTR:
1414 case PP_ELIFNUM:
1415 case PP_ELIFSTR:
1416 if (!istk->conds)
1417 error(ERR_FATAL|ERR_OFFBY1, "`%s': no matching `%%if'",
1418 directives[i]);
1419 if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
1420 istk->conds->state = COND_NEVER;
1421 else {
1422 j = if_condition(tline->next, i);
1423 tline->next = NULL; /* it got freed */
1424 free_tlist (origline);
1425 if (j < 0)
1426 return 3;
1427 else
1428 istk->conds->state = j ? COND_IF_TRUE : COND_IF_FALSE;
1429 }
1430 return (istk->conds->state == COND_IF_TRUE ? 5 : 1);
1431
1432 case PP_ELSE:
1433 if (tline->next)
1434 error(ERR_WARNING|ERR_OFFBY1,
1435 "trailing garbage after `%%else' ignored");
1436 if (!istk->conds)
1437 error(ERR_FATAL|ERR_OFFBY1,
1438 "`%%else': no matching `%%if'");
1439 if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
1440 istk->conds->state = COND_ELSE_FALSE;
1441 else
1442 istk->conds->state = COND_ELSE_TRUE;
1443 free_tlist (origline);
1444 return 5;
1445
1446 case PP_ENDIF:
1447 if (tline->next)
1448 error(ERR_WARNING|ERR_OFFBY1,
1449 "trailing garbage after `%%endif' ignored");
1450 if (!istk->conds)
1451 error(ERR_FATAL|ERR_OFFBY1,
1452 "`%%endif': no matching `%%if'");
1453 cond = istk->conds;
1454 istk->conds = cond->next;
1455 nasm_free (cond);
1456 free_tlist (origline);
1457 return 5;
1458
1459 case PP_MACRO:
1460 case PP_IMACRO:
1461 if (defining)
1462 error (ERR_FATAL|ERR_OFFBY1,
1463 "`%%%smacro': already defining a macro",
1464 (i == PP_IMACRO ? "i" : ""));
1465 tline = tline->next;
1466 if (tline && tline->type == TOK_WHITESPACE)
1467 tline = tline->next;
1468 if (!tline || tline->type != TOK_ID) {
1469 error (ERR_NONFATAL|ERR_OFFBY1,
1470 "`%%%smacro' expects a macro name",
1471 (i == PP_IMACRO ? "i" : ""));
1472 return 3;
1473 }
1474 defining = nasm_malloc(sizeof(MMacro));
1475 defining->name = nasm_strdup(tline->text);
1476 defining->casesense = (i == PP_MACRO);
1477 defining->plus = FALSE;
1478 defining->nolist = FALSE;
1479 defining->in_progress = FALSE;
1480 tline = tline->next;
1481 if (tline && tline->type == TOK_WHITESPACE)
1482 tline = tline->next;
1483 if (!tline || tline->type != TOK_NUMBER) {
1484 error (ERR_NONFATAL|ERR_OFFBY1,
1485 "`%%%smacro' expects a parameter count",
1486 (i == PP_IMACRO ? "i" : ""));
1487 defining->nparam_min = defining->nparam_max = 0;
1488 } else {
1489 defining->nparam_min = defining->nparam_max =
1490 readnum(tline->text, &j);
1491 if (j)
1492 error (ERR_NONFATAL|ERR_OFFBY1,
1493 "unable to parse parameter count `%s'", tline->text);
1494 }
1495 if (tline && tline->next && tline->next->type == TOK_OTHER &&
1496 !strcmp(tline->next->text, "-")) {
1497 tline = tline->next->next;
1498 if (tline && tline->type == TOK_OTHER &&
1499 !strcmp(tline->text, "*"))
1500 defining->nparam_max = INT_MAX;
1501 else if (!tline || tline->type != TOK_NUMBER)
1502 error (ERR_NONFATAL|ERR_OFFBY1,
1503 "`%%%smacro' expects a parameter count after `-'",
1504 (i == PP_IMACRO ? "i" : ""));
1505 else {
1506 defining->nparam_max = readnum(tline->text, &j);
1507 if (j)
1508 error (ERR_NONFATAL|ERR_OFFBY1,
1509 "unable to parse parameter count `%s'",
1510 tline->text);
1511 if (defining->nparam_min > defining->nparam_max)
1512 error (ERR_NONFATAL|ERR_OFFBY1,
1513 "minimum parameter count exceeds maximum");
1514 }
1515 }
1516 if (tline && tline->next && tline->next->type == TOK_OTHER &&
1517 !strcmp(tline->next->text, "+")) {
1518 tline = tline->next;
1519 defining->plus = TRUE;
1520 }
1521 if (tline && tline->next && tline->next->type == TOK_ID &&
1522 !nasm_stricmp(tline->next->text, ".nolist")) {
1523 tline = tline->next;
1524 defining->nolist = TRUE;
1525 }
1526 mmac = mmacros[hash(defining->name)];
1527 while (mmac) {
1528 if (!strcmp(mmac->name, defining->name) &&
1529 (mmac->nparam_min<=defining->nparam_max || defining->plus) &&
1530 (defining->nparam_min<=mmac->nparam_max || mmac->plus)) {
1531 error (ERR_WARNING|ERR_OFFBY1,
1532 "redefining multi-line macro `%s'", defining->name);
1533 break;
1534 }
1535 mmac = mmac->next;
1536 }
1537 /*
1538 * Handle default parameters.
1539 */
1540 if (tline && tline->next) {
1541 defining->dlist = tline->next;
1542 tline->next = NULL;
1543 count_mmac_params (defining->dlist, &defining->ndefs,
1544 &defining->defaults);
1545 } else {
1546 defining->dlist = NULL;
1547 defining->defaults = NULL;
1548 }
1549 defining->expansion = NULL;
1550 free_tlist (origline);
1551 return 1;
1552
1553 case PP_ENDM:
1554 case PP_ENDMACRO:
1555 if (!defining) {
1556 error (ERR_NONFATAL|ERR_OFFBY1, "`%s': not defining a macro",
1557 tline->text);
1558 return 3;
1559 }
1560 k = hash(defining->name);
1561 defining->next = mmacros[k];
1562 mmacros[k] = defining;
1563 defining = NULL;
1564 free_tlist (origline);
1565 return 5;
1566
1567 case PP_ROTATE:
1568 if (tline->next && tline->next->type == TOK_WHITESPACE)
1569 tline = tline->next;
1570 t = expand_smacro(tline->next);
1571 tline->next = NULL;
1572 free_tlist (origline);
1573 tline = t;
1574 tptr = &t;
1575 tokval.t_type = TOKEN_INVALID;
1576 evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
1577 free_tlist (tline);
1578 if (!evalresult)
1579 return 3;
1580 if (tokval.t_type)
1581 error(ERR_WARNING|ERR_OFFBY1,
1582 "trailing garbage after expression ignored");
1583 if (!is_simple(evalresult)) {
1584 error(ERR_NONFATAL|ERR_OFFBY1,
1585 "non-constant value given to `%%rotate'");
1586 return 3;
1587 }
1588 mmac = istk->mstk;
1589 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
1590 mmac = mmac->next_active;
1591 if (!mmac)
1592 error(ERR_NONFATAL, "`%rotate' invoked outside a macro call");
1593 mmac->rotate = mmac->rotate + reloc_value(evalresult);
1594 if (mmac->rotate < 0)
1595 mmac->rotate = mmac->nparam - (-mmac->rotate) % mmac->nparam;
1596 mmac->rotate %= mmac->nparam;
1597 return 1;
1598
1599 case PP_REP:
1600 nolist = FALSE;
1601 tline = tline->next;
1602 if (tline->next && tline->next->type == TOK_WHITESPACE)
1603 tline = tline->next;
1604 if (tline->next && tline->next->type == TOK_ID &&
1605 !nasm_stricmp(tline->next->text, ".nolist")) {
1606 tline = tline->next;
1607 nolist = TRUE;
1608 }
1609 t = expand_smacro(tline->next);
1610 tline->next = NULL;
1611 free_tlist (origline);
1612 tline = t;
1613 tptr = &t;
1614 tokval.t_type = TOKEN_INVALID;
1615 evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
1616 free_tlist (tline);
1617 if (!evalresult)
1618 return 3;
1619 if (tokval.t_type)
1620 error(ERR_WARNING|ERR_OFFBY1,
1621 "trailing garbage after expression ignored");
1622 if (!is_simple(evalresult)) {
1623 error(ERR_NONFATAL|ERR_OFFBY1,
1624 "non-constant value given to `%%rep'");
1625 return 3;
1626 }
1627 defining = nasm_malloc(sizeof(MMacro));
1628 defining->name = NULL; /* flags this macro as a %rep block */
1629 defining->casesense = 0;
1630 defining->plus = FALSE;
1631 defining->nolist = nolist;
1632 defining->in_progress = reloc_value(evalresult) + 1;
1633 defining->nparam_min = defining->nparam_max = 0;
1634 defining->expansion = NULL;
1635 defining->next_active = istk->mstk;
1636 return 1;
1637
1638 case PP_ENDREP:
1639 if (!defining) {
1640 error (ERR_NONFATAL|ERR_OFFBY1,
1641 "`%%endrep': no matching `%%rep'");
1642 return 3;
1643 }
1644
1645 /*
1646 * Now we have a "macro" defined - although it has no name
1647 * and we won't be entering it in the hash tables - we must
1648 * push a macro-end marker for it on to istk->expansion.
1649 * After that, it will take care of propagating itself (a
1650 * macro-end marker line for a macro which is really a %rep
1651 * block will cause the macro to be re-expanded, complete
1652 * with another macro-end marker to ensure the process
1653 * continues) until the whole expansion is forcibly removed
1654 * from istk->expansion by a %exitrep.
1655 */
1656 l = nasm_malloc(sizeof(Line));
1657 l->next = istk->expansion;
1658 l->finishes = defining;
1659 l->first = NULL;
1660 istk->expansion = l;
1661
1662 istk->mstk = defining;
1663
1664 list->uplevel (defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
1665 defining = NULL;
1666 free_tlist (origline);
1667 return 1; /* the expansion will line-sync */
1668
1669 case PP_EXITREP:
1670 /*
1671 * We must search along istk->expansion until we hit a
1672 * macro-end marker for a macro with no name. Then we set
1673 * its `in_progress' flag to 0.
1674 */
1675 for (l = istk->expansion; l; l = l->next)
1676 if (l->finishes && !l->finishes->name)
1677 break;
1678
1679 if (l->finishes && !l->finishes->name)
1680 l->finishes->in_progress = 0;
1681 else
1682 error (ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
1683 free_tlist (origline);
1684 return 1; /* the end marker will line-sync */
1685
1686 case PP_DEFINE:
1687 case PP_IDEFINE:
1688 tline = tline->next;
1689 if (tline && tline->type == TOK_WHITESPACE)
1690 tline = tline->next;
1691 if (!tline || (tline->type != TOK_ID &&
1692 (tline->type != TOK_PREPROC_ID ||
1693 tline->text[1] != '$'))) {
1694 error (ERR_NONFATAL|ERR_OFFBY1,
1695 "`%%%sdefine' expects a macro identifier",
1696 (i == PP_IDEFINE ? "i" : ""));
1697 free_tlist (origline);
1698 return 3;
1699 }
1700 mname = tline->text;
1701 if (tline->type == TOK_ID) {
1702 p = tline->text;
1703 smhead = &smacros[hash(mname)];
1704 } else {
1705 ctx = get_ctx (tline->text);
1706 if (ctx == NULL)
1707 return 3;
1708 else {
1709 p = tline->text+1;
1710 p += strspn(p, "$");
1711 smhead = &ctx->localmac;
1712 }
1713 }
1714 last = tline;
1715 param_start = tline = tline->next;
1716 nparam = 0;
1717 if (tline && tline->type == TOK_OTHER && !strcmp(tline->text, "(")) {
1718 /*
1719 * This macro has parameters.
1720 */
1721
1722 tline = tline->next;
1723 while (1) {
1724 if (tline && tline->type == TOK_WHITESPACE)
1725 tline = tline->next;
1726 if (!tline) {
1727 error (ERR_NONFATAL|ERR_OFFBY1,
1728 "parameter identifier expected");
1729 free_tlist (origline);
1730 return 3;
1731 }
1732 if (tline->type != TOK_ID) {
1733 error (ERR_NONFATAL|ERR_OFFBY1,
1734 "`%s': parameter identifier expected",
1735 tline->text);
1736 free_tlist (origline);
1737 return 3;
1738 }
1739 tline->type = TOK_SMAC_PARAM + nparam++;
1740 tline = tline->next;
1741 if (tline && tline->type == TOK_WHITESPACE)
1742 tline = tline->next;
1743 if (tline && tline->type == TOK_OTHER &&
1744 !strcmp(tline->text, ",")) {
1745 tline = tline->next;
1746 continue;
1747 }
1748 if (!tline || tline->type != TOK_OTHER ||
1749 strcmp(tline->text, ")")) {
1750 error (ERR_NONFATAL|ERR_OFFBY1,
1751 "`)' expected to terminate macro template");
1752 free_tlist (origline);
1753 return 3;
1754 }
1755 break;
1756 }
1757 last = tline;
1758 tline = tline->next;
1759 }
1760 if (tline && tline->type == TOK_WHITESPACE)
1761 last = tline, tline = tline->next;
1762 macro_start = NULL;
1763 last->next = NULL;
1764 t = tline;
1765 while (t) {
1766 if (t->type == TOK_ID) {
1767 for (tt = param_start; tt; tt = tt->next)
1768 if (tt->type >= TOK_SMAC_PARAM &&
1769 !strcmp(tt->text, t->text))
1770 t->type = tt->type;
1771 }
1772 tt = t->next;
1773 t->next = macro_start;
1774 macro_start = t;
1775 t = tt;
1776 }
1777 /*
1778 * Good. We now have a macro name, a parameter count, and a
1779 * token list (in reverse order) for an expansion. We ought
1780 * to be OK just to create an SMacro, store it, and let
1781 * free_tlist have the rest of the line (which we have
1782 * carefully re-terminated after chopping off the expansion
1783 * from the end).
1784 */
1785 if (smacro_defined (mname, nparam, &smac)) {
1786 if (!smac)
1787 error (ERR_WARNING|ERR_OFFBY1,
1788 "single-line macro `%s' defined both with and"
1789 " without parameters", mname);
1790 else {
1791 /*
1792 * We're redefining, so we have to take over an
1793 * existing SMacro structure. This means freeing
1794 * what was already in it.
1795 */
1796 nasm_free (smac->name);
1797 free_tlist (smac->expansion);
1798 }
1799 } else {
1800 smac = nasm_malloc(sizeof(SMacro));
1801 smac->next = *smhead;
1802 *smhead = smac;
1803 }
1804 smac->name = nasm_strdup(p);
1805 smac->casesense = (i == PP_DEFINE);
1806 smac->nparam = nparam;
1807 smac->expansion = macro_start;
1808 smac->in_progress = FALSE;
1809 free_tlist (origline);
1810 return 3;
1811
1812 case PP_ASSIGN:
1813 case PP_IASSIGN:
1814 tline = tline->next;
1815 if (tline && tline->type == TOK_WHITESPACE)
1816 tline = tline->next;
1817 if (!tline || (tline->type != TOK_ID &&
1818 (tline->type != TOK_PREPROC_ID ||
1819 tline->text[1] != '$'))) {
1820 error (ERR_NONFATAL|ERR_OFFBY1,
1821 "`%%%sassign' expects a macro identifier",
1822 (i == PP_IASSIGN ? "i" : ""));
1823 free_tlist (origline);
1824 return 3;
1825 }
1826 mname = tline->text;
1827 if (tline->type == TOK_ID) {
1828 p = tline->text;
1829 smhead = &smacros[hash(mname)];
1830 } else {
1831 ctx = get_ctx (tline->text);
1832 if (ctx == NULL) {
1833 free_tlist (origline);
1834 return 3;
1835 } else {
1836 p = tline->text+1;
1837 p += strspn(p, "$");
1838 smhead = &ctx->localmac;
1839 }
1840 }
1841 last = tline;
1842 tline = tline->next;
1843 last->next = NULL;
1844
1845 tline = expand_smacro (tline);
1846 t = tline;
1847 tptr = &t;
1848 tokval.t_type = TOKEN_INVALID;
1849 evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
1850 free_tlist (tline);
1851 if (!evalresult) {
1852 free_tlist (origline);
1853 return 3;
1854 }
1855
1856 if (tokval.t_type)
1857 error(ERR_WARNING|ERR_OFFBY1,
1858 "trailing garbage after expression ignored");
1859
1860 if (!is_simple(evalresult)) {
1861 error(ERR_NONFATAL|ERR_OFFBY1,
1862 "non-constant value given to `%%%sassign'",
1863 (i == PP_IASSIGN ? "i" : ""));
1864 free_tlist (origline);
1865 return 3;
1866 }
1867
1868 macro_start = nasm_malloc(sizeof(*macro_start));
1869 macro_start->next = NULL;
1870 {
1871 char numbuf[20];
1872 sprintf(numbuf, "%ld", reloc_value(evalresult));
1873 macro_start->text = nasm_strdup(numbuf);
1874 }
1875 macro_start->mac = NULL;
1876 macro_start->type = TOK_NUMBER;
1877
1878 /*
1879 * We now have a macro name, an implicit parameter count of
1880 * zero, and a numeric token to use as an expansion. Create
1881 * and store an SMacro.
1882 */
1883 if (smacro_defined (mname, 0, &smac)) {
1884 if (!smac)
1885 error (ERR_WARNING|ERR_OFFBY1,
1886 "single-line macro `%s' defined both with and"
1887 " without parameters", mname);
1888 else {
1889 /*
1890 * We're redefining, so we have to take over an
1891 * existing SMacro structure. This means freeing
1892 * what was already in it.
1893 */
1894 nasm_free (smac->name);
1895 free_tlist (smac->expansion);
1896 }
1897 } else {
1898 smac = nasm_malloc(sizeof(SMacro));
1899 smac->next = *smhead;
1900 *smhead = smac;
1901 }
1902 smac->name = nasm_strdup(p);
1903 smac->casesense = (i == PP_ASSIGN);
1904 smac->nparam = 0;
1905 smac->expansion = macro_start;
1906 smac->in_progress = FALSE;
1907 free_tlist (origline);
1908 return 3;
1909
1910 case PP_LINE:
1911 /*
1912 * Syntax is `%line nnn[+mmm] [filename]'
1913 */
1914 tline = tline->next;
1915 if (tline && tline->type == TOK_WHITESPACE)
1916 tline = tline->next;
1917 if (!tline || tline->type != TOK_NUMBER) {
1918 error (ERR_NONFATAL|ERR_OFFBY1, "`%%line' expects line number");
1919 free_tlist (origline);
1920 return 3;
1921 }
1922 k = readnum(tline->text, &j);
1923 m = 1;
1924 tline = tline->next;
1925 if (tline && tline->type == TOK_OTHER && !strcmp(tline->text, "+")) {
1926 tline = tline->next;
1927 if (!tline || tline->type != TOK_NUMBER) {
1928 error (ERR_NONFATAL|ERR_OFFBY1,
1929 "`%%line' expects line increment");
1930 free_tlist (origline);
1931 return 3;
1932 }
1933 m = readnum(tline->text, &j);
1934 tline = tline->next;
1935 }
1936 if (tline && tline->type == TOK_WHITESPACE)
1937 tline = tline->next;
1938 istk->lineno = k;
1939 istk->lineinc = m;
1940 update_fileline(3); /* update __FILE__ and __LINE__ */
1941 if (tline) {
1942 char *s = detoken(tline);
1943 nasm_free (istk->fname);
1944 istk->fname = s;
1945 }
1946 free_tlist (origline);
1947 return 5;
1948
1949 default:
1950 error(ERR_FATAL|ERR_OFFBY1,
1951 "preprocessor directive `%s' not yet implemented",
1952 directives[i]);
1953 break;
1954 }
1955 return 3;
1956}
1957
1958/*
1959 * Ensure that a macro parameter contains a condition code and
1960 * nothing else. Return the condition code index if so, or -1
1961 * otherwise.
1962 */
1963static int find_cc (Token *t) {
1964 Token *tt;
1965 int i, j, k, m;
1966
1967 if (t && t->type == TOK_WHITESPACE)
1968 t = t->next;
1969 if (t->type != TOK_ID)
1970 return -1;
1971 tt = t->next;
1972 if (tt && tt->type == TOK_WHITESPACE)
1973 tt = tt->next;
1974 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
1975 return -1;
1976
1977 i = -1;
1978 j = sizeof(conditions)/sizeof(*conditions);
1979 while (j-i > 1) {
1980 k = (j+i) / 2;
1981 m = nasm_stricmp(t->text, conditions[k]);
1982 if (m == 0) {
1983 i = k;
1984 j = -2;
1985 break;
1986 } else if (m < 0) {
1987 j = k;
1988 } else
1989 i = k;
1990 }
1991 if (j != -2)
1992 return -1;
1993 return i;
1994}
1995
1996/*
1997 * Expand MMacro-local things: parameter references (%0, %n, %+n,
1998 * %-n) and MMacro-local identifiers (%%foo).
1999 */
2000static Token *expand_mmac_params (Token *tline) {
2001 Token *t, *tt, *ttt, **tail, *thead;
2002
2003 tail = &thead;
2004 thead = NULL;
2005
2006 while (tline) {
2007 if (tline->type == TOK_PREPROC_ID &&
2008 (tline->text[1] == '+' || tline->text[1] == '-' ||
2009 tline->text[1] == '%' ||
2010 (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
2011 char *text = NULL;
2012 int type = 0, cc; /* type = 0 to placate optimisers */
2013 char tmpbuf[30];
2014 int n, i;
2015 MMacro *mac;
2016
2017 t = tline;
2018 tline = tline->next;
2019
2020 mac = istk->mstk;
2021 while (mac && !mac->name) /* avoid mistaking %reps for macros */
2022 mac = mac->next_active;
2023 if (!mac)
2024 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
2025 else switch (t->text[1]) {
2026 /*
2027 * We have to make a substitution of one of the
2028 * forms %1, %-1, %+1, %%foo, %0.
2029 */
2030 case '0':
2031 type = TOK_NUMBER;
2032 sprintf(tmpbuf, "%d", mac->nparam);
2033 text = nasm_strdup(tmpbuf);
2034 break;
2035 case '%':
2036 type = TOK_ID;
2037 sprintf(tmpbuf, "..@%lu.", mac->unique);
2038 text = nasm_malloc(strlen(tmpbuf)+strlen(t->text+2)+1);
2039 strcpy(text, tmpbuf);
2040 strcat(text, t->text+2);
2041 break;
2042 case '-':
2043 n = atoi(t->text+2)-1;
2044 if (n >= mac->nparam)
2045 tt = NULL;
2046 else {
2047 if (mac->nparam > 1)
2048 n = (n + mac->rotate) % mac->nparam;
2049 tt = mac->params[n];
2050 }
2051 cc = find_cc (tt);
2052 if (cc == -1) {
2053 error (ERR_NONFATAL|ERR_OFFBY1,
2054 "macro parameter %d is not a condition code",
2055 n+1);
2056 text = NULL;
2057 } else {
2058 type = TOK_ID;
2059 if (inverse_ccs[cc] == -1) {
2060 error (ERR_NONFATAL|ERR_OFFBY1,
2061 "condition code `%s' is not invertible",
2062 conditions[cc]);
2063 text = NULL;
2064 } else
2065 text = nasm_strdup(conditions[inverse_ccs[cc]]);
2066 }
2067 break;
2068 case '+':
2069 n = atoi(t->text+2)-1;
2070 if (n >= mac->nparam)
2071 tt = NULL;
2072 else {
2073 if (mac->nparam > 1)
2074 n = (n + mac->rotate) % mac->nparam;
2075 tt = mac->params[n];
2076 }
2077 cc = find_cc (tt);
2078 if (cc == -1) {
2079 error (ERR_NONFATAL|ERR_OFFBY1,
2080 "macro parameter %d is not a condition code",
2081 n+1);
2082 text = NULL;
2083 } else {
2084 type = TOK_ID;
2085 text = nasm_strdup(conditions[cc]);
2086 }
2087 break;
2088 default:
2089 n = atoi(t->text+1)-1;
2090 if (n >= mac->nparam)
2091 tt = NULL;
2092 else {
2093 if (mac->nparam > 1)
2094 n = (n + mac->rotate) % mac->nparam;
2095 tt = mac->params[n];
2096 }
2097 if (tt) {
2098 for (i=0; i<mac->paramlen[n]; i++) {
2099 ttt = *tail = nasm_malloc(sizeof(Token));
2100 ttt->next = NULL;
2101 tail = &ttt->next;
2102 ttt->type = tt->type;
2103 ttt->text = nasm_strdup(tt->text);
2104 ttt->mac = NULL;
2105 tt = tt->next;
2106 }
2107 }
2108 text = NULL; /* we've done it here */
2109 break;
2110 }
2111 nasm_free (t->text);
2112 nasm_free (t);
2113 if (text) {
2114 t = *tail = nasm_malloc(sizeof(Token));
2115 t->next = NULL;
2116 tail = &t->next;
2117 t->type = type;
2118 t->text = text;
2119 t->mac = NULL;
2120 }
2121 continue;
2122 } else {
2123 t = *tail = tline;
2124 tline = tline->next;
2125 t->mac = NULL;
2126 t->next = NULL;
2127 tail = &t->next;
2128 }
2129 }
2130 return thead;
2131}
2132
2133/*
2134 * Expand all single-line macro calls made in the given line.
2135 * Return the expanded version of the line. The original is deemed
2136 * to be destroyed in the process. (In reality we'll just move
2137 * Tokens from input to output a lot of the time, rather than
2138 * actually bothering to destroy and replicate.)
2139 */
2140static Token *expand_smacro (Token *tline) {
2141 Token *t, *tt, *mstart, **tail, *thead;
2142 SMacro *head, *m;
2143 Token **params;
2144 int *paramsize;
2145 int nparam, sparam, brackets;
2146 char *p;
2147
2148 tail = &thead;
2149 thead = NULL;
2150
2151 while (tline) {
2152 while (tline && tline->type != TOK_ID &&
2153 (tline->type != TOK_PREPROC_ID || tline->text[1] != '$')) {
2154 if (tline->type == TOK_SMAC_END) {
2155 tline->mac->in_progress = FALSE;
2156 t = tline;
2157 tline = tline->next;
2158 nasm_free (t);
2159 } else {
2160 t = *tail = tline;
2161 tline = tline->next;
2162 t->mac = NULL;
2163 t->next = NULL;
2164 tail = &t->next;
2165 if (t->type == TOK_PS_OTHER) {
2166 /*
2167 * If we see a PS_OTHER, we must at the very
2168 * least restore its correct token type. We
2169 * should also check for a %$ token, since this
2170 * is the point at which we expand context-
2171 * local labels.
2172 */
2173 t->type = TOK_ID;
2174 if (t->text[0] == '%' && t->text[1] == '$') {
2175 Context *c = get_ctx (t->text);
2176 char *p, *q, buffer[40];
2177
2178 if (c) {
2179 q = t->text+1;
2180 q += strspn(q, "$");
2181 sprintf(buffer, "..@%lu.", c->number);
2182 p = nasm_malloc (strlen(buffer)+strlen(q)+1);
2183 strcpy (p, buffer);
2184 strcat (p, q);
2185 nasm_free (t->text);
2186 t->text = p;
2187 }
2188 }
2189 }
2190 }
2191 }
2192
2193 if (!tline)
2194 break;
2195 /*
2196 * We've hit an identifier. As in is_mmacro below, we first
2197 * check whether the identifier is a single-line macro at
2198 * all, then think about checking for parameters if
2199 * necessary.
2200 */
2201 if (tline->type == TOK_ID) {
2202 head = smacros[hash(tline->text)];
2203 p = tline->text;
2204 } else {
2205 Context *ctx = get_ctx (tline->text);
2206 if (ctx) {
2207 p = tline->text+1;
2208 p += strspn(p, "$");
2209 head = ctx->localmac;
2210 } else {
2211 tline->type = TOK_OTHER; /* so it will get copied above */
2212 continue;
2213 }
2214 }
2215 for (m = head; m; m = m->next)
2216 if (!mstrcmp(m->name, p, m->casesense))
2217 break;
2218 if (!m || m->in_progress) {
2219 /*
2220 * Either we didn't find a macro, so this can't be a
2221 * macro call, or we found a macro which was already in
2222 * progress, in which case we don't _treat_ this as a
2223 * macro call. Copy it through and ignore it.
2224 */
2225 tline->type = TOK_PS_OTHER; /* so it will get copied above */
2226 continue;
2227 }
2228 mstart = tline;
2229 if (m->nparam == 0) {
2230 /*
2231 * Simple case: the macro is parameterless. Discard the
2232 * one token that the macro call took, and push the
2233 * expansion back on the to-do stack.
2234 */
2235 params = NULL;
2236 paramsize = NULL;
2237 } else {
2238 /*
2239 * Complicated case: at least one macro with this name
2240 * exists and takes parameters. We must find the
2241 * parameters in the call, count them, find the SMacro
2242 * that corresponds to that form of the macro call, and
2243 * substitute for the parameters when we expand. What a
2244 * pain.
2245 */
2246 nparam = sparam = 0;
2247 params = NULL;
2248 paramsize = NULL;
2249 tline = tline->next;
2250 if (tline && tline->type == TOK_WHITESPACE)
2251 tline = tline->next;
2252 if (!tline || tline->type != TOK_OTHER ||
2253 strcmp(tline->text, "(")) {
2254 /*
2255 * This macro wasn't called with parameters: ignore
2256 * the call. (Behaviour borrowed from gnu cpp.)
2257 */
2258 tline = mstart;
2259 tline->type = TOK_PS_OTHER;
2260 continue;
2261 }
2262 tline = tline->next;
2263 while (1) {
2264 if (tline && tline->type == TOK_WHITESPACE)
2265 tline = tline->next;
2266 if (!tline) {
2267 error(ERR_NONFATAL|ERR_OFFBY1,
2268 "macro call expects terminating `)'");
2269 break;
2270 }
2271 if (nparam >= sparam) {
2272 sparam += PARAM_DELTA;
2273 params = nasm_realloc (params, sparam*sizeof(Token *));
2274 paramsize = nasm_realloc (paramsize, sparam*sizeof(int));
2275 }
2276 params[nparam] = tline;
2277 paramsize[nparam] = 0;
2278 brackets = 0;
2279 if (tline && tline->type == TOK_OTHER &&
2280 !strcmp(tline->text, "{")) {
2281 params[nparam] = tline = tline->next;
2282 while (tline && (brackets > 0 ||
2283 tline->type != TOK_OTHER ||
2284 strcmp(tline->text, "}"))) {
2285 tline = tline->next;
2286 paramsize[nparam]++;
2287 }
2288 tline = tline->next;
2289 if (tline && tline->type == TOK_WHITESPACE)
2290 tline = tline->next;
2291 if (tline && (tline->type != TOK_OTHER ||
2292 (strcmp(tline->text, ")") &&
2293 strcmp(tline->text, ",")))) {
2294 error (ERR_NONFATAL|ERR_OFFBY1, "braces do not "
2295 "enclose all of macro parameter");
2296 }
2297 if (tline && tline->type == TOK_OTHER &&
2298 !strcmp(tline->text, ","))
2299 tline = tline->next;
2300 } else {
2301 while (tline && (brackets > 0 ||
2302 tline->type != TOK_OTHER ||
2303 (strcmp(tline->text, ",") &&
2304 strcmp(tline->text, ")")))) {
2305 if (tline->type == TOK_OTHER && !tline->text[1])
2306 brackets += (tline->text[0] == '(' ? 1 :
2307 tline->text[0] == ')' ? -1 : 0);
2308 tline = tline->next;
2309 paramsize[nparam]++;
2310 }
2311 }
2312 nparam++;
2313 if (tline && !strcmp(tline->text, ")"))
2314 break;
2315 if (tline && !strcmp(tline->text, ","))
2316 tline = tline->next;
2317 }
2318 while (m && m->nparam != nparam) {
2319 while ( (m = m->next) )
2320 if (!strcmp(m->name, mstart->text))
2321 break;
2322 }
2323 if (!m) {
2324 error (ERR_WARNING|ERR_OFFBY1|ERR_WARN_MNP,
2325 "macro `%s' exists, but not taking %d parameters",
2326 mstart->text, nparam);
2327 nasm_free (params);
2328 nasm_free (paramsize);
2329 tline = mstart;
2330 tline->type = TOK_PS_OTHER;
2331 continue;
2332 }
2333 }
2334 /*
2335 * Expand the macro: we are placed on the last token of the
2336 * call, so that we can easily split the call from the
2337 * following tokens. We also start by pushing an SMAC_END
2338 * token for the cycle removal.
2339 */
2340 t = tline;
2341 tline = tline->next;
2342 t->next = NULL;
2343 tt = nasm_malloc(sizeof(Token));
2344 tt->type = TOK_SMAC_END;
2345 tt->text = NULL;
2346 tt->mac = m;
2347 m->in_progress = TRUE;
2348 tt->next = tline;
2349 tline = tt;
2350 for (t = m->expansion; t; t = t->next) {
2351 if (t->type >= TOK_SMAC_PARAM) {
2352 Token *pcopy = tline, **ptail = &pcopy;
2353 Token *ttt, *pt;
2354 int i;
2355
2356 ttt = params[t->type - TOK_SMAC_PARAM];
2357 for (i=0; i<paramsize[t->type-TOK_SMAC_PARAM]; i++) {
2358 pt = *ptail = nasm_malloc(sizeof(Token));
2359 pt->next = tline;
2360 ptail = &pt->next;
2361 pt->text = nasm_strdup(ttt->text);
2362 pt->type = ttt->type;
2363 pt->mac = NULL;
2364 ttt = ttt->next;
2365 }
2366 tline = pcopy;
2367 } else {
2368 tt = nasm_malloc(sizeof(Token));
2369 tt->type = t->type;
2370 tt->text = nasm_strdup(t->text);
2371 tt->mac = NULL;
2372 tt->next = tline;
2373 tline = tt;
2374 }
2375 }
2376
2377 /*
2378 * Having done that, get rid of the macro call, and clean
2379 * up the parameters.
2380 */
2381 nasm_free (params);
2382 nasm_free (paramsize);
2383 free_tlist (mstart);
2384 }
2385
2386 return thead;
2387}
2388
2389/*
2390 * Determine whether the given line constitutes a multi-line macro
2391 * call, and return the MMacro structure called if so. Doesn't have
2392 * to check for an initial label - that's taken care of in
2393 * expand_mmacro - but must check numbers of parameters. Guaranteed
2394 * to be called with tline->type == TOK_ID, so the putative macro
2395 * name is easy to find.
2396 */
2397static MMacro *is_mmacro (Token *tline, Token ***params_array) {
2398 MMacro *head, *m;
2399 Token **params;
2400 int nparam;
2401
2402 head = mmacros[hash(tline->text)];
2403
2404 /*
2405 * Efficiency: first we see if any macro exists with the given
2406 * name. If not, we can return NULL immediately. _Then_ we
2407 * count the parameters, and then we look further along the
2408 * list if necessary to find the proper MMacro.
2409 */
2410 for (m = head; m; m = m->next)
2411 if (!mstrcmp(m->name, tline->text, m->casesense))
2412 break;
2413 if (!m)
2414 return NULL;
2415
2416 /*
2417 * OK, we have a potential macro. Count and demarcate the
2418 * parameters.
2419 */
2420 count_mmac_params (tline->next, &nparam, &params);
2421
2422 /*
2423 * So we know how many parameters we've got. Find the MMacro
2424 * structure that handles this number.
2425 */
2426 while (m) {
2427 if (m->nparam_min <= nparam && (m->plus || nparam <= m->nparam_max)) {
2428 /*
2429 * This one is right. Just check if cycle removal
2430 * prohibits us using it before we actually celebrate...
2431 */
2432 if (m->in_progress) {
2433 error (ERR_NONFATAL|ERR_OFFBY1,
2434 "self-reference in multi-line macro `%s'",
2435 m->name);
2436 nasm_free (params);
2437 return NULL;
2438 }
2439 /*
2440 * It's right, and we can use it. Add its default
2441 * parameters to the end of our list if necessary.
2442 */
2443 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
2444 params = nasm_realloc (params, ((m->nparam_min+m->ndefs+1) *
2445 sizeof(*params)));
2446 while (nparam < m->nparam_min + m->ndefs) {
2447 params[nparam] = m->defaults[nparam - m->nparam_min];
2448 nparam++;
2449 }
2450 }
2451 /*
2452 * If we've gone over the maximum parameter count (and
2453 * we're in Plus mode), ignore parameters beyond
2454 * nparam_max.
2455 */
2456 if (m->plus && nparam > m->nparam_max)
2457 nparam = m->nparam_max;
2458 /*
2459 * Then terminate the parameter list, and leave.
2460 */
2461 if (!params) { /* need this special case */
2462 params = nasm_malloc(sizeof(*params));
2463 nparam = 0;
2464 }
2465 params[nparam] = NULL;
2466 *params_array = params;
2467 return m;
2468 }
2469 /*
2470 * This one wasn't right: look for the next one with the
2471 * same name.
2472 */
2473 for (m = m->next; m; m = m->next)
2474 if (!mstrcmp(m->name, tline->text, m->casesense))
2475 break;
2476 }
2477
2478 /*
2479 * After all that, we didn't find one with the right number of
2480 * parameters. Issue a warning, and fail to expand the macro.
2481 */
2482 error (ERR_WARNING|ERR_OFFBY1|ERR_WARN_MNP,
2483 "macro `%s' exists, but not taking %d parameters",
2484 tline->text, nparam);
2485 nasm_free (params);
2486 return NULL;
2487}
2488
2489/*
2490 * Expand the multi-line macro call made by the given line, if
2491 * there is one to be expanded. If there is, push the expansion on
2492 * istk->expansion and return 1 or 2, as according to whether a
2493 * line sync is needed (2 if it is). Otherwise return 0.
2494 */
2495static int expand_mmacro (Token *tline) {
2496 Token *label = NULL, **params, *t, *tt, *last = NULL;
2497 MMacro *m = NULL;
2498 Line *l, *ll;
2499 int i, nparam, *paramlen;
2500 int need_sync = FALSE;
2501
2502 t = tline;
2503 if (t && t->type == TOK_WHITESPACE)
2504 t = t->next;
2505 if (t && t->type == TOK_ID) {
2506 m = is_mmacro (t, &params);
2507 if (!m) {
2508 /*
2509 * We have an id which isn't a macro call. We'll assume
2510 * it might be a label; we'll also check to see if a
2511 * colon follows it. Then, if there's another id after
2512 * that lot, we'll check it again for macro-hood.
2513 */
2514 last = t, t = t->next;
2515 if (t && t->type == TOK_WHITESPACE)
2516 last = t, t = t->next;
2517 if (t && t->type == TOK_OTHER && !strcmp(t->text, ":"))
2518 last = t, t = t->next;
2519 if (t && t->type == TOK_WHITESPACE)
2520 last = t, t = t->next;
2521 if (t && t->type == TOK_ID) {
2522 m = is_mmacro(t, &params);
2523 if (m) {
2524 last->next = NULL;
2525 label = tline;
2526 tline = t;
2527 }
2528 }
2529 }
2530 }
2531 if (!m)
2532 return 0;
2533
2534 /*
2535 * If we're not already inside another macro expansion, we'd
2536 * better push a line synchronisation to ensure we stay put on
2537 * line numbering.
2538 */
2539 if (!istk->expansion)
2540 need_sync = TRUE;
2541
2542 /*
2543 * Fix up the parameters: this involves stripping leading and
2544 * trailing whitespace, then stripping braces if they are
2545 * present.
2546 */
2547 for (nparam = 0; params[nparam]; nparam++);
2548 paramlen = nparam ? nasm_malloc(nparam*sizeof(*paramlen)) : NULL;
2549
2550 for (i = 0; params[i]; i++) {
2551 int brace = FALSE;
2552 int comma = (!m->plus || i < nparam-1);
2553
2554 t = params[i];
2555 if (t && t->type == TOK_WHITESPACE)
2556 t = t->next;
2557 if (t && t->type == TOK_OTHER && !strcmp(t->text, "{"))
2558 t = t->next, brace = TRUE, comma = FALSE;
2559 params[i] = t;
2560 paramlen[i] = 0;
2561 while (t) {
2562 if (!t) /* end of param because EOL */
2563 break;
2564 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
2565 break; /* ... because we have hit a comma */
2566 if (comma && t->type == TOK_WHITESPACE &&
2567 t->next->type == TOK_OTHER && !strcmp(t->next->text, ","))
2568 break; /* ... or a space then a comma */
2569 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
2570 break; /* ... or a brace */
2571 t = t->next;
2572 paramlen[i]++;
2573 }
2574 }
2575
2576 /*
2577 * OK, we have a MMacro structure together with a set of
2578 * parameters. We must now go through the expansion and push
2579 * copies of each Line on to istk->expansion. Substitution of
2580 * parameter tokens and macro-local tokens doesn't get done
2581 * until the single-line macro substitution process; this is
2582 * because delaying them allows us to change the semantics
2583 * later through %rotate.
2584 *
2585 * First, push an end marker on to istk->expansion, mark this
2586 * macro as in progress, and set up its invocation-specific
2587 * variables.
2588 */
2589 ll = nasm_malloc(sizeof(Line));
2590 ll->next = istk->expansion;
2591 ll->finishes = m;
2592 ll->first = NULL;
2593 istk->expansion = ll;
2594
2595 m->in_progress = TRUE;
2596 m->params = params;
2597 m->iline = tline;
2598 m->nparam = nparam;
2599 m->rotate = 0;
2600 m->paramlen = paramlen;
2601 m->unique = unique++;
2602
2603 m->next_active = istk->mstk;
2604 istk->mstk = m;
2605
2606 for (l = m->expansion; l; l = l->next) {
2607 Token **tail;
2608
2609 ll = nasm_malloc(sizeof(Line));
2610 ll->next = istk->expansion;
2611 ll->finishes = NULL;
2612 ll->first = NULL;
2613 tail = &ll->first;
2614
2615 for (t = l->first; t; t = t->next) {
2616 tt = *tail = nasm_malloc(sizeof(Token));
2617 tt->next = NULL;
2618 tail = &tt->next;
2619 tt->type = t->type;
2620 tt->text = nasm_strdup(t->text);
2621 tt->mac = NULL;
2622 }
2623
2624 istk->expansion = ll;
2625
2626 }
2627
2628 /*
2629 * If we had a label, push it on the front of the first line of
2630 * the macro expansion. We must check that this doesn't give
2631 * two consecutive TOK_WHITESPACE.
2632 */
2633 if (label) {
2634 if (last->type == TOK_WHITESPACE &&
2635 istk->expansion->first->type == TOK_WHITESPACE) {
2636 Token *victim = istk->expansion->first; /* kill this whitespace */
2637 istk->expansion->first = victim->next;
2638 nasm_free (victim->text);
2639 nasm_free (victim);
2640 }
2641 last->next = istk->expansion->first;
2642 istk->expansion->first = label;
2643 }
2644
2645 list->uplevel (m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2646
2647 return need_sync ? 2 : 1;
2648}
2649
2650static void pp_reset (char *file, int apass, efunc errfunc, evalfunc eval,
2651 ListGen *listgen) {
2652 int h;
2653
2654 error = errfunc;
2655 cstk = NULL;
2656 linesync = outline = NULL;
2657 istk = nasm_malloc(sizeof(Include));
2658 istk->next = NULL;
2659 istk->conds = NULL;
2660 istk->expansion = NULL;
2661 istk->mstk = NULL;
2662 istk->fp = fopen(file, "r");
2663 istk->fname = nasm_strdup(file);
2664 istk->lineno = istk->lineinc = 1;
2665 if (!istk->fp)
2666 error (ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'", file);
2667 defining = NULL;
2668 for (h=0; h<NHASH; h++) {
2669 mmacros[h] = NULL;
2670 smacros[h] = NULL;
2671 }
2672 unique = 0;
2673 stdmacpos = stdmac;
2674 any_extrastdmac = (extrastdmac != NULL);
2675 list = listgen;
2676 evaluate = eval;
2677 pass = apass;
2678}
2679
2680static char *pp_getline (void) {
2681 char *line;
2682 Token *tline;
2683 int ret;
2684
2685 if (outline) {
2686 line = outline;
2687 outline = NULL;
2688 return line;
2689 }
2690
2691 while (1) {
2692 /*
2693 * Fetch a tokenised line, either from the macro-expansion
2694 * buffer or from the input file.
2695 */
2696 tline = NULL;
2697 while (istk->expansion && istk->expansion->finishes) {
2698 Line *l = istk->expansion;
2699 if (!l->finishes->name && l->finishes->in_progress > 1) {
2700 Line *ll;
2701
2702 /*
2703 * This is a macro-end marker for a macro with no
2704 * name, which means it's not really a macro at all
2705 * but a %rep block, and the `in_progress' field is
2706 * more than 1, meaning that we still need to
2707 * repeat. (1 means the natural last repetition; 0
2708 * means termination by %exitrep.) We have
2709 * therefore expanded up to the %endrep, and must
2710 * push the whole block on to the expansion buffer
2711 * again. We don't bother to remove the macro-end
2712 * marker: we'd only have to generate another one
2713 * if we did.
2714 */
2715 l->finishes->in_progress--;
2716 for (l = l->finishes->expansion; l; l = l->next) {
2717 Token *t, *tt, **tail;
2718
2719 ll = nasm_malloc(sizeof(Line));
2720 ll->next = istk->expansion;
2721 ll->finishes = NULL;
2722 ll->first = NULL;
2723 tail = &ll->first;
2724
2725 for (t = l->first; t; t = t->next) {
2726 if (t->text) {
2727 tt = *tail = nasm_malloc(sizeof(Token));
2728 tt->next = NULL;
2729 tail = &tt->next;
2730 tt->type = t->type;
2731 tt->text = nasm_strdup(t->text);
2732 tt->mac = NULL;
2733 }
2734 }
2735
2736 istk->expansion = ll;
2737 }
2738 line_sync();
2739 } else {
2740 /*
2741 * Check whether a `%rep' was started and not ended
2742 * within this macro expansion. This can happen and
2743 * should be detected. It's a fatal error because
2744 * I'm too confused to work out how to recover
2745 * sensibly from it.
2746 */
2747 if (defining) {
2748 if (defining->name)
2749 error (ERR_PANIC,
2750 "defining with name in expansion");
2751 else if (!istk->mstk->name)
2752 error (ERR_PANIC, "istk->mstk has no name but"
2753 " defining is set at end of expansion");
2754 else
2755 error (ERR_FATAL, "`%%rep' without `%%endrep' within"
2756 " expansion of macro `%s'", istk->mstk->name);
2757 }
2758
2759 if (istk->mstk->name) {
2760 /*
2761 * This was a real macro call, not a %rep, and
2762 * therefore the parameter information needs to
2763 * be freed.
2764 */
2765 nasm_free(istk->mstk->params);
2766 free_tlist(istk->mstk->iline);
2767 nasm_free(istk->mstk->paramlen);
2768 }
2769 istk->mstk = istk->mstk->next_active;
2770 l->finishes->in_progress = FALSE;
2771 istk->expansion = l->next;
2772 nasm_free (l);
2773 list->downlevel (LIST_MACRO);
2774 if (!istk->expansion)
2775 line_sync();
2776 }
2777 }
2778 if (istk->expansion) {
2779 char *p;
2780 Line *l = istk->expansion;
2781 tline = l->first;
2782 istk->expansion = l->next;
2783 nasm_free (l);
2784 p = detoken(tline);
2785 list->line (LIST_MACRO, p);
2786 nasm_free(p);
2787 if (!istk->expansion)
2788 line_sync();
2789 } else {
2790 line = read_line();
2791 while (!line) {
2792 /*
2793 * The current file has ended; work down the istk
2794 * until we find a file we can read from.
2795 */
2796 Include *i;
2797 fclose(istk->fp);
2798 if (istk->conds)
2799 error(ERR_FATAL, "expected `%%endif' before end of file");
2800 i = istk;
2801 istk = istk->next;
2802 list->downlevel (LIST_INCLUDE);
2803 nasm_free (i->fname);
2804 nasm_free (i);
2805 if (!istk)
2806 return NULL;
2807 else
2808 line_sync();
2809 update_fileline(3); /* update __FILE__ and __LINE__ */
2810 line = read_line();
2811 }
2812 line = prepreproc(line);
2813 tline = tokenise(line);
2814 nasm_free (line);
2815 }
2816
2817 /*
2818 * We must expand MMacro parameters and MMacro-local labels
2819 * _before_ we plunge into directive processing, to cope
2820 * with things like `%define something %1' such as STRUC
2821 * uses. Unless we're _defining_ a MMacro, in which case
2822 * those tokens should be left alone to go into the
2823 * definition.
2824 */
2825 if (!defining)
2826 tline = expand_mmac_params(tline);
2827
2828 /*
2829 * Check the line to see if it's a preprocessor directive.
2830 */
2831 ret = do_directive(tline);
2832 if (ret & 1) {
2833 if (ret & 4)
2834 line_sync();
2835 if ((ret & 2) && !stdmacpos) {/* give a blank line to the output */
2836 outline = nasm_strdup("");
2837 break;
2838 }
2839 else
2840 continue;
2841 } else if (defining) {
2842 /*
2843 * We're defining a multi-line macro. We emit nothing
2844 * at all, not even a blank line (when we finish
2845 * defining the macro, we'll emit a line-number
2846 * directive so that we keep sync properly), and just
2847 * shove the tokenised line on to the macro definition.
2848 */
2849 Line *l = nasm_malloc(sizeof(Line));
2850 l->next = defining->expansion;
2851 l->first = tline;
2852 l->finishes = FALSE;
2853 defining->expansion = l;
2854 continue;
2855 } else if (istk->conds && !emitting(istk->conds->state)) {
2856 /*
2857 * We're in a non-emitting branch of a condition block.
2858 * Emit nothing at all, not even a blank line: when we
2859 * emerge from the condition we'll give a line-number
2860 * directive so we keep our place correctly.
2861 */
2862 free_tlist(tline);
2863 continue;
2864 } else if (istk->mstk && !istk->mstk->in_progress) {
2865 /*
2866 * We're in a %rep block which has been terminated, so
2867 * we're walking through to the %endrep without
2868 * emitting anything. Emit nothing at all, not even a
2869 * blank line: when we emerge from the %rep block we'll
2870 * give a line-number directive so we keep our place
2871 * correctly.
2872 */
2873 free_tlist(tline);
2874 continue;
2875 } else {
2876 tline = expand_smacro(tline);
2877 ret = expand_mmacro(tline);
2878 if (!ret) {
2879 /*
2880 * De-tokenise the line again, and emit it.
2881 */
2882 line = detoken(tline);
2883 free_tlist (tline);
2884 outline = line;
2885 break;
2886 } else {
2887 if (ret == 2)
2888 line_sync();
2889 continue; /* expand_mmacro calls free_tlist */
2890 }
2891 }
2892 }
2893
2894 /*
2895 * Once we're out of this loop, outline _must_ be non-NULL. The
2896 * only question is whether linesync is NULL or not.
2897 */
2898 if (linesync) {
2899 line = linesync;
2900 linesync = NULL;
2901 } else {
2902 line = outline;
2903 outline = NULL;
2904 }
2905 return line;
2906}
2907
2908static void pp_cleanup (void) {
2909 int h;
2910
2911 if (defining) {
2912 error (ERR_NONFATAL, "end of file while still defining macro `%s'",
2913 defining->name);
2914 nasm_free (defining->name);
2915 free_tlist (defining->dlist);
2916 free_llist (defining->expansion);
2917 nasm_free (defining);
2918 }
2919 nasm_free (linesync); /* might just be necessary */
2920 nasm_free (outline); /* really shouldn't be necessary */
2921 while (cstk)
2922 ctx_pop();
2923 for (h=0; h<NHASH; h++) {
2924 while (mmacros[h]) {
2925 MMacro *m = mmacros[h];
2926 mmacros[h] = mmacros[h]->next;
2927 nasm_free (m->name);
2928 free_tlist (m->dlist);
2929 nasm_free (m->defaults);
2930 free_llist (m->expansion);
2931 nasm_free (m);
2932 }
2933 while (smacros[h]) {
2934 SMacro *s = smacros[h];
2935 smacros[h] = smacros[h]->next;
2936 nasm_free (s->name);
2937 free_tlist (s->expansion);
2938 nasm_free (s);
2939 }
2940 }
2941 while (istk) {
2942 Include *i = istk;
2943 istk = istk->next;
2944 fclose(i->fp);
2945 nasm_free (i->fname);
2946 nasm_free (i);
2947 }
2948 while (cstk)
2949 ctx_pop();
2950}
2951
2952void pp_include_path (char *path) {
2953 IncPath *i;
2954
2955 i = nasm_malloc(sizeof(IncPath));
2956 i->path = nasm_strdup(path);
2957 i->next = ipath;
2958
2959 ipath = i;
2960}
2961
2962void pp_pre_include (char *fname) {
2963 Token *inc, *space, *name;
2964 Line *l;
2965
2966 inc = nasm_malloc(sizeof(Token));
2967 inc->next = space = nasm_malloc(sizeof(Token));
2968 space->next = name = nasm_malloc(sizeof(Token));
2969 name->next = NULL;
2970
2971 inc->type = TOK_PREPROC_ID;
2972 inc->text = nasm_strdup("%include");
2973 space->type = TOK_WHITESPACE;
2974 space->text = nasm_strdup(" ");
2975 name->type = TOK_INTERNAL_STRING;
2976 name->text = nasm_strdup(fname);
2977
2978 inc->mac = space->mac = name->mac = NULL;
2979
2980 l = nasm_malloc(sizeof(Line));
2981 l->next = predef;
2982 l->first = inc;
2983 l->finishes = FALSE;
2984 predef = l;
2985}
2986
2987void pp_pre_define (char *definition) {
2988 Token *def, *space, *name;
2989 Line *l;
2990 char *equals;
2991
2992 equals = strchr(definition, '=');
2993
2994 def = nasm_malloc(sizeof(Token));
2995 def->next = space = nasm_malloc(sizeof(Token));
2996 if (equals)
2997 *equals = ' ';
2998 space->next = name = tokenise(definition);
2999 if (equals)
3000 *equals = '=';
3001
3002 def->type = TOK_PREPROC_ID;
3003 def->text = nasm_strdup("%define");
3004 space->type = TOK_WHITESPACE;
3005 space->text = nasm_strdup(" ");
3006
3007 def->mac = space->mac = NULL;
3008
3009 l = nasm_malloc(sizeof(Line));
3010 l->next = predef;
3011 l->first = def;
3012 l->finishes = FALSE;
3013 predef = l;
3014}
3015
3016void pp_extra_stdmac (char **macros) {
3017 extrastdmac = macros;
3018}
3019
3020Preproc nasmpp = {
3021 pp_reset,
3022 pp_getline,
3023 pp_cleanup
3024};