NASM 0.95
[nasm.git] / preproc.c
blob574e852fbd5356660e772995b004633659dc0066
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;
27 typedef struct IncPath IncPath;
30 * Store the definition of a single-line macro.
32 struct SMacro {
33 SMacro *next;
34 char *name;
35 int casesense;
36 int nparam;
37 int in_progress;
38 Token *expansion;
42 * Store the definition of a multi-line macro.
44 struct MMacro {
45 MMacro *next;
46 char *name;
47 int casesense;
48 int nparam_min, nparam_max;
49 int plus; /* is the last parameter greedy? */
50 int nolist; /* is this macro listing-inhibited? */
51 int in_progress;
52 Token **defaults, *dlist;
53 Line *expansion;
57 * The context stack is composed of a linked list of these.
59 struct Context {
60 Context *next;
61 SMacro *localmac;
62 char *name;
63 unsigned long number;
67 * This is the internal form which we break input lines up into.
68 * Typically stored in linked lists.
70 * TOK_PS_OTHER is a token type used internally within
71 * expand_smacro(), to denote a token which has already been
72 * checked for being a potential macro, but may still be a context-
73 * local label.
75 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
76 * necessarily used as-is, but is intended to denote the number of
77 * the substituted parameter. So in the definition
79 * %define a(x,y) ( (x) & ~(y) )
81 * the token representing `x' will have its type changed to
82 * TOK_SMAC_PARAM, but the one representing `y' will be
83 * TOK_SMAC_PARAM+1.
85 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
86 * which doesn't need quotes around it. Used in the pre-include
87 * mechanism as an alternative to trying to find a sensible type of
88 * quote to use on the filename we were passed.
90 struct Token {
91 Token *next;
92 char *text;
93 SMacro *mac; /* associated macro for TOK_MAC_END */
94 int type;
96 enum {
97 TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING,
98 TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_PS_OTHER, TOK_SMAC_PARAM,
99 TOK_INTERNAL_STRING
103 * Multi-line macro definitions are stored as a linked list of
104 * these, which is essentially a container to allow several linked
105 * lists of Tokens.
107 * Note that in this module, linked lists are treated as stacks
108 * wherever possible. For this reason, Lines are _pushed_ on to the
109 * `expansion' field in MMacro structures, so that the linked list,
110 * if walked, would give the macro lines in reverse order; this
111 * means that we can walk the list when expanding a macro, and thus
112 * push the lines on to the `expansion' field in _istk_ in reverse
113 * order (so that when popped back off they are in the right
114 * order). It may seem cockeyed, and it relies on my design having
115 * an even number of steps in, but it works...
117 * Some of these structures, rather than being actual lines, are
118 * markers delimiting the end of the expansion of a given macro.
119 * This is for use in the cycle-tracking code. Such structures have
120 * `finishes' non-NULL, and `first' NULL. All others have
121 * `finishes' NULL, but `first' may still be NULL if the line is
122 * blank.
124 struct Line {
125 Line *next;
126 MMacro *finishes;
127 Token *first;
131 * To handle an arbitrary level of file inclusion, we maintain a
132 * stack (ie linked list) of these things.
134 struct Include {
135 Include *next;
136 FILE *fp;
137 Cond *conds;
138 Line *expansion;
139 char *fname;
140 int lineno, lineinc;
144 * Include search path. This is simply a list of strings which get
145 * prepended, in turn, to the name of an include file, in an
146 * attempt to find the file if it's not in the current directory.
148 struct IncPath {
149 IncPath *next;
150 char *path;
154 * Conditional assembly: we maintain a separate stack of these for
155 * each level of file inclusion. (The only reason we keep the
156 * stacks separate is to ensure that a stray `%endif' in a file
157 * included from within the true branch of a `%if' won't terminate
158 * it and cause confusion: instead, rightly, it'll cause an error.)
160 struct Cond {
161 Cond *next;
162 int state;
164 enum {
166 * These states are for use just after %if or %elif: IF_TRUE
167 * means the condition has evaluated to truth so we are
168 * currently emitting, whereas IF_FALSE means we are not
169 * currently emitting but will start doing so if a %else comes
170 * up. In these states, all directives are admissible: %elif,
171 * %else and %endif. (And of course %if.)
173 COND_IF_TRUE, COND_IF_FALSE,
175 * These states come up after a %else: ELSE_TRUE means we're
176 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
177 * any %elif or %else will cause an error.
179 COND_ELSE_TRUE, COND_ELSE_FALSE,
181 * This state means that we're not emitting now, and also that
182 * nothing until %endif will be emitted at all. It's for use in
183 * two circumstances: (i) when we've had our moment of emission
184 * and have now started seeing %elifs, and (ii) when the
185 * condition construct in question is contained within a
186 * non-emitting branch of a larger condition construct.
188 COND_NEVER
190 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
193 * Condition codes. Note that we use c_ prefix not C_ because C_ is
194 * used in nasm.h for the "real" condition codes. At _this_ level,
195 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
196 * ones, so we need a different enum...
198 static char *conditions[] = {
199 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
200 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
201 "np", "ns", "nz", "o", "p", "pe", "po", "s", "z"
203 enum {
204 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
205 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
206 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_S, c_Z
208 static int inverse_ccs[] = {
209 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
210 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,
211 c_Z, c_NO, c_NP, c_PO, c_PE, c_NS, c_NZ
214 static Context *cstk;
215 static Include *istk;
216 static IncPath *ipath = NULL;
218 static efunc error;
220 static unsigned long unique; /* unique identifier numbers */
222 static char *linesync, *outline;
224 static Line *predef = NULL;
226 static ListGen *list;
229 * The number of hash values we use for the macro lookup tables.
231 #define NHASH 31
234 * The current set of multi-line macros we have defined.
236 static MMacro *mmacros[NHASH];
239 * The current set of single-line macros we have defined.
241 static SMacro *smacros[NHASH];
244 * The multi-line macro we are currently defining, if any.
246 static MMacro *defining;
249 * The number of macro parameters to allocate space for at a time.
251 #define PARAM_DELTA 16
254 * The standard macro set: defined as `static char *stdmac[]'. Also
255 * gives our position in the macro set, when we're processing it.
257 #include "macros.c"
258 static char **stdmacpos;
261 * The pre-preprocessing stage... This function translates line
262 * number indications as they emerge from GNU cpp (`# lineno "file"
263 * flags') into NASM preprocessor line number indications (`%line
264 * lineno file').
266 static char *prepreproc(char *line) {
267 int lineno, fnlen;
268 char *fname, *oldline;
270 if (line[0] == '#' && line[1] == ' ') {
271 oldline = line;
272 fname = oldline+2;
273 lineno = atoi(fname);
274 fname += strspn(fname, "0123456789 ");
275 if (*fname == '"')
276 fname++;
277 fnlen = strcspn(fname, "\"");
278 line = nasm_malloc(20+fnlen);
279 sprintf(line, "%%line %d %.*s", lineno, fnlen, fname);
280 nasm_free (oldline);
282 return line;
286 * The hash function for macro lookups. Note that due to some
287 * macros having case-insensitive names, the hash function must be
288 * invariant under case changes. We implement this by applying a
289 * perfectly normal hash function to the uppercase of the string.
291 static int hash(char *s) {
293 * Powers of three, mod 31.
295 static const int multipliers[] = {
296 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10,
297 30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21
299 int h = 0;
300 int i = 0;
302 while (*s) {
303 h += multipliers[i] * (unsigned char) (toupper(*s));
304 s++;
305 if (++i >= sizeof(multipliers)/sizeof(*multipliers))
306 i = 0;
308 h %= NHASH;
309 return h;
313 * Free a linked list of tokens.
315 static void free_tlist (Token *list) {
316 Token *t;
317 while (list) {
318 t = list;
319 list = list->next;
320 nasm_free (t->text);
321 nasm_free (t);
326 * Free a linked list of lines.
328 static void free_llist (Line *list) {
329 Line *l;
330 while (list) {
331 l = list;
332 list = list->next;
333 free_tlist (l->first);
334 nasm_free (l);
339 * Pop the context stack.
341 static void ctx_pop (void) {
342 Context *c = cstk;
343 SMacro *smac, *s;
345 cstk = cstk->next;
346 smac = c->localmac;
347 while (smac) {
348 s = smac;
349 smac = smac->next;
350 nasm_free (s->name);
351 free_tlist (s->expansion);
352 nasm_free (s);
354 nasm_free (c->name);
355 nasm_free (c);
359 * Generate a line synchronisation comment, to ensure the assembler
360 * knows which source file the current output has really come from.
362 static void line_sync (void) {
363 char text[80];
364 sprintf(text, "%%line %d+%d %s",
365 (istk->expansion ? istk->lineno - istk->lineinc : istk->lineno),
366 (istk->expansion ? 0 : istk->lineinc), istk->fname);
367 if (linesync)
368 free (linesync);
369 linesync = nasm_strdup(text);
372 #define BUF_DELTA 512
374 * Read a line from the top file in istk, handling multiple CR/LFs
375 * at the end of the line read, and handling spurious ^Zs. Will
376 * return lines from the standard macro set if this has not already
377 * been done.
379 static char *read_line (void) {
380 char *buffer, *p, *q;
381 int bufsize;
383 if (stdmacpos) {
384 if (*stdmacpos) {
385 char *ret = nasm_strdup(*stdmacpos++);
387 * Nasty hack: here we push the contents of `predef' on
388 * to the top-level expansion stack, since this is the
389 * most convenient way to implement the pre-include and
390 * pre-define features.
392 if (!*stdmacpos) {
393 Line *pd, *l;
394 Token *head, **tail, *t, *tt;
396 for (pd = predef; pd; pd = pd->next) {
397 head = NULL;
398 tail = &head;
399 for (t = pd->first; t; t = t->next) {
400 tt = *tail = nasm_malloc(sizeof(Token));
401 tt->next = NULL;
402 tail = &tt->next;
403 tt->type = t->type;
404 tt->text = nasm_strdup(t->text);
405 tt->mac = t->mac; /* always NULL here, in fact */
407 l = nasm_malloc(sizeof(Line));
408 l->next = istk->expansion;
409 l->first = head;
410 l->finishes = FALSE;
411 istk->expansion = l;
414 return ret;
415 } else {
416 stdmacpos = NULL;
417 line_sync();
421 bufsize = BUF_DELTA;
422 buffer = nasm_malloc(BUF_DELTA);
423 p = buffer;
424 while (1) {
425 q = fgets(p, bufsize-(p-buffer), istk->fp);
426 if (!q)
427 break;
428 p += strlen(p);
429 if (p > buffer && p[-1] == '\n') {
430 istk->lineno += istk->lineinc;
431 break;
433 if (p-buffer > bufsize-10) {
434 bufsize += BUF_DELTA;
435 buffer = nasm_realloc(buffer, bufsize);
439 if (!q && p == buffer) {
440 nasm_free (buffer);
441 return NULL;
445 * Play safe: remove CRs as well as LFs, if any of either are
446 * present at the end of the line.
448 while (p > buffer && (p[-1] == '\n' || p[-1] == '\r'))
449 *--p = '\0';
452 * Handle spurious ^Z, which may be inserted into source files
453 * by some file transfer utilities.
455 buffer[strcspn(buffer, "\032")] = '\0';
457 list->line (LIST_READ, buffer);
459 return buffer;
463 * Tokenise a line of text. This is a very simple process since we
464 * don't need to parse the value out of e.g. numeric tokens: we
465 * simply split one string into many.
467 static Token *tokenise (char *line) {
468 char *p = line;
469 int type;
470 Token *list = NULL;
471 Token *t, **tail = &list;
473 while (*line) {
474 p = line;
475 if (*p == '%' &&
476 (p[1] == '{' || p[1] == '!' || (p[1] == '%' && isidchar(p[2])) ||
477 p[1] == '$' || p[1] == '+' || p[1] == '-' || isidchar(p[1]))) {
478 type = TOK_PREPROC_ID;
479 p++;
480 if (*p == '{') {
481 p++;
482 while (*p && *p != '}') {
483 p[-1] = *p;
484 p++;
486 p[-1] = '\0';
487 if (*p) p++;
488 } else {
489 if (*p == '!' || *p == '%' || *p == '$' ||
490 *p == '+' || *p == '-') p++;
491 while (*p && isidchar(*p))
492 p++;
494 } else if (isidstart(*p)) {
495 type = TOK_ID;
496 p++;
497 while (*p && isidchar(*p))
498 p++;
499 } else if (*p == '\'' || *p == '"') {
501 * A string token.
503 char c = *p;
504 p++;
505 type = TOK_STRING;
506 while (*p && *p != c)
507 p++;
508 if (*p) p++;
509 } else if (isnumstart(*p)) {
511 * A number token.
513 type = TOK_NUMBER;
514 p++;
515 while (*p && isnumchar(*p))
516 p++;
517 } else if (isspace(*p)) {
518 type = TOK_WHITESPACE;
519 p++;
520 while (*p && isspace(*p))
521 p++;
523 * Whitespace just before end-of-line is discarded by
524 * pretending it's a comment; whitespace just before a
525 * comment gets lumped into the comment.
527 if (!*p || *p == ';') {
528 type = TOK_COMMENT;
529 while (*p) p++;
531 } else if (*p == ';') {
532 type = TOK_COMMENT;
533 while (*p) p++;
534 } else {
536 * Anything else is an operator of some kind; with the
537 * exceptions of >>, <<, // and %%, all operator tokens
538 * are single-character.
540 char c = *p++;
541 type = TOK_OTHER;
542 if ( (c == '>' || c == '<' || c == '/' || c == '%') && *p == c)
543 p++;
545 if (type != TOK_COMMENT) {
546 *tail = t = nasm_malloc (sizeof(Token));
547 tail = &t->next;
548 t->next = NULL;
549 t->type = type;
550 t->text = nasm_malloc(1+p-line);
551 strncpy(t->text, line, p-line);
552 t->text[p-line] = '\0';
554 line = p;
557 return list;
561 * Convert a line of tokens back into text.
563 static char *detoken (Token *tlist) {
564 Token *t;
565 int len;
566 char *line, *p;
568 len = 0;
569 for (t = tlist; t; t = t->next) {
570 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
571 char *p = getenv(t->text+2);
572 nasm_free (t->text);
573 if (p)
574 t->text = nasm_strdup(p);
575 else
576 t->text = NULL;
578 if (t->text)
579 len += strlen(t->text);
581 p = line = nasm_malloc(len+1);
582 for (t = tlist; t; t = t->next) {
583 if (t->text) {
584 strcpy (p, t->text);
585 p += strlen(p);
588 *p = '\0';
589 return line;
593 * Return the Context structure associated with a %$ token. Return
594 * NULL, having _already_ reported an error condition, if the
595 * context stack isn't deep enough for the supplied number of $
596 * signs.
598 static Context *get_ctx (char *name) {
599 Context *ctx;
600 int i;
602 if (!cstk) {
603 error (ERR_NONFATAL|ERR_OFFBY1, "`%s': context stack is empty", name);
604 return NULL;
607 i = 1;
608 ctx = cstk;
609 while (name[i+1] == '$') {
610 i++;
611 ctx = ctx->next;
612 if (!ctx) {
613 error (ERR_NONFATAL|ERR_OFFBY1, "`%s': context stack is only"
614 " %d level%s deep", name, i-1, (i==2 ? "" : "s"));
615 return NULL;
618 return ctx;
622 * Compare a string to the name of an existing macro; this is a
623 * simple wrapper which calls either strcmp or nasm_stricmp
624 * depending on the value of the `casesense' parameter.
626 static int mstrcmp(char *p, char *q, int casesense) {
627 return casesense ? strcmp(p,q) : nasm_stricmp(p,q);
631 * Open an include file. This routine must always return a valid
632 * file pointer if it returns - it's responsible for throwing an
633 * ERR_FATAL and bombing out completely if not. It should also try
634 * the include path one by one until it finds the file or reaches
635 * the end of the path.
637 static FILE *inc_fopen(char *file) {
638 FILE *fp;
639 char *prefix = "", *combine;
640 IncPath *ip = ipath;
641 int len = strlen(file);
643 do {
644 combine = nasm_malloc(strlen(prefix)+len+1);
645 strcpy(combine, prefix);
646 strcat(combine, file);
647 fp = fopen(combine, "r");
648 nasm_free (combine);
649 if (fp)
650 return fp;
651 prefix = ip ? ip->path : NULL;
652 if (ip)
653 ip = ip->next;
654 } while (prefix);
656 error (ERR_FATAL|ERR_OFFBY1,
657 "unable to open include file `%s'", file);
658 return NULL; /* never reached - placate compilers */
662 * Determine if we should warn on defining a single-line macro of
663 * name `name', with `nparam' parameters. If nparam is 0, will
664 * return TRUE if _any_ single-line macro of that name is defined.
665 * Otherwise, will return TRUE if a single-line macro with either
666 * `nparam' or no parameters is defined.
668 * If a macro with precisely the right number of parameters is
669 * defined, the address of the definition structure will be
670 * returned in `defn'; otherwise NULL will be returned. If `defn'
671 * is NULL, no action will be taken regarding its contents, and no
672 * error will occur.
674 * Note that this is also called with nparam zero to resolve
675 * `ifdef'.
677 static int smacro_defined (char *name, int nparam, SMacro **defn) {
678 SMacro *m;
679 Context *ctx;
680 char *p;
682 if (name[0] == '%' && name[1] == '$') {
683 ctx = get_ctx (name);
684 if (!ctx)
685 return FALSE; /* got to return _something_ */
686 m = ctx->localmac;
687 p = name+1;
688 p += strspn(p, "$");
689 } else {
690 m = smacros[hash(name)];
691 p = name;
694 while (m) {
695 if (!mstrcmp(m->name, p, m->casesense) &&
696 (nparam == 0 || m->nparam == 0 || nparam == m->nparam)) {
697 if (defn) {
698 if (nparam == m->nparam)
699 *defn = m;
700 else
701 *defn = NULL;
703 return TRUE;
705 m = m->next;
707 return FALSE;
711 * Count and mark off the parameters in a multi-line macro call.
712 * This is called both from within the multi-line macro expansion
713 * code, and also to mark off the default parameters when provided
714 * in a %macro definition line.
716 static void count_mmac_params (Token *t, int *nparam, Token ***params) {
717 int paramsize, brace;
719 *nparam = paramsize = 0;
720 *params = NULL;
721 while (t) {
722 if (*nparam >= paramsize) {
723 paramsize += PARAM_DELTA;
724 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
726 if (t && t->type == TOK_WHITESPACE)
727 t = t->next;
728 brace = FALSE;
729 if (t && t->type == TOK_OTHER && !strcmp(t->text, "{"))
730 brace = TRUE;
731 (*params)[(*nparam)++] = t;
732 while (t && (t->type != TOK_OTHER ||
733 strcmp(t->text, brace ? "}" : ",")))
734 t = t->next;
735 if (t) { /* got a comma/brace */
736 t = t->next;
737 if (brace) {
739 * Now we've found the closing brace, look further
740 * for the comma.
742 if (t && t->type == TOK_WHITESPACE)
743 t = t->next;
744 if (t && (t->type != TOK_OTHER || strcmp(t->text, ","))) {
745 error (ERR_NONFATAL|ERR_OFFBY1,
746 "braces do not enclose all of macro parameter");
747 while (t && (t->type != TOK_OTHER ||
748 strcmp(t->text, ",")))
749 t = t->next;
751 if (t)
752 t = t->next; /* eat the comma */
755 else /* got EOL */
756 break;
761 * Find out if a line contains a preprocessor directive, and deal
762 * with it if so.
764 * If a directive _is_ found, the line will never be de-tokenised
765 * as is, so we have carte blanche to fiddle with it and adjust
766 * token values.
768 * Return values go like this:
770 * bit 0 is set if a directive was found
771 * bit 1 is set if a blank line should be emitted
772 * bit 2 is set if a re-sync line number comment should be emitted
774 * (bits 1 and 2 are mutually exclusive in that the rest of the
775 * preprocessor doesn't guarantee to be able to handle the case in
776 * which both are set)
778 static int do_directive (Token *tline) {
779 static char *directives[] = {
780 "%clear", "%define", "%elifctx", "%elifdef", "%elifnctx",
781 "%elifndef", "%else", "%endif", "%endm", "%endmacro", "%error",
782 "%idefine", "%ifctx", "%ifdef", "%ifnctx", "%ifndef", "%imacro",
783 "%include", "%line", "%macro", "%pop", "%push", "%repl"
785 enum {
786 PP_CLEAR, PP_DEFINE, PP_ELIFCTX, PP_ELIFDEF, PP_ELIFNCTX,
787 PP_ELIFNDEF, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO, PP_ERROR,
788 PP_IDEFINE, PP_IFCTX, PP_IFDEF, PP_IFNCTX, PP_IFNDEF, PP_IMACRO,
789 PP_INCLUDE, PP_LINE, PP_MACRO, PP_POP, PP_PUSH, PP_REPL
791 int i, j, k, m, nparam;
792 char *p, *mname;
793 Include *inc;
794 Context *ctx;
795 Cond *cond;
796 SMacro *smac, **smhead;
797 MMacro *mmac;
798 Token *t, *tt, *param_start, *macro_start, *last;
800 if (tline && tline->type == TOK_WHITESPACE)
801 tline = tline->next;
802 if (!tline || tline->type != TOK_PREPROC_ID ||
803 (tline->text[1]=='%' || tline->text[1]=='$' || tline->text[1]=='!'))
804 return 0;
806 i = -1;
807 j = sizeof(directives)/sizeof(*directives);
808 while (j-i > 1) {
809 k = (j+i) / 2;
810 m = nasm_stricmp(tline->text, directives[k]);
811 if (m == 0) {
812 i = k;
813 j = -2;
814 break;
815 } else if (m < 0) {
816 j = k;
817 } else
818 i = k;
822 * If we're in a non-emitting branch of a condition construct,
823 * we should ignore all directives except for condition
824 * directives.
826 if (istk->conds && !emitting(istk->conds->state) &&
827 i != PP_IFCTX && i != PP_IFDEF && i != PP_IFNCTX && i != PP_IFNDEF &&
828 i!=PP_ELIFCTX && i!=PP_ELIFDEF && i!=PP_ELIFNCTX && i!=PP_ELIFNDEF &&
829 i != PP_ELSE && i != PP_ENDIF)
830 return 0;
833 * If we're defining a macro, we should ignore all directives
834 * except for %macro/%imacro (which generate an error) and
835 * %endm/%endmacro.
837 if (defining && i != PP_MACRO && i != PP_IMACRO &&
838 i != PP_ENDMACRO && i != PP_ENDM)
839 return 0;
841 if (j != -2) {
842 error(ERR_NONFATAL|ERR_OFFBY1, "unknown preprocessor directive `%s'",
843 tline->text);
844 return 0; /* didn't get it */
847 switch (i) {
849 case PP_CLEAR:
850 if (tline->next)
851 error(ERR_WARNING|ERR_OFFBY1,
852 "trailing garbage after `%%clear' ignored");
853 for (j=0; j<NHASH; j++) {
854 while (mmacros[j]) {
855 MMacro *m = mmacros[j];
856 mmacros[j] = mmacros[j]->next;
857 nasm_free (m->name);
858 free_tlist (m->dlist);
859 free_llist (m->expansion);
860 nasm_free (m);
862 while (smacros[j]) {
863 SMacro *s = smacros[j];
864 smacros[j] = smacros[j]->next;
865 nasm_free (s->name);
866 free_tlist (s->expansion);
867 nasm_free (s);
870 return 3;
872 case PP_INCLUDE:
873 tline = tline->next;
874 if (tline && tline->type == TOK_WHITESPACE)
875 tline = tline->next;
876 if (!tline || (tline->type != TOK_STRING &&
877 tline->type != TOK_INTERNAL_STRING)) {
878 error(ERR_NONFATAL|ERR_OFFBY1, "`%%include' expects a file name");
879 return 3; /* but we did _something_ */
881 if (tline->next)
882 error(ERR_WARNING|ERR_OFFBY1,
883 "trailing garbage after `%%include' ignored");
884 if (tline->type != TOK_INTERNAL_STRING) {
885 p = tline->text+1; /* point past the quote to the name */
886 p[strlen(p)-1] = '\0'; /* remove the trailing quote */
887 } else
888 p = tline->text; /* internal_string is easier */
889 inc = nasm_malloc(sizeof(Include));
890 inc->next = istk;
891 inc->conds = NULL;
892 inc->fp = inc_fopen(p);
893 inc->fname = nasm_strdup(p);
894 inc->lineno = inc->lineinc = 1;
895 inc->expansion = NULL;
896 istk = inc;
897 list->uplevel (LIST_INCLUDE);
898 return 5;
900 case PP_PUSH:
901 tline = tline->next;
902 if (tline && tline->type == TOK_WHITESPACE)
903 tline = tline->next;
904 if (!tline || tline->type != TOK_ID) {
905 error(ERR_NONFATAL|ERR_OFFBY1,
906 "`%%push' expects a context identifier");
907 return 3; /* but we did _something_ */
909 if (tline->next)
910 error(ERR_WARNING|ERR_OFFBY1,
911 "trailing garbage after `%%push' ignored");
912 ctx = nasm_malloc(sizeof(Context));
913 ctx->next = cstk;
914 ctx->localmac = NULL;
915 ctx->name = nasm_strdup(tline->text);
916 ctx->number = unique++;
917 cstk = ctx;
918 break;
920 case PP_REPL:
921 tline = tline->next;
922 if (tline && tline->type == TOK_WHITESPACE)
923 tline = tline->next;
924 if (!tline || tline->type != TOK_ID) {
925 error(ERR_NONFATAL|ERR_OFFBY1,
926 "`%%repl' expects a context identifier");
927 return 3; /* but we did _something_ */
929 if (tline->next)
930 error(ERR_WARNING|ERR_OFFBY1,
931 "trailing garbage after `%%repl' ignored");
932 if (!cstk)
933 error(ERR_NONFATAL|ERR_OFFBY1,
934 "`%%repl': context stack is empty");
935 else {
936 nasm_free (cstk->name);
937 cstk->name = nasm_strdup(tline->text);
939 break;
941 case PP_POP:
942 if (tline->next)
943 error(ERR_WARNING|ERR_OFFBY1,
944 "trailing garbage after `%%pop' ignored");
945 if (!cstk)
946 error(ERR_NONFATAL|ERR_OFFBY1,
947 "`%%pop': context stack is already empty");
948 else
949 ctx_pop();
950 break;
952 case PP_ERROR:
953 tline = tline->next;
954 if (tline && tline->type == TOK_WHITESPACE)
955 tline = tline->next;
956 if (!tline || tline->type != TOK_STRING) {
957 error(ERR_NONFATAL|ERR_OFFBY1,
958 "`%%error' expects an error string");
959 return 3; /* but we did _something_ */
961 if (tline->next)
962 error(ERR_WARNING|ERR_OFFBY1,
963 "trailing garbage after `%%error' ignored");
964 p = tline->text+1; /* point past the quote to the name */
965 p[strlen(p)-1] = '\0'; /* remove the trailing quote */
966 error(ERR_NONFATAL|ERR_OFFBY1, "user error: %s", p);
967 break;
969 case PP_IFCTX:
970 case PP_IFNCTX:
971 tline = tline->next;
972 if (istk->conds && !emitting(istk->conds->state))
973 j = COND_NEVER;
974 else {
975 j = FALSE; /* have we matched yet? */
976 if (!cstk)
977 error(ERR_FATAL|ERR_OFFBY1,
978 "`%%if%sctx': context stack is empty",
979 (i==PP_IFNCTX ? "n" : ""));
980 else while (tline) {
981 if (tline->type == TOK_WHITESPACE)
982 tline = tline->next;
983 if (!tline || tline->type != TOK_ID) {
984 error(ERR_NONFATAL|ERR_OFFBY1,
985 "`%%ifctx' expects context identifiers");
986 return 3; /* but we did _something_ */
988 if (!nasm_stricmp(tline->text, cstk->name))
989 j = TRUE;
990 tline = tline->next;
992 if (i == PP_IFNCTX)
993 j = !j;
994 j = (j ? COND_IF_TRUE : COND_IF_FALSE);
996 cond = nasm_malloc(sizeof(Cond));
997 cond->next = istk->conds;
998 cond->state = j;
999 istk->conds = cond;
1000 return 1;
1002 case PP_ELIFCTX:
1003 case PP_ELIFNCTX:
1004 tline = tline->next;
1005 if (!istk->conds)
1006 error(ERR_FATAL|ERR_OFFBY1, "`%%elif%sctx': no matching `%%if'",
1007 (i==PP_ELIFNCTX ? "n" : ""));
1008 if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
1009 istk->conds->state = COND_NEVER;
1010 else {
1011 j = FALSE; /* have we matched yet? */
1012 if (!cstk)
1013 error(ERR_FATAL|ERR_OFFBY1,
1014 "`%%elif%sctx': context stack is empty",
1015 (i==PP_ELIFNCTX ? "n" : ""));
1016 else while (tline) {
1017 if (tline->type == TOK_WHITESPACE)
1018 tline = tline->next;
1019 if (!tline || tline->type != TOK_ID) {
1020 error(ERR_NONFATAL|ERR_OFFBY1,
1021 "`%%elif%sctx' expects context identifiers",
1022 (i==PP_ELIFNCTX ? "n" : ""));
1023 return 3; /* but we did _something_ */
1025 if (!nasm_stricmp(tline->text, cstk->name))
1026 j = TRUE;
1027 tline = tline->next;
1029 if (i == PP_ELIFNCTX)
1030 j = !j;
1031 istk->conds->state = (j ? COND_IF_TRUE : COND_IF_FALSE);
1033 return 1;
1035 case PP_IFDEF:
1036 case PP_IFNDEF:
1037 tline = tline->next;
1038 if (istk->conds && !emitting(istk->conds->state))
1039 j = COND_NEVER;
1040 else {
1041 j = FALSE; /* have we matched yet? */
1042 while (tline) {
1043 if (tline->type == TOK_WHITESPACE)
1044 tline = tline->next;
1045 if (!tline || (tline->type != TOK_ID &&
1046 (tline->type != TOK_PREPROC_ID ||
1047 tline->text[1] != '$'))) {
1048 error(ERR_NONFATAL|ERR_OFFBY1,
1049 "`%%if%sdef' expects macro identifiers",
1050 (i==PP_ELIFNDEF ? "n" : ""));
1051 return 3; /* but we did _something_ */
1053 if (smacro_defined(tline->text, 0, NULL))
1054 j = TRUE;
1055 tline = tline->next;
1057 if (i == PP_IFNDEF)
1058 j = !j;
1059 j = (j ? COND_IF_TRUE : COND_IF_FALSE);
1061 cond = nasm_malloc(sizeof(Cond));
1062 cond->next = istk->conds;
1063 cond->state = j;
1064 istk->conds = cond;
1065 return 1;
1067 case PP_ELIFDEF:
1068 case PP_ELIFNDEF:
1069 tline = tline->next;
1070 if (!istk->conds)
1071 error(ERR_FATAL|ERR_OFFBY1, "`%%elif%sctx': no matching `%%if'",
1072 (i==PP_ELIFNCTX ? "n" : ""));
1073 if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
1074 istk->conds->state = COND_NEVER;
1075 else {
1076 j = FALSE; /* have we matched yet? */
1077 while (tline) {
1078 if (tline->type == TOK_WHITESPACE)
1079 tline = tline->next;
1080 if (!tline || (tline->type != TOK_ID &&
1081 (tline->type != TOK_PREPROC_ID ||
1082 tline->text[1] != '$'))) {
1083 error(ERR_NONFATAL|ERR_OFFBY1,
1084 "`%%elif%sdef' expects macro identifiers",
1085 (i==PP_ELIFNDEF ? "n" : ""));
1086 return 3; /* but we did _something_ */
1088 if (smacro_defined(tline->text, 0, NULL))
1089 j = TRUE;
1090 tline = tline->next;
1092 if (i == PP_ELIFNDEF)
1093 j = !j;
1094 istk->conds->state = (j ? COND_IF_TRUE : COND_IF_FALSE);
1096 return 1;
1098 case PP_ELSE:
1099 if (tline->next)
1100 error(ERR_WARNING|ERR_OFFBY1,
1101 "trailing garbage after `%%else' ignored");
1102 if (!istk->conds)
1103 error(ERR_FATAL|ERR_OFFBY1,
1104 "`%%else': no matching `%%if'");
1105 if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
1106 istk->conds->state = COND_ELSE_FALSE;
1107 else
1108 istk->conds->state = COND_ELSE_TRUE;
1109 return 1;
1111 case PP_ENDIF:
1112 if (tline->next)
1113 error(ERR_WARNING|ERR_OFFBY1,
1114 "trailing garbage after `%%endif' ignored");
1115 if (!istk->conds)
1116 error(ERR_FATAL|ERR_OFFBY1,
1117 "`%%endif': no matching `%%if'");
1118 cond = istk->conds;
1119 istk->conds = cond->next;
1120 nasm_free (cond);
1121 return 5;
1123 case PP_MACRO:
1124 case PP_IMACRO:
1125 if (defining)
1126 error (ERR_FATAL|ERR_OFFBY1,
1127 "`%%%smacro': already defining a macro",
1128 (i == PP_IMACRO ? "i" : ""));
1129 tline = tline->next;
1130 if (tline && tline->type == TOK_WHITESPACE)
1131 tline = tline->next;
1132 if (!tline || tline->type != TOK_ID) {
1133 error (ERR_NONFATAL|ERR_OFFBY1,
1134 "`%%%smacro' expects a macro name",
1135 (i == PP_IMACRO ? "i" : ""));
1136 return 3;
1138 defining = nasm_malloc(sizeof(MMacro));
1139 defining->name = nasm_strdup(tline->text);
1140 defining->casesense = (i == PP_MACRO);
1141 defining->plus = FALSE;
1142 defining->nolist = FALSE;
1143 defining->in_progress = FALSE;
1144 tline = tline->next;
1145 if (tline && tline->type == TOK_WHITESPACE)
1146 tline = tline->next;
1147 if (!tline || tline->type != TOK_NUMBER) {
1148 error (ERR_NONFATAL|ERR_OFFBY1,
1149 "`%%%smacro' expects a parameter count",
1150 (i == PP_IMACRO ? "i" : ""));
1151 defining->nparam_min = defining->nparam_max = 0;
1152 } else {
1153 defining->nparam_min = defining->nparam_max =
1154 readnum(tline->text, &j);
1155 if (j)
1156 error (ERR_NONFATAL|ERR_OFFBY1,
1157 "unable to parse parameter count `%s'", tline->text);
1159 if (tline && tline->next && tline->next->type == TOK_OTHER &&
1160 !strcmp(tline->next->text, "-")) {
1161 tline = tline->next->next;
1162 if (!tline || tline->type != TOK_NUMBER)
1163 error (ERR_NONFATAL|ERR_OFFBY1,
1164 "`%%%smacro' expects a parameter count after `-'",
1165 (i == PP_IMACRO ? "i" : ""));
1166 else {
1167 defining->nparam_max = readnum(tline->text, &j);
1168 if (j)
1169 error (ERR_NONFATAL|ERR_OFFBY1,
1170 "unable to parse parameter count `%s'",
1171 tline->text);
1172 if (defining->nparam_min > defining->nparam_max)
1173 error (ERR_NONFATAL|ERR_OFFBY1,
1174 "minimum parameter count exceeds maximum");
1177 if (tline && tline->next && tline->next->type == TOK_OTHER &&
1178 !strcmp(tline->next->text, "+")) {
1179 tline = tline->next;
1180 defining->plus = TRUE;
1182 if (tline && tline->next && tline->next->type == TOK_ID &&
1183 !nasm_stricmp(tline->next->text, ".nolist")) {
1184 tline = tline->next;
1185 defining->nolist = TRUE;
1187 mmac = mmacros[hash(defining->name)];
1188 while (mmac) {
1189 if (!strcmp(mmac->name, defining->name) &&
1190 (mmac->nparam_min<=defining->nparam_max || defining->plus) &&
1191 (defining->nparam_min<=mmac->nparam_max || mmac->plus)) {
1192 error (ERR_WARNING|ERR_OFFBY1,
1193 "redefining multi-line macro `%s'", defining->name);
1194 break;
1196 mmac = mmac->next;
1199 * Handle default parameters.
1201 if (tline && tline->next) {
1202 int np, want_np;
1204 defining->dlist = tline->next;
1205 tline->next = NULL;
1206 count_mmac_params (defining->dlist, &np, &defining->defaults);
1207 want_np = defining->nparam_max - defining->nparam_min;
1208 defining->defaults = nasm_realloc (defining->defaults,
1209 want_np*sizeof(Token *));
1210 while (np < want_np)
1211 defining->defaults[np++] = NULL;
1212 } else {
1213 defining->dlist = NULL;
1214 defining->defaults = NULL;
1216 defining->expansion = NULL;
1217 return 1;
1219 case PP_ENDM:
1220 case PP_ENDMACRO:
1221 if (!defining) {
1222 error (ERR_NONFATAL|ERR_OFFBY1, "`%s': not defining a macro",
1223 tline->text);
1224 return 3;
1226 k = hash(defining->name);
1227 defining->next = mmacros[k];
1228 mmacros[k] = defining;
1229 defining = NULL;
1230 return 5;
1232 case PP_DEFINE:
1233 case PP_IDEFINE:
1234 tline = tline->next;
1235 if (tline && tline->type == TOK_WHITESPACE)
1236 tline = tline->next;
1237 if (!tline || (tline->type != TOK_ID &&
1238 (tline->type != TOK_PREPROC_ID ||
1239 tline->text[1] != '$'))) {
1240 error (ERR_NONFATAL|ERR_OFFBY1,
1241 "`%%%sdefine' expects a macro identifier",
1242 (i == PP_IDEFINE ? "i" : ""));
1243 return 3;
1245 mname = tline->text;
1246 if (tline->type == TOK_ID) {
1247 p = tline->text;
1248 smhead = &smacros[hash(mname)];
1249 } else {
1250 ctx = get_ctx (tline->text);
1251 if (ctx == NULL)
1252 return 3;
1253 else {
1254 p = tline->text+1;
1255 p += strspn(p, "$");
1256 smhead = &ctx->localmac;
1259 last = tline;
1260 param_start = tline = tline->next;
1261 nparam = 0;
1262 if (tline && tline->type == TOK_OTHER && !strcmp(tline->text, "(")) {
1264 * This macro has parameters.
1267 tline = tline->next;
1268 while (1) {
1269 if (tline && tline->type == TOK_WHITESPACE)
1270 tline = tline->next;
1271 if (!tline) {
1272 error (ERR_NONFATAL|ERR_OFFBY1,
1273 "parameter identifier expected");
1274 return 3;
1276 if (tline->type != TOK_ID) {
1277 error (ERR_NONFATAL|ERR_OFFBY1,
1278 "`%s': parameter identifier expected",
1279 tline->text);
1280 return 3;
1282 tline->type = TOK_SMAC_PARAM + nparam++;
1283 tline = tline->next;
1284 if (tline && tline->type == TOK_WHITESPACE)
1285 tline = tline->next;
1286 if (tline && tline->type == TOK_OTHER &&
1287 !strcmp(tline->text, ",")) {
1288 tline = tline->next;
1289 continue;
1291 if (!tline || tline->type != TOK_OTHER ||
1292 strcmp(tline->text, ")")) {
1293 error (ERR_NONFATAL|ERR_OFFBY1,
1294 "`)' expected to terminate macro template");
1295 return 3;
1297 break;
1299 last = tline;
1300 tline = tline->next;
1302 if (tline && tline->type == TOK_WHITESPACE)
1303 last = tline, tline = tline->next;
1304 macro_start = NULL;
1305 last->next = NULL;
1306 t = tline;
1307 while (t) {
1308 if (t->type == TOK_ID) {
1309 for (tt = param_start; tt; tt = tt->next)
1310 if (tt->type >= TOK_SMAC_PARAM &&
1311 !strcmp(tt->text, t->text))
1312 t->type = tt->type;
1314 tt = t->next;
1315 t->next = macro_start;
1316 macro_start = t;
1317 t = tt;
1320 * Good. We now have a macro name, a parameter count, and a
1321 * token list (in reverse order) for an expansion. We ought
1322 * to be OK just to create an SMacro, store it, and let
1323 * free_tlist have the rest of the line (which we have
1324 * carefully re-terminated after chopping off the expansion
1325 * from the end).
1327 if (smacro_defined (mname, nparam, &smac)) {
1328 if (!smac)
1329 error (ERR_WARNING|ERR_OFFBY1,
1330 "single-line macro `%s' defined both with and"
1331 " without parameters", mname);
1332 else {
1334 * We're redefining, so we have to take over an
1335 * existing SMacro structure. This means freeing
1336 * what was already in it.
1338 nasm_free (smac->name);
1339 free_tlist (smac->expansion);
1341 } else {
1342 smac = nasm_malloc(sizeof(SMacro));
1343 smac->next = *smhead;
1344 *smhead = smac;
1346 smac->name = nasm_strdup(p);
1347 smac->casesense = (i == PP_DEFINE);
1348 smac->nparam = nparam;
1349 smac->expansion = macro_start;
1350 smac->in_progress = FALSE;
1351 return 3;
1353 case PP_LINE:
1355 * Syntax is `%line nnn[+mmm] [filename]'
1357 tline = tline->next;
1358 if (tline && tline->type == TOK_WHITESPACE)
1359 tline = tline->next;
1360 if (!tline || tline->type != TOK_NUMBER) {
1361 error (ERR_NONFATAL|ERR_OFFBY1, "`%%line' expects line number");
1362 return 3;
1364 k = readnum(tline->text, &j);
1365 m = 1;
1366 tline = tline->next;
1367 if (tline && tline->type == TOK_OTHER && !strcmp(tline->text, "+")) {
1368 tline = tline->next;
1369 if (!tline || tline->type != TOK_NUMBER) {
1370 error (ERR_NONFATAL|ERR_OFFBY1,
1371 "`%%line' expects line increment");
1372 return 3;
1374 m = readnum(tline->text, &j);
1375 tline = tline->next;
1377 if (tline && tline->type == TOK_WHITESPACE)
1378 tline = tline->next;
1379 istk->lineno = k;
1380 istk->lineinc = m;
1381 if (tline) {
1382 char *s = detoken(tline);
1383 nasm_free (istk->fname);
1384 istk->fname = s;
1386 return 5;
1388 default:
1389 error(ERR_FATAL|ERR_OFFBY1,
1390 "preprocessor directive `%s' not yet implemented",
1391 directives[k]);
1392 break;
1394 return 3;
1398 * Expand all single-line macro calls made in the given line.
1399 * Return the expanded version of the line. The original is deemed
1400 * to be destroyed in the process. (In reality we'll just move
1401 * Tokens from input to output a lot of the time, rather than
1402 * actually bothering to destroy and replicate.)
1404 static Token *expand_smacro (Token *tline) {
1405 Token *t, *tt, *mstart, **tail, *thead;
1406 SMacro *head, *m;
1407 Token **params;
1408 int *paramsize;
1409 int nparam, sparam, brackets;
1410 char *p;
1412 tail = &thead;
1413 thead = NULL;
1415 while (tline) {
1416 while (tline && tline->type != TOK_ID &&
1417 (tline->type != TOK_PREPROC_ID || tline->text[1] != '$')) {
1418 if (tline->type == TOK_SMAC_END) {
1419 tline->mac->in_progress = FALSE;
1420 t = tline;
1421 tline = tline->next;
1422 nasm_free (t);
1423 } else {
1424 t = *tail = tline;
1425 tline = tline->next;
1426 t->mac = NULL;
1427 t->next = NULL;
1428 tail = &t->next;
1429 if (t->type == TOK_PS_OTHER) {
1431 * If we see a PS_OTHER, we must at the very
1432 * least restore its correct token type. We
1433 * should also check for a %$ token, since this
1434 * is the point at which we expand context-
1435 * local labels.
1437 t->type = TOK_ID;
1438 if (t->text[0] == '%' && t->text[1] == '$') {
1439 Context *c = get_ctx (t->text);
1440 char *p, *q, buffer[40];
1442 if (c) {
1443 q = t->text+1;
1444 q += strspn(q, "$");
1445 sprintf(buffer, "..@%lu.", c->number);
1446 p = nasm_malloc (strlen(buffer)+strlen(q)+1);
1447 strcpy (p, buffer);
1448 strcat (p, q);
1449 nasm_free (t->text);
1450 t->text = p;
1456 if (!tline)
1457 break;
1459 * We've hit an identifier. As in is_mmacro below, we first
1460 * check whether the identifier is a single-line macro at
1461 * all, then think about checking for parameters if
1462 * necessary.
1464 if (tline->type == TOK_ID) {
1465 head = smacros[hash(tline->text)];
1466 p = tline->text;
1467 } else {
1468 Context *ctx = get_ctx (tline->text);
1469 if (ctx) {
1470 p = tline->text+1;
1471 p += strspn(p, "$");
1472 head = ctx->localmac;
1473 } else {
1474 tline->type = TOK_OTHER; /* so it will get copied above */
1475 continue;
1478 for (m = head; m; m = m->next)
1479 if (!mstrcmp(m->name, p, m->casesense))
1480 break;
1481 if (!m || m->in_progress) {
1483 * Either we didn't find a macro, so this can't be a
1484 * macro call, or we found a macro which was already in
1485 * progress, in which case we don't _treat_ this as a
1486 * macro call. Copy it through and ignore it.
1488 tline->type = TOK_PS_OTHER; /* so it will get copied above */
1489 continue;
1491 mstart = tline;
1492 if (m->nparam == 0) {
1494 * Simple case: the macro is parameterless. Discard the
1495 * one token that the macro call took, and push the
1496 * expansion back on the to-do stack.
1498 params = NULL;
1499 paramsize = NULL;
1500 } else {
1502 * Complicated case: at least one macro with this name
1503 * exists and takes parameters. We must find the
1504 * parameters in the call, count them, find the SMacro
1505 * that corresponds to that form of the macro call, and
1506 * substitute for the parameters when we expand. What a
1507 * pain.
1509 nparam = sparam = 0;
1510 params = NULL;
1511 paramsize = NULL;
1512 tline = tline->next;
1513 if (tline && tline->type == TOK_WHITESPACE)
1514 tline = tline->next;
1515 if (!tline || tline->type != TOK_OTHER ||
1516 strcmp(tline->text, "(")) {
1518 * This macro wasn't called with parameters: ignore
1519 * the call. (Behaviour borrowed from gnu cpp.)
1521 tline = mstart;
1522 tline->type = TOK_PS_OTHER;
1523 continue;
1525 tline = tline->next;
1526 while (1) {
1527 if (tline && tline->type == TOK_WHITESPACE)
1528 tline = tline->next;
1529 if (!tline) {
1530 error(ERR_NONFATAL|ERR_OFFBY1,
1531 "macro call expects terminating `)'");
1532 break;
1534 if (nparam >= sparam) {
1535 sparam += PARAM_DELTA;
1536 params = nasm_realloc (params, sparam*sizeof(Token *));
1537 paramsize = nasm_realloc (paramsize, sparam*sizeof(int));
1539 params[nparam] = tline;
1540 paramsize[nparam] = 0;
1541 brackets = 0;
1542 if (tline && tline->type == TOK_OTHER &&
1543 !strcmp(tline->text, "{")) {
1544 params[nparam] = tline = tline->next;
1545 while (tline && (brackets > 0 ||
1546 tline->type != TOK_OTHER ||
1547 strcmp(tline->text, "}"))) {
1548 tline = tline->next;
1549 paramsize[nparam]++;
1551 tline = tline->next;
1552 if (tline && tline->type == TOK_WHITESPACE)
1553 tline = tline->next;
1554 if (tline && (tline->type != TOK_OTHER ||
1555 (strcmp(tline->text, ")") &&
1556 strcmp(tline->text, ",")))) {
1557 error (ERR_NONFATAL|ERR_OFFBY1, "braces do not "
1558 "enclose all of macro parameter");
1560 if (tline && tline->type == TOK_OTHER &&
1561 !strcmp(tline->text, ","))
1562 tline = tline->next;
1563 } else {
1564 while (tline && (brackets > 0 ||
1565 tline->type != TOK_OTHER ||
1566 (strcmp(tline->text, ",") &&
1567 strcmp(tline->text, ")")))) {
1568 if (tline->type == TOK_OTHER && !tline->text[1])
1569 brackets += (tline->text[0] == '(' ? 1 :
1570 tline->text[0] == ')' ? -1 : 0);
1571 tline = tline->next;
1572 paramsize[nparam]++;
1575 nparam++;
1576 if (tline && !strcmp(tline->text, ")"))
1577 break;
1578 if (tline && !strcmp(tline->text, ","))
1579 tline = tline->next;
1581 while (m && m->nparam != nparam) {
1582 while ( (m = m->next) )
1583 if (!strcmp(m->name, mstart->text))
1584 break;
1586 if (!m) {
1587 error (ERR_WARNING|ERR_OFFBY1|ERR_WARN_MNP,
1588 "macro `%s' exists, but not taking %d parameters",
1589 mstart->text, nparam);
1590 nasm_free (params);
1591 nasm_free (paramsize);
1592 tline = mstart;
1593 tline->type = TOK_PS_OTHER;
1594 continue;
1598 * Expand the macro: we are placed on the last token of the
1599 * call, so that we can easily split the call from the
1600 * following tokens. We also start by pushing an SMAC_END
1601 * token for the cycle removal.
1603 t = tline;
1604 tline = tline->next;
1605 t->next = NULL;
1606 tt = nasm_malloc(sizeof(Token));
1607 tt->type = TOK_SMAC_END;
1608 tt->text = NULL;
1609 tt->mac = m;
1610 m->in_progress = TRUE;
1611 tt->next = tline;
1612 tline = tt;
1613 for (t = m->expansion; t; t = t->next) {
1614 if (t->type >= TOK_SMAC_PARAM) {
1615 Token *pcopy = tline, **ptail = &pcopy;
1616 Token *ttt, *pt;
1617 int i;
1619 ttt = params[t->type - TOK_SMAC_PARAM];
1620 for (i=0; i<paramsize[t->type-TOK_SMAC_PARAM]; i++) {
1621 pt = *ptail = nasm_malloc(sizeof(Token));
1622 pt->next = tline;
1623 ptail = &pt->next;
1624 pt->text = nasm_strdup(ttt->text);
1625 pt->type = ttt->type;
1626 pt->mac = NULL;
1627 ttt = ttt->next;
1629 tline = pcopy;
1630 } else {
1631 tt = nasm_malloc(sizeof(Token));
1632 tt->type = t->type;
1633 tt->text = nasm_strdup(t->text);
1634 tt->mac = NULL;
1635 tt->next = tline;
1636 tline = tt;
1641 * Having done that, get rid of the macro call, and clean
1642 * up the parameters.
1644 nasm_free (params);
1645 nasm_free (paramsize);
1646 free_tlist (mstart);
1649 return thead;
1653 * Ensure that a macro parameter contains a condition code and
1654 * nothing else. Return the condition code index if so, or -1
1655 * otherwise.
1657 static int find_cc (Token *t) {
1658 Token *tt;
1659 int i, j, k, m;
1661 if (t && t->type == TOK_WHITESPACE)
1662 t = t->next;
1663 if (t->type != TOK_ID)
1664 return -1;
1665 tt = t->next;
1666 if (tt && tt->type == TOK_WHITESPACE)
1667 tt = tt->next;
1668 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
1669 return -1;
1671 i = -1;
1672 j = sizeof(conditions)/sizeof(*conditions);
1673 while (j-i > 1) {
1674 k = (j+i) / 2;
1675 m = nasm_stricmp(t->text, conditions[k]);
1676 if (m == 0) {
1677 i = k;
1678 j = -2;
1679 break;
1680 } else if (m < 0) {
1681 j = k;
1682 } else
1683 i = k;
1685 if (j != -2)
1686 return -1;
1687 return i;
1691 * Determine whether the given line constitutes a multi-line macro
1692 * call, and return the MMacro structure called if so. Doesn't have
1693 * to check for an initial label - that's taken care of in
1694 * expand_mmacro - but must check numbers of parameters. Guaranteed
1695 * to be called with tline->type == TOK_ID, so the putative macro
1696 * name is easy to find.
1698 static MMacro *is_mmacro (Token *tline, Token ***params_array) {
1699 MMacro *head, *m;
1700 Token **params;
1701 int nparam;
1703 head = mmacros[hash(tline->text)];
1706 * Efficiency: first we see if any macro exists with the given
1707 * name. If not, we can return NULL immediately. _Then_ we
1708 * count the parameters, and then we look further along the
1709 * list if necessary to find the proper MMacro.
1711 for (m = head; m; m = m->next)
1712 if (!mstrcmp(m->name, tline->text, m->casesense))
1713 break;
1714 if (!m)
1715 return NULL;
1718 * OK, we have a potential macro. Count and demarcate the
1719 * parameters.
1721 count_mmac_params (tline->next, &nparam, &params);
1724 * So we know how many parameters we've got. Find the MMacro
1725 * structure that handles this number.
1727 while (m) {
1728 if (m->nparam_min <= nparam && (m->plus || nparam <= m->nparam_max)) {
1730 * This one is right. Just check if cycle removal
1731 * prohibits us using it before we actually celebrate...
1733 if (m->in_progress) {
1734 error (ERR_NONFATAL|ERR_OFFBY1,
1735 "self-reference in multi-line macro `%s'",
1736 m->name);
1737 nasm_free (params);
1738 return NULL;
1741 * It's right, and we can use it. Add its default
1742 * parameters to the end of our list if necessary.
1744 params = nasm_realloc (params, (m->nparam_max+1)*sizeof(*params));
1745 if (m->defaults) {
1746 while (nparam < m->nparam_max) {
1747 params[nparam] = m->defaults[nparam - m->nparam_min];
1748 nparam++;
1750 } else {
1751 while (nparam < m->nparam_max) {
1752 params[nparam] = NULL;
1753 nparam++;
1757 * Then terminate the parameter list, and leave.
1759 params[m->nparam_max] = NULL;
1760 *params_array = params;
1761 return m;
1764 * This one wasn't right: look for the next one with the
1765 * same name.
1767 for (m = m->next; m; m = m->next)
1768 if (!mstrcmp(m->name, tline->text, m->casesense))
1769 break;
1773 * After all that, we didn't find one with the right number of
1774 * parameters. Issue a warning, and fail to expand the macro.
1776 error (ERR_WARNING|ERR_OFFBY1|ERR_WARN_MNP,
1777 "macro `%s' exists, but not taking %d parameters",
1778 tline->text, nparam);
1779 nasm_free (params);
1780 return NULL;
1784 * Expand the multi-line macro call made by the given line, if
1785 * there is one to be expanded. If there is, push the expansion on
1786 * istk->expansion and return 1 or 2, as according to whether a
1787 * line sync is needed (2 if it is). Otherwise return 0.
1789 static int expand_mmacro (Token *tline) {
1790 Token *label = NULL, **params, *t, *tt, *ttt, *last = NULL;
1791 MMacro *m = NULL;
1792 Line *l, *ll;
1793 int i, n, nparam, *paramlen;
1794 int need_sync = FALSE;
1796 t = tline;
1797 if (t && t->type == TOK_WHITESPACE)
1798 t = t->next;
1799 if (t && t->type == TOK_ID) {
1800 m = is_mmacro (t, &params);
1801 if (!m) {
1803 * We have an id which isn't a macro call. We'll assume
1804 * it might be a label; we'll also check to see if a
1805 * colon follows it. Then, if there's another id after
1806 * that lot, we'll check it again for macro-hood.
1808 last = t, t = t->next;
1809 if (t && t->type == TOK_WHITESPACE)
1810 last = t, t = t->next;
1811 if (t && t->type == TOK_OTHER && !strcmp(t->text, ":"))
1812 last = t, t = t->next;
1813 if (t && t->type == TOK_WHITESPACE)
1814 last = t, t = t->next;
1815 if (t && t->type == TOK_ID) {
1816 m = is_mmacro(t, &params);
1817 if (m) {
1818 last->next = NULL;
1819 label = tline;
1820 tline = t;
1825 if (!m)
1826 return 0;
1829 * If we're not already inside another macro expansion, we'd
1830 * better push a line synchronisation to ensure we stay put on
1831 * line numbering.
1833 if (!istk->expansion)
1834 need_sync = TRUE;
1837 * Fix up the parameters: this involves stripping leading and
1838 * trailing whitespace, then stripping braces if they are
1839 * present.
1841 for (nparam = 0; params[nparam]; nparam++);
1842 paramlen = nparam ? nasm_malloc(nparam*sizeof(*paramlen)) : NULL;
1844 for (i = 0; params[i]; i++) {
1845 int brace = FALSE;
1846 int comma = (!m->plus || i < nparam-1);
1848 t = params[i];
1849 if (t && t->type == TOK_WHITESPACE)
1850 t = t->next;
1851 if (t && t->type == TOK_OTHER && !strcmp(t->text, "{"))
1852 t = t->next, brace = TRUE, comma = FALSE;
1853 params[i] = t;
1854 paramlen[i] = 0;
1855 while (t) {
1856 if (!t) /* end of param because EOL */
1857 break;
1858 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
1859 break; /* ... because we have hit a comma */
1860 if (comma && t->type == TOK_WHITESPACE &&
1861 t->next->type == TOK_OTHER && !strcmp(t->next->text, ","))
1862 break; /* ... or a space then a comma */
1863 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
1864 break; /* ... or a brace */
1865 t = t->next;
1866 paramlen[i]++;
1871 * OK, we have a MMacro structure together with a set of
1872 * parameters. We must now go through the expansion and push
1873 * _copies_ of each Line on to istk->expansion, having first
1874 * substituted for most % tokens (%1, %+1, %-1, %%foo). Note
1875 * that %$bar, %$$baz, %$$$quux, and so on, do not get
1876 * substituted here but rather have to wait until the
1877 * single-line macro substitution process. This is because they
1878 * don't just crop up in macro definitions, but can appear
1879 * anywhere they like.
1881 * First, push an end marker on to istk->expansion, and mark
1882 * this macro as in progress.
1884 ll = nasm_malloc(sizeof(Line));
1885 ll->next = istk->expansion;
1886 ll->finishes = m;
1887 ll->first = NULL;
1888 istk->expansion = ll;
1889 m->in_progress = TRUE;
1890 for (l = m->expansion; l; l = l->next) {
1891 Token **tail;
1893 ll = nasm_malloc(sizeof(Line));
1894 ll->next = istk->expansion;
1895 ll->finishes = NULL;
1896 ll->first = NULL;
1897 tail = &ll->first;
1899 for (t = l->first; t; t = t->next) {
1900 char *text;
1901 int type = 0, cc; /* type = 0 to placate optimisers */
1902 char tmpbuf[30];
1904 if (t->type == TOK_PREPROC_ID &&
1905 (t->text[1] == '+' || t->text[1] == '-' ||
1906 t->text[1] == '%' ||
1907 (t->text[1] >= '0' && t->text[1] <= '9'))) {
1909 * We have to make a substitution of one of the
1910 * forms %1, %-1, %+1, %%foo.
1912 switch (t->text[1]) {
1913 case '%':
1914 type = TOK_ID;
1915 sprintf(tmpbuf, "..@%lu.", unique);
1916 text = nasm_malloc(strlen(tmpbuf)+strlen(t->text+2)+1);
1917 strcpy(text, tmpbuf);
1918 strcat(text, t->text+2);
1919 break;
1920 case '-':
1921 n = atoi(t->text+2)-1;
1922 tt = params[n];
1923 cc = find_cc (tt);
1924 if (cc == -1) {
1925 error (ERR_NONFATAL|ERR_OFFBY1,
1926 "macro parameter %d is not a condition code",
1927 n+1);
1928 text = NULL;
1929 } else {
1930 type = TOK_ID;
1931 if (inverse_ccs[cc] == -1) {
1932 error (ERR_NONFATAL|ERR_OFFBY1,
1933 "condition code `%s' is not invertible",
1934 conditions[cc]);
1935 text = NULL;
1936 } else
1937 text = nasm_strdup(conditions[inverse_ccs[cc]]);
1939 break;
1940 case '+':
1941 n = atoi(t->text+2)-1;
1942 tt = params[n];
1943 cc = find_cc (tt);
1944 if (cc == -1) {
1945 error (ERR_NONFATAL|ERR_OFFBY1,
1946 "macro parameter %d is not a condition code",
1947 n+1);
1948 text = NULL;
1949 } else {
1950 type = TOK_ID;
1951 text = nasm_strdup(conditions[cc]);
1953 break;
1954 default:
1955 n = atoi(t->text+1)-1;
1956 if (n < nparam) {
1957 ttt = params[n];
1958 for (i=0; i<paramlen[n]; i++) {
1959 tt = *tail = nasm_malloc(sizeof(Token));
1960 tt->next = NULL;
1961 tail = &tt->next;
1962 tt->type = ttt->type;
1963 tt->text = nasm_strdup(ttt->text);
1964 tt->mac = NULL;
1965 ttt = ttt->next;
1968 text = NULL; /* we've done it here */
1969 break;
1971 } else {
1972 type = t->type;
1973 text = nasm_strdup(t->text);
1976 if (text) {
1977 tt = *tail = nasm_malloc(sizeof(Token));
1978 tt->next = NULL;
1979 tail = &tt->next;
1980 tt->type = type;
1981 tt->text = text;
1982 tt->mac = NULL;
1986 istk->expansion = ll;
1991 * If we had a label, push it on the front of the first line of
1992 * the macro expansion.
1994 if (label) {
1995 last->next = istk->expansion->first;
1996 istk->expansion->first = label;
2000 * Clean up.
2002 unique++;
2003 nasm_free (paramlen);
2004 nasm_free (params);
2005 free_tlist (tline);
2007 list->uplevel (m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2009 return need_sync ? 2 : 1;
2012 static void pp_reset (char *file, efunc errfunc, ListGen *listgen) {
2013 int h;
2015 error = errfunc;
2016 cstk = NULL;
2017 linesync = outline = NULL;
2018 istk = nasm_malloc(sizeof(Include));
2019 istk->next = NULL;
2020 istk->conds = NULL;
2021 istk->expansion = NULL;
2022 istk->fp = fopen(file, "r");
2023 istk->fname = nasm_strdup(file);
2024 istk->lineno = istk->lineinc = 1;
2025 if (!istk->fp)
2026 error (ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'", file);
2027 defining = NULL;
2028 for (h=0; h<NHASH; h++) {
2029 mmacros[h] = NULL;
2030 smacros[h] = NULL;
2032 unique = 0;
2033 stdmacpos = stdmac;
2034 list = listgen;
2037 static char *pp_getline (void) {
2038 char *line;
2039 Token *tline;
2040 int ret;
2042 if (outline) {
2043 line = outline;
2044 outline = NULL;
2045 return line;
2048 while (1) {
2050 * Fetch a tokenised line, either from the macro-expansion
2051 * buffer or from the input file.
2053 tline = NULL;
2054 while (istk->expansion && istk->expansion->finishes) {
2055 Line *l = istk->expansion;
2056 l->finishes->in_progress = FALSE;
2057 istk->expansion = l->next;
2058 nasm_free (l);
2059 list->downlevel (LIST_MACRO);
2060 if (!istk->expansion)
2061 line_sync();
2063 if (istk->expansion) {
2064 char *p;
2065 Line *l = istk->expansion;
2066 tline = l->first;
2067 istk->expansion = l->next;
2068 nasm_free (l);
2069 p = detoken(tline);
2070 list->line (LIST_MACRO, p);
2071 nasm_free(p);
2072 if (!istk->expansion)
2073 line_sync();
2074 } else {
2075 line = read_line();
2076 while (!line) {
2078 * The current file has ended; work down the istk
2079 * until we find a file we can read from.
2081 Include *i;
2082 fclose(istk->fp);
2083 if (istk->conds)
2084 error(ERR_FATAL, "expected `%%endif' before end of file");
2085 i = istk;
2086 istk = istk->next;
2087 list->downlevel (LIST_INCLUDE);
2088 nasm_free (i->fname);
2089 nasm_free (i);
2090 if (!istk)
2091 return NULL;
2092 else
2093 line_sync();
2094 line = read_line();
2096 line = prepreproc(line);
2097 tline = tokenise(line);
2098 nasm_free (line);
2102 * Check the line to see if it's a preprocessor directive.
2104 ret = do_directive(tline);
2105 if (ret & 1) {
2106 free_tlist (tline);
2107 if (ret & 4)
2108 line_sync();
2109 if ((ret & 2) && !stdmacpos) {/* give a blank line to the output */
2110 outline = nasm_strdup("");
2111 break;
2113 else
2114 continue;
2115 } else if (defining) {
2117 * We're defining a multi-line macro. We emit nothing
2118 * at all, not even a blank line (when we finish
2119 * defining the macro, we'll emit a line-number
2120 * directive so that we keep sync properly), and just
2121 * shove the tokenised line on to the macro definition.
2123 Line *l = nasm_malloc(sizeof(Line));
2124 l->next = defining->expansion;
2125 l->first = tline;
2126 l->finishes = FALSE;
2127 defining->expansion = l;
2128 continue;
2129 } else if (istk->conds && !emitting(istk->conds->state)) {
2131 * We're in a non-emitting branch of a condition block.
2132 * Emit nothing at all, not even a blank line: when we
2133 * emerge from the condition we'll give a line-number
2134 * directive so we keep our place correctly.
2136 free_tlist(tline);
2137 continue;
2138 } else {
2139 tline = expand_smacro(tline);
2140 ret = expand_mmacro(tline);
2141 if (!ret) {
2143 * De-tokenise the line again, and emit it.
2145 line = detoken(tline);
2146 free_tlist (tline);
2147 outline = line;
2148 break;
2149 } else {
2150 if (ret == 2)
2151 line_sync();
2152 continue; /* expand_mmacro calls free_tlist */
2158 * Once we're out of this loop, outline _must_ be non-NULL. The
2159 * only question is whether linesync is NULL or not.
2161 if (linesync) {
2162 line = linesync;
2163 linesync = NULL;
2164 } else {
2165 line = outline;
2166 outline = NULL;
2168 return line;
2171 static void pp_cleanup (void) {
2172 int h;
2174 if (defining) {
2175 error (ERR_NONFATAL, "end of file while still defining macro `%s'",
2176 defining->name);
2177 nasm_free (defining->name);
2178 free_tlist (defining->dlist);
2179 free_llist (defining->expansion);
2180 nasm_free (defining);
2182 nasm_free (linesync); /* might just be necessary */
2183 nasm_free (outline); /* really shouldn't be necessary */
2184 while (cstk)
2185 ctx_pop();
2186 for (h=0; h<NHASH; h++) {
2187 while (mmacros[h]) {
2188 MMacro *m = mmacros[h];
2189 mmacros[h] = mmacros[h]->next;
2190 nasm_free (m->name);
2191 free_tlist (m->dlist);
2192 free_llist (m->expansion);
2193 nasm_free (m);
2195 while (smacros[h]) {
2196 SMacro *s = smacros[h];
2197 smacros[h] = smacros[h]->next;
2198 nasm_free (s->name);
2199 free_tlist (s->expansion);
2200 nasm_free (s);
2203 while (istk) {
2204 Include *i = istk;
2205 istk = istk->next;
2206 fclose(i->fp);
2207 nasm_free (i->fname);
2208 nasm_free (i);
2210 while (cstk)
2211 ctx_pop();
2214 void pp_include_path (char *path) {
2215 IncPath *i;
2217 i = nasm_malloc(sizeof(IncPath));
2218 i->path = nasm_strdup(path);
2219 i->next = ipath;
2221 ipath = i;
2224 void pp_pre_include (char *fname) {
2225 Token *inc, *space, *name;
2226 Line *l;
2228 inc = nasm_malloc(sizeof(Token));
2229 inc->next = space = nasm_malloc(sizeof(Token));
2230 space->next = name = nasm_malloc(sizeof(Token));
2231 name->next = NULL;
2233 inc->type = TOK_PREPROC_ID;
2234 inc->text = nasm_strdup("%include");
2235 space->type = TOK_WHITESPACE;
2236 space->text = nasm_strdup(" ");
2237 name->type = TOK_INTERNAL_STRING;
2238 name->text = nasm_strdup(fname);
2240 inc->mac = space->mac = name->mac = NULL;
2242 l = nasm_malloc(sizeof(Line));
2243 l->next = predef;
2244 l->first = inc;
2245 l->finishes = FALSE;
2246 predef = l;
2249 void pp_pre_define (char *definition) {
2250 Token *def, *space, *name;
2251 Line *l;
2252 char *equals;
2254 equals = strchr(definition, '=');
2256 def = nasm_malloc(sizeof(Token));
2257 def->next = space = nasm_malloc(sizeof(Token));
2258 if (equals)
2259 *equals = ' ';
2260 space->next = name = tokenise(definition);
2261 if (equals)
2262 *equals = '=';
2264 def->type = TOK_PREPROC_ID;
2265 def->text = nasm_strdup("%define");
2266 space->type = TOK_WHITESPACE;
2267 space->text = nasm_strdup(" ");
2269 def->mac = space->mac = NULL;
2271 l = nasm_malloc(sizeof(Line));
2272 l->next = predef;
2273 l->first = def;
2274 l->finishes = FALSE;
2275 predef = l;
2278 Preproc nasmpp = {
2279 pp_reset,
2280 pp_getline,
2281 pp_cleanup