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