NASM 0.98p3
[nasm.git] / preproc.c
blob291b57eca300d758a0f9bf967ebe993c8215b20b
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 #define br0 '{'
12 #define br1 "{"
13 #define br2 '}'
14 #define br3 "}"
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <stddef.h>
19 #include <string.h>
20 #include <ctype.h>
21 #include <limits.h>
23 #include "nasm.h"
24 #include "nasmlib.h"
26 typedef struct SMacro SMacro;
27 typedef struct MMacro MMacro;
28 typedef struct Context Context;
29 typedef struct Token Token;
30 typedef struct Line Line;
31 typedef struct Include Include;
32 typedef struct Cond Cond;
33 typedef struct IncPath IncPath;
36 * Store the definition of a single-line macro.
38 struct SMacro {
39 SMacro *next;
40 char *name;
41 int casesense;
42 int nparam;
43 int in_progress;
44 Token *expansion;
48 * Store the definition of a multi-line macro. This is also used to
49 * store the interiors of `%rep...%endrep' blocks, which are
50 * effectively self-re-invoking multi-line macros which simply
51 * don't have a name or bother to appear in the hash tables. %rep
52 * blocks are signified by having a NULL `name' field.
54 * In a MMacro describing a `%rep' block, the `in_progress' field
55 * isn't merely boolean, but gives the number of repeats left to
56 * run.
58 * The `next' field is used for storing MMacros in hash tables; the
59 * `next_active' field is for stacking them on istk entries.
61 * When a MMacro is being expanded, `params', `iline', `nparam',
62 * `paramlen', `rotate' and `unique' are local to the invocation.
64 struct MMacro {
65 MMacro *next;
66 char *name;
67 int casesense;
68 int nparam_min, nparam_max;
69 int plus; /* is the last parameter greedy? */
70 int nolist; /* is this macro listing-inhibited? */
71 int in_progress;
72 Token *dlist; /* All defaults as one list */
73 Token **defaults; /* Parameter default pointers */
74 int ndefs; /* number of default parameters */
75 Line *expansion;
77 MMacro *next_active;
78 Token **params; /* actual parameters */
79 Token *iline; /* invocation line */
80 int nparam, rotate, *paramlen;
81 unsigned long unique;
85 * The context stack is composed of a linked list of these.
87 struct Context {
88 Context *next;
89 SMacro *localmac;
90 char *name;
91 unsigned long number;
95 * This is the internal form which we break input lines up into.
96 * Typically stored in linked lists.
98 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
99 * necessarily used as-is, but is intended to denote the number of
100 * the substituted parameter. So in the definition
102 * %define a(x,y) ( (x) & ~(y) )
104 * the token representing `x' will have its type changed to
105 * TOK_SMAC_PARAM, but the one representing `y' will be
106 * TOK_SMAC_PARAM+1.
108 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
109 * which doesn't need quotes around it. Used in the pre-include
110 * mechanism as an alternative to trying to find a sensible type of
111 * quote to use on the filename we were passed.
113 struct Token {
114 Token *next;
115 char *text;
116 SMacro *mac; /* associated macro for TOK_SMAC_END */
117 int type;
119 enum {
120 TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING,
121 TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_SMAC_PARAM,
122 TOK_INTERNAL_STRING
126 * Multi-line macro definitions are stored as a linked list of
127 * these, which is essentially a container to allow several linked
128 * lists of Tokens.
130 * Note that in this module, linked lists are treated as stacks
131 * wherever possible. For this reason, Lines are _pushed_ on to the
132 * `expansion' field in MMacro structures, so that the linked list,
133 * if walked, would give the macro lines in reverse order; this
134 * means that we can walk the list when expanding a macro, and thus
135 * push the lines on to the `expansion' field in _istk_ in reverse
136 * order (so that when popped back off they are in the right
137 * order). It may seem cockeyed, and it relies on my design having
138 * an even number of steps in, but it works...
140 * Some of these structures, rather than being actual lines, are
141 * markers delimiting the end of the expansion of a given macro.
142 * This is for use in the cycle-tracking and %rep-handling code.
143 * Such structures have `finishes' non-NULL, and `first' NULL. All
144 * others have `finishes' NULL, but `first' may still be NULL if
145 * the line is blank.
147 struct Line {
148 Line *next;
149 MMacro *finishes;
150 Token *first;
154 * To handle an arbitrary level of file inclusion, we maintain a
155 * stack (ie linked list) of these things.
157 struct Include {
158 Include *next;
159 FILE *fp;
160 Cond *conds;
161 Line *expansion;
162 char *fname;
163 int lineno, lineinc;
164 MMacro *mstk; /* stack of active macros/reps */
168 * Include search path. This is simply a list of strings which get
169 * prepended, in turn, to the name of an include file, in an
170 * attempt to find the file if it's not in the current directory.
172 struct IncPath {
173 IncPath *next;
174 char *path;
178 * Conditional assembly: we maintain a separate stack of these for
179 * each level of file inclusion. (The only reason we keep the
180 * stacks separate is to ensure that a stray `%endif' in a file
181 * included from within the true branch of a `%if' won't terminate
182 * it and cause confusion: instead, rightly, it'll cause an error.)
184 struct Cond {
185 Cond *next;
186 int state;
188 enum {
190 * These states are for use just after %if or %elif: IF_TRUE
191 * means the condition has evaluated to truth so we are
192 * currently emitting, whereas IF_FALSE means we are not
193 * currently emitting but will start doing so if a %else comes
194 * up. In these states, all directives are admissible: %elif,
195 * %else and %endif. (And of course %if.)
197 COND_IF_TRUE, COND_IF_FALSE,
199 * These states come up after a %else: ELSE_TRUE means we're
200 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
201 * any %elif or %else will cause an error.
203 COND_ELSE_TRUE, COND_ELSE_FALSE,
205 * This state means that we're not emitting now, and also that
206 * nothing until %endif will be emitted at all. It's for use in
207 * two circumstances: (i) when we've had our moment of emission
208 * and have now started seeing %elifs, and (ii) when the
209 * condition construct in question is contained within a
210 * non-emitting branch of a larger condition construct.
212 COND_NEVER
214 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
217 * Condition codes. Note that we use c_ prefix not C_ because C_ is
218 * used in nasm.h for the "real" condition codes. At _this_ level,
219 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
220 * ones, so we need a different enum...
222 static char *conditions[] = {
223 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
224 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
225 "np", "ns", "nz", "o", "p", "pe", "po", "s", "z"
227 enum {
228 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
229 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
230 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_S, c_Z
232 static int inverse_ccs[] = {
233 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
234 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,
235 c_Z, c_NO, c_NP, c_PO, c_PE, c_NS, c_NZ
239 * Directive names.
241 static char *directives[] = {
242 "%assign", "%clear", "%define", "%elif", "%elifctx", "%elifdef",
243 "%elifid", "%elifidn", "%elifidni", "%elifnctx", "%elifndef",
244 "%elifnid", "%elifnidn", "%elifnidni", "%elifnnum", "%elifnstr",
245 "%elifnum", "%elifstr", "%else", "%endif", "%endm", "%endmacro",
246 "%endrep", "%error", "%exitrep", "%iassign", "%idefine", "%if",
247 "%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifnctx",
248 "%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnnum",
249 "%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include", "%line",
250 "%macro", "%pop", "%push", "%rep", "%repl", "%rotate"
252 enum {
253 PP_ASSIGN, PP_CLEAR, PP_DEFINE, PP_ELIF, PP_ELIFCTX, PP_ELIFDEF,
254 PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFNCTX, PP_ELIFNDEF,
255 PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNNUM, PP_ELIFNSTR,
256 PP_ELIFNUM, PP_ELIFSTR, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO,
257 PP_ENDREP, PP_ERROR, PP_EXITREP, PP_IASSIGN, PP_IDEFINE, PP_IF,
258 PP_IFCTX, PP_IFDEF, PP_IFID, PP_IFIDN, PP_IFIDNI, PP_IFNCTX,
259 PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNNUM,
260 PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE, PP_LINE,
261 PP_MACRO, PP_POP, PP_PUSH, PP_REP, PP_REPL, PP_ROTATE
265 static Context *cstk;
266 static Include *istk;
267 static IncPath *ipath = NULL;
269 static efunc error;
270 static evalfunc evaluate;
272 static int pass;
274 static unsigned long unique; /* unique identifier numbers */
276 static Line *predef = NULL;
278 static ListGen *list;
281 * The number of hash values we use for the macro lookup tables.
282 * FIXME: We should *really* be able to configure this at run time,
283 * or even have the hash table automatically expanding when necessary.
285 #define NHASH 31
288 * The current set of multi-line macros we have defined.
290 static MMacro *mmacros[NHASH];
293 * The current set of single-line macros we have defined.
295 static SMacro *smacros[NHASH];
298 * The multi-line macro we are currently defining, or the %rep
299 * block we are currently reading, if any.
301 static MMacro *defining;
304 * The number of macro parameters to allocate space for at a time.
306 #define PARAM_DELTA 16
309 * The standard macro set: defined as `static char *stdmac[]'. Also
310 * gives our position in the macro set, when we're processing it.
312 #include "macros.c"
313 static char **stdmacpos;
316 * The extra standard macros that come from the object format, if
317 * any.
319 static char **extrastdmac = NULL;
320 int any_extrastdmac;
323 * Forward declarations.
325 static Token *expand_smacro (Token *tline);
326 static void make_tok_num(Token *tok, long val);
329 * Macros for safe checking of token pointers, avoid *(NULL)
331 #define tok_type_(x,t) ((x) && (x)->type == (t))
332 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
333 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
334 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
337 * The pre-preprocessing stage... This function translates line
338 * number indications as they emerge from GNU cpp (`# lineno "file"
339 * flags') into NASM preprocessor line number indications (`%line
340 * lineno file').
342 static char *prepreproc(char *line)
344 int lineno, fnlen;
345 char *fname, *oldline;
347 if (line[0] == '#' && line[1] == ' ') {
348 oldline = line;
349 fname = oldline+2;
350 lineno = atoi(fname);
351 fname += strspn(fname, "0123456789 ");
352 if (*fname == '"')
353 fname++;
354 fnlen = strcspn(fname, "\"");
355 line = nasm_malloc(20+fnlen);
356 sprintf(line, "%%line %d %.*s", lineno, fnlen, fname);
357 nasm_free (oldline);
359 return line;
363 * The hash function for macro lookups. Note that due to some
364 * macros having case-insensitive names, the hash function must be
365 * invariant under case changes. We implement this by applying a
366 * perfectly normal hash function to the uppercase of the string.
368 static int hash(char *s)
370 unsigned int h = 0;
371 int i = 0;
373 * Powers of three, mod 31.
375 static const int multipliers[] = {
376 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10,
377 30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21
381 while (*s) {
382 h += multipliers[i] * (unsigned char) (toupper(*s));
383 s++;
384 if (++i >= sizeof(multipliers)/sizeof(*multipliers))
385 i = 0;
387 h %= NHASH;
388 return h;
392 * Free a linked list of tokens.
394 static void free_tlist (Token *list)
396 Token *t;
397 while (list) {
398 t = list;
399 list = list->next;
400 nasm_free (t->text);
401 nasm_free (t);
406 * Free a linked list of lines.
408 static void free_llist (Line *list)
410 Line *l;
411 while (list) {
412 l = list;
413 list = list->next;
414 free_tlist (l->first);
415 nasm_free (l);
420 * Free an MMacro
422 static void free_mmacro (MMacro *m)
424 nasm_free (m->name);
425 free_tlist (m->dlist);
426 nasm_free (m->defaults);
427 free_llist (m->expansion);
428 nasm_free (m);
432 * Pop the context stack.
434 static void ctx_pop (void)
436 Context *c = cstk;
437 SMacro *smac, *s;
439 cstk = cstk->next;
440 smac = c->localmac;
441 while (smac) {
442 s = smac;
443 smac = smac->next;
444 nasm_free (s->name);
445 free_tlist (s->expansion);
446 nasm_free (s);
448 nasm_free (c->name);
449 nasm_free (c);
452 #define BUF_DELTA 512
454 * Read a line from the top file in istk, handling multiple CR/LFs
455 * at the end of the line read, and handling spurious ^Zs. Will
456 * return lines from the standard macro set if this has not already
457 * been done.
459 static char *read_line (void)
461 char *buffer, *p, *q;
462 int bufsize;
464 if (stdmacpos) {
465 if (*stdmacpos) {
466 char *ret = nasm_strdup(*stdmacpos++);
467 if (!*stdmacpos && any_extrastdmac)
469 stdmacpos = extrastdmac;
470 any_extrastdmac = FALSE;
471 return ret;
474 * Nasty hack: here we push the contents of `predef' on
475 * to the top-level expansion stack, since this is the
476 * most convenient way to implement the pre-include and
477 * pre-define features.
479 if (!*stdmacpos)
481 Line *pd, *l;
482 Token *head, **tail, *t, *tt;
484 for (pd = predef; pd; pd = pd->next) {
485 head = NULL;
486 tail = &head;
487 for (t = pd->first; t; t = t->next) {
488 tt = *tail = nasm_malloc(sizeof(Token));
489 tt->next = NULL;
490 tail = &tt->next;
491 tt->type = t->type;
492 tt->text = nasm_strdup(t->text);
493 tt->mac = t->mac; /* always NULL here, in fact */
495 l = nasm_malloc(sizeof(Line));
496 l->next = istk->expansion;
497 l->first = head;
498 l->finishes = FALSE;
499 istk->expansion = l;
502 return ret;
504 else {
505 stdmacpos = NULL;
509 bufsize = BUF_DELTA;
510 buffer = nasm_malloc(BUF_DELTA);
511 p = buffer;
512 while (1) {
513 q = fgets(p, bufsize-(p-buffer), istk->fp);
514 if (!q)
515 break;
516 p += strlen(p);
517 if (p > buffer && p[-1] == '\n') {
518 break;
520 if (p-buffer > bufsize-10) {
521 long offset = p-buffer;
522 bufsize += BUF_DELTA;
523 buffer = nasm_realloc(buffer, bufsize);
524 p = buffer+offset; /* prevent stale-pointer problems */
528 if (!q && p == buffer) {
529 nasm_free (buffer);
530 return NULL;
533 src_set_linnum(src_get_linnum() + istk->lineinc);
536 * Play safe: remove CRs as well as LFs, if any of either are
537 * present at the end of the line.
539 while (--p >= buffer && (*p == '\n' || *p == '\r'))
540 *p = '\0';
543 * Handle spurious ^Z, which may be inserted into source files
544 * by some file transfer utilities.
546 buffer[strcspn(buffer, "\032")] = '\0';
548 list->line (LIST_READ, buffer);
550 return buffer;
554 * Tokenise a line of text. This is a very simple process since we
555 * don't need to parse the value out of e.g. numeric tokens: we
556 * simply split one string into many.
558 static Token *tokenise (char *line)
560 char *p = line;
561 int type;
562 Token *list = NULL;
563 Token *t, **tail = &list;
565 while (*line) {
566 p = line;
567 if (*p == '%' && ( isdigit(p[1]) ||
568 ((p[1] == '-' || p[1] == '+') && isdigit(p[2]))))
570 p++;
571 do {
572 p++;
573 } while (isdigit(*p));
574 type = TOK_PREPROC_ID;
576 else if (*p == '%' && p[1] == '{') {
577 p += 2;
578 while (*p && *p != '}') {
579 p[-1] = *p;
580 p++;
582 p[-1] = '\0';
583 if (*p) p++;
584 type = TOK_PREPROC_ID;
586 else if (*p == '%' && (isidchar(p[1]) ||
587 ((p[1] == '!' || p[1] == '%' || p[1] == '$') &&
588 isidchar(p[2]))))
590 p++;
591 do {
592 p++;
593 } while (isidchar(*p));
594 type = TOK_PREPROC_ID;
596 else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
597 type = TOK_ID;
598 p++;
599 while (*p && isidchar(*p))
600 p++;
602 else if (*p == '\'' || *p == '"') {
604 * A string token.
606 char c = *p;
607 p++;
608 type = TOK_STRING;
609 while (*p && *p != c)
610 p++;
611 if (*p) p++;
613 else if (isnumstart(*p)) {
615 * A number token.
617 type = TOK_NUMBER;
618 p++;
619 while (*p && isnumchar(*p))
620 p++;
622 else if (isspace(*p)) {
623 type = TOK_WHITESPACE;
624 p++;
625 while (*p && isspace(*p))
626 p++;
628 * Whitespace just before end-of-line is discarded by
629 * pretending it's a comment; whitespace just before a
630 * comment gets lumped into the comment.
632 if (!*p || *p == ';') {
633 type = TOK_COMMENT;
634 while (*p) p++;
637 else if (*p == ';') {
638 type = TOK_COMMENT;
639 while (*p) p++;
641 else {
643 * Anything else is an operator of some kind. We check
644 * for all the double-character operators (>>, <<, //,
645 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
646 * else is a single-character operator.
648 type = TOK_OTHER;
649 if ((p[0] == '>' && p[1] == '>') ||
650 (p[0] == '<' && p[1] == '<') ||
651 (p[0] == '/' && p[1] == '/') ||
652 (p[0] == '%' && p[1] == '%') ||
653 (p[0] == '<' && p[1] == '=') ||
654 (p[0] == '>' && p[1] == '=') ||
655 (p[0] == '=' && p[1] == '=') ||
656 (p[0] == '!' && p[1] == '=') ||
657 (p[0] == '<' && p[1] == '>') ||
658 (p[0] == '&' && p[1] == '&') ||
659 (p[0] == '|' && p[1] == '|') ||
660 (p[0] == '^' && p[1] == '^'))
662 p++;
664 p++;
666 if (type != TOK_COMMENT) {
667 *tail = t = nasm_malloc (sizeof(Token));
668 tail = &t->next;
669 t->next = NULL;
670 t->type = type;
671 t->text = nasm_malloc(1+p-line);
672 strncpy(t->text, line, p-line);
673 t->text[p-line] = '\0';
675 line = p;
678 return list;
682 * Convert a line of tokens back into text.
684 char *detoken (Token *tlist)
686 Token *t;
687 int len;
688 char *line, *p;
690 len = 0;
691 for (t = tlist; t; t = t->next) {
692 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
693 char *p = getenv(t->text+2);
694 nasm_free (t->text);
695 if (p)
696 t->text = nasm_strdup(p);
697 else
698 t->text = NULL;
700 if (t->text)
701 len += strlen(t->text);
703 p = line = nasm_malloc(len+1);
704 for (t = tlist; t; t = t->next) {
705 if (t->text) {
706 strcpy (p, t->text);
707 p += strlen(p);
710 *p = '\0';
711 return line;
715 * A scanner, suitable for use by the expression evaluator, which
716 * operates on a line of Tokens. Expects a pointer to a pointer to
717 * the first token in the line to be passed in as its private_data
718 * field.
720 static int ppscan(void *private_data, struct tokenval *tokval)
722 Token **tlineptr = private_data;
723 Token *tline;
725 do {
726 tline = *tlineptr;
727 *tlineptr = tline ? tline->next : NULL;
728 } while (tline && (tline->type == TOK_WHITESPACE ||
729 tline->type == TOK_COMMENT));
731 if (!tline)
732 return tokval->t_type = TOKEN_EOS;
734 if (tline->text[0] == '$' && !tline->text[1])
735 return tokval->t_type = TOKEN_HERE;
736 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[1])
737 return tokval->t_type = TOKEN_BASE;
739 if (tline->type == TOK_ID) {
740 tokval->t_charptr = tline->text;
741 if (tline->text[0] == '$') {
742 tokval->t_charptr++;
743 return tokval->t_type = TOKEN_ID;
747 * This is the only special case we actually need to worry
748 * about in this restricted context.
750 if (!nasm_stricmp(tline->text, "seg"))
751 return tokval->t_type = TOKEN_SEG;
753 return tokval->t_type = TOKEN_ID;
756 if (tline->type == TOK_NUMBER) {
757 int rn_error;
759 tokval->t_integer = readnum(tline->text, &rn_error);
760 if (rn_error)
761 return tokval->t_type = TOKEN_ERRNUM;
762 tokval->t_charptr = NULL;
763 return tokval->t_type = TOKEN_NUM;
766 if (tline->type == TOK_STRING) {
767 int rn_warn;
768 char q, *r;
769 int l;
771 r = tline->text;
772 q = *r++;
773 l = strlen(r);
775 if (l == 0 || r[l-1] != q)
776 return tokval->t_type = TOKEN_ERRNUM;
777 tokval->t_integer = readstrnum(r, l-1, &rn_warn);
778 if (rn_warn)
779 error(ERR_WARNING|ERR_PASS1,
780 "character constant too long");
781 tokval->t_charptr = NULL;
782 return tokval->t_type = TOKEN_NUM;
785 if (tline->type == TOK_OTHER) {
786 if (!strcmp(tline->text, "<<")) return tokval->t_type = TOKEN_SHL;
787 if (!strcmp(tline->text, ">>")) return tokval->t_type = TOKEN_SHR;
788 if (!strcmp(tline->text, "//")) return tokval->t_type = TOKEN_SDIV;
789 if (!strcmp(tline->text, "%%")) return tokval->t_type = TOKEN_SMOD;
790 if (!strcmp(tline->text, "==")) return tokval->t_type = TOKEN_EQ;
791 if (!strcmp(tline->text, "<>")) return tokval->t_type = TOKEN_NE;
792 if (!strcmp(tline->text, "!=")) return tokval->t_type = TOKEN_NE;
793 if (!strcmp(tline->text, "<=")) return tokval->t_type = TOKEN_LE;
794 if (!strcmp(tline->text, ">=")) return tokval->t_type = TOKEN_GE;
795 if (!strcmp(tline->text, "&&")) return tokval->t_type = TOKEN_DBL_AND;
796 if (!strcmp(tline->text, "^^")) return tokval->t_type = TOKEN_DBL_XOR;
797 if (!strcmp(tline->text, "||")) return tokval->t_type = TOKEN_DBL_OR;
801 * We have no other options: just return the first character of
802 * the token text.
804 return tokval->t_type = tline->text[0];
808 * Return the Context structure associated with a %$ token. Return
809 * NULL, having _already_ reported an error condition, if the
810 * context stack isn't deep enough for the supplied number of $
811 * signs.
813 static Context *get_ctx (char *name)
815 Context *ctx;
816 int i;
818 if (!cstk) {
819 error (ERR_NONFATAL, "`%s': context stack is empty", name);
820 return NULL;
823 i = 1;
824 ctx = cstk;
825 while (name[i+1] == '$') {
826 i++;
827 ctx = ctx->next;
828 if (!ctx) {
829 error (ERR_NONFATAL, "`%s': context stack is only"
830 " %d level%s deep", name, i-1, (i==2 ? "" : "s"));
831 return NULL;
834 return ctx;
838 * Compare a string to the name of an existing macro; this is a
839 * simple wrapper which calls either strcmp or nasm_stricmp
840 * depending on the value of the `casesense' parameter.
842 static int mstrcmp(char *p, char *q, int casesense)
844 return casesense ? strcmp(p,q) : nasm_stricmp(p,q);
848 * Open an include file. This routine must always return a valid
849 * file pointer if it returns - it's responsible for throwing an
850 * ERR_FATAL and bombing out completely if not. It should also try
851 * the include path one by one until it finds the file or reaches
852 * the end of the path.
854 static FILE *inc_fopen(char *file)
856 FILE *fp;
857 char *prefix = "", *combine;
858 IncPath *ip = ipath;
860 while (1) {
861 combine = nasm_strcat(prefix,file);
862 fp = fopen(combine, "r");
863 nasm_free (combine);
864 if (fp)
865 return fp;
866 if (!ip)
867 break;
868 prefix = ip->path;
869 ip = ip->next;
872 error (ERR_FATAL,
873 "unable to open include file `%s'", file);
874 return NULL; /* never reached - placate compilers */
878 * Determine if we should warn on defining a single-line macro of
879 * name `name', with `nparam' parameters. If nparam is 0, will
880 * return TRUE if _any_ single-line macro of that name is defined.
881 * Otherwise, will return TRUE if a single-line macro with either
882 * `nparam' or no parameters is defined.
884 * If a macro with precisely the right number of parameters is
885 * defined, the address of the definition structure will be
886 * returned in `defn'; otherwise NULL will be returned. If `defn'
887 * is NULL, no action will be taken regarding its contents, and no
888 * error will occur.
890 * Note that this is also called with nparam zero to resolve
891 * `ifdef'.
893 static int smacro_defined (char *name, int nparam, SMacro **defn, int nocase)
895 SMacro *m;
896 Context *ctx;
897 char *p;
899 if (name[0] == '%' && name[1] == '$') {
900 ctx = get_ctx (name);
901 if (!ctx)
902 return FALSE; /* got to return _something_ */
903 m = ctx->localmac;
904 p = name+1;
905 p += strspn(p, "$");
906 } else {
907 m = smacros[hash(name)];
908 p = name;
911 while (m) {
912 if (!mstrcmp(m->name, p, m->casesense & nocase) &&
913 (nparam == 0 || m->nparam == 0 || nparam == m->nparam)) {
914 if (defn) {
915 if (nparam == m->nparam)
916 *defn = m;
917 else
918 *defn = NULL;
920 return TRUE;
922 m = m->next;
924 return FALSE;
928 * Count and mark off the parameters in a multi-line macro call.
929 * This is called both from within the multi-line macro expansion
930 * code, and also to mark off the default parameters when provided
931 * in a %macro definition line.
933 static void count_mmac_params (Token *t, int *nparam, Token ***params)
935 int paramsize, brace;
937 *nparam = paramsize = 0;
938 *params = NULL;
939 while (t) {
940 if (*nparam >= paramsize) {
941 paramsize += PARAM_DELTA;
942 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
944 skip_white_(t);
945 brace = FALSE;
946 if (tok_is_(t, "{"))
947 brace = TRUE;
948 (*params)[(*nparam)++] = t;
949 while (tok_isnt_(t, brace ? "}" : ","))
950 t = t->next;
951 if (t) { /* got a comma/brace */
952 t = t->next;
953 if (brace) {
955 * Now we've found the closing brace, look further
956 * for the comma.
958 skip_white_(t);
959 if (tok_isnt_(t, ",")) {
960 error (ERR_NONFATAL,
961 "braces do not enclose all of macro parameter");
962 while (tok_isnt_(t, ","))
963 t = t->next;
965 if (t)
966 t = t->next; /* eat the comma */
973 * Determine whether one of the various `if' conditions is true or
974 * not.
976 * We must free the tline we get passed.
978 static int if_condition (Token *tline, int i)
980 int j, casesense;
981 Token * t, * tt, ** tptr, * origline;
982 struct tokenval tokval;
983 expr * evalresult;
985 origline = tline;
987 switch (i) {
988 case PP_IFCTX: case PP_ELIFCTX:
989 case PP_IFNCTX: case PP_ELIFNCTX:
990 j = FALSE; /* have we matched yet? */
991 if (!cstk)
992 error(ERR_FATAL,
993 "`%s': context stack is empty", directives[i]);
994 else while (tline) {
995 skip_white_(tline);
996 if (!tline || tline->type != TOK_ID) {
997 error(ERR_NONFATAL,
998 "`%s' expects context identifiers", directives[i]);
999 free_tlist (origline);
1000 return -1;
1002 if (!nasm_stricmp(tline->text, cstk->name))
1003 j = TRUE;
1004 tline = tline->next;
1006 if (i == PP_IFNCTX || i == PP_ELIFNCTX)
1007 j = !j;
1008 free_tlist (origline);
1009 return j;
1011 case PP_IFDEF: case PP_ELIFDEF:
1012 case PP_IFNDEF: case PP_ELIFNDEF:
1013 j = FALSE; /* have we matched yet? */
1014 while (tline) {
1015 skip_white_(tline);
1016 if (!tline || (tline->type != TOK_ID &&
1017 (tline->type != TOK_PREPROC_ID ||
1018 tline->text[1] != '$'))) {
1019 error(ERR_NONFATAL,
1020 "`%%if%sdef' expects macro identifiers",
1021 (i==PP_ELIFNDEF ? "n" : ""));
1022 free_tlist (origline);
1023 return -1;
1025 if (smacro_defined(tline->text, 0, NULL, 1))
1026 j = TRUE;
1027 tline = tline->next;
1029 if (i == PP_IFNDEF || i == PP_ELIFNDEF)
1030 j = !j;
1031 free_tlist (origline);
1032 return j;
1034 case PP_IFIDN: case PP_ELIFIDN: case PP_IFNIDN: case PP_ELIFNIDN:
1035 case PP_IFIDNI: case PP_ELIFIDNI: case PP_IFNIDNI: case PP_ELIFNIDNI:
1036 tline = expand_smacro(tline);
1037 t = tt = tline;
1038 while (tok_isnt_(tt, ","))
1039 tt = tt->next;
1040 if (!tt) {
1041 error(ERR_NONFATAL, "`%s' expects two comma-separated arguments");
1042 free_tlist (tline);
1043 return -1;
1045 tt = tt->next;
1046 casesense = (i == PP_IFIDN || i == PP_ELIFIDN ||
1047 i == PP_IFNIDN || i == PP_ELIFNIDN);
1048 j = TRUE; /* assume equality unless proved not */
1049 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1050 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1051 error(ERR_NONFATAL, "`%s': more than one comma on line",
1052 directives[i]);
1053 free_tlist (tline);
1054 return -1;
1056 if (t->type == TOK_WHITESPACE) {
1057 t = t->next;
1058 continue;
1059 } else if (tt->type == TOK_WHITESPACE) {
1060 tt = tt->next;
1061 continue;
1062 } else if (tt->type != t->type ||
1063 (casesense ? strcmp(tt->text, t->text) :
1064 nasm_stricmp(tt->text, t->text))) {
1065 j = FALSE; /* found mismatching tokens */
1066 break;
1067 } else {
1068 t = t->next;
1069 tt = tt->next;
1070 continue;
1073 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
1074 j = FALSE; /* trailing gunk on one end or other */
1075 if (i == PP_IFNIDN || i == PP_ELIFNIDN ||
1076 i == PP_IFNIDNI || i == PP_ELIFNIDNI)
1077 j = !j;
1078 free_tlist (tline);
1079 return j;
1081 case PP_IFID: case PP_ELIFID: case PP_IFNID: case PP_ELIFNID:
1082 case PP_IFNUM: case PP_ELIFNUM: case PP_IFNNUM: case PP_ELIFNNUM:
1083 case PP_IFSTR: case PP_ELIFSTR: case PP_IFNSTR: case PP_ELIFNSTR:
1084 tline = expand_smacro(tline);
1085 t = tline;
1086 while (tok_type_(t, TOK_WHITESPACE))
1087 t = t->next;
1088 j = FALSE; /* placate optimiser */
1089 if (t) switch (i) {
1090 case PP_IFID: case PP_ELIFID: case PP_IFNID: case PP_ELIFNID:
1091 j = (t->type == TOK_ID);
1092 break;
1093 case PP_IFNUM: case PP_ELIFNUM: case PP_IFNNUM: case PP_ELIFNNUM:
1094 j = (t->type == TOK_NUMBER);
1095 break;
1096 case PP_IFSTR: case PP_ELIFSTR: case PP_IFNSTR: case PP_ELIFNSTR:
1097 j = (t->type == TOK_STRING);
1098 break;
1100 if (i == PP_IFNID || i == PP_ELIFNID ||
1101 i == PP_IFNNUM || i == PP_ELIFNNUM ||
1102 i == PP_IFNSTR || i == PP_ELIFNSTR)
1103 j = !j;
1104 free_tlist (tline);
1105 return j;
1107 case PP_IF: case PP_ELIF:
1108 t = tline = expand_smacro(tline);
1109 tptr = &t;
1110 tokval.t_type = TOKEN_INVALID;
1111 evalresult = evaluate (ppscan, tptr, &tokval,
1112 NULL, pass | 0x10, error, NULL);
1113 free_tlist (tline);
1114 if (!evalresult)
1115 return -1;
1116 if (tokval.t_type)
1117 error(ERR_WARNING,
1118 "trailing garbage after expression ignored");
1119 if (!is_simple(evalresult)) {
1120 error(ERR_NONFATAL,
1121 "non-constant value given to `%s'", directives[i]);
1122 return -1;
1124 return reloc_value(evalresult) != 0;
1126 default:
1127 error(ERR_FATAL,
1128 "preprocessor directive `%s' not yet implemented",
1129 directives[i]);
1130 free_tlist (origline);
1131 return -1; /* yeah, right */
1136 * Find out if a line contains a preprocessor directive, and deal
1137 * with it if so.
1139 * If a directive _is_ found, we are expected to free_tlist() the
1140 * line.
1142 * Return values go like this:
1144 * bit 0 is set if a directive was found (so the line gets freed)
1146 static int do_directive (Token *tline)
1148 int i, j, k, m, nparam, nolist;
1149 char *p, *mname;
1150 Include *inc;
1151 Context *ctx;
1152 Cond *cond;
1153 SMacro *smac, **smhead;
1154 MMacro *mmac;
1155 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
1156 Line *l;
1157 struct tokenval tokval;
1158 expr *evalresult;
1160 origline = tline;
1162 skip_white_(tline);
1163 if (!tok_type_(tline, TOK_PREPROC_ID) ||
1164 (tline->text[1]=='%' || tline->text[1]=='$' || tline->text[1]=='!'))
1165 return 0;
1167 i = -1;
1168 j = sizeof(directives)/sizeof(*directives);
1169 while (j-i > 1) {
1170 k = (j+i) / 2;
1171 m = nasm_stricmp(tline->text, directives[k]);
1172 if (m == 0) {
1173 i = k;
1174 j = -2;
1175 break;
1176 } else if (m < 0) {
1177 j = k;
1178 } else
1179 i = k;
1183 * If we're in a non-emitting branch of a condition construct,
1184 * or walking to the end of an already terminated %rep block,
1185 * we should ignore all directives except for condition
1186 * directives.
1188 if (((istk->conds && !emitting(istk->conds->state)) ||
1189 (istk->mstk && !istk->mstk->in_progress)) &&
1190 i != PP_IF && i != PP_ELIF &&
1191 i != PP_IFCTX && i != PP_ELIFCTX &&
1192 i != PP_IFDEF && i != PP_ELIFDEF &&
1193 i != PP_IFID && i != PP_ELIFID &&
1194 i != PP_IFIDN && i != PP_ELIFIDN &&
1195 i != PP_IFIDNI && i != PP_ELIFIDNI &&
1196 i != PP_IFNCTX && i != PP_ELIFNCTX &&
1197 i != PP_IFNDEF && i != PP_ELIFNDEF &&
1198 i != PP_IFNID && i != PP_ELIFNID &&
1199 i != PP_IFNIDN && i != PP_ELIFNIDN &&
1200 i != PP_IFNIDNI && i != PP_ELIFNIDNI &&
1201 i != PP_IFNNUM && i != PP_ELIFNNUM &&
1202 i != PP_IFNSTR && i != PP_ELIFNSTR &&
1203 i != PP_IFNUM && i != PP_ELIFNUM &&
1204 i != PP_IFSTR && i != PP_ELIFSTR &&
1205 i != PP_ELSE && i != PP_ENDIF)
1207 return 0;
1211 * If we're defining a macro or reading a %rep block, we should
1212 * ignore all directives except for %macro/%imacro (which
1213 * generate an error), %endm/%endmacro, and (only if we're in a
1214 * %rep block) %endrep. If we're in a %rep block, another %rep
1215 * causes an error, so should be let through.
1217 if (defining && i != PP_MACRO && i != PP_IMACRO &&
1218 i != PP_ENDMACRO && i != PP_ENDM &&
1219 (defining->name || (i != PP_ENDREP && i != PP_REP)))
1221 return 0;
1224 if (j != -2) {
1225 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
1226 tline->text);
1227 return 0; /* didn't get it */
1230 switch (i) {
1232 case PP_CLEAR:
1233 if (tline->next)
1234 error(ERR_WARNING,
1235 "trailing garbage after `%%clear' ignored");
1236 for (j=0; j<NHASH; j++) {
1237 while (mmacros[j]) {
1238 MMacro *m = mmacros[j];
1239 mmacros[j] = m->next;
1240 free_mmacro(m);
1242 while (smacros[j]) {
1243 SMacro *s = smacros[j];
1244 smacros[j] = smacros[j]->next;
1245 nasm_free (s->name);
1246 free_tlist (s->expansion);
1247 nasm_free (s);
1250 free_tlist (origline);
1251 return 3;
1253 case PP_INCLUDE:
1254 tline = tline->next;
1255 skip_white_(tline);
1256 if (!tline || (tline->type != TOK_STRING &&
1257 tline->type != TOK_INTERNAL_STRING))
1259 error(ERR_NONFATAL, "`%%include' expects a file name");
1260 free_tlist (origline);
1261 return 3; /* but we did _something_ */
1263 if (tline->next)
1264 error(ERR_WARNING,
1265 "trailing garbage after `%%include' ignored");
1266 if (tline->type != TOK_INTERNAL_STRING) {
1267 p = tline->text+1; /* point past the quote to the name */
1268 p[strlen(p)-1] = '\0'; /* remove the trailing quote */
1269 } else
1270 p = tline->text; /* internal_string is easier */
1271 inc = nasm_malloc(sizeof(Include));
1272 inc->next = istk;
1273 inc->conds = NULL;
1274 inc->fp = inc_fopen(p);
1275 inc->fname = src_set_fname(nasm_strdup(p));
1276 inc->lineno = src_set_linnum(0);
1277 inc->lineinc = 1;
1278 inc->expansion = NULL;
1279 inc->mstk = NULL;
1280 istk = inc;
1281 list->uplevel (LIST_INCLUDE);
1282 free_tlist (origline);
1283 return 5;
1285 case PP_PUSH:
1286 tline = tline->next;
1287 skip_white_(tline);
1288 if (!tok_type_(tline, TOK_ID)) {
1289 error(ERR_NONFATAL,
1290 "`%%push' expects a context identifier");
1291 free_tlist (origline);
1292 return 3; /* but we did _something_ */
1294 if (tline->next)
1295 error(ERR_WARNING,
1296 "trailing garbage after `%%push' ignored");
1297 ctx = nasm_malloc(sizeof(Context));
1298 ctx->next = cstk;
1299 ctx->localmac = NULL;
1300 ctx->name = nasm_strdup(tline->text);
1301 ctx->number = unique++;
1302 cstk = ctx;
1303 free_tlist (origline);
1304 break;
1306 case PP_REPL:
1307 tline = tline->next;
1308 skip_white_(tline);
1309 if (!tok_type_(tline, TOK_ID)) {
1310 error(ERR_NONFATAL,
1311 "`%%repl' expects a context identifier");
1312 free_tlist (origline);
1313 return 3; /* but we did _something_ */
1315 if (tline->next)
1316 error(ERR_WARNING,
1317 "trailing garbage after `%%repl' ignored");
1318 if (!cstk)
1319 error(ERR_NONFATAL,
1320 "`%%repl': context stack is empty");
1321 else {
1322 nasm_free (cstk->name);
1323 cstk->name = nasm_strdup(tline->text);
1325 free_tlist (origline);
1326 break;
1328 case PP_POP:
1329 if (tline->next)
1330 error(ERR_WARNING,
1331 "trailing garbage after `%%pop' ignored");
1332 if (!cstk)
1333 error(ERR_NONFATAL,
1334 "`%%pop': context stack is already empty");
1335 else
1336 ctx_pop();
1337 free_tlist (origline);
1338 break;
1340 case PP_ERROR:
1341 tline->next = expand_smacro (tline->next);
1342 tline = tline->next;
1343 skip_white_(tline);
1344 if (tok_type_(tline, TOK_STRING)) {
1345 p = tline->text+1; /* point past the quote to the name */
1346 p[strlen(p)-1] = '\0'; /* remove the trailing quote */
1347 error(ERR_NONFATAL, "user error: %s", p);
1348 } else {
1349 p = detoken(tline);
1350 error(ERR_WARNING, "user error: %s", p);
1351 nasm_free(p);
1353 free_tlist (origline);
1354 break;
1356 case PP_IF:
1357 case PP_IFCTX:
1358 case PP_IFDEF:
1359 case PP_IFID:
1360 case PP_IFIDN:
1361 case PP_IFIDNI:
1362 case PP_IFNCTX:
1363 case PP_IFNDEF:
1364 case PP_IFNID:
1365 case PP_IFNIDN:
1366 case PP_IFNIDNI:
1367 case PP_IFNNUM:
1368 case PP_IFNSTR:
1369 case PP_IFNUM:
1370 case PP_IFSTR:
1371 if (istk->conds && !emitting(istk->conds->state))
1372 j = COND_NEVER;
1373 else {
1374 j = if_condition(tline->next, i);
1375 tline->next = NULL; /* it got freed */
1376 free_tlist (origline);
1377 if (j < 0)
1379 * Bogus expression in %if, but we should pretend
1380 * it was OK anyway, so that we don't get an error
1381 * cascade on the subsequent %else / %endif.
1383 j = COND_NEVER;
1384 else
1385 j = j ? COND_IF_TRUE : COND_IF_FALSE;
1387 cond = nasm_malloc(sizeof(Cond));
1388 cond->next = istk->conds;
1389 cond->state = j;
1390 istk->conds = cond;
1391 return (j == COND_IF_TRUE ? 3 : 1);
1393 case PP_ELIF:
1394 case PP_ELIFCTX:
1395 case PP_ELIFDEF:
1396 case PP_ELIFID:
1397 case PP_ELIFIDN:
1398 case PP_ELIFIDNI:
1399 case PP_ELIFNCTX:
1400 case PP_ELIFNDEF:
1401 case PP_ELIFNID:
1402 case PP_ELIFNIDN:
1403 case PP_ELIFNIDNI:
1404 case PP_ELIFNNUM:
1405 case PP_ELIFNSTR:
1406 case PP_ELIFNUM:
1407 case PP_ELIFSTR:
1408 if (!istk->conds)
1409 error(ERR_FATAL, "`%s': no matching `%%if'",
1410 directives[i]);
1411 if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
1412 istk->conds->state = COND_NEVER;
1413 else {
1414 j = if_condition(tline->next, i);
1415 tline->next = NULL; /* it got freed */
1416 free_tlist (origline);
1417 if (j < 0)
1419 * The expression was bogus, but let's make
1420 * %endif not complain about missing %if
1422 j = COND_NEVER;
1423 else
1424 istk->conds->state = j ? COND_IF_TRUE : COND_IF_FALSE;
1426 return (istk->conds->state == COND_IF_TRUE ? 5 : 1);
1428 case PP_ELSE:
1429 if (tline->next)
1430 error(ERR_WARNING,
1431 "trailing garbage after `%%else' ignored");
1432 if (!istk->conds)
1433 error(ERR_FATAL,
1434 "`%%else': no matching `%%if'");
1435 if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
1436 istk->conds->state = COND_ELSE_FALSE;
1437 else
1438 istk->conds->state = COND_ELSE_TRUE;
1439 free_tlist (origline);
1440 return 5;
1442 case PP_ENDIF:
1443 if (tline->next)
1444 error(ERR_WARNING,
1445 "trailing garbage after `%%endif' ignored");
1446 if (!istk->conds)
1447 error(ERR_FATAL,
1448 "`%%endif': no matching `%%if'");
1449 cond = istk->conds;
1450 istk->conds = cond->next;
1451 nasm_free (cond);
1452 free_tlist (origline);
1453 return 5;
1455 case PP_MACRO:
1456 case PP_IMACRO:
1457 if (defining)
1458 error (ERR_FATAL,
1459 "`%%%smacro': already defining a macro",
1460 (i == PP_IMACRO ? "i" : ""));
1461 tline = tline->next;
1462 skip_white_(tline);
1463 if (!tok_type_(tline, TOK_ID)) {
1464 error (ERR_NONFATAL,
1465 "`%%%smacro' expects a macro name",
1466 (i == PP_IMACRO ? "i" : ""));
1467 return 3;
1469 defining = nasm_malloc(sizeof(MMacro));
1470 defining->name = nasm_strdup(tline->text);
1471 defining->casesense = (i == PP_MACRO);
1472 defining->plus = FALSE;
1473 defining->nolist = FALSE;
1474 defining->in_progress = FALSE;
1475 tline = tline->next;
1476 skip_white_(tline);
1477 if (!tok_type_(tline, TOK_NUMBER)) {
1478 error (ERR_NONFATAL,
1479 "`%%%smacro' expects a parameter count",
1480 (i == PP_IMACRO ? "i" : ""));
1481 defining->nparam_min = defining->nparam_max = 0;
1482 } else {
1483 defining->nparam_min = defining->nparam_max =
1484 readnum(tline->text, &j);
1485 if (j)
1486 error (ERR_NONFATAL,
1487 "unable to parse parameter count `%s'", tline->text);
1489 if (tline && tok_is_(tline->next, "-")) {
1490 tline = tline->next->next;
1491 if (tok_is_(tline, "*"))
1492 defining->nparam_max = INT_MAX;
1493 else if (!tok_type_(tline, TOK_NUMBER))
1494 error (ERR_NONFATAL,
1495 "`%%%smacro' expects a parameter count after `-'",
1496 (i == PP_IMACRO ? "i" : ""));
1497 else {
1498 defining->nparam_max = readnum(tline->text, &j);
1499 if (j)
1500 error (ERR_NONFATAL,
1501 "unable to parse parameter count `%s'",
1502 tline->text);
1503 if (defining->nparam_min > defining->nparam_max)
1504 error (ERR_NONFATAL,
1505 "minimum parameter count exceeds maximum");
1508 if (tline && tok_is_(tline->next, "+")) {
1509 tline = tline->next;
1510 defining->plus = TRUE;
1512 if (tline && tok_type_(tline->next, TOK_ID) &&
1513 !nasm_stricmp(tline->next->text, ".nolist"))
1515 tline = tline->next;
1516 defining->nolist = TRUE;
1518 mmac = mmacros[hash(defining->name)];
1519 while (mmac) {
1520 if (!strcmp(mmac->name, defining->name) &&
1521 (mmac->nparam_min<=defining->nparam_max || defining->plus) &&
1522 (defining->nparam_min<=mmac->nparam_max || mmac->plus))
1524 error (ERR_WARNING,
1525 "redefining multi-line macro `%s'", defining->name);
1526 break;
1528 mmac = mmac->next;
1531 * Handle default parameters.
1533 if (tline && tline->next) {
1534 defining->dlist = tline->next;
1535 tline->next = NULL;
1536 count_mmac_params (defining->dlist, &defining->ndefs,
1537 &defining->defaults);
1538 } else {
1539 defining->dlist = NULL;
1540 defining->defaults = NULL;
1542 defining->expansion = NULL;
1543 free_tlist (origline);
1544 return 1;
1546 case PP_ENDM:
1547 case PP_ENDMACRO:
1548 if (!defining) {
1549 error (ERR_NONFATAL, "`%s': not defining a macro",
1550 tline->text);
1551 return 3;
1553 k = hash(defining->name);
1554 defining->next = mmacros[k];
1555 mmacros[k] = defining;
1556 defining = NULL;
1557 free_tlist (origline);
1558 return 5;
1560 case PP_ROTATE:
1561 if (tline->next && tline->next->type == TOK_WHITESPACE)
1562 tline = tline->next;
1563 t = expand_smacro(tline->next);
1564 tline->next = NULL;
1565 free_tlist (origline);
1566 tline = t;
1567 tptr = &t;
1568 tokval.t_type = TOKEN_INVALID;
1569 evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
1570 free_tlist (tline);
1571 if (!evalresult)
1572 return 3;
1573 if (tokval.t_type)
1574 error(ERR_WARNING,
1575 "trailing garbage after expression ignored");
1576 if (!is_simple(evalresult)) {
1577 error(ERR_NONFATAL,
1578 "non-constant value given to `%%rotate'");
1579 return 3;
1581 mmac = istk->mstk;
1582 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
1583 mmac = mmac->next_active;
1584 if (!mmac)
1585 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
1586 mmac->rotate = mmac->rotate + reloc_value(evalresult);
1587 if (mmac->rotate < 0)
1588 mmac->rotate = mmac->nparam - (-mmac->rotate) % mmac->nparam;
1589 mmac->rotate %= mmac->nparam;
1590 return 1;
1592 case PP_REP:
1593 if (defining) {
1595 * We don't allow nested %reps, because of a strange bug
1596 * that was causing a panic. The cause of the bug appears to be
1597 * that the nested %rep isn't taken into account when matching
1598 * against the %endreps, so some mechanism to count the
1599 * %reps in and the %endreps out may well work here.
1601 * That's for experimentation with later, though.
1602 * For informations sake, the panic produced by
1603 * nesting %reps was:
1605 * istk->mstk has no name but defining is set at end
1606 * of expansion
1608 error(ERR_NONFATAL, "nested `%%rep' invocation not allowed");
1609 break;
1611 nolist = FALSE;
1612 tline = tline->next;
1613 if (tline->next && tline->next->type == TOK_WHITESPACE)
1614 tline = tline->next;
1615 if (tline->next && tline->next->type == TOK_ID &&
1616 !nasm_stricmp(tline->next->text, ".nolist")) {
1617 tline = tline->next;
1618 nolist = TRUE;
1620 t = expand_smacro(tline->next);
1621 tline->next = NULL;
1622 free_tlist (origline);
1623 tline = t;
1624 tptr = &t;
1625 tokval.t_type = TOKEN_INVALID;
1626 evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
1627 free_tlist (tline);
1628 if (!evalresult)
1629 return 3;
1630 if (tokval.t_type)
1631 error(ERR_WARNING,
1632 "trailing garbage after expression ignored");
1633 if (!is_simple(evalresult)) {
1634 error(ERR_NONFATAL,
1635 "non-constant value given to `%%rep'");
1636 return 3;
1638 defining = nasm_malloc(sizeof(MMacro));
1639 defining->name = NULL; /* flags this macro as a %rep block */
1640 defining->casesense = 0;
1641 defining->plus = FALSE;
1642 defining->nolist = nolist;
1643 defining->in_progress = reloc_value(evalresult) + 1;
1644 defining->nparam_min = defining->nparam_max = 0;
1645 defining->defaults = NULL;
1646 defining->dlist = NULL;
1647 defining->expansion = NULL;
1648 defining->next_active = istk->mstk;
1649 return 1;
1651 case PP_ENDREP:
1652 if (!defining || defining->name) {
1653 error (ERR_NONFATAL,
1654 "`%%endrep': no matching `%%rep'");
1655 return 3;
1659 * Now we have a "macro" defined - although it has no name
1660 * and we won't be entering it in the hash tables - we must
1661 * push a macro-end marker for it on to istk->expansion.
1662 * After that, it will take care of propagating itself (a
1663 * macro-end marker line for a macro which is really a %rep
1664 * block will cause the macro to be re-expanded, complete
1665 * with another macro-end marker to ensure the process
1666 * continues) until the whole expansion is forcibly removed
1667 * from istk->expansion by a %exitrep.
1669 l = nasm_malloc(sizeof(Line));
1670 l->next = istk->expansion;
1671 l->finishes = defining;
1672 l->first = NULL;
1673 istk->expansion = l;
1675 istk->mstk = defining;
1677 list->uplevel (defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
1678 defining = NULL;
1679 free_tlist (origline);
1680 return 1;
1682 case PP_EXITREP:
1684 * We must search along istk->expansion until we hit a
1685 * macro-end marker for a macro with no name. Then we set
1686 * its `in_progress' flag to 0.
1688 for (l = istk->expansion; l; l = l->next)
1689 if (l->finishes && !l->finishes->name)
1690 break;
1692 if (l)
1693 l->finishes->in_progress = 0;
1694 else
1695 error (ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
1696 free_tlist (origline);
1697 return 1;
1699 case PP_DEFINE:
1700 case PP_IDEFINE:
1701 tline = tline->next;
1702 skip_white_(tline);
1703 if (!tline || (tline->type != TOK_ID &&
1704 (tline->type != TOK_PREPROC_ID ||
1705 tline->text[1] != '$'))) {
1706 error (ERR_NONFATAL,
1707 "`%%%sdefine' expects a macro identifier",
1708 (i == PP_IDEFINE ? "i" : ""));
1709 free_tlist (origline);
1710 return 3;
1712 mname = tline->text;
1713 if (tline->type == TOK_ID) {
1714 p = tline->text;
1715 smhead = &smacros[hash(mname)];
1716 } else {
1717 ctx = get_ctx (tline->text);
1718 if (ctx == NULL)
1719 return 3;
1720 else {
1721 p = tline->text+1;
1722 p += strspn(p, "$");
1723 smhead = &ctx->localmac;
1726 last = tline;
1727 param_start = tline = tline->next;
1728 nparam = 0;
1729 if (tok_is_(tline, "(")) {
1731 * This macro has parameters.
1734 tline = tline->next;
1735 while (1) {
1736 skip_white_(tline);
1737 if (!tline) {
1738 error (ERR_NONFATAL,
1739 "parameter identifier expected");
1740 free_tlist (origline);
1741 return 3;
1743 if (tline->type != TOK_ID) {
1744 error (ERR_NONFATAL,
1745 "`%s': parameter identifier expected",
1746 tline->text);
1747 free_tlist (origline);
1748 return 3;
1750 tline->type = TOK_SMAC_PARAM + nparam++;
1751 tline = tline->next;
1752 skip_white_(tline);
1753 if (tok_is_(tline, ",")) {
1754 tline = tline->next;
1755 continue;
1757 if (!tok_is_(tline, ")")) {
1758 error (ERR_NONFATAL,
1759 "`)' expected to terminate macro template");
1760 free_tlist (origline);
1761 return 3;
1763 break;
1765 last = tline;
1766 tline = tline->next;
1768 if (tok_type_(tline, TOK_WHITESPACE))
1769 last = tline, tline = tline->next;
1770 macro_start = NULL;
1771 last->next = NULL;
1772 t = tline;
1773 while (t) {
1774 if (t->type == TOK_ID) {
1775 for (tt = param_start; tt; tt = tt->next)
1776 if (tt->type >= TOK_SMAC_PARAM &&
1777 !strcmp(tt->text, t->text))
1778 t->type = tt->type;
1780 tt = t->next;
1781 t->next = macro_start;
1782 macro_start = t;
1783 t = tt;
1786 * Good. We now have a macro name, a parameter count, and a
1787 * token list (in reverse order) for an expansion. We ought
1788 * to be OK just to create an SMacro, store it, and let
1789 * free_tlist have the rest of the line (which we have
1790 * carefully re-terminated after chopping off the expansion
1791 * from the end).
1793 if (smacro_defined (mname, nparam, &smac, i==PP_DEFINE)) {
1794 if (!smac) {
1795 error (ERR_WARNING,
1796 "single-line macro `%s' defined both with and"
1797 " without parameters", mname);
1798 free_tlist (origline);
1799 free_tlist (macro_start);
1800 return 3;
1801 } else {
1803 * We're redefining, so we have to take over an
1804 * existing SMacro structure. This means freeing
1805 * what was already in it.
1807 nasm_free (smac->name);
1808 free_tlist (smac->expansion);
1810 } else {
1811 smac = nasm_malloc(sizeof(SMacro));
1812 smac->next = *smhead;
1813 *smhead = smac;
1815 smac->name = nasm_strdup(p);
1816 smac->casesense = (i == PP_DEFINE);
1817 smac->nparam = nparam;
1818 smac->expansion = macro_start;
1819 smac->in_progress = FALSE;
1820 free_tlist (origline);
1821 return 3;
1823 case PP_ASSIGN:
1824 case PP_IASSIGN:
1825 tline = tline->next;
1826 skip_white_(tline);
1827 if (!tline || (tline->type != TOK_ID &&
1828 (tline->type != TOK_PREPROC_ID ||
1829 tline->text[1] != '$'))) {
1830 error (ERR_NONFATAL,
1831 "`%%%sassign' expects a macro identifier",
1832 (i == PP_IASSIGN ? "i" : ""));
1833 free_tlist (origline);
1834 return 3;
1836 mname = tline->text;
1837 if (tline->type == TOK_ID) {
1838 p = tline->text;
1839 smhead = &smacros[hash(mname)];
1840 } else {
1841 ctx = get_ctx (tline->text);
1842 if (ctx == NULL) {
1843 free_tlist (origline);
1844 return 3;
1845 } else {
1846 p = tline->text+1;
1847 p += strspn(p, "$");
1848 smhead = &ctx->localmac;
1851 last = tline;
1852 tline = tline->next;
1853 last->next = NULL;
1855 tline = expand_smacro (tline);
1856 t = tline;
1857 tptr = &t;
1858 tokval.t_type = TOKEN_INVALID;
1859 evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
1860 free_tlist (tline);
1861 if (!evalresult) {
1862 free_tlist (origline);
1863 return 3;
1866 if (tokval.t_type)
1867 error(ERR_WARNING,
1868 "trailing garbage after expression ignored");
1870 if (!is_simple(evalresult)) {
1871 error(ERR_NONFATAL,
1872 "non-constant value given to `%%%sassign'",
1873 (i == PP_IASSIGN ? "i" : ""));
1874 free_tlist (origline);
1875 return 3;
1878 macro_start = nasm_malloc(sizeof(*macro_start));
1879 macro_start->next = NULL;
1880 make_tok_num(macro_start, reloc_value(evalresult));
1881 macro_start->mac = NULL;
1884 * We now have a macro name, an implicit parameter count of
1885 * zero, and a numeric token to use as an expansion. Create
1886 * and store an SMacro.
1888 if (smacro_defined (mname, 0, &smac, i==PP_ASSIGN)) {
1889 if (!smac)
1890 error (ERR_WARNING,
1891 "single-line macro `%s' defined both with and"
1892 " without parameters", mname);
1893 else {
1895 * We're redefining, so we have to take over an
1896 * existing SMacro structure. This means freeing
1897 * what was already in it.
1899 nasm_free (smac->name);
1900 free_tlist (smac->expansion);
1903 else {
1904 smac = nasm_malloc(sizeof(SMacro));
1905 smac->next = *smhead;
1906 *smhead = smac;
1908 smac->name = nasm_strdup(p);
1909 smac->casesense = (i == PP_ASSIGN);
1910 smac->nparam = 0;
1911 smac->expansion = macro_start;
1912 smac->in_progress = FALSE;
1913 free_tlist (origline);
1914 return 3;
1916 case PP_LINE:
1918 * Syntax is `%line nnn[+mmm] [filename]'
1920 tline = tline->next;
1921 skip_white_(tline);
1922 if (!tok_type_(tline, TOK_NUMBER)) {
1923 error (ERR_NONFATAL, "`%%line' expects line number");
1924 free_tlist (origline);
1925 return 3;
1927 k = readnum(tline->text, &j);
1928 m = 1;
1929 tline = tline->next;
1930 if (tok_is_(tline, "+")) {
1931 tline = tline->next;
1932 if (!tok_type_(tline, TOK_NUMBER)) {
1933 error (ERR_NONFATAL,
1934 "`%%line' expects line increment");
1935 free_tlist (origline);
1936 return 3;
1938 m = readnum(tline->text, &j);
1939 tline = tline->next;
1941 skip_white_(tline);
1942 src_set_linnum(k);
1943 istk->lineinc = m;
1944 if (tline) {
1945 nasm_free ( src_set_fname ( detoken(tline) ) );
1947 free_tlist (origline);
1948 return 5;
1950 default:
1951 error(ERR_FATAL,
1952 "preprocessor directive `%s' not yet implemented",
1953 directives[i]);
1954 break;
1956 return 3;
1960 * Ensure that a macro parameter contains a condition code and
1961 * nothing else. Return the condition code index if so, or -1
1962 * otherwise.
1964 static int find_cc (Token *t)
1966 Token *tt;
1967 int i, j, k, m;
1969 skip_white_(t);
1970 if (t->type != TOK_ID)
1971 return -1;
1972 tt = t->next;
1973 skip_white_(tt);
1974 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
1975 return -1;
1977 i = -1;
1978 j = sizeof(conditions)/sizeof(*conditions);
1979 while (j-i > 1) {
1980 k = (j+i) / 2;
1981 m = nasm_stricmp(t->text, conditions[k]);
1982 if (m == 0) {
1983 i = k;
1984 j = -2;
1985 break;
1986 } else if (m < 0) {
1987 j = k;
1988 } else
1989 i = k;
1991 if (j != -2)
1992 return -1;
1993 return i;
1997 * Expand MMacro-local things: parameter references (%0, %n, %+n,
1998 * %-n) and MMacro-local identifiers (%%foo).
2000 static Token *expand_mmac_params (Token *tline)
2002 Token *t, *tt, *ttt, **tail, *thead;
2004 tail = &thead;
2005 thead = NULL;
2007 while (tline) {
2008 if (tline->type == TOK_PREPROC_ID &&
2009 (tline->text[1] == '+' || tline->text[1] == '-' ||
2010 tline->text[1] == '%' ||
2011 (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
2012 char *text = NULL;
2013 int type = 0, cc; /* type = 0 to placate optimisers */
2014 char tmpbuf[30];
2015 int n, i;
2016 MMacro *mac;
2018 t = tline;
2019 tline = tline->next;
2021 mac = istk->mstk;
2022 while (mac && !mac->name) /* avoid mistaking %reps for macros */
2023 mac = mac->next_active;
2024 if (!mac)
2025 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
2026 else switch (t->text[1]) {
2028 * We have to make a substitution of one of the
2029 * forms %1, %-1, %+1, %%foo, %0.
2031 case '0':
2032 type = TOK_NUMBER;
2033 sprintf(tmpbuf, "%d", mac->nparam);
2034 text = nasm_strdup(tmpbuf);
2035 break;
2036 case '%':
2037 type = TOK_ID;
2038 sprintf(tmpbuf, "..@%lu.", mac->unique);
2039 text = nasm_strcat(tmpbuf, t->text+2);
2040 break;
2041 case '-':
2042 n = atoi(t->text+2)-1;
2043 if (n >= mac->nparam)
2044 tt = NULL;
2045 else {
2046 if (mac->nparam > 1)
2047 n = (n + mac->rotate) % mac->nparam;
2048 tt = mac->params[n];
2050 cc = find_cc (tt);
2051 if (cc == -1) {
2052 error (ERR_NONFATAL,
2053 "macro parameter %d is not a condition code",
2054 n+1);
2055 text = NULL;
2056 } else {
2057 type = TOK_ID;
2058 if (inverse_ccs[cc] == -1) {
2059 error (ERR_NONFATAL,
2060 "condition code `%s' is not invertible",
2061 conditions[cc]);
2062 text = NULL;
2063 } else
2064 text = nasm_strdup(conditions[inverse_ccs[cc]]);
2066 break;
2067 case '+':
2068 n = atoi(t->text+2)-1;
2069 if (n >= mac->nparam)
2070 tt = NULL;
2071 else {
2072 if (mac->nparam > 1)
2073 n = (n + mac->rotate) % mac->nparam;
2074 tt = mac->params[n];
2076 cc = find_cc (tt);
2077 if (cc == -1) {
2078 error (ERR_NONFATAL,
2079 "macro parameter %d is not a condition code",
2080 n+1);
2081 text = NULL;
2082 } else {
2083 type = TOK_ID;
2084 text = nasm_strdup(conditions[cc]);
2086 break;
2087 default:
2088 n = atoi(t->text+1)-1;
2089 if (n >= mac->nparam)
2090 tt = NULL;
2091 else {
2092 if (mac->nparam > 1)
2093 n = (n + mac->rotate) % mac->nparam;
2094 tt = mac->params[n];
2096 if (tt) {
2097 for (i=0; i<mac->paramlen[n]; i++) {
2098 ttt = *tail = nasm_malloc(sizeof(Token));
2099 tail = &ttt->next;
2100 ttt->type = tt->type;
2101 ttt->text = nasm_strdup(tt->text);
2102 ttt->mac = NULL;
2103 tt = tt->next;
2106 text = NULL; /* we've done it here */
2107 break;
2109 nasm_free (t->text);
2110 if (!text) {
2111 nasm_free (t);
2112 } else {
2113 *tail = t;
2114 tail = &t->next;
2115 t->type = type;
2116 t->text = text;
2117 t->mac = NULL;
2119 continue;
2120 } else {
2121 t = *tail = tline;
2122 tline = tline->next;
2123 t->mac = NULL;
2124 tail = &t->next;
2127 *tail = NULL;
2128 t = thead;
2129 for (; t && (tt=t->next)!=NULL ; t = t->next)
2130 switch (t->type) {
2131 case TOK_WHITESPACE:
2132 if (tt->type == TOK_WHITESPACE) {
2133 t->next = tt->next;
2134 nasm_free(tt->text);
2135 nasm_free(tt);
2137 break;
2138 case TOK_ID:
2139 if (tt->type == TOK_ID || tt->type == TOK_NUMBER) {
2140 char *tmp = nasm_strcat(t->text, tt->text);
2141 nasm_free(t->text);
2142 t->text = tmp;
2143 t->next = tt->next;
2144 nasm_free(tt->text);
2145 nasm_free(tt);
2147 break;
2148 case TOK_NUMBER:
2149 if (tt->type == TOK_NUMBER) {
2150 char *tmp = nasm_strcat(t->text, tt->text);
2151 nasm_free(t->text);
2152 t->text = tmp;
2153 t->next = tt->next;
2154 nasm_free(tt->text);
2155 nasm_free(tt);
2157 break;
2160 return thead;
2164 * Expand all single-line macro calls made in the given line.
2165 * Return the expanded version of the line. The original is deemed
2166 * to be destroyed in the process. (In reality we'll just move
2167 * Tokens from input to output a lot of the time, rather than
2168 * actually bothering to destroy and replicate.)
2170 static Token *expand_smacro (Token *tline)
2172 Token *t, *tt, *mstart, **tail, *thead;
2173 SMacro *head = NULL, *m;
2174 Token **params;
2175 int *paramsize;
2176 int nparam, sparam, brackets;
2177 char *p;
2179 tail = &thead;
2180 thead = NULL;
2182 while (tline) { /* main token loop */
2183 p = NULL;
2184 if (tline->type == TOK_ID) {
2185 head = smacros[hash(tline->text)];
2186 p = tline->text;
2187 } else if (tline->type == TOK_PREPROC_ID && tline->text[1] == '$') {
2188 Context *ctx = get_ctx (tline->text);
2189 if (ctx) {
2190 head = ctx->localmac;
2191 p = tline->text+2;
2192 p += strspn(p, "$");
2195 if (p) {
2197 * We've hit an identifier. As in is_mmacro below, we first
2198 * check whether the identifier is a single-line macro at
2199 * all, then think about checking for parameters if
2200 * necessary.
2202 for (m = head; m; m = m->next)
2203 if (!mstrcmp(m->name, p, m->casesense))
2204 break;
2205 if (m) {
2206 mstart = tline;
2207 params = NULL;
2208 paramsize = NULL;
2209 if (m->nparam == 0) {
2211 * Simple case: the macro is parameterless. Discard the
2212 * one token that the macro call took, and push the
2213 * expansion back on the to-do stack.
2215 if (!m->expansion)
2217 if (!strcmp("__FILE__", m->name)) {
2218 long num=0;
2219 src_get(&num, &(tline->text));
2220 nasm_quote(&(tline->text));
2221 tline->type = TOK_STRING;
2222 continue;
2224 if (!strcmp("__LINE__", m->name)) {
2225 nasm_free(tline->text);
2226 make_tok_num(tline, src_get_linnum());
2227 continue;
2229 t = tline;
2230 tline = tline->next;
2231 nasm_free (t->text);
2232 nasm_free (t);
2233 continue;
2236 else {
2238 * Complicated case: at least one macro with this name
2239 * exists and takes parameters. We must find the
2240 * parameters in the call, count them, find the SMacro
2241 * that corresponds to that form of the macro call, and
2242 * substitute for the parameters when we expand. What a
2243 * pain.
2245 tline = tline->next;
2246 skip_white_(tline);
2247 if (!tok_is_(tline, "(")) {
2249 * This macro wasn't called with parameters: ignore
2250 * the call. (Behaviour borrowed from gnu cpp.)
2252 tline = mstart;
2253 m = NULL;
2255 else {
2256 int paren = 0;
2257 int white = 0;
2258 brackets = 0;
2259 nparam = 0;
2260 tline = tline->next;
2261 sparam = PARAM_DELTA;
2262 params = nasm_malloc (sparam*sizeof(Token *));
2263 params[0] = tline;
2264 paramsize = nasm_malloc (sparam*sizeof(int));
2265 paramsize[0] = 0;
2266 for (;;tline = tline->next) { /* parameter loop */
2267 if (!tline) {
2268 error(ERR_NONFATAL,
2269 "macro call expects terminating `)'");
2270 break;
2272 if (tline->type == TOK_WHITESPACE && brackets<=0) {
2273 if (paramsize[nparam])
2274 white++;
2275 else
2276 params[nparam] = tline->next;
2277 continue; /* parameter loop */
2279 if (tline->type == TOK_OTHER && tline->text[1]==0) {
2280 char ch = tline->text[0];
2281 if (ch == ',' && !paren && brackets<=0) {
2282 if (++nparam >= sparam) {
2283 sparam += PARAM_DELTA;
2284 params = nasm_realloc (params,
2285 sparam*sizeof(Token *));
2286 paramsize = nasm_realloc (paramsize,
2287 sparam*sizeof(int));
2289 params[nparam] = tline->next;
2290 paramsize[nparam] = 0;
2291 white = 0;
2292 continue; /* parameter loop */
2294 if (ch == br0 &&
2295 (brackets>0 || (brackets==0 &&
2296 !paramsize[nparam])))
2298 if (!(brackets++))
2300 params[nparam] = tline->next;
2301 continue; /* parameter loop */
2304 if (ch == br2 && brackets>0)
2305 if (--brackets == 0) {
2306 brackets = -1;
2307 continue; /* parameter loop */
2309 if (ch == '(' && !brackets)
2310 paren++;
2311 if (ch == ')' && brackets<=0)
2312 if (--paren < 0)
2313 break;
2315 if (brackets<0) {
2316 brackets = 0;
2317 error (ERR_NONFATAL, "braces do not "
2318 "enclose all of macro parameter");
2320 paramsize[nparam] += white+1;
2321 white = 0;
2322 } /* parameter loop */
2323 nparam++;
2324 while (m && (m->nparam != nparam ||
2325 mstrcmp(m->name, p, m->casesense)))
2326 m = m->next;
2327 if (!m)
2328 error (ERR_WARNING|ERR_WARN_MNP,
2329 "macro `%s' exists, "
2330 "but not taking %d parameters",
2331 mstart->text, nparam);
2334 if (m && m->in_progress)
2335 m = NULL;
2336 if (!m) /* in progess or didn't find '(' or wrong nparam */
2339 * Design question: should we handle !tline, which
2340 * indicates missing ')' here, or expand those
2341 * macros anyway, which requires the (t) test a few
2342 * lines down?
2344 nasm_free (params);
2345 nasm_free (paramsize);
2346 tline = mstart;
2348 else {
2350 * Expand the macro: we are placed on the last token of the
2351 * call, so that we can easily split the call from the
2352 * following tokens. We also start by pushing an SMAC_END
2353 * token for the cycle removal.
2355 t = tline;
2356 if (t) {
2357 tline = t->next;
2358 t->next = NULL;
2360 tt = nasm_malloc(sizeof(Token));
2361 tt->type = TOK_SMAC_END;
2362 tt->text = NULL;
2363 tt->mac = m;
2364 m->in_progress = TRUE;
2365 tt->next = tline;
2366 tline = tt;
2367 for (t = m->expansion; t; t = t->next) {
2368 if (t->type >= TOK_SMAC_PARAM) {
2369 Token *pcopy = tline, **ptail = &pcopy;
2370 Token *ttt, *pt;
2371 int i;
2373 ttt = params[t->type - TOK_SMAC_PARAM];
2374 for (i=paramsize[t->type-TOK_SMAC_PARAM]; --i>=0;) {
2375 pt = *ptail = nasm_malloc(sizeof(Token));
2376 pt->next = tline;
2377 ptail = &pt->next;
2378 pt->text = nasm_strdup(ttt->text);
2379 pt->type = ttt->type;
2380 pt->mac = NULL;
2381 ttt = ttt->next;
2383 tline = pcopy;
2384 } else {
2385 tt = nasm_malloc(sizeof(Token));
2386 tt->type = t->type;
2387 tt->text = nasm_strdup(t->text);
2388 tt->mac = NULL;
2389 tt->next = tline;
2390 tline = tt;
2395 * Having done that, get rid of the macro call, and clean
2396 * up the parameters.
2398 nasm_free (params);
2399 nasm_free (paramsize);
2400 free_tlist (mstart);
2401 continue; /* main token loop */
2406 if (tline->type == TOK_SMAC_END) {
2407 tline->mac->in_progress = FALSE;
2408 t = tline;
2409 tline = tline->next;
2410 nasm_free (t);
2411 } else {
2412 t = *tail = tline;
2413 tline = tline->next;
2414 t->mac = NULL;
2415 t->next = NULL;
2416 tail = &t->next;
2417 if (t->type == TOK_PREPROC_ID && t->text[1] == '$') {
2418 Context *c = get_ctx (t->text);
2419 char *p, *q, buffer[40];
2421 t->type = TOK_ID;
2422 if (c) {
2423 q = t->text+1;
2424 q += strspn(q, "$");
2425 sprintf(buffer, "..@%lu.", c->number);
2426 p = nasm_strcat (buffer,q);
2427 nasm_free (t->text);
2428 t->text = p;
2434 return thead;
2438 * Determine whether the given line constitutes a multi-line macro
2439 * call, and return the MMacro structure called if so. Doesn't have
2440 * to check for an initial label - that's taken care of in
2441 * expand_mmacro - but must check numbers of parameters. Guaranteed
2442 * to be called with tline->type == TOK_ID, so the putative macro
2443 * name is easy to find.
2445 static MMacro *is_mmacro (Token *tline, Token ***params_array)
2447 MMacro *head, *m;
2448 Token **params;
2449 int nparam;
2451 head = mmacros[hash(tline->text)];
2454 * Efficiency: first we see if any macro exists with the given
2455 * name. If not, we can return NULL immediately. _Then_ we
2456 * count the parameters, and then we look further along the
2457 * list if necessary to find the proper MMacro.
2459 for (m = head; m; m = m->next)
2460 if (!mstrcmp(m->name, tline->text, m->casesense))
2461 break;
2462 if (!m)
2463 return NULL;
2466 * OK, we have a potential macro. Count and demarcate the
2467 * parameters.
2469 count_mmac_params (tline->next, &nparam, &params);
2472 * So we know how many parameters we've got. Find the MMacro
2473 * structure that handles this number.
2475 while (m) {
2476 if (m->nparam_min <= nparam && (m->plus || nparam <= m->nparam_max)) {
2478 * This one is right. Just check if cycle removal
2479 * prohibits us using it before we actually celebrate...
2481 if (m->in_progress) {
2482 #if 0
2483 error (ERR_NONFATAL,
2484 "self-reference in multi-line macro `%s'",
2485 m->name);
2486 #endif
2487 nasm_free (params);
2488 return NULL;
2491 * It's right, and we can use it. Add its default
2492 * parameters to the end of our list if necessary.
2494 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
2495 params = nasm_realloc (params, ((m->nparam_min+m->ndefs+1) *
2496 sizeof(*params)));
2497 while (nparam < m->nparam_min + m->ndefs) {
2498 params[nparam] = m->defaults[nparam - m->nparam_min];
2499 nparam++;
2503 * If we've gone over the maximum parameter count (and
2504 * we're in Plus mode), ignore parameters beyond
2505 * nparam_max.
2507 if (m->plus && nparam > m->nparam_max)
2508 nparam = m->nparam_max;
2510 * Then terminate the parameter list, and leave.
2512 if (!params) { /* need this special case */
2513 params = nasm_malloc(sizeof(*params));
2514 nparam = 0;
2516 params[nparam] = NULL;
2517 *params_array = params;
2518 return m;
2521 * This one wasn't right: look for the next one with the
2522 * same name.
2524 for (m = m->next; m; m = m->next)
2525 if (!mstrcmp(m->name, tline->text, m->casesense))
2526 break;
2530 * After all that, we didn't find one with the right number of
2531 * parameters. Issue a warning, and fail to expand the macro.
2533 error (ERR_WARNING|ERR_WARN_MNP,
2534 "macro `%s' exists, but not taking %d parameters",
2535 tline->text, nparam);
2536 nasm_free (params);
2537 return NULL;
2541 * Expand the multi-line macro call made by the given line, if
2542 * there is one to be expanded. If there is, push the expansion on
2543 * istk->expansion and return 1. Otherwise return 0.
2545 static int expand_mmacro (Token *tline)
2547 Token *startline = tline;
2548 Token *label = NULL;
2549 int dont_prepend = 0;
2550 Token **params, *t, *tt;
2551 MMacro *m;
2552 Line *l, *ll;
2553 int i, nparam, *paramlen;
2555 t = tline;
2556 skip_white_(t);
2557 if (!tok_type_(t, TOK_ID))
2558 return 0;
2559 m = is_mmacro (t, &params);
2560 if (!m) {
2561 Token *last;
2563 * We have an id which isn't a macro call. We'll assume
2564 * it might be a label; we'll also check to see if a
2565 * colon follows it. Then, if there's another id after
2566 * that lot, we'll check it again for macro-hood.
2568 label = last = t;
2569 t = t->next;
2570 if (tok_type_(t, TOK_WHITESPACE))
2571 last = t, t = t->next;
2572 if (tok_is_(t, ":")) {
2573 dont_prepend = 1;
2574 last = t, t = t->next;
2575 if (tok_type_(t, TOK_WHITESPACE))
2576 last = t, t = t->next;
2578 if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
2579 return 0;
2580 last->next = NULL;
2581 tline = t;
2585 * Fix up the parameters: this involves stripping leading and
2586 * trailing whitespace, then stripping braces if they are
2587 * present.
2589 for (nparam = 0; params[nparam]; nparam++)
2591 paramlen = nparam ? nasm_malloc(nparam*sizeof(*paramlen)) : NULL;
2593 for (i = 0; params[i]; i++) {
2594 int brace = FALSE;
2595 int comma = (!m->plus || i < nparam-1);
2597 t = params[i];
2598 skip_white_(t);
2599 if (tok_is_(t, "{"))
2600 t = t->next, brace = TRUE, comma = FALSE;
2601 params[i] = t;
2602 paramlen[i] = 0;
2603 while (t) {
2604 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
2605 break; /* ... because we have hit a comma */
2606 if (comma && t->type == TOK_WHITESPACE && tok_is_(t->next, ","))
2607 break; /* ... or a space then a comma */
2608 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
2609 break; /* ... or a brace */
2610 t = t->next;
2611 paramlen[i]++;
2616 * OK, we have a MMacro structure together with a set of
2617 * parameters. We must now go through the expansion and push
2618 * copies of each Line on to istk->expansion. Substitution of
2619 * parameter tokens and macro-local tokens doesn't get done
2620 * until the single-line macro substitution process; this is
2621 * because delaying them allows us to change the semantics
2622 * later through %rotate.
2624 * First, push an end marker on to istk->expansion, mark this
2625 * macro as in progress, and set up its invocation-specific
2626 * variables.
2628 ll = nasm_malloc(sizeof(Line));
2629 ll->next = istk->expansion;
2630 ll->finishes = m;
2631 ll->first = NULL;
2632 istk->expansion = ll;
2634 m->in_progress = TRUE;
2635 m->params = params;
2636 m->iline = tline;
2637 m->nparam = nparam;
2638 m->rotate = 0;
2639 m->paramlen = paramlen;
2640 m->unique = unique++;
2642 m->next_active = istk->mstk;
2643 istk->mstk = m;
2645 for (l = m->expansion; l; l = l->next) {
2646 Token **tail;
2648 ll = nasm_malloc(sizeof(Line));
2649 ll->finishes = NULL;
2650 ll->next = istk->expansion;
2651 istk->expansion = ll;
2652 tail = &ll->first;
2654 for (t = l->first; t; t = t->next) {
2655 Token *x = t;
2656 if (t->type == TOK_PREPROC_ID &&
2657 t->text[1]=='0' && t->text[2]=='0')
2659 dont_prepend = -1;
2660 x = label;
2661 if (!x)
2662 continue;
2664 tt = *tail = nasm_malloc(sizeof(Token));
2665 tail = &tt->next;
2666 tt->type = x->type;
2667 tt->text = nasm_strdup(x->text);
2668 tt->mac = NULL;
2670 *tail = NULL;
2674 * If we had a label, push it on as the first line of
2675 * the macro expansion.
2677 if (label)
2678 if (dont_prepend<0)
2679 free_tlist(startline);
2680 else {
2681 ll = nasm_malloc(sizeof(Line));
2682 ll->finishes = NULL;
2683 ll->next = istk->expansion;
2684 istk->expansion = ll;
2685 ll->first = startline;
2686 if (!dont_prepend) {
2687 while (label->next)
2688 label = label->next;
2689 label->next = tt = nasm_malloc(sizeof(Token));
2690 tt->next = NULL;
2691 tt->mac = NULL;
2692 tt->type = TOK_OTHER;
2693 tt->text = nasm_strdup(":");
2697 list->uplevel (m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2699 return 1;
2702 static void pp_reset (char *file, int apass, efunc errfunc, evalfunc eval,
2703 ListGen *listgen)
2705 int h;
2707 error = errfunc;
2708 cstk = NULL;
2709 istk = nasm_malloc(sizeof(Include));
2710 istk->next = NULL;
2711 istk->conds = NULL;
2712 istk->expansion = NULL;
2713 istk->mstk = NULL;
2714 istk->fp = fopen(file, "r");
2715 istk->fname = NULL;
2716 src_set_fname(nasm_strdup(file));
2717 src_set_linnum(0);
2718 istk->lineinc = 1;
2719 if (!istk->fp)
2720 error (ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'", file);
2721 defining = NULL;
2722 for (h=0; h<NHASH; h++) {
2723 mmacros[h] = NULL;
2724 smacros[h] = NULL;
2726 unique = 0;
2727 stdmacpos = stdmac;
2728 any_extrastdmac = (extrastdmac != NULL);
2729 list = listgen;
2730 evaluate = eval;
2731 pass = apass;
2734 static char *pp_getline (void)
2736 char *line;
2737 Token *tline;
2738 int ret;
2740 while (1) {
2742 * Fetch a tokenised line, either from the macro-expansion
2743 * buffer or from the input file.
2745 tline = NULL;
2746 while (istk->expansion && istk->expansion->finishes) {
2747 Line *l = istk->expansion;
2748 if (!l->finishes->name && l->finishes->in_progress > 1) {
2749 Line *ll;
2752 * This is a macro-end marker for a macro with no
2753 * name, which means it's not really a macro at all
2754 * but a %rep block, and the `in_progress' field is
2755 * more than 1, meaning that we still need to
2756 * repeat. (1 means the natural last repetition; 0
2757 * means termination by %exitrep.) We have
2758 * therefore expanded up to the %endrep, and must
2759 * push the whole block on to the expansion buffer
2760 * again. We don't bother to remove the macro-end
2761 * marker: we'd only have to generate another one
2762 * if we did.
2764 l->finishes->in_progress--;
2765 for (l = l->finishes->expansion; l; l = l->next) {
2766 Token *t, *tt, **tail;
2768 ll = nasm_malloc(sizeof(Line));
2769 ll->next = istk->expansion;
2770 ll->finishes = NULL;
2771 ll->first = NULL;
2772 tail = &ll->first;
2774 for (t = l->first; t; t = t->next) {
2775 if (t->text) {
2776 tt = *tail = nasm_malloc(sizeof(Token));
2777 tt->next = NULL;
2778 tail = &tt->next;
2779 tt->type = t->type;
2780 tt->text = nasm_strdup(t->text);
2781 tt->mac = NULL;
2785 istk->expansion = ll;
2787 } else {
2789 * Check whether a `%rep' was started and not ended
2790 * within this macro expansion. This can happen and
2791 * should be detected. It's a fatal error because
2792 * I'm too confused to work out how to recover
2793 * sensibly from it.
2795 if (defining) {
2796 if (defining->name)
2797 error (ERR_PANIC,
2798 "defining with name in expansion");
2799 else if (!istk->mstk->name)
2800 error (ERR_PANIC, "istk->mstk has no name but"
2801 " defining is set at end of expansion");
2802 else
2803 error (ERR_FATAL, "`%%rep' without `%%endrep' within"
2804 " expansion of macro `%s'", istk->mstk->name);
2808 * FIXME: investigate the relationship at this point between
2809 * istk->mstk and l->finishes
2812 MMacro *m = istk->mstk;
2813 istk->mstk = m->next_active;
2814 if (m->name) {
2816 * This was a real macro call, not a %rep, and
2817 * therefore the parameter information needs to
2818 * be freed.
2820 nasm_free(m->params);
2821 free_tlist(m->iline);
2822 nasm_free(m->paramlen);
2823 l->finishes->in_progress = FALSE;
2825 else
2826 free_mmacro(m);
2828 istk->expansion = l->next;
2829 nasm_free (l);
2830 list->downlevel (LIST_MACRO);
2833 while (1) { /* until we get a line we can use */
2835 if (istk->expansion) { /* from a macro expansion */
2836 char *p;
2837 Line *l = istk->expansion;
2838 tline = l->first;
2839 istk->expansion = l->next;
2840 nasm_free (l);
2841 p = detoken(tline);
2842 list->line (LIST_MACRO, p);
2843 nasm_free(p);
2844 break;
2846 line = read_line();
2847 if (line) { /* from the current input file */
2848 line = prepreproc(line);
2849 tline = tokenise(line);
2850 nasm_free (line);
2851 break;
2854 * The current file has ended; work down the istk
2857 Include *i = istk;
2858 fclose(i->fp);
2859 if (i->conds)
2860 error(ERR_FATAL, "expected `%%endif' before end of file");
2861 istk = i->next;
2862 list->downlevel (LIST_INCLUDE);
2863 src_set_linnum(i->lineno);
2864 nasm_free ( src_set_fname(i->fname) );
2865 nasm_free (i);
2866 if (!istk)
2867 return NULL;
2872 * We must expand MMacro parameters and MMacro-local labels
2873 * _before_ we plunge into directive processing, to cope
2874 * with things like `%define something %1' such as STRUC
2875 * uses. Unless we're _defining_ a MMacro, in which case
2876 * those tokens should be left alone to go into the
2877 * definition; and unless we're in a non-emitting
2878 * condition, in which case we don't want to meddle with
2879 * anything.
2881 if (!defining && !(istk->conds && !emitting(istk->conds->state)))
2882 tline = expand_mmac_params(tline);
2885 * Check the line to see if it's a preprocessor directive.
2887 ret = do_directive(tline);
2888 if (ret & 1) {
2889 continue;
2890 } else if (defining) {
2892 * We're defining a multi-line macro. We emit nothing
2893 * at all, and just
2894 * shove the tokenised line on to the macro definition.
2896 Line *l = nasm_malloc(sizeof(Line));
2897 l->next = defining->expansion;
2898 l->first = tline;
2899 l->finishes = FALSE;
2900 defining->expansion = l;
2901 continue;
2902 } else if (istk->conds && !emitting(istk->conds->state)) {
2904 * We're in a non-emitting branch of a condition block.
2905 * Emit nothing at all, not even a blank line: when we
2906 * emerge from the condition we'll give a line-number
2907 * directive so we keep our place correctly.
2909 free_tlist(tline);
2910 continue;
2911 } else if (istk->mstk && !istk->mstk->in_progress) {
2913 * We're in a %rep block which has been terminated, so
2914 * we're walking through to the %endrep without
2915 * emitting anything. Emit nothing at all, not even a
2916 * blank line: when we emerge from the %rep block we'll
2917 * give a line-number directive so we keep our place
2918 * correctly.
2920 free_tlist(tline);
2921 continue;
2922 } else {
2923 tline = expand_smacro(tline);
2924 ret = expand_mmacro(tline);
2925 if (!ret) {
2927 * De-tokenise the line again, and emit it.
2929 line = detoken(tline);
2930 free_tlist (tline);
2931 break;
2932 } else {
2933 continue; /* expand_mmacro calls free_tlist */
2938 return line;
2941 static void pp_cleanup (void)
2943 int h;
2945 if (defining) {
2946 error (ERR_NONFATAL, "end of file while still defining macro `%s'",
2947 defining->name);
2948 free_mmacro (defining);
2950 while (cstk)
2951 ctx_pop();
2952 for (h=0; h<NHASH; h++) {
2953 while (mmacros[h]) {
2954 MMacro *m = mmacros[h];
2955 mmacros[h] = mmacros[h]->next;
2956 free_mmacro(m);
2958 while (smacros[h]) {
2959 SMacro *s = smacros[h];
2960 smacros[h] = smacros[h]->next;
2961 nasm_free (s->name);
2962 free_tlist (s->expansion);
2963 nasm_free (s);
2966 while (istk) {
2967 Include *i = istk;
2968 istk = istk->next;
2969 fclose(i->fp);
2970 nasm_free (i->fname);
2971 nasm_free (i);
2973 while (cstk)
2974 ctx_pop();
2977 void pp_include_path (char *path)
2979 IncPath *i;
2981 i = nasm_malloc(sizeof(IncPath));
2982 i->path = nasm_strdup(path);
2983 i->next = ipath;
2985 ipath = i;
2988 void pp_pre_include (char *fname)
2990 Token *inc, *space, *name;
2991 Line *l;
2993 inc = nasm_malloc(sizeof(Token));
2994 inc->next = space = nasm_malloc(sizeof(Token));
2995 space->next = name = nasm_malloc(sizeof(Token));
2996 name->next = NULL;
2998 inc->type = TOK_PREPROC_ID;
2999 inc->text = nasm_strdup("%include");
3000 space->type = TOK_WHITESPACE;
3001 space->text = nasm_strdup(" ");
3002 name->type = TOK_INTERNAL_STRING;
3003 name->text = nasm_strdup(fname);
3005 inc->mac = space->mac = name->mac = NULL;
3007 l = nasm_malloc(sizeof(Line));
3008 l->next = predef;
3009 l->first = inc;
3010 l->finishes = FALSE;
3011 predef = l;
3014 void pp_pre_define (char *definition)
3016 Token *def, *space;
3017 Line *l;
3018 char *equals;
3020 equals = strchr(definition, '=');
3022 def = nasm_malloc(sizeof(Token));
3023 def->next = space = nasm_malloc(sizeof(Token));
3024 if (equals)
3025 *equals = ' ';
3026 space->next = tokenise(definition);
3027 if (equals)
3028 *equals = '=';
3030 def->type = TOK_PREPROC_ID;
3031 def->text = nasm_strdup("%define");
3032 space->type = TOK_WHITESPACE;
3033 space->text = nasm_strdup(" ");
3035 def->mac = space->mac = NULL;
3037 l = nasm_malloc(sizeof(Line));
3038 l->next = predef;
3039 l->first = def;
3040 l->finishes = FALSE;
3041 predef = l;
3044 void pp_extra_stdmac (char **macros)
3046 extrastdmac = macros;
3049 static void make_tok_num(Token *tok, long val)
3051 char numbuf[20];
3052 sprintf(numbuf, "%ld", val);
3053 tok->text = nasm_strdup(numbuf);
3054 tok->type = TOK_NUMBER;
3057 Preproc nasmpp = {
3058 pp_reset,
3059 pp_getline,
3060 pp_cleanup