NASM 0.94
[nasm/avx512.git] / preproc.c
blobcd8c6170115a63ae097bf699c3688faa2a4a2030
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>
17 #include "nasm.h"
18 #include "nasmlib.h"
20 typedef struct SMacro SMacro;
21 typedef struct MMacro MMacro;
22 typedef struct Context Context;
23 typedef struct Token Token;
24 typedef struct Line Line;
25 typedef struct Include Include;
26 typedef struct Cond Cond;
29 * Store the definition of a single-line macro.
31 struct SMacro {
32 SMacro *next;
33 char *name;
34 int casesense;
35 int nparam;
36 int in_progress;
37 Token *expansion;
41 * Store the definition of a multi-line macro.
43 struct MMacro {
44 MMacro *next;
45 char *name;
46 int casesense;
47 int nparam_min, nparam_max;
48 int plus; /* is the last parameter greedy? */
49 int in_progress;
50 Token **defaults, *dlist;
51 Line *expansion;
55 * The context stack is composed of a linked list of these.
57 struct Context {
58 Context *next;
59 SMacro *localmac;
60 char *name;
61 unsigned long number;
65 * This is the internal form which we break input lines up into.
66 * Typically stored in linked lists.
68 * TOK_PS_OTHER is a token type used internally within
69 * expand_smacro(), to denote a token which has already been
70 * checked for being a potential macro, but may still be a context-
71 * local label.
73 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
74 * necessarily used as-is, but is intended to denote the number of
75 * the substituted parameter. So in the definition
77 * %define a(x,y) ( (x) & ~(y) )
79 * the token representing `x' will have its type changed to
80 * TOK_SMAC_PARAM, but the one representing `y' will be
81 * TOK_SMAC_PARAM+1.
83 struct Token {
84 Token *next;
85 char *text;
86 SMacro *mac; /* associated macro for TOK_MAC_END */
87 int type;
89 enum {
90 TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING,
91 TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_PS_OTHER, TOK_SMAC_PARAM
95 * Multi-line macro definitions are stored as a linked list of
96 * these, which is essentially a container to allow several linked
97 * lists of Tokens.
99 * Note that in this module, linked lists are treated as stacks
100 * wherever possible. For this reason, Lines are _pushed_ on to the
101 * `expansion' field in MMacro structures, so that the linked list,
102 * if walked, would give the macro lines in reverse order; this
103 * means that we can walk the list when expanding a macro, and thus
104 * push the lines on to the `expansion' field in _istk_ in reverse
105 * order (so that when popped back off they are in the right
106 * order). It may seem cockeyed, and it relies on my design having
107 * an even number of steps in, but it works...
109 * Some of these structures, rather than being actual lines, are
110 * markers delimiting the end of the expansion of a given macro.
111 * This is for use in the cycle-tracking code. Such structures have
112 * `finishes' non-NULL, and `first' NULL. All others have
113 * `finishes' NULL, but `first' may still be non-NULL if the line
114 * is blank.
116 struct Line {
117 Line *next;
118 MMacro *finishes;
119 Token *first;
123 * To handle an arbitrary level of file inclusion, we maintain a
124 * stack (ie linked list) of these things.
126 struct Include {
127 Include *next;
128 FILE *fp;
129 Cond *conds;
130 Line *expansion;
131 char *fname;
132 int lineno, lineinc;
136 * Conditional assembly: we maintain a separate stack of these for
137 * each level of file inclusion. (The only reason we keep the
138 * stacks separate is to ensure that a stray `%endif' in a file
139 * included from within the true branch of a `%if' won't terminate
140 * it and cause confusion: instead, rightly, it'll cause an error.)
142 struct Cond {
143 Cond *next;
144 int state;
146 enum {
148 * These states are for use just after %if or %elif: IF_TRUE
149 * means the condition has evaluated to truth so we are
150 * currently emitting, whereas IF_FALSE means we are not
151 * currently emitting but will start doing so if a %else comes
152 * up. In these states, all directives are admissible: %elif,
153 * %else and %endif. (And of course %if.)
155 COND_IF_TRUE, COND_IF_FALSE,
157 * These states come up after a %else: ELSE_TRUE means we're
158 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
159 * any %elif or %else will cause an error.
161 COND_ELSE_TRUE, COND_ELSE_FALSE,
163 * This state means that we're not emitting now, and also that
164 * nothing until %endif will be emitted at all. It's for use in
165 * two circumstances: (i) when we've had our moment of emission
166 * and have now started seeing %elifs, and (ii) when the
167 * condition construct in question is contained within a
168 * non-emitting branch of a larger condition construct.
170 COND_NEVER
172 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
175 * Condition codes. Note that we use c_ prefix not C_ because C_ is
176 * used in nasm.h for the "real" condition codes. At _this_ level,
177 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
178 * ones, so we need a different enum...
180 static char *conditions[] = {
181 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
182 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
183 "np", "ns", "nz", "o", "p", "pe", "po", "s", "z"
185 enum {
186 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
187 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
188 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_S, c_Z
190 static int inverse_ccs[] = {
191 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
192 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,
193 c_Z, c_NO, c_NP, c_PO, c_PE, c_NS, c_NZ
196 static Context *cstk;
197 static Include *istk;
199 static efunc error;
201 static unsigned long unique; /* unique identifier numbers */
203 static char *linesync, *outline;
206 * The number of hash values we use for the macro lookup tables.
208 #define NHASH 31
211 * The current set of multi-line macros we have defined.
213 static MMacro *mmacros[NHASH];
216 * The current set of single-line macros we have defined.
218 static SMacro *smacros[NHASH];
221 * The multi-line macro we are currently defining, if any.
223 static MMacro *defining;
226 * The number of macro parameters to allocate space for at a time.
228 #define PARAM_DELTA 16
231 * The standard macro set: defined as `static char *stdmac[]'. Also
232 * gives our position in the macro set, when we're processing it.
234 #include "macros.c"
235 static char **stdmacpos;
238 * The pre-preprocessing stage... This function has two purposes:
239 * firstly, it translates line number indications as they emerge
240 * from GNU cpp (`# lineno "file" flags') into NASM preprocessor
241 * line number indications (`%line lineno file'), and secondly, it
242 * converts [INCLUDE] and [INC] old-style inclusion directives into
243 * the new-style `%include' form (though in the next version it
244 * won't do that any more).
246 static char *prepreproc(char *line) {
247 int lineno, fnlen;
248 char *fname, *oldline;
250 if (line[0] == '#' && line[1] == ' ') {
251 oldline = line;
252 fname = oldline+2;
253 lineno = atoi(fname);
254 fname += strspn(fname, "0123456789 ");
255 if (*fname == '"')
256 fname++;
257 fnlen = strcspn(fname, "\"");
258 line = nasm_malloc(20+fnlen);
259 sprintf(line, "%%line %d %.*s", lineno, fnlen, fname);
260 nasm_free (oldline);
261 return line;
262 } else if (!nasm_strnicmp(line, "[include", 8)) {
263 oldline = line;
264 fname = oldline+8;
265 fname += strspn(fname, " \t");
266 fnlen = strcspn(fname, "]");
267 line = nasm_malloc(20+fnlen);
268 sprintf(line, "%%include \"%.*s\"", fnlen, fname);
269 error (ERR_WARNING|ERR_OFFBY1, "use of [INCLUDE] is being phased out;"
270 " suggest `%%include'");
271 nasm_free (oldline);
272 return line;
273 } else if (!nasm_strnicmp(line, "[inc", 4)) {
274 oldline = line;
275 fname = oldline+4;
276 fname += strspn(fname, " \t");
277 fnlen = strcspn(fname, "]");
278 line = nasm_malloc(20+fnlen);
279 sprintf(line, "%%include \"%.*s\"", fnlen, fname);
280 error (ERR_WARNING|ERR_OFFBY1, "use of [INC] is being phased out;"
281 " suggest `%%include'");
282 nasm_free (oldline);
283 return line;
284 } else
285 return line;
289 * The hash function for macro lookups. Note that due to some
290 * macros having case-insensitive names, the hash function must be
291 * invariant under case changes. We implement this by applying a
292 * perfectly normal hash function to the uppercase of the string.
294 static int hash(char *s) {
296 * Powers of three, mod 31.
298 static const int multipliers[] = {
299 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10,
300 30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21
302 int h = 0;
303 int i = 0;
305 while (*s) {
306 h += multipliers[i] * (unsigned char) (toupper(*s));
307 s++;
308 if (++i >= sizeof(multipliers)/sizeof(*multipliers))
309 i = 0;
311 h %= NHASH;
312 return h;
316 * Free a linked list of tokens.
318 static void free_tlist (Token *list) {
319 Token *t;
320 while (list) {
321 t = list;
322 list = list->next;
323 nasm_free (t->text);
324 nasm_free (t);
329 * Free a linked list of lines.
331 static void free_llist (Line *list) {
332 Line *l;
333 while (list) {
334 l = list;
335 list = list->next;
336 free_tlist (l->first);
337 nasm_free (l);
342 * Pop the context stack.
344 static void ctx_pop (void) {
345 Context *c = cstk;
346 SMacro *smac, *s;
348 cstk = cstk->next;
349 smac = c->localmac;
350 while (smac) {
351 s = smac;
352 smac = smac->next;
353 nasm_free (s->name);
354 free_tlist (s->expansion);
355 nasm_free (s);
357 nasm_free (c->name);
358 nasm_free (c);
362 * Generate a line synchronisation comment, to ensure the assembler
363 * knows which source file the current output has really come from.
365 static void line_sync (void) {
366 char text[80];
367 sprintf(text, "%%line %d+%d %s",
368 (istk->expansion ? istk->lineno - istk->lineinc : istk->lineno),
369 (istk->expansion ? 0 : istk->lineinc), istk->fname);
370 if (linesync)
371 free (linesync);
372 linesync = nasm_strdup(text);
375 #define BUF_DELTA 512
377 * Read a line from the top file in istk, handling multiple CR/LFs
378 * at the end of the line read, and handling spurious ^Zs. Will
379 * return lines from the standard macro set if this has not already
380 * been done.
382 static char *read_line (void) {
383 char *buffer, *p, *q;
384 int bufsize;
386 if (stdmacpos) {
387 if (*stdmacpos)
388 return nasm_strdup(*stdmacpos++);
389 else {
390 stdmacpos = NULL;
391 line_sync();
395 bufsize = BUF_DELTA;
396 buffer = nasm_malloc(BUF_DELTA);
397 p = buffer;
398 while (1) {
399 q = fgets(p, bufsize-(p-buffer), istk->fp);
400 if (!q)
401 break;
402 p += strlen(p);
403 if (p > buffer && p[-1] == '\n') {
404 istk->lineno += istk->lineinc;
405 break;
407 if (p-buffer > bufsize-10) {
408 bufsize += BUF_DELTA;
409 buffer = nasm_realloc(buffer, bufsize);
413 if (!q && p == buffer) {
414 nasm_free (buffer);
415 return NULL;
419 * Play safe: remove CRs as well as LFs, if any of either are
420 * present at the end of the line.
422 while (p > buffer && (p[-1] == '\n' || p[-1] == '\r'))
423 *--p = '\0';
426 * Handle spurious ^Z, which may be inserted into source files
427 * by some file transfer utilities.
429 buffer[strcspn(buffer, "\032")] = '\0';
431 return buffer;
435 * Tokenise a line of text. This is a very simple process since we
436 * don't need to parse the value out of e.g. numeric tokens: we
437 * simply split one string into many.
439 static Token *tokenise (char *line) {
440 char *p = line;
441 int type;
442 Token *list = NULL;
443 Token *t, **tail = &list;
445 while (*line) {
446 p = line;
447 if (*p == '%' &&
448 (p[1] == '{' || p[1] == '!' || (p[1] == '%' && isidchar(p[2])) ||
449 p[1] == '$' || p[1] == '+' || p[1] == '-' || isidchar(p[1]))) {
450 type = TOK_PREPROC_ID;
451 p++;
452 if (*p == '{') {
453 p++;
454 while (*p && *p != '}') {
455 p[-1] = *p;
456 p++;
458 p[-1] = '\0';
459 if (*p) p++;
460 } else {
461 if (*p == '!' || *p == '%' || *p == '$' ||
462 *p == '+' || *p == '-') p++;
463 while (*p && isidchar(*p))
464 p++;
466 } else if (isidstart(*p)) {
467 type = TOK_ID;
468 p++;
469 while (*p && isidchar(*p))
470 p++;
471 } else if (*p == '\'' || *p == '"') {
473 * A string token.
475 char c = *p;
476 p++;
477 type = TOK_STRING;
478 while (*p && *p != c)
479 p++;
480 if (*p) p++;
481 } else if (isnumstart(*p)) {
483 * A number token.
485 type = TOK_NUMBER;
486 p++;
487 while (*p && isnumchar(*p))
488 p++;
489 } else if (isspace(*p)) {
490 type = TOK_WHITESPACE;
491 p++;
492 while (*p && isspace(*p))
493 p++;
495 * Whitespace just before end-of-line is discarded by
496 * pretending it's a comment; whitespace just before a
497 * comment gets lumped into the comment.
499 if (!*p || *p == ';') {
500 type = TOK_COMMENT;
501 while (*p) p++;
503 } else if (*p == ';') {
504 type = TOK_COMMENT;
505 while (*p) p++;
506 } else {
508 * Anything else is an operator of some kind; with the
509 * exceptions of >>, <<, // and %%, all operator tokens
510 * are single-character.
512 char c = *p++;
513 type = TOK_OTHER;
514 if ( (c == '>' || c == '<' || c == '/' || c == '%') && *p == c)
515 p++;
517 if (type != TOK_COMMENT) {
518 *tail = t = nasm_malloc (sizeof(Token));
519 tail = &t->next;
520 t->next = NULL;
521 t->type = type;
522 t->text = nasm_malloc(1+p-line);
523 strncpy(t->text, line, p-line);
524 t->text[p-line] = '\0';
526 line = p;
529 return list;
533 * Convert a line of tokens back into text.
535 static char *detoken (Token *tlist) {
536 Token *t;
537 int len;
538 char *line, *p;
540 len = 0;
541 for (t = tlist; t; t = t->next) {
542 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
543 char *p = getenv(t->text+2);
544 nasm_free (t->text);
545 if (p)
546 t->text = nasm_strdup(p);
547 else
548 t->text = NULL;
550 if (t->text)
551 len += strlen(t->text);
553 p = line = nasm_malloc(len+1);
554 for (t = tlist; t; t = t->next) {
555 if (t->text) {
556 strcpy (p, t->text);
557 p += strlen(p);
560 *p = '\0';
561 return line;
565 * Return the Context structure associated with a %$ token. Return
566 * NULL, having _already_ reported an error condition, if the
567 * context stack isn't deep enough for the supplied number of $
568 * signs.
570 static Context *get_ctx (char *name) {
571 Context *ctx;
572 int i;
574 if (!cstk) {
575 error (ERR_NONFATAL|ERR_OFFBY1, "`%s': context stack is empty", name);
576 return NULL;
579 i = 1;
580 ctx = cstk;
581 while (name[i+1] == '$') {
582 i++;
583 ctx = ctx->next;
584 if (!ctx) {
585 error (ERR_NONFATAL|ERR_OFFBY1, "`%s': context stack is only"
586 " %d level%s deep", name, i-1, (i==2 ? "" : "s"));
587 return NULL;
590 return ctx;
594 * Compare a string to the name of an existing macro; this is a
595 * simple wrapper which calls either strcmp or nasm_stricmp
596 * depending on the value of the `casesense' parameter.
598 static int mstrcmp(char *p, char *q, int casesense) {
599 return casesense ? strcmp(p,q) : nasm_stricmp(p,q);
603 * Determine if we should warn on defining a single-line macro of
604 * name `name', with `nparam' parameters. If nparam is 0, will
605 * return TRUE if _any_ single-line macro of that name is defined.
606 * Otherwise, will return TRUE if a single-line macro with either
607 * `nparam' or no parameters is defined.
609 * If a macro with precisely the right number of parameters is
610 * defined, the address of the definition structure will be
611 * returned in `defn'; otherwise NULL will be returned. If `defn'
612 * is NULL, no action will be taken regarding its contents, and no
613 * error will occur.
615 * Note that this is also called with nparam zero to resolve
616 * `ifdef'.
618 static int smacro_defined (char *name, int nparam, SMacro **defn) {
619 SMacro *m;
620 Context *ctx;
621 char *p;
623 if (name[0] == '%' && name[1] == '$') {
624 ctx = get_ctx (name);
625 if (!ctx)
626 return FALSE; /* got to return _something_ */
627 m = ctx->localmac;
628 p = name+1;
629 p += strspn(p, "$");
630 } else {
631 m = smacros[hash(name)];
632 p = name;
635 while (m) {
636 if (!mstrcmp(m->name, p, m->casesense) &&
637 (nparam == 0 || m->nparam == 0 || nparam == m->nparam)) {
638 if (defn) {
639 if (nparam == m->nparam)
640 *defn = m;
641 else
642 *defn = NULL;
644 return TRUE;
646 m = m->next;
648 return FALSE;
652 * Count and mark off the parameters in a multi-line macro call.
653 * This is called both from within the multi-line macro expansion
654 * code, and also to mark off the default parameters when provided
655 * in a %macro definition line.
657 static void count_mmac_params (Token *t, int *nparam, Token ***params) {
658 int paramsize, brace;
660 *nparam = paramsize = 0;
661 *params = NULL;
662 while (t) {
663 if (*nparam >= paramsize) {
664 paramsize += PARAM_DELTA;
665 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
667 if (t && t->type == TOK_WHITESPACE)
668 t = t->next;
669 brace = FALSE;
670 if (t && t->type == TOK_OTHER && !strcmp(t->text, "{"))
671 brace = TRUE;
672 (*params)[(*nparam)++] = t;
673 while (t && (t->type != TOK_OTHER ||
674 strcmp(t->text, brace ? "}" : ",")))
675 t = t->next;
676 if (t) { /* got a comma/brace */
677 t = t->next;
678 if (brace) {
680 * Now we've found the closing brace, look further
681 * for the comma.
683 if (t && t->type == TOK_WHITESPACE)
684 t = t->next;
685 if (t && (t->type != TOK_OTHER || strcmp(t->text, ","))) {
686 error (ERR_NONFATAL|ERR_OFFBY1,
687 "braces do not enclose all of macro parameter");
688 while (t && (t->type != TOK_OTHER ||
689 strcmp(t->text, ",")))
690 t = t->next;
692 if (t)
693 t = t->next; /* eat the comma */
696 else /* got EOL */
697 break;
702 * Find out if a line contains a preprocessor directive, and deal
703 * with it if so.
705 * If a directive _is_ found, the line will never be de-tokenised
706 * as is, so we have carte blanche to fiddle with it and adjust
707 * token values.
709 * Return values go like this:
711 * bit 0 is set if a directive was found
712 * bit 1 is set if a blank line should be emitted
713 * bit 2 is set if a re-sync line number comment should be emitted
715 * (bits 1 and 2 are mutually exclusive in that the rest of the
716 * preprocessor doesn't guarantee to be able to handle the case in
717 * which both are set)
719 static int do_directive (Token *tline) {
720 static char *directives[] = {
721 "%clear", "%define", "%elifctx", "%elifdef", "%elifnctx",
722 "%elifndef", "%else", "%endif", "%endm", "%endmacro", "%error",
723 "%idefine", "%ifctx", "%ifdef", "%ifnctx", "%ifndef", "%imacro",
724 "%include", "%line", "%macro", "%pop", "%push", "%repl"
726 enum {
727 PP_CLEAR, PP_DEFINE, PP_ELIFCTX, PP_ELIFDEF, PP_ELIFNCTX,
728 PP_ELIFNDEF, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO, PP_ERROR,
729 PP_IDEFINE, PP_IFCTX, PP_IFDEF, PP_IFNCTX, PP_IFNDEF, PP_IMACRO,
730 PP_INCLUDE, PP_LINE, PP_MACRO, PP_POP, PP_PUSH, PP_REPL
732 int i, j, k, m, nparam;
733 char *p, *mname;
734 Include *inc;
735 Context *ctx;
736 Cond *cond;
737 SMacro *smac, **smhead;
738 MMacro *mmac;
739 Token *t, *tt, *param_start, *macro_start, *last;
741 if (tline && tline->type == TOK_WHITESPACE)
742 tline = tline->next;
743 if (!tline || tline->type != TOK_PREPROC_ID ||
744 (tline->text[1] == '%' || tline->text[1] == '$'))
745 return 0;
747 i = -1;
748 j = sizeof(directives)/sizeof(*directives);
749 while (j-i > 1) {
750 k = (j+i) / 2;
751 m = nasm_stricmp(tline->text, directives[k]);
752 if (m == 0) {
753 i = k;
754 j = -2;
755 break;
756 } else if (m < 0) {
757 j = k;
758 } else
759 i = k;
763 * If we're in a non-emitting branch of a condition construct,
764 * we should ignore all directives except for condition
765 * directives.
767 if (istk->conds && !emitting(istk->conds->state) &&
768 i != PP_IFCTX && i != PP_IFDEF && i != PP_IFNCTX && i != PP_IFNDEF &&
769 i!=PP_ELIFCTX && i!=PP_ELIFDEF && i!=PP_ELIFNCTX && i!=PP_ELIFNDEF &&
770 i != PP_ELSE && i != PP_ENDIF)
771 return 0;
774 * If we're defining a macro, we should ignore all directives
775 * except for %macro/%imacro (which generate an error) and
776 * %endm/%endmacro.
778 if (defining && i != PP_MACRO && i != PP_IMACRO &&
779 i != PP_ENDMACRO && i != PP_ENDM)
780 return 0;
782 if (j != -2) {
783 error(ERR_NONFATAL|ERR_OFFBY1, "unknown preprocessor directive `%s'",
784 tline->text);
785 return 0; /* didn't get it */
788 switch (i) {
790 case PP_CLEAR:
791 if (tline->next)
792 error(ERR_WARNING|ERR_OFFBY1,
793 "trailing garbage after `%%pop' ignored");
794 for (j=0; j<NHASH; j++) {
795 while (mmacros[j]) {
796 MMacro *m = mmacros[j];
797 mmacros[j] = mmacros[j]->next;
798 nasm_free (m->name);
799 free_tlist (m->dlist);
800 free_llist (m->expansion);
801 nasm_free (m);
803 while (smacros[j]) {
804 SMacro *s = smacros[j];
805 smacros[j] = smacros[j]->next;
806 nasm_free (s->name);
807 free_tlist (s->expansion);
808 nasm_free (s);
811 return 3;
813 case PP_INCLUDE:
814 tline = tline->next;
815 if (tline && tline->type == TOK_WHITESPACE)
816 tline = tline->next;
817 if (!tline || tline->type != TOK_STRING) {
818 error(ERR_NONFATAL|ERR_OFFBY1, "`%%include' expects a file name");
819 return 3; /* but we did _something_ */
821 if (tline->next)
822 error(ERR_WARNING|ERR_OFFBY1,
823 "trailing garbage after `%%include' ignored");
824 p = tline->text+1; /* point past the quote to the name */
825 p[strlen(p)-1] = '\0'; /* remove the trailing quote */
826 inc = nasm_malloc(sizeof(Include));
827 inc->next = istk;
828 inc->conds = NULL;
829 inc->fp = fopen(p, "r");
830 inc->fname = nasm_strdup(p);
831 inc->lineno = inc->lineinc = 1;
832 inc->expansion = NULL;
833 if (!inc->fp)
834 error (ERR_FATAL|ERR_OFFBY1,
835 "unable to open include file `%s'", p);
836 istk = inc;
837 return 5;
839 case PP_PUSH:
840 tline = tline->next;
841 if (tline && tline->type == TOK_WHITESPACE)
842 tline = tline->next;
843 if (!tline || tline->type != TOK_ID) {
844 error(ERR_NONFATAL|ERR_OFFBY1,
845 "`%%push' expects a context identifier");
846 return 3; /* but we did _something_ */
848 if (tline->next)
849 error(ERR_WARNING|ERR_OFFBY1,
850 "trailing garbage after `%%push' ignored");
851 ctx = nasm_malloc(sizeof(Context));
852 ctx->next = cstk;
853 ctx->localmac = NULL;
854 ctx->name = nasm_strdup(tline->text);
855 ctx->number = unique++;
856 cstk = ctx;
857 break;
859 case PP_REPL:
860 tline = tline->next;
861 if (tline && tline->type == TOK_WHITESPACE)
862 tline = tline->next;
863 if (!tline || tline->type != TOK_ID) {
864 error(ERR_NONFATAL|ERR_OFFBY1,
865 "`%%repl' expects a context identifier");
866 return 3; /* but we did _something_ */
868 if (tline->next)
869 error(ERR_WARNING|ERR_OFFBY1,
870 "trailing garbage after `%%repl' ignored");
871 if (!cstk)
872 error(ERR_NONFATAL|ERR_OFFBY1,
873 "`%%repl': context stack is empty");
874 else {
875 nasm_free (cstk->name);
876 cstk->name = nasm_strdup(tline->text);
878 break;
880 case PP_POP:
881 if (tline->next)
882 error(ERR_WARNING|ERR_OFFBY1,
883 "trailing garbage after `%%pop' ignored");
884 if (!cstk)
885 error(ERR_NONFATAL|ERR_OFFBY1,
886 "`%%pop': context stack is already empty");
887 else
888 ctx_pop();
889 break;
891 case PP_ERROR:
892 tline = tline->next;
893 if (tline && tline->type == TOK_WHITESPACE)
894 tline = tline->next;
895 if (!tline || tline->type != TOK_STRING) {
896 error(ERR_NONFATAL|ERR_OFFBY1,
897 "`%%error' expects an error string");
898 return 3; /* but we did _something_ */
900 if (tline->next)
901 error(ERR_WARNING|ERR_OFFBY1,
902 "trailing garbage after `%%error' ignored");
903 p = tline->text+1; /* point past the quote to the name */
904 p[strlen(p)-1] = '\0'; /* remove the trailing quote */
905 error(ERR_NONFATAL|ERR_OFFBY1, "user error: %s", p);
906 break;
908 case PP_IFCTX:
909 case PP_IFNCTX:
910 tline = tline->next;
911 if (istk->conds && !emitting(istk->conds->state))
912 j = COND_NEVER;
913 else {
914 j = FALSE; /* have we matched yet? */
915 if (!cstk)
916 error(ERR_FATAL|ERR_OFFBY1,
917 "`%%if%sctx': context stack is empty",
918 (i==PP_IFNCTX ? "n" : ""));
919 else while (tline) {
920 if (tline->type == TOK_WHITESPACE)
921 tline = tline->next;
922 if (!tline || tline->type != TOK_ID) {
923 error(ERR_NONFATAL|ERR_OFFBY1,
924 "`%%ifctx' expects context identifiers");
925 return 3; /* but we did _something_ */
927 if (!nasm_stricmp(tline->text, cstk->name))
928 j = TRUE;
929 tline = tline->next;
931 if (i == PP_IFNCTX)
932 j = !j;
933 j = (j ? COND_IF_TRUE : COND_IF_FALSE);
935 cond = nasm_malloc(sizeof(Cond));
936 cond->next = istk->conds;
937 cond->state = j;
938 istk->conds = cond;
939 return 1;
941 case PP_ELIFCTX:
942 case PP_ELIFNCTX:
943 tline = tline->next;
944 if (!istk->conds)
945 error(ERR_FATAL|ERR_OFFBY1, "`%%elif%sctx': no matching `%%if'",
946 (i==PP_ELIFNCTX ? "n" : ""));
947 if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
948 istk->conds->state = COND_NEVER;
949 else {
950 j = FALSE; /* have we matched yet? */
951 if (!cstk)
952 error(ERR_FATAL|ERR_OFFBY1,
953 "`%%elif%sctx': context stack is empty",
954 (i==PP_ELIFNCTX ? "n" : ""));
955 else while (tline) {
956 if (tline->type == TOK_WHITESPACE)
957 tline = tline->next;
958 if (!tline || tline->type != TOK_ID) {
959 error(ERR_NONFATAL|ERR_OFFBY1,
960 "`%%elif%sctx' expects context identifiers",
961 (i==PP_ELIFNCTX ? "n" : ""));
962 return 3; /* but we did _something_ */
964 if (!nasm_stricmp(tline->text, cstk->name))
965 j = TRUE;
966 tline = tline->next;
968 if (i == PP_ELIFNCTX)
969 j = !j;
970 istk->conds->state = (j ? COND_IF_TRUE : COND_IF_FALSE);
972 return 1;
974 case PP_IFDEF:
975 case PP_IFNDEF:
976 tline = tline->next;
977 if (istk->conds && !emitting(istk->conds->state))
978 j = COND_NEVER;
979 else {
980 j = FALSE; /* have we matched yet? */
981 while (tline) {
982 if (tline->type == TOK_WHITESPACE)
983 tline = tline->next;
984 if (!tline || (tline->type != TOK_ID &&
985 (tline->type != TOK_PREPROC_ID ||
986 tline->text[1] != '$'))) {
987 error(ERR_NONFATAL|ERR_OFFBY1,
988 "`%%if%sdef' expects macro identifiers",
989 (i==PP_ELIFNDEF ? "n" : ""));
990 return 3; /* but we did _something_ */
992 if (smacro_defined(tline->text, 0, NULL))
993 j = TRUE;
994 tline = tline->next;
996 if (i == PP_IFNDEF)
997 j = !j;
998 j = (j ? COND_IF_TRUE : COND_IF_FALSE);
1000 cond = nasm_malloc(sizeof(Cond));
1001 cond->next = istk->conds;
1002 cond->state = j;
1003 istk->conds = cond;
1004 return 1;
1006 case PP_ELIFDEF:
1007 case PP_ELIFNDEF:
1008 tline = tline->next;
1009 if (!istk->conds)
1010 error(ERR_FATAL|ERR_OFFBY1, "`%%elif%sctx': no matching `%%if'",
1011 (i==PP_ELIFNCTX ? "n" : ""));
1012 if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
1013 istk->conds->state = COND_NEVER;
1014 else {
1015 j = FALSE; /* have we matched yet? */
1016 while (tline) {
1017 if (tline->type == TOK_WHITESPACE)
1018 tline = tline->next;
1019 if (!tline || (tline->type != TOK_ID &&
1020 (tline->type != TOK_PREPROC_ID ||
1021 tline->text[1] != '$'))) {
1022 error(ERR_NONFATAL|ERR_OFFBY1,
1023 "`%%elif%sdef' expects macro identifiers",
1024 (i==PP_ELIFNDEF ? "n" : ""));
1025 return 3; /* but we did _something_ */
1027 if (smacro_defined(tline->text, 0, NULL))
1028 j = TRUE;
1029 tline = tline->next;
1031 if (i == PP_ELIFNDEF)
1032 j = !j;
1033 istk->conds->state = (j ? COND_IF_TRUE : COND_IF_FALSE);
1035 return 1;
1037 case PP_ELSE:
1038 if (tline->next)
1039 error(ERR_WARNING|ERR_OFFBY1,
1040 "trailing garbage after `%%else' ignored");
1041 if (!istk->conds)
1042 error(ERR_FATAL|ERR_OFFBY1,
1043 "`%%else': no matching `%%if'");
1044 if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
1045 istk->conds->state = COND_ELSE_FALSE;
1046 else
1047 istk->conds->state = COND_ELSE_TRUE;
1048 return 1;
1050 case PP_ENDIF:
1051 if (tline->next)
1052 error(ERR_WARNING|ERR_OFFBY1,
1053 "trailing garbage after `%%endif' ignored");
1054 if (!istk->conds)
1055 error(ERR_FATAL|ERR_OFFBY1,
1056 "`%%endif': no matching `%%if'");
1057 cond = istk->conds;
1058 istk->conds = cond->next;
1059 nasm_free (cond);
1060 return 5;
1062 case PP_MACRO:
1063 case PP_IMACRO:
1064 if (defining)
1065 error (ERR_FATAL|ERR_OFFBY1,
1066 "`%%%smacro': already defining a macro",
1067 (i == PP_IMACRO ? "i" : ""));
1068 tline = tline->next;
1069 if (tline && tline->type == TOK_WHITESPACE)
1070 tline = tline->next;
1071 if (!tline || tline->type != TOK_ID) {
1072 error (ERR_NONFATAL|ERR_OFFBY1,
1073 "`%%%smacro' expects a macro name",
1074 (i == PP_IMACRO ? "i" : ""));
1075 return 3;
1077 defining = nasm_malloc(sizeof(MMacro));
1078 defining->name = nasm_strdup(tline->text);
1079 defining->casesense = (i == PP_MACRO);
1080 defining->plus = FALSE;
1081 defining->in_progress = FALSE;
1082 tline = tline->next;
1083 if (tline && tline->type == TOK_WHITESPACE)
1084 tline = tline->next;
1085 if (!tline || tline->type != TOK_NUMBER) {
1086 error (ERR_NONFATAL|ERR_OFFBY1,
1087 "`%%%smacro' expects a parameter count",
1088 (i == PP_IMACRO ? "i" : ""));
1089 defining->nparam_min = defining->nparam_max = 0;
1090 } else {
1091 defining->nparam_min = defining->nparam_max =
1092 readnum(tline->text, &j);
1093 if (j)
1094 error (ERR_NONFATAL|ERR_OFFBY1,
1095 "unable to parse parameter count `%s'", tline->text);
1097 if (tline && tline->next && tline->next->type == TOK_OTHER &&
1098 !strcmp(tline->next->text, "-")) {
1099 tline = tline->next->next;
1100 if (!tline || tline->type != TOK_NUMBER)
1101 error (ERR_NONFATAL|ERR_OFFBY1,
1102 "`%%%smacro' expects a parameter count after `-'",
1103 (i == PP_IMACRO ? "i" : ""));
1104 else {
1105 defining->nparam_max = readnum(tline->text, &j);
1106 if (j)
1107 error (ERR_NONFATAL|ERR_OFFBY1,
1108 "unable to parse parameter count `%s'",
1109 tline->text);
1110 if (defining->nparam_min > defining->nparam_max)
1111 error (ERR_NONFATAL|ERR_OFFBY1,
1112 "minimum parameter count exceeds maximum");
1115 if (tline && tline->next && tline->next->type == TOK_OTHER &&
1116 !strcmp(tline->next->text, "+")) {
1117 tline = tline->next;
1118 defining->plus = TRUE;
1120 mmac = mmacros[hash(defining->name)];
1121 while (mmac) {
1122 if (!strcmp(mmac->name, defining->name) &&
1123 (mmac->nparam_min<=defining->nparam_max || defining->plus) &&
1124 (defining->nparam_min<=mmac->nparam_max || mmac->plus)) {
1125 error (ERR_WARNING|ERR_OFFBY1,
1126 "redefining multi-line macro `%s'", defining->name);
1127 break;
1129 mmac = mmac->next;
1132 * Handle default parameters.
1134 if (tline && tline->next) {
1135 int np, want_np;
1137 defining->dlist = tline->next;
1138 tline->next = NULL;
1139 count_mmac_params (defining->dlist, &np, &defining->defaults);
1140 want_np = defining->nparam_max - defining->nparam_min;
1141 defining->defaults = nasm_realloc (defining->defaults,
1142 want_np*sizeof(Token *));
1143 while (np < want_np)
1144 defining->defaults[np++] = NULL;
1145 } else {
1146 defining->dlist = NULL;
1147 defining->defaults = NULL;
1149 defining->expansion = NULL;
1150 return 1;
1152 case PP_ENDM:
1153 case PP_ENDMACRO:
1154 if (!defining) {
1155 error (ERR_NONFATAL|ERR_OFFBY1, "`%s': not defining a macro",
1156 tline->text);
1157 return 3;
1159 k = hash(defining->name);
1160 defining->next = mmacros[k];
1161 mmacros[k] = defining;
1162 defining = NULL;
1163 return 5;
1165 case PP_DEFINE:
1166 case PP_IDEFINE:
1167 tline = tline->next;
1168 if (tline && tline->type == TOK_WHITESPACE)
1169 tline = tline->next;
1170 if (!tline || (tline->type != TOK_ID &&
1171 (tline->type != TOK_PREPROC_ID ||
1172 tline->text[1] != '$'))) {
1173 error (ERR_NONFATAL|ERR_OFFBY1,
1174 "`%%%sdefine' expects a macro identifier",
1175 (i == PP_IDEFINE ? "i" : ""));
1176 return 3;
1178 mname = tline->text;
1179 if (tline->type == TOK_ID) {
1180 p = tline->text;
1181 smhead = &smacros[hash(mname)];
1182 } else {
1183 ctx = get_ctx (tline->text);
1184 if (ctx == NULL)
1185 return 3;
1186 else {
1187 p = tline->text+1;
1188 p += strspn(p, "$");
1189 smhead = &ctx->localmac;
1192 last = tline;
1193 param_start = tline = tline->next;
1194 nparam = 0;
1195 if (tline && tline->type == TOK_OTHER && !strcmp(tline->text, "(")) {
1197 * This macro has parameters.
1200 tline = tline->next;
1201 while (1) {
1202 if (tline && tline->type == TOK_WHITESPACE)
1203 tline = tline->next;
1204 if (!tline) {
1205 error (ERR_NONFATAL|ERR_OFFBY1,
1206 "parameter identifier expected");
1207 return 3;
1209 if (tline->type != TOK_ID) {
1210 error (ERR_NONFATAL|ERR_OFFBY1,
1211 "`%s': parameter identifier expected",
1212 tline->text);
1213 return 3;
1215 tline->type = TOK_SMAC_PARAM + nparam++;
1216 tline = tline->next;
1217 if (tline && tline->type == TOK_WHITESPACE)
1218 tline = tline->next;
1219 if (tline && tline->type == TOK_OTHER &&
1220 !strcmp(tline->text, ",")) {
1221 tline = tline->next;
1222 continue;
1224 if (!tline || tline->type != TOK_OTHER ||
1225 strcmp(tline->text, ")")) {
1226 error (ERR_NONFATAL|ERR_OFFBY1,
1227 "`)' expected to terminate macro template");
1228 return 3;
1230 break;
1232 last = tline;
1233 tline = tline->next;
1235 if (tline && tline->type == TOK_WHITESPACE)
1236 last = tline, tline = tline->next;
1237 macro_start = NULL;
1238 last->next = NULL;
1239 t = tline;
1240 while (t) {
1241 if (t->type == TOK_ID) {
1242 for (tt = param_start; tt; tt = tt->next)
1243 if (tt->type >= TOK_SMAC_PARAM &&
1244 !strcmp(tt->text, t->text))
1245 t->type = tt->type;
1247 tt = t->next;
1248 t->next = macro_start;
1249 macro_start = t;
1250 t = tt;
1253 * Good. We now have a macro name, a parameter count, and a
1254 * token list (in reverse order) for an expansion. We ought
1255 * to be OK just to create an SMacro, store it, and let
1256 * tlist_free have the rest of the line (which we have
1257 * carefully re-terminated after chopping off the expansion
1258 * from the end).
1260 if (smacro_defined (mname, nparam, &smac)) {
1261 if (!smac)
1262 error (ERR_WARNING|ERR_OFFBY1,
1263 "single-line macro `%s' defined both with and"
1264 " without parameters", mname);
1265 else {
1267 * We're redefining, so we have to take over an
1268 * existing SMacro structure. This means freeing
1269 * what was already in it.
1271 nasm_free (smac->name);
1272 free_tlist (smac->expansion);
1274 } else {
1275 smac = nasm_malloc(sizeof(SMacro));
1276 smac->next = *smhead;
1277 *smhead = smac;
1279 smac->name = nasm_strdup(p);
1280 smac->casesense = (i == PP_DEFINE);
1281 smac->nparam = nparam;
1282 smac->expansion = macro_start;
1283 smac->in_progress = FALSE;
1284 return 3;
1286 case PP_LINE:
1288 * Syntax is `%line nnn[+mmm] [filename]'
1290 tline = tline->next;
1291 if (tline && tline->type == TOK_WHITESPACE)
1292 tline = tline->next;
1293 if (!tline || tline->type != TOK_NUMBER) {
1294 error (ERR_NONFATAL|ERR_OFFBY1, "`%%line' expects line number");
1295 return 3;
1297 k = readnum(tline->text, &j);
1298 m = 1;
1299 tline = tline->next;
1300 if (tline && tline->type == TOK_OTHER && !strcmp(tline->text, "+")) {
1301 tline = tline->next;
1302 if (!tline || tline->type != TOK_NUMBER) {
1303 error (ERR_NONFATAL|ERR_OFFBY1,
1304 "`%%line' expects line increment");
1305 return 3;
1307 m = readnum(tline->text, &j);
1308 tline = tline->next;
1310 if (tline && tline->type == TOK_WHITESPACE)
1311 tline = tline->next;
1312 istk->lineno = k;
1313 istk->lineinc = m;
1314 if (tline) {
1315 char *s = detoken(tline);
1316 nasm_free (istk->fname);
1317 istk->fname = s;
1319 return 5;
1321 default:
1322 error(ERR_FATAL|ERR_OFFBY1,
1323 "preprocessor directive `%s' not yet implemented",
1324 directives[k]);
1325 break;
1327 return 3;
1331 * Expand all single-line macro calls made in the given line.
1332 * Return the expanded version of the line. The original is deemed
1333 * to be destroyed in the process. (In reality we'll just move
1334 * Tokens from input to output a lot of the time, rather than
1335 * actually bothering to destroy and replicate.)
1337 static Token *expand_smacro (Token *tline) {
1338 Token *t, *tt, *mstart, **tail, *thead;
1339 SMacro *head, *m;
1340 Token **params;
1341 int *paramsize;
1342 int nparam, sparam, brackets;
1343 char *p;
1345 tail = &thead;
1346 thead = NULL;
1348 while (tline) {
1349 while (tline && tline->type != TOK_ID &&
1350 (tline->type != TOK_PREPROC_ID || tline->text[1] != '$')) {
1351 if (tline->type == TOK_SMAC_END) {
1352 tline->mac->in_progress = FALSE;
1353 t = tline;
1354 tline = tline->next;
1355 nasm_free (t);
1356 } else {
1357 t = *tail = tline;
1358 tline = tline->next;
1359 t->mac = NULL;
1360 t->next = NULL;
1361 tail = &t->next;
1362 if (t->type == TOK_PS_OTHER) {
1364 * If we see a PS_OTHER, we must at the very
1365 * least restore its correct token type. We
1366 * should also check for a %$ token, since this
1367 * is the point at which we expand context-
1368 * local labels.
1370 t->type = TOK_ID;
1371 if (t->text[0] == '%' && t->text[1] == '$') {
1372 Context *c = get_ctx (t->text);
1373 char *p, *q, buffer[40];
1375 if (c) {
1376 q = t->text+1;
1377 q += strspn(q, "$");
1378 sprintf(buffer, "macro.%lu.", c->number);
1379 p = nasm_malloc (strlen(buffer)+strlen(q)+1);
1380 strcpy (p, buffer);
1381 strcat (p, q);
1382 nasm_free (t->text);
1383 t->text = p;
1389 if (!tline)
1390 break;
1392 * We've hit an identifier. As in is_mmacro below, we first
1393 * check whether the identifier is a single-line macro at
1394 * all, then think about checking for parameters if
1395 * necessary.
1397 if (tline->type == TOK_ID) {
1398 head = smacros[hash(tline->text)];
1399 p = tline->text;
1400 } else {
1401 Context *ctx = get_ctx (tline->text);
1402 if (ctx) {
1403 p = tline->text+1;
1404 p += strspn(p, "$");
1405 head = ctx->localmac;
1406 } else {
1407 tline->type = TOK_OTHER; /* so it will get copied above */
1408 continue;
1411 for (m = head; m; m = m->next)
1412 if (!mstrcmp(m->name, p, m->casesense))
1413 break;
1414 if (!m) {
1416 * Didn't find one: this can't be a macro call. Copy it
1417 * through and ignore it.
1419 tline->type = TOK_PS_OTHER; /* so it will get copied above */
1420 continue;
1422 mstart = tline;
1423 if (m->nparam == 0) {
1425 * Simple case: the macro is parameterless. Discard the
1426 * one token that the macro call took, and push the
1427 * expansion back on the to-do stack.
1429 params = NULL;
1430 paramsize = NULL;
1431 } else {
1433 * Complicated case: at least one macro with this name
1434 * exists and takes parameters. We must find the
1435 * parameters in the call, count them, find the SMacro
1436 * that corresponds to that form of the macro call, and
1437 * substitute for the parameters when we expand. What a
1438 * pain.
1440 nparam = sparam = 0;
1441 params = NULL;
1442 paramsize = NULL;
1443 tline = tline->next;
1444 if (tline && tline->type == TOK_WHITESPACE)
1445 tline = tline->next;
1446 if (!tline || tline->type != TOK_OTHER ||
1447 strcmp(tline->text, "(")) {
1449 * This macro wasn't called with parameters: ignore
1450 * the call. (Behaviour borrowed from gnu cpp.)
1452 tline = mstart;
1453 tline->type = TOK_PS_OTHER;
1454 continue;
1456 tline = tline->next;
1457 while (1) {
1458 if (tline && tline->type == TOK_WHITESPACE)
1459 tline = tline->next;
1460 if (!tline) {
1461 error(ERR_NONFATAL|ERR_OFFBY1,
1462 "macro call expects terminating `)'");
1463 break;
1465 if (nparam >= sparam) {
1466 sparam += PARAM_DELTA;
1467 params = nasm_realloc (params, sparam*sizeof(Token *));
1468 paramsize = nasm_realloc (paramsize, sparam*sizeof(int));
1470 params[nparam] = tline;
1471 paramsize[nparam] = 0;
1472 brackets = 0;
1473 if (tline && tline->type == TOK_OTHER &&
1474 !strcmp(tline->text, "{")) {
1475 params[nparam] = tline = tline->next;
1476 while (tline && (brackets > 0 ||
1477 tline->type != TOK_OTHER ||
1478 strcmp(tline->text, "}"))) {
1479 tline = tline->next;
1480 paramsize[nparam]++;
1482 tline = tline->next;
1483 if (tline && tline->type == TOK_WHITESPACE)
1484 tline = tline->next;
1485 if (tline && (tline->type != TOK_OTHER ||
1486 (strcmp(tline->text, ")") &&
1487 strcmp(tline->text, ",")))) {
1488 error (ERR_NONFATAL|ERR_OFFBY1, "braces do not "
1489 "enclose all of macro parameter");
1491 if (tline && tline->type == TOK_OTHER &&
1492 !strcmp(tline->text, ","))
1493 tline = tline->next;
1494 } else {
1495 while (tline && (brackets > 0 ||
1496 tline->type != TOK_OTHER ||
1497 (strcmp(tline->text, ",") &&
1498 strcmp(tline->text, ")")))) {
1499 if (tline->type == TOK_OTHER && !tline->text[1])
1500 brackets += (tline->text[0] == '(' ? 1 :
1501 tline->text[0] == ')' ? -1 : 0);
1502 tline = tline->next;
1503 paramsize[nparam]++;
1506 nparam++;
1507 if (tline && !strcmp(tline->text, ")"))
1508 break;
1509 if (tline && !strcmp(tline->text, ","))
1510 tline = tline->next;
1512 while (m && m->nparam != nparam) {
1513 while ( (m = m->next) )
1514 if (!strcmp(m->name, mstart->text))
1515 break;
1517 if (!m) {
1518 error (ERR_WARNING|ERR_OFFBY1,
1519 "macro `%s' exists, but not taking %d parameters",
1520 mstart->text, nparam);
1521 nasm_free (params);
1522 nasm_free (paramsize);
1523 tline = mstart;
1524 tline->type = TOK_PS_OTHER;
1525 continue;
1527 if (m->in_progress) {
1528 error (ERR_NONFATAL, "self-reference in single-line macro"
1529 " `%s'", mstart->text);
1530 nasm_free (params);
1531 nasm_free (paramsize);
1532 tline = mstart;
1533 tline->type = TOK_PS_OTHER;
1534 continue;
1538 * Expand the macro: we are placed on the last token of the
1539 * call, so that we can easily split the call from the
1540 * following tokens. We also start by pushing an SMAC_END
1541 * token for the cycle removal.
1543 t = tline;
1544 tline = tline->next;
1545 t->next = NULL;
1546 tt = nasm_malloc(sizeof(Token));
1547 tt->type = TOK_SMAC_END;
1548 tt->text = NULL;
1549 tt->mac = m;
1550 m->in_progress = TRUE;
1551 tt->next = tline;
1552 tline = tt;
1553 for (t = m->expansion; t; t = t->next) {
1554 if (t->type >= TOK_SMAC_PARAM) {
1555 Token *pcopy = tline, **ptail = &pcopy;
1556 Token *ttt, *pt;
1557 int i;
1559 ttt = params[t->type - TOK_SMAC_PARAM];
1560 for (i=0; i<paramsize[t->type-TOK_SMAC_PARAM]; i++) {
1561 pt = *ptail = nasm_malloc(sizeof(Token));
1562 pt->next = tline;
1563 ptail = &pt->next;
1564 pt->text = nasm_strdup(ttt->text);
1565 pt->type = ttt->type;
1566 pt->mac = NULL;
1567 ttt = ttt->next;
1569 tline = pcopy;
1570 } else {
1571 tt = nasm_malloc(sizeof(Token));
1572 tt->type = t->type;
1573 tt->text = nasm_strdup(t->text);
1574 tt->mac = NULL;
1575 tt->next = tline;
1576 tline = tt;
1581 * Having done that, get rid of the macro call, and clean
1582 * up the parameters.
1584 nasm_free (params);
1585 nasm_free (paramsize);
1586 free_tlist (mstart);
1589 return thead;
1593 * Ensure that a macro parameter contains a condition code and
1594 * nothing else. Return the condition code index if so, or -1
1595 * otherwise.
1597 static int find_cc (Token *t) {
1598 Token *tt;
1599 int i, j, k, m;
1601 if (t && t->type == TOK_WHITESPACE)
1602 t = t->next;
1603 if (t->type != TOK_ID)
1604 return -1;
1605 tt = t->next;
1606 if (tt && tt->type == TOK_WHITESPACE)
1607 tt = tt->next;
1608 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
1609 return -1;
1611 i = -1;
1612 j = sizeof(conditions)/sizeof(*conditions);
1613 while (j-i > 1) {
1614 k = (j+i) / 2;
1615 m = nasm_stricmp(t->text, conditions[k]);
1616 if (m == 0) {
1617 i = k;
1618 j = -2;
1619 break;
1620 } else if (m < 0) {
1621 j = k;
1622 } else
1623 i = k;
1625 if (j != -2)
1626 return -1;
1627 return i;
1631 * Determine whether the given line constitutes a multi-line macro
1632 * call, and return the MMacro structure called if so. Doesn't have
1633 * to check for an initial label - that's taken care of in
1634 * expand_mmacro - but must check numbers of parameters. Guaranteed
1635 * to be called with tline->type == TOK_ID, so the putative macro
1636 * name is easy to find.
1638 static MMacro *is_mmacro (Token *tline, Token ***params_array) {
1639 MMacro *head, *m;
1640 Token **params;
1641 int nparam;
1643 head = mmacros[hash(tline->text)];
1646 * Efficiency: first we see if any macro exists with the given
1647 * name. If not, we can return NULL immediately. _Then_ we
1648 * count the parameters, and then we look further along the
1649 * list if necessary to find the proper MMacro.
1651 for (m = head; m; m = m->next)
1652 if (!mstrcmp(m->name, tline->text, m->casesense))
1653 break;
1654 if (!m)
1655 return NULL;
1658 * OK, we have a potential macro. Count and demarcate the
1659 * parameters.
1661 count_mmac_params (tline->next, &nparam, &params);
1664 * So we know how many parameters we've got. Find the MMacro
1665 * structure that handles this number.
1667 while (m) {
1668 if (m->nparam_min <= nparam && (m->plus || nparam <= m->nparam_max)) {
1670 * This one is right. Just check if cycle removal
1671 * prohibits us using it before we actually celebrate...
1673 if (m->in_progress) {
1674 error (ERR_NONFATAL|ERR_OFFBY1,
1675 "self-reference in multi-line macro `%s'",
1676 m->name);
1677 nasm_free (params);
1678 return NULL;
1681 * It's right, and we can use it. Add its default
1682 * parameters to the end of our list if necessary.
1684 params = nasm_realloc (params, (m->nparam_max+1)*sizeof(*params));
1685 if (m->defaults) {
1686 while (nparam < m->nparam_max) {
1687 params[nparam] = m->defaults[nparam - m->nparam_min];
1688 nparam++;
1690 } else {
1691 while (nparam < m->nparam_max) {
1692 params[nparam] = NULL;
1693 nparam++;
1697 * Then terminate the parameter list, and leave.
1699 params[m->nparam_max] = NULL;
1700 *params_array = params;
1701 return m;
1704 * This one wasn't right: look for the next one with the
1705 * same name.
1707 for (m = m->next; m; m = m->next)
1708 if (!mstrcmp(m->name, tline->text, m->casesense))
1709 break;
1713 * After all that, we didn't find one with the right number of
1714 * parameters. Issue a warning, and fail to expand the macro.
1716 error (ERR_WARNING|ERR_OFFBY1,
1717 "macro `%s' exists, but not taking %d parameters",
1718 tline->text, nparam);
1719 nasm_free (params);
1720 return NULL;
1724 * Expand the multi-line macro call made by the given line, if
1725 * there is one to be expanded. If there is, push the expansion on
1726 * istk->expansion and return 1 or 2, as according to whether a
1727 * line sync is needed (2 if it is). Otherwise return 0.
1729 static int expand_mmacro (Token *tline) {
1730 Token *label = NULL, **params, *t, *tt, *ttt, *last = NULL;
1731 MMacro *m = NULL;
1732 Line *l, *ll;
1733 int i, n, nparam, *paramlen;
1734 int need_sync = FALSE;
1736 t = tline;
1737 if (t && t->type == TOK_WHITESPACE)
1738 t = t->next;
1739 if (t && t->type == TOK_ID) {
1740 m = is_mmacro (t, &params);
1741 if (!m) {
1743 * We have an id which isn't a macro call. We'll assume
1744 * it might be a label; we'll also check to see if a
1745 * colon follows it. Then, if there's another id after
1746 * that lot, we'll check it again for macro-hood.
1748 last = t, t = t->next;
1749 if (t && t->type == TOK_WHITESPACE)
1750 last = t, t = t->next;
1751 if (t && t->type == TOK_OTHER && !strcmp(t->text, ":"))
1752 last = t, t = t->next;
1753 if (t && t->type == TOK_WHITESPACE)
1754 last = t, t = t->next;
1755 if (t && t->type == TOK_ID) {
1756 m = is_mmacro(t, &params);
1757 if (m) {
1758 last->next = NULL;
1759 label = tline;
1760 tline = t;
1765 if (!m)
1766 return 0;
1769 * If we're not already inside another macro expansion, we'd
1770 * better push a line synchronisation to ensure we stay put on
1771 * line numbering.
1773 if (!istk->expansion)
1774 need_sync = TRUE;
1777 * Fix up the parameters: this involves stripping leading and
1778 * trailing whitespace, then stripping braces if they are
1779 * present.
1781 for (nparam = 0; params[nparam]; nparam++);
1782 paramlen = nparam ? nasm_malloc(nparam*sizeof(*paramlen)) : NULL;
1784 for (i = 0; params[i]; i++) {
1785 int brace = FALSE;
1786 int comma = !m->plus;
1788 t = params[i];
1789 if (t && t->type == TOK_WHITESPACE)
1790 t = t->next;
1791 if (t && t->type == TOK_OTHER && !strcmp(t->text, "{"))
1792 t = t->next, brace = TRUE, comma = FALSE;
1793 params[i] = t;
1794 paramlen[i] = 0;
1795 while (t) {
1796 if (!t) /* end of param because EOL */
1797 break;
1798 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
1799 break; /* ... because we have hit a comma */
1800 if (comma && t->type == TOK_WHITESPACE &&
1801 t->next->type == TOK_OTHER && !strcmp(t->next->text, ","))
1802 break; /* ... or a space then a comma */
1803 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
1804 break; /* ... or a brace */
1805 t = t->next;
1806 paramlen[i]++;
1811 * OK, we have a MMacro structure together with a set of
1812 * parameters. We must now go through the expansion and push
1813 * _copies_ of each Line on to istk->expansion, having first
1814 * substituted for most % tokens (%1, %+1, %-1, %%foo). Note
1815 * that %$bar, %$$baz, %$$$quux, and so on, do not get
1816 * substituted here but rather have to wait until the
1817 * single-line macro substitution process. This is because they
1818 * don't just crop up in macro definitions, but can appear
1819 * anywhere they like.
1821 * First, push an end marker on to istk->expansion, and mark
1822 * this macro as in progress.
1824 ll = nasm_malloc(sizeof(Line));
1825 ll->next = istk->expansion;
1826 ll->finishes = m;
1827 ll->first = NULL;
1828 istk->expansion = ll;
1829 m->in_progress = TRUE;
1830 for (l = m->expansion; l; l = l->next) {
1831 Token **tail;
1833 ll = nasm_malloc(sizeof(Line));
1834 ll->next = istk->expansion;
1835 ll->finishes = NULL;
1836 tail = &ll->first;
1838 for (t = l->first; t; t = t->next) {
1839 char *text;
1840 int type = 0, cc; /* type = 0 to placate optimisers */
1841 char tmpbuf[30];
1843 if (t->type == TOK_PREPROC_ID &&
1844 (t->text[1] == '+' || t->text[1] == '-' ||
1845 t->text[1] == '%' ||
1846 (t->text[1] >= '0' && t->text[1] <= '9'))) {
1848 * We have to make a substitution of one of the
1849 * forms %1, %-1, %+1, %%foo.
1851 switch (t->text[1]) {
1852 case '%':
1853 type = TOK_ID;
1854 sprintf(tmpbuf, "macro.%lu.", unique);
1855 text = nasm_malloc(strlen(tmpbuf)+strlen(t->text+2)+1);
1856 strcpy(text, tmpbuf);
1857 strcat(text, t->text+2);
1858 break;
1859 case '-':
1860 n = atoi(t->text+2)-1;
1861 tt = params[n];
1862 cc = find_cc (tt);
1863 if (cc == -1) {
1864 error (ERR_NONFATAL|ERR_OFFBY1,
1865 "macro parameter %d is not a condition code",
1866 n+1);
1867 text = NULL;
1868 } else {
1869 type = TOK_ID;
1870 if (inverse_ccs[cc] == -1) {
1871 error (ERR_NONFATAL|ERR_OFFBY1,
1872 "condition code `%s' is not invertible",
1873 conditions[cc]);
1874 text = NULL;
1875 } else
1876 text = nasm_strdup(conditions[inverse_ccs[cc]]);
1878 break;
1879 case '+':
1880 n = atoi(t->text+2)-1;
1881 tt = params[n];
1882 cc = find_cc (tt);
1883 if (cc == -1) {
1884 error (ERR_NONFATAL|ERR_OFFBY1,
1885 "macro parameter %d is not a condition code",
1886 n+1);
1887 text = NULL;
1888 } else {
1889 type = TOK_ID;
1890 text = nasm_strdup(conditions[cc]);
1892 break;
1893 default:
1894 n = atoi(t->text+1)-1;
1895 if (n < nparam) {
1896 ttt = params[n];
1897 for (i=0; i<paramlen[n]; i++) {
1898 tt = *tail = nasm_malloc(sizeof(Token));
1899 tt->next = NULL;
1900 tail = &tt->next;
1901 tt->type = ttt->type;
1902 tt->text = nasm_strdup(ttt->text);
1903 tt->mac = NULL;
1904 ttt = ttt->next;
1907 text = NULL; /* we've done it here */
1908 break;
1910 } else {
1911 type = t->type;
1912 text = nasm_strdup(t->text);
1915 if (text) {
1916 tt = *tail = nasm_malloc(sizeof(Token));
1917 tt->next = NULL;
1918 tail = &tt->next;
1919 tt->type = type;
1920 tt->text = text;
1921 tt->mac = NULL;
1925 istk->expansion = ll;
1929 * If we had a label, push it on the front of the first line of
1930 * the macro expansion.
1932 if (label) {
1933 last->next = istk->expansion->first;
1934 istk->expansion->first = label;
1938 * Clean up.
1940 unique++;
1941 nasm_free (paramlen);
1942 nasm_free (params);
1943 free_tlist (tline);
1945 return need_sync ? 2 : 1;
1948 static void pp_reset (char *file, efunc errfunc) {
1949 int h;
1951 error = errfunc;
1952 cstk = NULL;
1953 linesync = outline = NULL;
1954 istk = nasm_malloc(sizeof(Include));
1955 istk->next = NULL;
1956 istk->conds = NULL;
1957 istk->expansion = NULL;
1958 istk->fp = fopen(file, "r");
1959 istk->fname = nasm_strdup(file);
1960 istk->lineno = istk->lineinc = 1;
1961 if (!istk->fp)
1962 error (ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'", file);
1963 defining = NULL;
1964 for (h=0; h<NHASH; h++) {
1965 mmacros[h] = NULL;
1966 smacros[h] = NULL;
1968 unique = 0;
1969 stdmacpos = stdmac;
1972 static char *pp_getline (void) {
1973 char *line;
1974 Token *tline;
1975 int ret;
1977 if (outline) {
1978 line = outline;
1979 outline = NULL;
1980 return line;
1983 while (1) {
1985 * Fetch a tokenised line, either from the macro-expansion
1986 * buffer or from the input file.
1988 tline = NULL;
1989 while (istk->expansion && istk->expansion->finishes) {
1990 Line *l = istk->expansion;
1991 tline = l->first;
1992 l->finishes->in_progress = FALSE;
1993 istk->expansion = l->next;
1994 nasm_free (l);
1995 if (!istk->expansion)
1996 line_sync();
1998 if (istk->expansion) {
1999 Line *l = istk->expansion;
2000 tline = l->first;
2001 istk->expansion = l->next;
2002 nasm_free (l);
2003 if (!istk->expansion)
2004 line_sync();
2005 } else {
2006 line = read_line();
2007 while (!line) {
2009 * The current file has ended; work down the istk
2010 * until we find a file we can read from.
2012 Include *i;
2013 fclose(istk->fp);
2014 if (istk->conds)
2015 error(ERR_FATAL, "expected `%%endif' before end of file");
2016 i = istk;
2017 istk = istk->next;
2018 nasm_free (i->fname);
2019 nasm_free (i);
2020 if (!istk)
2021 return NULL;
2022 else
2023 line_sync();
2024 line = read_line();
2026 line = prepreproc(line);
2027 tline = tokenise(line);
2028 nasm_free (line);
2032 * Check the line to see if it's a preprocessor directive.
2034 ret = do_directive(tline);
2035 if (ret & 1) {
2036 free_tlist (tline);
2037 if (ret & 4)
2038 line_sync();
2039 if ((ret & 2) && !stdmacpos) {/* give a blank line to the output */
2040 outline = nasm_strdup("");
2041 break;
2043 else
2044 continue;
2045 } else if (defining) {
2047 * We're defining a multi-line macro. We emit nothing
2048 * at all, not even a blank line (when we finish
2049 * defining the macro, we'll emit a line-number
2050 * directive so that we keep sync properly), and just
2051 * shove the tokenised line on to the macro definition.
2053 Line *l = nasm_malloc(sizeof(Line));
2054 l->next = defining->expansion;
2055 l->first = tline;
2056 l->finishes = FALSE;
2057 defining->expansion = l;
2058 continue;
2059 } else if (istk->conds && !emitting(istk->conds->state)) {
2061 * We're in a non-emitting branch of a condition block.
2062 * Emit nothing at all, not even a blank line: when we
2063 * emerge from the condition we'll give a line-number
2064 * directive so we keep our place correctly.
2066 free_tlist(tline);
2067 continue;
2068 } else {
2069 tline = expand_smacro(tline);
2070 ret = expand_mmacro(tline);
2071 if (!ret) {
2073 * De-tokenise the line again, and emit it.
2075 line = detoken(tline);
2076 free_tlist (tline);
2077 outline = line;
2078 break;
2079 } else {
2080 if (ret == 2)
2081 line_sync();
2082 continue; /* expand_mmacro calls free_tlist */
2088 * Once we're out of this loop, outline _must_ be non-NULL. The
2089 * only question is whether linesync is NULL or not.
2091 if (linesync) {
2092 line = linesync;
2093 linesync = NULL;
2094 } else {
2095 line = outline;
2096 outline = NULL;
2098 return line;
2101 static void pp_cleanup (void) {
2102 int h;
2104 if (defining) {
2105 error (ERR_NONFATAL, "end of file while still defining macro `%s'",
2106 defining->name);
2107 nasm_free (defining->name);
2108 free_tlist (defining->dlist);
2109 free_llist (defining->expansion);
2110 nasm_free (defining);
2112 nasm_free (linesync); /* might just be necessary */
2113 nasm_free (outline); /* really shouldn't be necessary */
2114 while (cstk)
2115 ctx_pop();
2116 for (h=0; h<NHASH; h++) {
2117 while (mmacros[h]) {
2118 MMacro *m = mmacros[h];
2119 mmacros[h] = mmacros[h]->next;
2120 nasm_free (m->name);
2121 free_tlist (m->dlist);
2122 free_llist (m->expansion);
2123 nasm_free (m);
2125 while (smacros[h]) {
2126 SMacro *s = smacros[h];
2127 smacros[h] = smacros[h]->next;
2128 nasm_free (s->name);
2129 free_tlist (s->expansion);
2130 nasm_free (s);
2133 while (istk) {
2134 Include *i = istk;
2135 istk = istk->next;
2136 fclose(i->fp);
2137 nasm_free (i->fname);
2138 nasm_free (i);
2140 while (cstk)
2141 ctx_pop();
2144 Preproc nasmpp = {
2145 pp_reset,
2146 pp_getline,
2147 pp_cleanup