Apply Nindent to all .c and .h files
[nasm/avx512.git] / preproc.c
blob90c83e4c28a1a24074365ca2e000db414f244678
1 /* -*- mode: c; c-file-style: "bsd" -*- */
2 /* preproc.c macro preprocessor for the Netwide Assembler
4 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
5 * Julian Hall. All rights reserved. The software is
6 * redistributable under the licence given in the file "Licence"
7 * distributed in the NASM archive.
9 * initial version 18/iii/97 by Simon Tatham
12 /* Typical flow of text through preproc
14 * pp_getline gets tokenised lines, either
16 * from a macro expansion
18 * or
19 * {
20 * read_line gets raw text from stdmacpos, or predef, or current input file
21 * tokenise converts to tokens
22 * }
24 * expand_mmac_params is used to expand %1 etc., unless a macro is being
25 * defined or a false conditional is being processed
26 * (%0, %1, %+1, %-1, %%foo
28 * do_directive checks for directives
30 * expand_smacro is used to expand single line macros
32 * expand_mmacro is used to expand multi-line macros
34 * detoken is used to convert the line back to text
37 #include <stdio.h>
38 #include <stdarg.h>
39 #include <stdlib.h>
40 #include <stddef.h>
41 #include <string.h>
42 #include <ctype.h>
43 #include <limits.h>
45 #include "nasm.h"
46 #include "nasmlib.h"
48 typedef struct SMacro SMacro;
49 typedef struct MMacro MMacro;
50 typedef struct Context Context;
51 typedef struct Token Token;
52 typedef struct Blocks Blocks;
53 typedef struct Line Line;
54 typedef struct Include Include;
55 typedef struct Cond Cond;
56 typedef struct IncPath IncPath;
59 * Store the definition of a single-line macro.
61 struct SMacro {
62 SMacro *next;
63 char *name;
64 int casesense;
65 int nparam;
66 int in_progress;
67 Token *expansion;
71 * Store the definition of a multi-line macro. This is also used to
72 * store the interiors of `%rep...%endrep' blocks, which are
73 * effectively self-re-invoking multi-line macros which simply
74 * don't have a name or bother to appear in the hash tables. %rep
75 * blocks are signified by having a NULL `name' field.
77 * In a MMacro describing a `%rep' block, the `in_progress' field
78 * isn't merely boolean, but gives the number of repeats left to
79 * run.
81 * The `next' field is used for storing MMacros in hash tables; the
82 * `next_active' field is for stacking them on istk entries.
84 * When a MMacro is being expanded, `params', `iline', `nparam',
85 * `paramlen', `rotate' and `unique' are local to the invocation.
87 struct MMacro {
88 MMacro *next;
89 char *name;
90 int casesense;
91 int nparam_min, nparam_max;
92 int plus; /* is the last parameter greedy? */
93 int nolist; /* is this macro listing-inhibited? */
94 int in_progress;
95 Token *dlist; /* All defaults as one list */
96 Token **defaults; /* Parameter default pointers */
97 int ndefs; /* number of default parameters */
98 Line *expansion;
100 MMacro *next_active;
101 MMacro *rep_nest; /* used for nesting %rep */
102 Token **params; /* actual parameters */
103 Token *iline; /* invocation line */
104 int nparam, rotate, *paramlen;
105 unsigned long unique;
106 int lineno; /* Current line number on expansion */
110 * The context stack is composed of a linked list of these.
112 struct Context {
113 Context *next;
114 SMacro *localmac;
115 char *name;
116 unsigned long number;
120 * This is the internal form which we break input lines up into.
121 * Typically stored in linked lists.
123 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
124 * necessarily used as-is, but is intended to denote the number of
125 * the substituted parameter. So in the definition
127 * %define a(x,y) ( (x) & ~(y) )
129 * the token representing `x' will have its type changed to
130 * TOK_SMAC_PARAM, but the one representing `y' will be
131 * TOK_SMAC_PARAM+1.
133 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
134 * which doesn't need quotes around it. Used in the pre-include
135 * mechanism as an alternative to trying to find a sensible type of
136 * quote to use on the filename we were passed.
138 struct Token {
139 Token *next;
140 char *text;
141 SMacro *mac; /* associated macro for TOK_SMAC_END */
142 int type;
144 enum {
145 TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING,
146 TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_SMAC_PARAM,
147 TOK_INTERNAL_STRING
151 * Multi-line macro definitions are stored as a linked list of
152 * these, which is essentially a container to allow several linked
153 * lists of Tokens.
155 * Note that in this module, linked lists are treated as stacks
156 * wherever possible. For this reason, Lines are _pushed_ on to the
157 * `expansion' field in MMacro structures, so that the linked list,
158 * if walked, would give the macro lines in reverse order; this
159 * means that we can walk the list when expanding a macro, and thus
160 * push the lines on to the `expansion' field in _istk_ in reverse
161 * order (so that when popped back off they are in the right
162 * order). It may seem cockeyed, and it relies on my design having
163 * an even number of steps in, but it works...
165 * Some of these structures, rather than being actual lines, are
166 * markers delimiting the end of the expansion of a given macro.
167 * This is for use in the cycle-tracking and %rep-handling code.
168 * Such structures have `finishes' non-NULL, and `first' NULL. All
169 * others have `finishes' NULL, but `first' may still be NULL if
170 * the line is blank.
172 struct Line {
173 Line *next;
174 MMacro *finishes;
175 Token *first;
179 * To handle an arbitrary level of file inclusion, we maintain a
180 * stack (ie linked list) of these things.
182 struct Include {
183 Include *next;
184 FILE *fp;
185 Cond *conds;
186 Line *expansion;
187 char *fname;
188 int lineno, lineinc;
189 MMacro *mstk; /* stack of active macros/reps */
193 * Include search path. This is simply a list of strings which get
194 * prepended, in turn, to the name of an include file, in an
195 * attempt to find the file if it's not in the current directory.
197 struct IncPath {
198 IncPath *next;
199 char *path;
203 * Conditional assembly: we maintain a separate stack of these for
204 * each level of file inclusion. (The only reason we keep the
205 * stacks separate is to ensure that a stray `%endif' in a file
206 * included from within the true branch of a `%if' won't terminate
207 * it and cause confusion: instead, rightly, it'll cause an error.)
209 struct Cond {
210 Cond *next;
211 int state;
213 enum {
215 * These states are for use just after %if or %elif: IF_TRUE
216 * means the condition has evaluated to truth so we are
217 * currently emitting, whereas IF_FALSE means we are not
218 * currently emitting but will start doing so if a %else comes
219 * up. In these states, all directives are admissible: %elif,
220 * %else and %endif. (And of course %if.)
222 COND_IF_TRUE, COND_IF_FALSE,
224 * These states come up after a %else: ELSE_TRUE means we're
225 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
226 * any %elif or %else will cause an error.
228 COND_ELSE_TRUE, COND_ELSE_FALSE,
230 * This state means that we're not emitting now, and also that
231 * nothing until %endif will be emitted at all. It's for use in
232 * two circumstances: (i) when we've had our moment of emission
233 * and have now started seeing %elifs, and (ii) when the
234 * condition construct in question is contained within a
235 * non-emitting branch of a larger condition construct.
237 COND_NEVER
239 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
242 * These defines are used as the possible return values for do_directive
244 #define NO_DIRECTIVE_FOUND 0
245 #define DIRECTIVE_FOUND 1
248 * Condition codes. Note that we use c_ prefix not C_ because C_ is
249 * used in nasm.h for the "real" condition codes. At _this_ level,
250 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
251 * ones, so we need a different enum...
253 static const char *conditions[] = {
254 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
255 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
256 "np", "ns", "nz", "o", "p", "pe", "po", "s", "z"
258 enum {
259 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
260 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
261 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_S, c_Z
263 static int inverse_ccs[] = {
264 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
265 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,
266 c_Z, c_NO, c_NP, c_PO, c_PE, c_NS, c_NZ
270 * Directive names.
272 static const char *directives[] = {
273 "%arg",
274 "%assign", "%clear", "%define", "%elif", "%elifctx", "%elifdef",
275 "%elifid", "%elifidn", "%elifidni", "%elifmacro", "%elifnctx",
276 "%elifndef",
277 "%elifnid", "%elifnidn", "%elifnidni", "%elifnmacro", "%elifnnum",
278 "%elifnstr",
279 "%elifnum", "%elifstr", "%else", "%endif", "%endm", "%endmacro",
280 "%endrep", "%error", "%exitrep", "%iassign", "%idefine", "%if",
281 "%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifmacro",
282 "%ifnctx",
283 "%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnmacro", "%ifnnum",
284 "%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include",
285 "%ixdefine", "%line",
286 "%local",
287 "%macro", "%pop", "%push", "%rep", "%repl", "%rotate",
288 "%stacksize",
289 "%strlen", "%substr", "%undef", "%xdefine"
291 enum {
292 PP_ARG,
293 PP_ASSIGN, PP_CLEAR, PP_DEFINE, PP_ELIF, PP_ELIFCTX, PP_ELIFDEF,
294 PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFMACRO, PP_ELIFNCTX,
295 PP_ELIFNDEF,
296 PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNMACRO, PP_ELIFNNUM,
297 PP_ELIFNSTR,
298 PP_ELIFNUM, PP_ELIFSTR, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO,
299 PP_ENDREP, PP_ERROR, PP_EXITREP, PP_IASSIGN, PP_IDEFINE, PP_IF,
300 PP_IFCTX, PP_IFDEF, PP_IFID, PP_IFIDN, PP_IFIDNI, PP_IFMACRO,
301 PP_IFNCTX,
302 PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNMACRO, PP_IFNNUM,
303 PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE,
304 PP_IXDEFINE, PP_LINE,
305 PP_LOCAL,
306 PP_MACRO, PP_POP, PP_PUSH, PP_REP, PP_REPL, PP_ROTATE,
307 PP_STACKSIZE,
308 PP_STRLEN, PP_SUBSTR, PP_UNDEF, PP_XDEFINE
311 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
312 static int is_condition(int arg)
314 return ((arg >= PP_ELIF) && (arg <= PP_ENDIF)) ||
315 ((arg >= PP_IF) && (arg <= PP_IFSTR));
318 /* For TASM compatibility we need to be able to recognise TASM compatible
319 * conditional compilation directives. Using the NASM pre-processor does
320 * not work, so we look for them specifically from the following list and
321 * then jam in the equivalent NASM directive into the input stream.
324 #ifndef MAX
325 # define MAX(a,b) ( ((a) > (b)) ? (a) : (b))
326 #endif
328 enum {
329 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
330 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
333 static const char *tasm_directives[] = {
334 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
335 "ifndef", "include", "local"
338 static int StackSize = 4;
339 static char *StackPointer = "ebp";
340 static int ArgOffset = 8;
341 static int LocalOffset = 4;
343 static Context *cstk;
344 static Include *istk;
345 static IncPath *ipath = NULL;
347 static efunc _error; /* Pointer to client-provided error reporting function */
348 static evalfunc evaluate;
350 static int pass; /* HACK: pass 0 = generate dependencies only */
352 static unsigned long unique; /* unique identifier numbers */
354 static Line *predef = NULL;
356 static ListGen *list;
359 * The number of hash values we use for the macro lookup tables.
360 * FIXME: We should *really* be able to configure this at run time,
361 * or even have the hash table automatically expanding when necessary.
363 #define NHASH 31
366 * The current set of multi-line macros we have defined.
368 static MMacro *mmacros[NHASH];
371 * The current set of single-line macros we have defined.
373 static SMacro *smacros[NHASH];
376 * The multi-line macro we are currently defining, or the %rep
377 * block we are currently reading, if any.
379 static MMacro *defining;
382 * The number of macro parameters to allocate space for at a time.
384 #define PARAM_DELTA 16
387 * The standard macro set: defined as `static char *stdmac[]'. Also
388 * gives our position in the macro set, when we're processing it.
390 #include "macros.c"
391 static const char **stdmacpos;
394 * The extra standard macros that come from the object format, if
395 * any.
397 static const char **extrastdmac = NULL;
398 int any_extrastdmac;
401 * Tokens are allocated in blocks to improve speed
403 #define TOKEN_BLOCKSIZE 4096
404 static Token *freeTokens = NULL;
405 struct Blocks {
406 Blocks *next;
407 void *chunk;
410 static Blocks blocks = { NULL, NULL };
413 * Forward declarations.
415 static Token *expand_mmac_params(Token * tline);
416 static Token *expand_smacro(Token * tline);
417 static Token *expand_id(Token * tline);
418 static Context *get_ctx(char *name, int all_contexts);
419 static void make_tok_num(Token * tok, long val);
420 static void error(int severity, const char *fmt, ...);
421 static void *new_Block(size_t size);
422 static void delete_Blocks(void);
423 static Token *new_Token(Token * next, int type, char *text, int txtlen);
424 static Token *delete_Token(Token * t);
427 * Macros for safe checking of token pointers, avoid *(NULL)
429 #define tok_type_(x,t) ((x) && (x)->type == (t))
430 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
431 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
432 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
434 /* Handle TASM specific directives, which do not contain a % in
435 * front of them. We do it here because I could not find any other
436 * place to do it for the moment, and it is a hack (ideally it would
437 * be nice to be able to use the NASM pre-processor to do it).
439 static char *check_tasm_directive(char *line)
441 int i, j, k, m, len;
442 char *p = line, *oldline, oldchar;
444 /* Skip whitespace */
445 while (isspace(*p) && *p != 0)
446 p++;
448 /* Binary search for the directive name */
449 i = -1;
450 j = elements(tasm_directives);
451 len = 0;
452 while (!isspace(p[len]) && p[len] != 0)
453 len++;
454 if (len) {
455 oldchar = p[len];
456 p[len] = 0;
457 while (j - i > 1) {
458 k = (j + i) / 2;
459 m = nasm_stricmp(p, tasm_directives[k]);
460 if (m == 0) {
461 /* We have found a directive, so jam a % in front of it
462 * so that NASM will then recognise it as one if it's own.
464 p[len] = oldchar;
465 len = strlen(p);
466 oldline = line;
467 line = nasm_malloc(len + 2);
468 line[0] = '%';
469 if (k == TM_IFDIFI) {
470 /* NASM does not recognise IFDIFI, so we convert it to
471 * %ifdef BOGUS. This is not used in NASM comaptible
472 * code, but does need to parse for the TASM macro
473 * package.
475 strcpy(line + 1, "ifdef BOGUS");
476 } else {
477 memcpy(line + 1, p, len + 1);
479 nasm_free(oldline);
480 return line;
481 } else if (m < 0) {
482 j = k;
483 } else
484 i = k;
486 p[len] = oldchar;
488 return line;
492 * The pre-preprocessing stage... This function translates line
493 * number indications as they emerge from GNU cpp (`# lineno "file"
494 * flags') into NASM preprocessor line number indications (`%line
495 * lineno file').
497 static char *prepreproc(char *line)
499 int lineno, fnlen;
500 char *fname, *oldline;
502 if (line[0] == '#' && line[1] == ' ') {
503 oldline = line;
504 fname = oldline + 2;
505 lineno = atoi(fname);
506 fname += strspn(fname, "0123456789 ");
507 if (*fname == '"')
508 fname++;
509 fnlen = strcspn(fname, "\"");
510 line = nasm_malloc(20 + fnlen);
511 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
512 nasm_free(oldline);
514 if (tasm_compatible_mode)
515 return check_tasm_directive(line);
516 return line;
520 * The hash function for macro lookups. Note that due to some
521 * macros having case-insensitive names, the hash function must be
522 * invariant under case changes. We implement this by applying a
523 * perfectly normal hash function to the uppercase of the string.
525 static int hash(char *s)
527 unsigned int h = 0;
528 int i = 0;
530 * Powers of three, mod 31.
532 static const int multipliers[] = {
533 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10,
534 30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21
537 while (*s) {
538 h += multipliers[i] * (unsigned char)(toupper(*s));
539 s++;
540 if (++i >= elements(multipliers))
541 i = 0;
543 h %= NHASH;
544 return h;
548 * Free a linked list of tokens.
550 static void free_tlist(Token * list)
552 while (list) {
553 list = delete_Token(list);
558 * Free a linked list of lines.
560 static void free_llist(Line * list)
562 Line *l;
563 while (list) {
564 l = list;
565 list = list->next;
566 free_tlist(l->first);
567 nasm_free(l);
572 * Free an MMacro
574 static void free_mmacro(MMacro * m)
576 nasm_free(m->name);
577 free_tlist(m->dlist);
578 nasm_free(m->defaults);
579 free_llist(m->expansion);
580 nasm_free(m);
584 * Pop the context stack.
586 static void ctx_pop(void)
588 Context *c = cstk;
589 SMacro *smac, *s;
591 cstk = cstk->next;
592 smac = c->localmac;
593 while (smac) {
594 s = smac;
595 smac = smac->next;
596 nasm_free(s->name);
597 free_tlist(s->expansion);
598 nasm_free(s);
600 nasm_free(c->name);
601 nasm_free(c);
604 #define BUF_DELTA 512
606 * Read a line from the top file in istk, handling multiple CR/LFs
607 * at the end of the line read, and handling spurious ^Zs. Will
608 * return lines from the standard macro set if this has not already
609 * been done.
611 static char *read_line(void)
613 char *buffer, *p, *q;
614 int bufsize, continued_count;
616 if (stdmacpos) {
617 if (*stdmacpos) {
618 char *ret = nasm_strdup(*stdmacpos++);
619 if (!*stdmacpos && any_extrastdmac) {
620 stdmacpos = extrastdmac;
621 any_extrastdmac = FALSE;
622 return ret;
625 * Nasty hack: here we push the contents of `predef' on
626 * to the top-level expansion stack, since this is the
627 * most convenient way to implement the pre-include and
628 * pre-define features.
630 if (!*stdmacpos) {
631 Line *pd, *l;
632 Token *head, **tail, *t;
634 for (pd = predef; pd; pd = pd->next) {
635 head = NULL;
636 tail = &head;
637 for (t = pd->first; t; t = t->next) {
638 *tail = new_Token(NULL, t->type, t->text, 0);
639 tail = &(*tail)->next;
641 l = nasm_malloc(sizeof(Line));
642 l->next = istk->expansion;
643 l->first = head;
644 l->finishes = FALSE;
645 istk->expansion = l;
648 return ret;
649 } else {
650 stdmacpos = NULL;
654 bufsize = BUF_DELTA;
655 buffer = nasm_malloc(BUF_DELTA);
656 p = buffer;
657 continued_count = 0;
658 while (1) {
659 q = fgets(p, bufsize - (p - buffer), istk->fp);
660 if (!q)
661 break;
662 p += strlen(p);
663 if (p > buffer && p[-1] == '\n') {
664 /* Convert backslash-CRLF line continuation sequences into
665 nothing at all (for DOS and Windows) */
666 if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
667 p -= 3;
668 *p = 0;
669 continued_count++;
671 /* Also convert backslash-LF line continuation sequences into
672 nothing at all (for Unix) */
673 else if (((p - 1) > buffer) && (p[-2] == '\\')) {
674 p -= 2;
675 *p = 0;
676 continued_count++;
677 } else {
678 break;
681 if (p - buffer > bufsize - 10) {
682 long offset = p - buffer;
683 bufsize += BUF_DELTA;
684 buffer = nasm_realloc(buffer, bufsize);
685 p = buffer + offset; /* prevent stale-pointer problems */
689 if (!q && p == buffer) {
690 nasm_free(buffer);
691 return NULL;
694 src_set_linnum(src_get_linnum() + istk->lineinc +
695 (continued_count * istk->lineinc));
698 * Play safe: remove CRs as well as LFs, if any of either are
699 * present at the end of the line.
701 while (--p >= buffer && (*p == '\n' || *p == '\r'))
702 *p = '\0';
705 * Handle spurious ^Z, which may be inserted into source files
706 * by some file transfer utilities.
708 buffer[strcspn(buffer, "\032")] = '\0';
710 list->line(LIST_READ, buffer);
712 return buffer;
716 * Tokenise a line of text. This is a very simple process since we
717 * don't need to parse the value out of e.g. numeric tokens: we
718 * simply split one string into many.
720 static Token *tokenise(char *line)
722 char *p = line;
723 int type;
724 Token *list = NULL;
725 Token *t, **tail = &list;
727 while (*line) {
728 p = line;
729 if (*p == '%') {
730 p++;
731 if (isdigit(*p) ||
732 ((*p == '-' || *p == '+') && isdigit(p[1])) ||
733 ((*p == '+') && (isspace(p[1]) || !p[1]))) {
734 do {
735 p++;
737 while (isdigit(*p));
738 type = TOK_PREPROC_ID;
739 } else if (*p == '{') {
740 p++;
741 while (*p && *p != '}') {
742 p[-1] = *p;
743 p++;
745 p[-1] = '\0';
746 if (*p)
747 p++;
748 type = TOK_PREPROC_ID;
749 } else if (isidchar(*p) ||
750 ((*p == '!' || *p == '%' || *p == '$') &&
751 isidchar(p[1]))) {
752 do {
753 p++;
755 while (isidchar(*p));
756 type = TOK_PREPROC_ID;
757 } else {
758 type = TOK_OTHER;
759 if (*p == '%')
760 p++;
762 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
763 type = TOK_ID;
764 p++;
765 while (*p && isidchar(*p))
766 p++;
767 } else if (*p == '\'' || *p == '"') {
769 * A string token.
771 char c = *p;
772 p++;
773 type = TOK_STRING;
774 while (*p && *p != c)
775 p++;
777 if (*p) {
778 p++;
779 } else {
780 error(ERR_WARNING, "unterminated string");
781 /* Handling unterminated strings by UNV */
782 /* type = -1; */
784 } else if (isnumstart(*p)) {
786 * A number token.
788 type = TOK_NUMBER;
789 p++;
790 while (*p && isnumchar(*p))
791 p++;
792 } else if (isspace(*p)) {
793 type = TOK_WHITESPACE;
794 p++;
795 while (*p && isspace(*p))
796 p++;
798 * Whitespace just before end-of-line is discarded by
799 * pretending it's a comment; whitespace just before a
800 * comment gets lumped into the comment.
802 if (!*p || *p == ';') {
803 type = TOK_COMMENT;
804 while (*p)
805 p++;
807 } else if (*p == ';') {
808 type = TOK_COMMENT;
809 while (*p)
810 p++;
811 } else {
813 * Anything else is an operator of some kind. We check
814 * for all the double-character operators (>>, <<, //,
815 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
816 * else is a single-character operator.
818 type = TOK_OTHER;
819 if ((p[0] == '>' && p[1] == '>') ||
820 (p[0] == '<' && p[1] == '<') ||
821 (p[0] == '/' && p[1] == '/') ||
822 (p[0] == '<' && p[1] == '=') ||
823 (p[0] == '>' && p[1] == '=') ||
824 (p[0] == '=' && p[1] == '=') ||
825 (p[0] == '!' && p[1] == '=') ||
826 (p[0] == '<' && p[1] == '>') ||
827 (p[0] == '&' && p[1] == '&') ||
828 (p[0] == '|' && p[1] == '|') ||
829 (p[0] == '^' && p[1] == '^')) {
830 p++;
832 p++;
835 /* Handling unterminated string by UNV */
836 /*if (type == -1)
838 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
839 t->text[p-line] = *line;
840 tail = &t->next;
842 else */
843 if (type != TOK_COMMENT) {
844 *tail = t = new_Token(NULL, type, line, p - line);
845 tail = &t->next;
847 line = p;
849 return list;
853 * this function allocates a new managed block of memory and
854 * returns a pointer to the block. The managed blocks are
855 * deleted only all at once by the delete_Blocks function.
857 static void *new_Block(size_t size)
859 Blocks *b = &blocks;
861 /* first, get to the end of the linked list */
862 while (b->next)
863 b = b->next;
864 /* now allocate the requested chunk */
865 b->chunk = nasm_malloc(size);
867 /* now allocate a new block for the next request */
868 b->next = nasm_malloc(sizeof(Blocks));
869 /* and initialize the contents of the new block */
870 b->next->next = NULL;
871 b->next->chunk = NULL;
872 return b->chunk;
876 * this function deletes all managed blocks of memory
878 static void delete_Blocks(void)
880 Blocks *a, *b = &blocks;
883 * keep in mind that the first block, pointed to by blocks
884 * is a static and not dynamically allocated, so we don't
885 * free it.
887 while (b) {
888 if (b->chunk)
889 nasm_free(b->chunk);
890 a = b;
891 b = b->next;
892 if (a != &blocks)
893 nasm_free(a);
898 * this function creates a new Token and passes a pointer to it
899 * back to the caller. It sets the type and text elements, and
900 * also the mac and next elements to NULL.
902 static Token *new_Token(Token * next, int type, char *text, int txtlen)
904 Token *t;
905 int i;
907 if (freeTokens == NULL) {
908 freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
909 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
910 freeTokens[i].next = &freeTokens[i + 1];
911 freeTokens[i].next = NULL;
913 t = freeTokens;
914 freeTokens = t->next;
915 t->next = next;
916 t->mac = NULL;
917 t->type = type;
918 if (type == TOK_WHITESPACE || text == NULL) {
919 t->text = NULL;
920 } else {
921 if (txtlen == 0)
922 txtlen = strlen(text);
923 t->text = nasm_malloc(1 + txtlen);
924 strncpy(t->text, text, txtlen);
925 t->text[txtlen] = '\0';
927 return t;
930 static Token *delete_Token(Token * t)
932 Token *next = t->next;
933 nasm_free(t->text);
934 t->next = freeTokens;
935 freeTokens = t;
936 return next;
940 * Convert a line of tokens back into text.
941 * If expand_locals is not zero, identifiers of the form "%$*xxx"
942 * will be transformed into ..@ctxnum.xxx
944 static char *detoken(Token * tlist, int expand_locals)
946 Token *t;
947 int len;
948 char *line, *p;
950 len = 0;
951 for (t = tlist; t; t = t->next) {
952 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
953 char *p = getenv(t->text + 2);
954 nasm_free(t->text);
955 if (p)
956 t->text = nasm_strdup(p);
957 else
958 t->text = NULL;
960 /* Expand local macros here and not during preprocessing */
961 if (expand_locals &&
962 t->type == TOK_PREPROC_ID && t->text &&
963 t->text[0] == '%' && t->text[1] == '$') {
964 Context *ctx = get_ctx(t->text, FALSE);
965 if (ctx) {
966 char buffer[40];
967 char *p, *q = t->text + 2;
969 q += strspn(q, "$");
970 snprintf(buffer, sizeof(buffer), "..@%lu.", ctx->number);
971 p = nasm_strcat(buffer, q);
972 nasm_free(t->text);
973 t->text = p;
976 if (t->type == TOK_WHITESPACE) {
977 len++;
978 } else if (t->text) {
979 len += strlen(t->text);
982 p = line = nasm_malloc(len + 1);
983 for (t = tlist; t; t = t->next) {
984 if (t->type == TOK_WHITESPACE) {
985 *p = ' ';
986 p++;
987 *p = '\0';
988 } else if (t->text) {
989 strcpy(p, t->text);
990 p += strlen(p);
993 *p = '\0';
994 return line;
998 * A scanner, suitable for use by the expression evaluator, which
999 * operates on a line of Tokens. Expects a pointer to a pointer to
1000 * the first token in the line to be passed in as its private_data
1001 * field.
1003 static int ppscan(void *private_data, struct tokenval *tokval)
1005 Token **tlineptr = private_data;
1006 Token *tline;
1008 do {
1009 tline = *tlineptr;
1010 *tlineptr = tline ? tline->next : NULL;
1012 while (tline && (tline->type == TOK_WHITESPACE ||
1013 tline->type == TOK_COMMENT));
1015 if (!tline)
1016 return tokval->t_type = TOKEN_EOS;
1018 if (tline->text[0] == '$' && !tline->text[1])
1019 return tokval->t_type = TOKEN_HERE;
1020 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
1021 return tokval->t_type = TOKEN_BASE;
1023 if (tline->type == TOK_ID) {
1024 tokval->t_charptr = tline->text;
1025 if (tline->text[0] == '$') {
1026 tokval->t_charptr++;
1027 return tokval->t_type = TOKEN_ID;
1031 * This is the only special case we actually need to worry
1032 * about in this restricted context.
1034 if (!nasm_stricmp(tline->text, "seg"))
1035 return tokval->t_type = TOKEN_SEG;
1037 return tokval->t_type = TOKEN_ID;
1040 if (tline->type == TOK_NUMBER) {
1041 int rn_error;
1043 tokval->t_integer = readnum(tline->text, &rn_error);
1044 if (rn_error)
1045 return tokval->t_type = TOKEN_ERRNUM;
1046 tokval->t_charptr = NULL;
1047 return tokval->t_type = TOKEN_NUM;
1050 if (tline->type == TOK_STRING) {
1051 int rn_warn;
1052 char q, *r;
1053 int l;
1055 r = tline->text;
1056 q = *r++;
1057 l = strlen(r);
1059 if (l == 0 || r[l - 1] != q)
1060 return tokval->t_type = TOKEN_ERRNUM;
1061 tokval->t_integer = readstrnum(r, l - 1, &rn_warn);
1062 if (rn_warn)
1063 error(ERR_WARNING | ERR_PASS1, "character constant too long");
1064 tokval->t_charptr = NULL;
1065 return tokval->t_type = TOKEN_NUM;
1068 if (tline->type == TOK_OTHER) {
1069 if (!strcmp(tline->text, "<<"))
1070 return tokval->t_type = TOKEN_SHL;
1071 if (!strcmp(tline->text, ">>"))
1072 return tokval->t_type = TOKEN_SHR;
1073 if (!strcmp(tline->text, "//"))
1074 return tokval->t_type = TOKEN_SDIV;
1075 if (!strcmp(tline->text, "%%"))
1076 return tokval->t_type = TOKEN_SMOD;
1077 if (!strcmp(tline->text, "=="))
1078 return tokval->t_type = TOKEN_EQ;
1079 if (!strcmp(tline->text, "<>"))
1080 return tokval->t_type = TOKEN_NE;
1081 if (!strcmp(tline->text, "!="))
1082 return tokval->t_type = TOKEN_NE;
1083 if (!strcmp(tline->text, "<="))
1084 return tokval->t_type = TOKEN_LE;
1085 if (!strcmp(tline->text, ">="))
1086 return tokval->t_type = TOKEN_GE;
1087 if (!strcmp(tline->text, "&&"))
1088 return tokval->t_type = TOKEN_DBL_AND;
1089 if (!strcmp(tline->text, "^^"))
1090 return tokval->t_type = TOKEN_DBL_XOR;
1091 if (!strcmp(tline->text, "||"))
1092 return tokval->t_type = TOKEN_DBL_OR;
1096 * We have no other options: just return the first character of
1097 * the token text.
1099 return tokval->t_type = tline->text[0];
1103 * Compare a string to the name of an existing macro; this is a
1104 * simple wrapper which calls either strcmp or nasm_stricmp
1105 * depending on the value of the `casesense' parameter.
1107 static int mstrcmp(char *p, char *q, int casesense)
1109 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
1113 * Return the Context structure associated with a %$ token. Return
1114 * NULL, having _already_ reported an error condition, if the
1115 * context stack isn't deep enough for the supplied number of $
1116 * signs.
1117 * If all_contexts == TRUE, contexts that enclose current are
1118 * also scanned for such smacro, until it is found; if not -
1119 * only the context that directly results from the number of $'s
1120 * in variable's name.
1122 static Context *get_ctx(char *name, int all_contexts)
1124 Context *ctx;
1125 SMacro *m;
1126 int i;
1128 if (!name || name[0] != '%' || name[1] != '$')
1129 return NULL;
1131 if (!cstk) {
1132 error(ERR_NONFATAL, "`%s': context stack is empty", name);
1133 return NULL;
1136 for (i = strspn(name + 2, "$"), ctx = cstk; (i > 0) && ctx; i--) {
1137 ctx = ctx->next;
1138 /* i--; Lino - 02/25/02 */
1140 if (!ctx) {
1141 error(ERR_NONFATAL, "`%s': context stack is only"
1142 " %d level%s deep", name, i - 1, (i == 2 ? "" : "s"));
1143 return NULL;
1145 if (!all_contexts)
1146 return ctx;
1148 do {
1149 /* Search for this smacro in found context */
1150 m = ctx->localmac;
1151 while (m) {
1152 if (!mstrcmp(m->name, name, m->casesense))
1153 return ctx;
1154 m = m->next;
1156 ctx = ctx->next;
1158 while (ctx);
1159 return NULL;
1163 * Open an include file. This routine must always return a valid
1164 * file pointer if it returns - it's responsible for throwing an
1165 * ERR_FATAL and bombing out completely if not. It should also try
1166 * the include path one by one until it finds the file or reaches
1167 * the end of the path.
1169 static FILE *inc_fopen(char *file)
1171 FILE *fp;
1172 char *prefix = "", *combine;
1173 IncPath *ip = ipath;
1174 static int namelen = 0;
1175 int len = strlen(file);
1177 while (1) {
1178 combine = nasm_malloc(strlen(prefix) + len + 1);
1179 strcpy(combine, prefix);
1180 strcat(combine, file);
1181 fp = fopen(combine, "r");
1182 if (pass == 0 && fp) {
1183 namelen += strlen(combine) + 1;
1184 if (namelen > 62) {
1185 printf(" \\\n ");
1186 namelen = 2;
1188 printf(" %s", combine);
1190 nasm_free(combine);
1191 if (fp)
1192 return fp;
1193 if (!ip)
1194 break;
1195 prefix = ip->path;
1196 ip = ip->next;
1199 error(ERR_FATAL, "unable to open include file `%s'", file);
1200 return NULL; /* never reached - placate compilers */
1204 * Determine if we should warn on defining a single-line macro of
1205 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1206 * return TRUE if _any_ single-line macro of that name is defined.
1207 * Otherwise, will return TRUE if a single-line macro with either
1208 * `nparam' or no parameters is defined.
1210 * If a macro with precisely the right number of parameters is
1211 * defined, or nparam is -1, the address of the definition structure
1212 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1213 * is NULL, no action will be taken regarding its contents, and no
1214 * error will occur.
1216 * Note that this is also called with nparam zero to resolve
1217 * `ifdef'.
1219 * If you already know which context macro belongs to, you can pass
1220 * the context pointer as first parameter; if you won't but name begins
1221 * with %$ the context will be automatically computed. If all_contexts
1222 * is true, macro will be searched in outer contexts as well.
1224 static int
1225 smacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn,
1226 int nocase)
1228 SMacro *m;
1230 if (ctx)
1231 m = ctx->localmac;
1232 else if (name[0] == '%' && name[1] == '$') {
1233 if (cstk)
1234 ctx = get_ctx(name, FALSE);
1235 if (!ctx)
1236 return FALSE; /* got to return _something_ */
1237 m = ctx->localmac;
1238 } else
1239 m = smacros[hash(name)];
1241 while (m) {
1242 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
1243 (nparam <= 0 || m->nparam == 0 || nparam == m->nparam)) {
1244 if (defn) {
1245 if (nparam == m->nparam || nparam == -1)
1246 *defn = m;
1247 else
1248 *defn = NULL;
1250 return TRUE;
1252 m = m->next;
1255 return FALSE;
1259 * Count and mark off the parameters in a multi-line macro call.
1260 * This is called both from within the multi-line macro expansion
1261 * code, and also to mark off the default parameters when provided
1262 * in a %macro definition line.
1264 static void count_mmac_params(Token * t, int *nparam, Token *** params)
1266 int paramsize, brace;
1268 *nparam = paramsize = 0;
1269 *params = NULL;
1270 while (t) {
1271 if (*nparam >= paramsize) {
1272 paramsize += PARAM_DELTA;
1273 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1275 skip_white_(t);
1276 brace = FALSE;
1277 if (tok_is_(t, "{"))
1278 brace = TRUE;
1279 (*params)[(*nparam)++] = t;
1280 while (tok_isnt_(t, brace ? "}" : ","))
1281 t = t->next;
1282 if (t) { /* got a comma/brace */
1283 t = t->next;
1284 if (brace) {
1286 * Now we've found the closing brace, look further
1287 * for the comma.
1289 skip_white_(t);
1290 if (tok_isnt_(t, ",")) {
1291 error(ERR_NONFATAL,
1292 "braces do not enclose all of macro parameter");
1293 while (tok_isnt_(t, ","))
1294 t = t->next;
1296 if (t)
1297 t = t->next; /* eat the comma */
1304 * Determine whether one of the various `if' conditions is true or
1305 * not.
1307 * We must free the tline we get passed.
1309 static int if_condition(Token * tline, int i)
1311 int j, casesense;
1312 Token *t, *tt, **tptr, *origline;
1313 struct tokenval tokval;
1314 expr *evalresult;
1316 origline = tline;
1318 switch (i) {
1319 case PP_IFCTX:
1320 case PP_ELIFCTX:
1321 case PP_IFNCTX:
1322 case PP_ELIFNCTX:
1323 j = FALSE; /* have we matched yet? */
1324 while (cstk && tline) {
1325 skip_white_(tline);
1326 if (!tline || tline->type != TOK_ID) {
1327 error(ERR_NONFATAL,
1328 "`%s' expects context identifiers", directives[i]);
1329 free_tlist(origline);
1330 return -1;
1332 if (!nasm_stricmp(tline->text, cstk->name))
1333 j = TRUE;
1334 tline = tline->next;
1336 if (i == PP_IFNCTX || i == PP_ELIFNCTX)
1337 j = !j;
1338 free_tlist(origline);
1339 return j;
1341 case PP_IFDEF:
1342 case PP_ELIFDEF:
1343 case PP_IFNDEF:
1344 case PP_ELIFNDEF:
1345 j = FALSE; /* have we matched yet? */
1346 while (tline) {
1347 skip_white_(tline);
1348 if (!tline || (tline->type != TOK_ID &&
1349 (tline->type != TOK_PREPROC_ID ||
1350 tline->text[1] != '$'))) {
1351 error(ERR_NONFATAL,
1352 "`%s' expects macro identifiers", directives[i]);
1353 free_tlist(origline);
1354 return -1;
1356 if (smacro_defined(NULL, tline->text, 0, NULL, 1))
1357 j = TRUE;
1358 tline = tline->next;
1360 if (i == PP_IFNDEF || i == PP_ELIFNDEF)
1361 j = !j;
1362 free_tlist(origline);
1363 return j;
1365 case PP_IFIDN:
1366 case PP_ELIFIDN:
1367 case PP_IFNIDN:
1368 case PP_ELIFNIDN:
1369 case PP_IFIDNI:
1370 case PP_ELIFIDNI:
1371 case PP_IFNIDNI:
1372 case PP_ELIFNIDNI:
1373 tline = expand_smacro(tline);
1374 t = tt = tline;
1375 while (tok_isnt_(tt, ","))
1376 tt = tt->next;
1377 if (!tt) {
1378 error(ERR_NONFATAL,
1379 "`%s' expects two comma-separated arguments",
1380 directives[i]);
1381 free_tlist(tline);
1382 return -1;
1384 tt = tt->next;
1385 casesense = (i == PP_IFIDN || i == PP_ELIFIDN ||
1386 i == PP_IFNIDN || i == PP_ELIFNIDN);
1387 j = TRUE; /* assume equality unless proved not */
1388 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1389 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1390 error(ERR_NONFATAL, "`%s': more than one comma on line",
1391 directives[i]);
1392 free_tlist(tline);
1393 return -1;
1395 if (t->type == TOK_WHITESPACE) {
1396 t = t->next;
1397 continue;
1399 if (tt->type == TOK_WHITESPACE) {
1400 tt = tt->next;
1401 continue;
1403 if (tt->type != t->type) {
1404 j = FALSE; /* found mismatching tokens */
1405 break;
1407 /* Unify surrounding quotes for strings */
1408 if (t->type == TOK_STRING) {
1409 tt->text[0] = t->text[0];
1410 tt->text[strlen(tt->text) - 1] = t->text[0];
1412 if (mstrcmp(tt->text, t->text, casesense) != 0) {
1413 j = FALSE; /* found mismatching tokens */
1414 break;
1417 t = t->next;
1418 tt = tt->next;
1420 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
1421 j = FALSE; /* trailing gunk on one end or other */
1422 if (i == PP_IFNIDN || i == PP_ELIFNIDN ||
1423 i == PP_IFNIDNI || i == PP_ELIFNIDNI)
1424 j = !j;
1425 free_tlist(tline);
1426 return j;
1428 case PP_IFMACRO:
1429 case PP_ELIFMACRO:
1430 case PP_IFNMACRO:
1431 case PP_ELIFNMACRO:
1433 int found = 0;
1434 MMacro searching, *mmac;
1436 tline = tline->next;
1437 skip_white_(tline);
1438 tline = expand_id(tline);
1439 if (!tok_type_(tline, TOK_ID)) {
1440 error(ERR_NONFATAL,
1441 "`%s' expects a macro name", directives[i]);
1442 return -1;
1444 searching.name = nasm_strdup(tline->text);
1445 searching.casesense = (i == PP_MACRO);
1446 searching.plus = FALSE;
1447 searching.nolist = FALSE;
1448 searching.in_progress = FALSE;
1449 searching.rep_nest = NULL;
1450 searching.nparam_min = 0;
1451 searching.nparam_max = INT_MAX;
1452 tline = expand_smacro(tline->next);
1453 skip_white_(tline);
1454 if (!tline) {
1455 } else if (!tok_type_(tline, TOK_NUMBER)) {
1456 error(ERR_NONFATAL,
1457 "`%s' expects a parameter count or nothing",
1458 directives[i]);
1459 } else {
1460 searching.nparam_min = searching.nparam_max =
1461 readnum(tline->text, &j);
1462 if (j)
1463 error(ERR_NONFATAL,
1464 "unable to parse parameter count `%s'",
1465 tline->text);
1467 if (tline && tok_is_(tline->next, "-")) {
1468 tline = tline->next->next;
1469 if (tok_is_(tline, "*"))
1470 searching.nparam_max = INT_MAX;
1471 else if (!tok_type_(tline, TOK_NUMBER))
1472 error(ERR_NONFATAL,
1473 "`%s' expects a parameter count after `-'",
1474 directives[i]);
1475 else {
1476 searching.nparam_max = readnum(tline->text, &j);
1477 if (j)
1478 error(ERR_NONFATAL,
1479 "unable to parse parameter count `%s'",
1480 tline->text);
1481 if (searching.nparam_min > searching.nparam_max)
1482 error(ERR_NONFATAL,
1483 "minimum parameter count exceeds maximum");
1486 if (tline && tok_is_(tline->next, "+")) {
1487 tline = tline->next;
1488 searching.plus = TRUE;
1490 mmac = mmacros[hash(searching.name)];
1491 while (mmac) {
1492 if (!strcmp(mmac->name, searching.name) &&
1493 (mmac->nparam_min <= searching.nparam_max
1494 || searching.plus)
1495 && (searching.nparam_min <= mmac->nparam_max
1496 || mmac->plus)) {
1497 found = TRUE;
1498 break;
1500 mmac = mmac->next;
1502 nasm_free(searching.name);
1503 free_tlist(origline);
1504 if (i == PP_IFNMACRO || i == PP_ELIFNMACRO)
1505 found = !found;
1506 return found;
1509 case PP_IFID:
1510 case PP_ELIFID:
1511 case PP_IFNID:
1512 case PP_ELIFNID:
1513 case PP_IFNUM:
1514 case PP_ELIFNUM:
1515 case PP_IFNNUM:
1516 case PP_ELIFNNUM:
1517 case PP_IFSTR:
1518 case PP_ELIFSTR:
1519 case PP_IFNSTR:
1520 case PP_ELIFNSTR:
1521 tline = expand_smacro(tline);
1522 t = tline;
1523 while (tok_type_(t, TOK_WHITESPACE))
1524 t = t->next;
1525 j = FALSE; /* placate optimiser */
1526 if (t)
1527 switch (i) {
1528 case PP_IFID:
1529 case PP_ELIFID:
1530 case PP_IFNID:
1531 case PP_ELIFNID:
1532 j = (t->type == TOK_ID);
1533 break;
1534 case PP_IFNUM:
1535 case PP_ELIFNUM:
1536 case PP_IFNNUM:
1537 case PP_ELIFNNUM:
1538 j = (t->type == TOK_NUMBER);
1539 break;
1540 case PP_IFSTR:
1541 case PP_ELIFSTR:
1542 case PP_IFNSTR:
1543 case PP_ELIFNSTR:
1544 j = (t->type == TOK_STRING);
1545 break;
1547 if (i == PP_IFNID || i == PP_ELIFNID ||
1548 i == PP_IFNNUM || i == PP_ELIFNNUM ||
1549 i == PP_IFNSTR || i == PP_ELIFNSTR)
1550 j = !j;
1551 free_tlist(tline);
1552 return j;
1554 case PP_IF:
1555 case PP_ELIF:
1556 t = tline = expand_smacro(tline);
1557 tptr = &t;
1558 tokval.t_type = TOKEN_INVALID;
1559 evalresult = evaluate(ppscan, tptr, &tokval,
1560 NULL, pass | CRITICAL, error, NULL);
1561 free_tlist(tline);
1562 if (!evalresult)
1563 return -1;
1564 if (tokval.t_type)
1565 error(ERR_WARNING,
1566 "trailing garbage after expression ignored");
1567 if (!is_simple(evalresult)) {
1568 error(ERR_NONFATAL,
1569 "non-constant value given to `%s'", directives[i]);
1570 return -1;
1572 return reloc_value(evalresult) != 0;
1574 default:
1575 error(ERR_FATAL,
1576 "preprocessor directive `%s' not yet implemented",
1577 directives[i]);
1578 free_tlist(origline);
1579 return -1; /* yeah, right */
1584 * Expand macros in a string. Used in %error and %include directives.
1585 * First tokenise the string, apply "expand_smacro" and then de-tokenise back.
1586 * The returned variable should ALWAYS be freed after usage.
1588 void expand_macros_in_string(char **p)
1590 Token *line = tokenise(*p);
1591 line = expand_smacro(line);
1592 *p = detoken(line, FALSE);
1596 * find and process preprocessor directive in passed line
1597 * Find out if a line contains a preprocessor directive, and deal
1598 * with it if so.
1600 * If a directive _is_ found, it is the responsibility of this routine
1601 * (and not the caller) to free_tlist() the line.
1603 * @param tline a pointer to the current tokeninzed line linked list
1604 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
1607 static int do_directive(Token * tline)
1609 int i, j, k, m, nparam, nolist;
1610 int offset;
1611 char *p, *mname;
1612 Include *inc;
1613 Context *ctx;
1614 Cond *cond;
1615 SMacro *smac, **smhead;
1616 MMacro *mmac;
1617 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
1618 Line *l;
1619 struct tokenval tokval;
1620 expr *evalresult;
1621 MMacro *tmp_defining; /* Used when manipulating rep_nest */
1623 origline = tline;
1625 skip_white_(tline);
1626 if (!tok_type_(tline, TOK_PREPROC_ID) ||
1627 (tline->text[1] == '%' || tline->text[1] == '$'
1628 || tline->text[1] == '!'))
1629 return NO_DIRECTIVE_FOUND;
1631 i = -1;
1632 j = elements(directives);
1633 while (j - i > 1) {
1634 k = (j + i) / 2;
1635 m = nasm_stricmp(tline->text, directives[k]);
1636 if (m == 0) {
1637 if (tasm_compatible_mode) {
1638 i = k;
1639 j = -2;
1640 } else if (k != PP_ARG && k != PP_LOCAL && k != PP_STACKSIZE) {
1641 i = k;
1642 j = -2;
1644 break;
1645 } else if (m < 0) {
1646 j = k;
1647 } else
1648 i = k;
1652 * If we're in a non-emitting branch of a condition construct,
1653 * or walking to the end of an already terminated %rep block,
1654 * we should ignore all directives except for condition
1655 * directives.
1657 if (((istk->conds && !emitting(istk->conds->state)) ||
1658 (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
1659 return NO_DIRECTIVE_FOUND;
1663 * If we're defining a macro or reading a %rep block, we should
1664 * ignore all directives except for %macro/%imacro (which
1665 * generate an error), %endm/%endmacro, and (only if we're in a
1666 * %rep block) %endrep. If we're in a %rep block, another %rep
1667 * causes an error, so should be let through.
1669 if (defining && i != PP_MACRO && i != PP_IMACRO &&
1670 i != PP_ENDMACRO && i != PP_ENDM &&
1671 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
1672 return NO_DIRECTIVE_FOUND;
1675 if (j != -2) {
1676 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
1677 tline->text);
1678 return NO_DIRECTIVE_FOUND; /* didn't get it */
1681 switch (i) {
1682 case PP_STACKSIZE:
1683 /* Directive to tell NASM what the default stack size is. The
1684 * default is for a 16-bit stack, and this can be overriden with
1685 * %stacksize large.
1686 * the following form:
1688 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1690 tline = tline->next;
1691 if (tline && tline->type == TOK_WHITESPACE)
1692 tline = tline->next;
1693 if (!tline || tline->type != TOK_ID) {
1694 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
1695 free_tlist(origline);
1696 return DIRECTIVE_FOUND;
1698 if (nasm_stricmp(tline->text, "flat") == 0) {
1699 /* All subsequent ARG directives are for a 32-bit stack */
1700 StackSize = 4;
1701 StackPointer = "ebp";
1702 ArgOffset = 8;
1703 LocalOffset = 4;
1704 } else if (nasm_stricmp(tline->text, "large") == 0) {
1705 /* All subsequent ARG directives are for a 16-bit stack,
1706 * far function call.
1708 StackSize = 2;
1709 StackPointer = "bp";
1710 ArgOffset = 4;
1711 LocalOffset = 2;
1712 } else if (nasm_stricmp(tline->text, "small") == 0) {
1713 /* All subsequent ARG directives are for a 16-bit stack,
1714 * far function call. We don't support near functions.
1716 StackSize = 2;
1717 StackPointer = "bp";
1718 ArgOffset = 6;
1719 LocalOffset = 2;
1720 } else {
1721 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
1722 free_tlist(origline);
1723 return DIRECTIVE_FOUND;
1725 free_tlist(origline);
1726 return DIRECTIVE_FOUND;
1728 case PP_ARG:
1729 /* TASM like ARG directive to define arguments to functions, in
1730 * the following form:
1732 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1734 offset = ArgOffset;
1735 do {
1736 char *arg, directive[256];
1737 int size = StackSize;
1739 /* Find the argument name */
1740 tline = tline->next;
1741 if (tline && tline->type == TOK_WHITESPACE)
1742 tline = tline->next;
1743 if (!tline || tline->type != TOK_ID) {
1744 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
1745 free_tlist(origline);
1746 return DIRECTIVE_FOUND;
1748 arg = tline->text;
1750 /* Find the argument size type */
1751 tline = tline->next;
1752 if (!tline || tline->type != TOK_OTHER
1753 || tline->text[0] != ':') {
1754 error(ERR_NONFATAL,
1755 "Syntax error processing `%%arg' directive");
1756 free_tlist(origline);
1757 return DIRECTIVE_FOUND;
1759 tline = tline->next;
1760 if (!tline || tline->type != TOK_ID) {
1761 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
1762 free_tlist(origline);
1763 return DIRECTIVE_FOUND;
1766 /* Allow macro expansion of type parameter */
1767 tt = tokenise(tline->text);
1768 tt = expand_smacro(tt);
1769 if (nasm_stricmp(tt->text, "byte") == 0) {
1770 size = MAX(StackSize, 1);
1771 } else if (nasm_stricmp(tt->text, "word") == 0) {
1772 size = MAX(StackSize, 2);
1773 } else if (nasm_stricmp(tt->text, "dword") == 0) {
1774 size = MAX(StackSize, 4);
1775 } else if (nasm_stricmp(tt->text, "qword") == 0) {
1776 size = MAX(StackSize, 8);
1777 } else if (nasm_stricmp(tt->text, "tword") == 0) {
1778 size = MAX(StackSize, 10);
1779 } else {
1780 error(ERR_NONFATAL,
1781 "Invalid size type for `%%arg' missing directive");
1782 free_tlist(tt);
1783 free_tlist(origline);
1784 return DIRECTIVE_FOUND;
1786 free_tlist(tt);
1788 /* Now define the macro for the argument */
1789 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
1790 arg, StackPointer, offset);
1791 do_directive(tokenise(directive));
1792 offset += size;
1794 /* Move to the next argument in the list */
1795 tline = tline->next;
1796 if (tline && tline->type == TOK_WHITESPACE)
1797 tline = tline->next;
1799 while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
1800 free_tlist(origline);
1801 return DIRECTIVE_FOUND;
1803 case PP_LOCAL:
1804 /* TASM like LOCAL directive to define local variables for a
1805 * function, in the following form:
1807 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
1809 * The '= LocalSize' at the end is ignored by NASM, but is
1810 * required by TASM to define the local parameter size (and used
1811 * by the TASM macro package).
1813 offset = LocalOffset;
1814 do {
1815 char *local, directive[256];
1816 int size = StackSize;
1818 /* Find the argument name */
1819 tline = tline->next;
1820 if (tline && tline->type == TOK_WHITESPACE)
1821 tline = tline->next;
1822 if (!tline || tline->type != TOK_ID) {
1823 error(ERR_NONFATAL,
1824 "`%%local' missing argument parameter");
1825 free_tlist(origline);
1826 return DIRECTIVE_FOUND;
1828 local = tline->text;
1830 /* Find the argument size type */
1831 tline = tline->next;
1832 if (!tline || tline->type != TOK_OTHER
1833 || tline->text[0] != ':') {
1834 error(ERR_NONFATAL,
1835 "Syntax error processing `%%local' directive");
1836 free_tlist(origline);
1837 return DIRECTIVE_FOUND;
1839 tline = tline->next;
1840 if (!tline || tline->type != TOK_ID) {
1841 error(ERR_NONFATAL,
1842 "`%%local' missing size type parameter");
1843 free_tlist(origline);
1844 return DIRECTIVE_FOUND;
1847 /* Allow macro expansion of type parameter */
1848 tt = tokenise(tline->text);
1849 tt = expand_smacro(tt);
1850 if (nasm_stricmp(tt->text, "byte") == 0) {
1851 size = MAX(StackSize, 1);
1852 } else if (nasm_stricmp(tt->text, "word") == 0) {
1853 size = MAX(StackSize, 2);
1854 } else if (nasm_stricmp(tt->text, "dword") == 0) {
1855 size = MAX(StackSize, 4);
1856 } else if (nasm_stricmp(tt->text, "qword") == 0) {
1857 size = MAX(StackSize, 8);
1858 } else if (nasm_stricmp(tt->text, "tword") == 0) {
1859 size = MAX(StackSize, 10);
1860 } else {
1861 error(ERR_NONFATAL,
1862 "Invalid size type for `%%local' missing directive");
1863 free_tlist(tt);
1864 free_tlist(origline);
1865 return DIRECTIVE_FOUND;
1867 free_tlist(tt);
1869 /* Now define the macro for the argument */
1870 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
1871 local, StackPointer, offset);
1872 do_directive(tokenise(directive));
1873 offset += size;
1875 /* Now define the assign to setup the enter_c macro correctly */
1876 snprintf(directive, sizeof(directive),
1877 "%%assign %%$localsize %%$localsize+%d", size);
1878 do_directive(tokenise(directive));
1880 /* Move to the next argument in the list */
1881 tline = tline->next;
1882 if (tline && tline->type == TOK_WHITESPACE)
1883 tline = tline->next;
1885 while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
1886 free_tlist(origline);
1887 return DIRECTIVE_FOUND;
1889 case PP_CLEAR:
1890 if (tline->next)
1891 error(ERR_WARNING, "trailing garbage after `%%clear' ignored");
1892 for (j = 0; j < NHASH; j++) {
1893 while (mmacros[j]) {
1894 MMacro *m = mmacros[j];
1895 mmacros[j] = m->next;
1896 free_mmacro(m);
1898 while (smacros[j]) {
1899 SMacro *s = smacros[j];
1900 smacros[j] = smacros[j]->next;
1901 nasm_free(s->name);
1902 free_tlist(s->expansion);
1903 nasm_free(s);
1906 free_tlist(origline);
1907 return DIRECTIVE_FOUND;
1909 case PP_INCLUDE:
1910 tline = tline->next;
1911 skip_white_(tline);
1912 if (!tline || (tline->type != TOK_STRING &&
1913 tline->type != TOK_INTERNAL_STRING)) {
1914 error(ERR_NONFATAL, "`%%include' expects a file name");
1915 free_tlist(origline);
1916 return DIRECTIVE_FOUND; /* but we did _something_ */
1918 if (tline->next)
1919 error(ERR_WARNING,
1920 "trailing garbage after `%%include' ignored");
1921 if (tline->type != TOK_INTERNAL_STRING) {
1922 p = tline->text + 1; /* point past the quote to the name */
1923 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
1924 } else
1925 p = tline->text; /* internal_string is easier */
1926 expand_macros_in_string(&p);
1927 inc = nasm_malloc(sizeof(Include));
1928 inc->next = istk;
1929 inc->conds = NULL;
1930 inc->fp = inc_fopen(p);
1931 inc->fname = src_set_fname(p);
1932 inc->lineno = src_set_linnum(0);
1933 inc->lineinc = 1;
1934 inc->expansion = NULL;
1935 inc->mstk = NULL;
1936 istk = inc;
1937 list->uplevel(LIST_INCLUDE);
1938 free_tlist(origline);
1939 return DIRECTIVE_FOUND;
1941 case PP_PUSH:
1942 tline = tline->next;
1943 skip_white_(tline);
1944 tline = expand_id(tline);
1945 if (!tok_type_(tline, TOK_ID)) {
1946 error(ERR_NONFATAL, "`%%push' expects a context identifier");
1947 free_tlist(origline);
1948 return DIRECTIVE_FOUND; /* but we did _something_ */
1950 if (tline->next)
1951 error(ERR_WARNING, "trailing garbage after `%%push' ignored");
1952 ctx = nasm_malloc(sizeof(Context));
1953 ctx->next = cstk;
1954 ctx->localmac = NULL;
1955 ctx->name = nasm_strdup(tline->text);
1956 ctx->number = unique++;
1957 cstk = ctx;
1958 free_tlist(origline);
1959 break;
1961 case PP_REPL:
1962 tline = tline->next;
1963 skip_white_(tline);
1964 tline = expand_id(tline);
1965 if (!tok_type_(tline, TOK_ID)) {
1966 error(ERR_NONFATAL, "`%%repl' expects a context identifier");
1967 free_tlist(origline);
1968 return DIRECTIVE_FOUND; /* but we did _something_ */
1970 if (tline->next)
1971 error(ERR_WARNING, "trailing garbage after `%%repl' ignored");
1972 if (!cstk)
1973 error(ERR_NONFATAL, "`%%repl': context stack is empty");
1974 else {
1975 nasm_free(cstk->name);
1976 cstk->name = nasm_strdup(tline->text);
1978 free_tlist(origline);
1979 break;
1981 case PP_POP:
1982 if (tline->next)
1983 error(ERR_WARNING, "trailing garbage after `%%pop' ignored");
1984 if (!cstk)
1985 error(ERR_NONFATAL, "`%%pop': context stack is already empty");
1986 else
1987 ctx_pop();
1988 free_tlist(origline);
1989 break;
1991 case PP_ERROR:
1992 tline->next = expand_smacro(tline->next);
1993 tline = tline->next;
1994 skip_white_(tline);
1995 if (tok_type_(tline, TOK_STRING)) {
1996 p = tline->text + 1; /* point past the quote to the name */
1997 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
1998 expand_macros_in_string(&p);
1999 error(ERR_NONFATAL, "%s", p);
2000 nasm_free(p);
2001 } else {
2002 p = detoken(tline, FALSE);
2003 error(ERR_WARNING, "%s", p);
2004 nasm_free(p);
2006 free_tlist(origline);
2007 break;
2009 case PP_IF:
2010 case PP_IFCTX:
2011 case PP_IFDEF:
2012 case PP_IFID:
2013 case PP_IFIDN:
2014 case PP_IFIDNI:
2015 case PP_IFMACRO:
2016 case PP_IFNCTX:
2017 case PP_IFNDEF:
2018 case PP_IFNID:
2019 case PP_IFNIDN:
2020 case PP_IFNIDNI:
2021 case PP_IFNMACRO:
2022 case PP_IFNNUM:
2023 case PP_IFNSTR:
2024 case PP_IFNUM:
2025 case PP_IFSTR:
2026 if (istk->conds && !emitting(istk->conds->state))
2027 j = COND_NEVER;
2028 else {
2029 j = if_condition(tline->next, i);
2030 tline->next = NULL; /* it got freed */
2031 free_tlist(origline);
2032 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2034 cond = nasm_malloc(sizeof(Cond));
2035 cond->next = istk->conds;
2036 cond->state = j;
2037 istk->conds = cond;
2038 return DIRECTIVE_FOUND;
2040 case PP_ELIF:
2041 case PP_ELIFCTX:
2042 case PP_ELIFDEF:
2043 case PP_ELIFID:
2044 case PP_ELIFIDN:
2045 case PP_ELIFIDNI:
2046 case PP_ELIFMACRO:
2047 case PP_ELIFNCTX:
2048 case PP_ELIFNDEF:
2049 case PP_ELIFNID:
2050 case PP_ELIFNIDN:
2051 case PP_ELIFNIDNI:
2052 case PP_ELIFNMACRO:
2053 case PP_ELIFNNUM:
2054 case PP_ELIFNSTR:
2055 case PP_ELIFNUM:
2056 case PP_ELIFSTR:
2057 if (!istk->conds)
2058 error(ERR_FATAL, "`%s': no matching `%%if'", directives[i]);
2059 if (emitting(istk->conds->state)
2060 || istk->conds->state == COND_NEVER)
2061 istk->conds->state = COND_NEVER;
2062 else {
2064 * IMPORTANT: In the case of %if, we will already have
2065 * called expand_mmac_params(); however, if we're
2066 * processing an %elif we must have been in a
2067 * non-emitting mode, which would have inhibited
2068 * the normal invocation of expand_mmac_params(). Therefore,
2069 * we have to do it explicitly here.
2071 j = if_condition(expand_mmac_params(tline->next), i);
2072 tline->next = NULL; /* it got freed */
2073 free_tlist(origline);
2074 istk->conds->state =
2075 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2077 return DIRECTIVE_FOUND;
2079 case PP_ELSE:
2080 if (tline->next)
2081 error(ERR_WARNING, "trailing garbage after `%%else' ignored");
2082 if (!istk->conds)
2083 error(ERR_FATAL, "`%%else': no matching `%%if'");
2084 if (emitting(istk->conds->state)
2085 || istk->conds->state == COND_NEVER)
2086 istk->conds->state = COND_ELSE_FALSE;
2087 else
2088 istk->conds->state = COND_ELSE_TRUE;
2089 free_tlist(origline);
2090 return DIRECTIVE_FOUND;
2092 case PP_ENDIF:
2093 if (tline->next)
2094 error(ERR_WARNING, "trailing garbage after `%%endif' ignored");
2095 if (!istk->conds)
2096 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2097 cond = istk->conds;
2098 istk->conds = cond->next;
2099 nasm_free(cond);
2100 free_tlist(origline);
2101 return DIRECTIVE_FOUND;
2103 case PP_MACRO:
2104 case PP_IMACRO:
2105 if (defining)
2106 error(ERR_FATAL,
2107 "`%%%smacro': already defining a macro",
2108 (i == PP_IMACRO ? "i" : ""));
2109 tline = tline->next;
2110 skip_white_(tline);
2111 tline = expand_id(tline);
2112 if (!tok_type_(tline, TOK_ID)) {
2113 error(ERR_NONFATAL,
2114 "`%%%smacro' expects a macro name",
2115 (i == PP_IMACRO ? "i" : ""));
2116 return DIRECTIVE_FOUND;
2118 defining = nasm_malloc(sizeof(MMacro));
2119 defining->name = nasm_strdup(tline->text);
2120 defining->casesense = (i == PP_MACRO);
2121 defining->plus = FALSE;
2122 defining->nolist = FALSE;
2123 defining->in_progress = FALSE;
2124 defining->rep_nest = NULL;
2125 tline = expand_smacro(tline->next);
2126 skip_white_(tline);
2127 if (!tok_type_(tline, TOK_NUMBER)) {
2128 error(ERR_NONFATAL,
2129 "`%%%smacro' expects a parameter count",
2130 (i == PP_IMACRO ? "i" : ""));
2131 defining->nparam_min = defining->nparam_max = 0;
2132 } else {
2133 defining->nparam_min = defining->nparam_max =
2134 readnum(tline->text, &j);
2135 if (j)
2136 error(ERR_NONFATAL,
2137 "unable to parse parameter count `%s'", tline->text);
2139 if (tline && tok_is_(tline->next, "-")) {
2140 tline = tline->next->next;
2141 if (tok_is_(tline, "*"))
2142 defining->nparam_max = INT_MAX;
2143 else if (!tok_type_(tline, TOK_NUMBER))
2144 error(ERR_NONFATAL,
2145 "`%%%smacro' expects a parameter count after `-'",
2146 (i == PP_IMACRO ? "i" : ""));
2147 else {
2148 defining->nparam_max = readnum(tline->text, &j);
2149 if (j)
2150 error(ERR_NONFATAL,
2151 "unable to parse parameter count `%s'",
2152 tline->text);
2153 if (defining->nparam_min > defining->nparam_max)
2154 error(ERR_NONFATAL,
2155 "minimum parameter count exceeds maximum");
2158 if (tline && tok_is_(tline->next, "+")) {
2159 tline = tline->next;
2160 defining->plus = TRUE;
2162 if (tline && tok_type_(tline->next, TOK_ID) &&
2163 !nasm_stricmp(tline->next->text, ".nolist")) {
2164 tline = tline->next;
2165 defining->nolist = TRUE;
2167 mmac = mmacros[hash(defining->name)];
2168 while (mmac) {
2169 if (!strcmp(mmac->name, defining->name) &&
2170 (mmac->nparam_min <= defining->nparam_max
2171 || defining->plus)
2172 && (defining->nparam_min <= mmac->nparam_max
2173 || mmac->plus)) {
2174 error(ERR_WARNING,
2175 "redefining multi-line macro `%s'", defining->name);
2176 break;
2178 mmac = mmac->next;
2181 * Handle default parameters.
2183 if (tline && tline->next) {
2184 defining->dlist = tline->next;
2185 tline->next = NULL;
2186 count_mmac_params(defining->dlist, &defining->ndefs,
2187 &defining->defaults);
2188 } else {
2189 defining->dlist = NULL;
2190 defining->defaults = NULL;
2192 defining->expansion = NULL;
2193 free_tlist(origline);
2194 return DIRECTIVE_FOUND;
2196 case PP_ENDM:
2197 case PP_ENDMACRO:
2198 if (!defining) {
2199 error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2200 return DIRECTIVE_FOUND;
2202 k = hash(defining->name);
2203 defining->next = mmacros[k];
2204 mmacros[k] = defining;
2205 defining = NULL;
2206 free_tlist(origline);
2207 return DIRECTIVE_FOUND;
2209 case PP_ROTATE:
2210 if (tline->next && tline->next->type == TOK_WHITESPACE)
2211 tline = tline->next;
2212 if (tline->next == NULL) {
2213 free_tlist(origline);
2214 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
2215 return DIRECTIVE_FOUND;
2217 t = expand_smacro(tline->next);
2218 tline->next = NULL;
2219 free_tlist(origline);
2220 tline = t;
2221 tptr = &t;
2222 tokval.t_type = TOKEN_INVALID;
2223 evalresult =
2224 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2225 free_tlist(tline);
2226 if (!evalresult)
2227 return DIRECTIVE_FOUND;
2228 if (tokval.t_type)
2229 error(ERR_WARNING,
2230 "trailing garbage after expression ignored");
2231 if (!is_simple(evalresult)) {
2232 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2233 return DIRECTIVE_FOUND;
2235 mmac = istk->mstk;
2236 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2237 mmac = mmac->next_active;
2238 if (!mmac) {
2239 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
2240 } else if (mmac->nparam == 0) {
2241 error(ERR_NONFATAL,
2242 "`%%rotate' invoked within macro without parameters");
2243 } else {
2244 mmac->rotate = mmac->rotate + reloc_value(evalresult);
2246 if (mmac->rotate < 0)
2247 mmac->rotate =
2248 mmac->nparam - (-mmac->rotate) % mmac->nparam;
2249 mmac->rotate %= mmac->nparam;
2251 return DIRECTIVE_FOUND;
2253 case PP_REP:
2254 nolist = FALSE;
2255 do {
2256 tline = tline->next;
2257 } while (tok_type_(tline, TOK_WHITESPACE));
2259 if (tok_type_(tline, TOK_ID) &&
2260 nasm_stricmp(tline->text, ".nolist") == 0) {
2261 nolist = TRUE;
2262 do {
2263 tline = tline->next;
2264 } while (tok_type_(tline, TOK_WHITESPACE));
2267 if (tline) {
2268 t = expand_smacro(tline);
2269 tptr = &t;
2270 tokval.t_type = TOKEN_INVALID;
2271 evalresult =
2272 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2273 if (!evalresult) {
2274 free_tlist(origline);
2275 return DIRECTIVE_FOUND;
2277 if (tokval.t_type)
2278 error(ERR_WARNING,
2279 "trailing garbage after expression ignored");
2280 if (!is_simple(evalresult)) {
2281 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2282 return DIRECTIVE_FOUND;
2284 i = (int)reloc_value(evalresult) + 1;
2285 } else {
2286 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
2287 i = 0;
2289 free_tlist(origline);
2291 tmp_defining = defining;
2292 defining = nasm_malloc(sizeof(MMacro));
2293 defining->name = NULL; /* flags this macro as a %rep block */
2294 defining->casesense = 0;
2295 defining->plus = FALSE;
2296 defining->nolist = nolist;
2297 defining->in_progress = i;
2298 defining->nparam_min = defining->nparam_max = 0;
2299 defining->defaults = NULL;
2300 defining->dlist = NULL;
2301 defining->expansion = NULL;
2302 defining->next_active = istk->mstk;
2303 defining->rep_nest = tmp_defining;
2304 return DIRECTIVE_FOUND;
2306 case PP_ENDREP:
2307 if (!defining || defining->name) {
2308 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2309 return DIRECTIVE_FOUND;
2313 * Now we have a "macro" defined - although it has no name
2314 * and we won't be entering it in the hash tables - we must
2315 * push a macro-end marker for it on to istk->expansion.
2316 * After that, it will take care of propagating itself (a
2317 * macro-end marker line for a macro which is really a %rep
2318 * block will cause the macro to be re-expanded, complete
2319 * with another macro-end marker to ensure the process
2320 * continues) until the whole expansion is forcibly removed
2321 * from istk->expansion by a %exitrep.
2323 l = nasm_malloc(sizeof(Line));
2324 l->next = istk->expansion;
2325 l->finishes = defining;
2326 l->first = NULL;
2327 istk->expansion = l;
2329 istk->mstk = defining;
2331 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2332 tmp_defining = defining;
2333 defining = defining->rep_nest;
2334 free_tlist(origline);
2335 return DIRECTIVE_FOUND;
2337 case PP_EXITREP:
2339 * We must search along istk->expansion until we hit a
2340 * macro-end marker for a macro with no name. Then we set
2341 * its `in_progress' flag to 0.
2343 for (l = istk->expansion; l; l = l->next)
2344 if (l->finishes && !l->finishes->name)
2345 break;
2347 if (l)
2348 l->finishes->in_progress = 0;
2349 else
2350 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2351 free_tlist(origline);
2352 return DIRECTIVE_FOUND;
2354 case PP_XDEFINE:
2355 case PP_IXDEFINE:
2356 case PP_DEFINE:
2357 case PP_IDEFINE:
2358 tline = tline->next;
2359 skip_white_(tline);
2360 tline = expand_id(tline);
2361 if (!tline || (tline->type != TOK_ID &&
2362 (tline->type != TOK_PREPROC_ID ||
2363 tline->text[1] != '$'))) {
2364 error(ERR_NONFATAL,
2365 "`%%%s%sdefine' expects a macro identifier",
2366 ((i == PP_IDEFINE || i == PP_IXDEFINE) ? "i" : ""),
2367 ((i == PP_XDEFINE || i == PP_IXDEFINE) ? "x" : ""));
2368 free_tlist(origline);
2369 return DIRECTIVE_FOUND;
2372 ctx = get_ctx(tline->text, FALSE);
2373 if (!ctx)
2374 smhead = &smacros[hash(tline->text)];
2375 else
2376 smhead = &ctx->localmac;
2377 mname = tline->text;
2378 last = tline;
2379 param_start = tline = tline->next;
2380 nparam = 0;
2382 /* Expand the macro definition now for %xdefine and %ixdefine */
2383 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2384 tline = expand_smacro(tline);
2386 if (tok_is_(tline, "(")) {
2388 * This macro has parameters.
2391 tline = tline->next;
2392 while (1) {
2393 skip_white_(tline);
2394 if (!tline) {
2395 error(ERR_NONFATAL, "parameter identifier expected");
2396 free_tlist(origline);
2397 return DIRECTIVE_FOUND;
2399 if (tline->type != TOK_ID) {
2400 error(ERR_NONFATAL,
2401 "`%s': parameter identifier expected",
2402 tline->text);
2403 free_tlist(origline);
2404 return DIRECTIVE_FOUND;
2406 tline->type = TOK_SMAC_PARAM + nparam++;
2407 tline = tline->next;
2408 skip_white_(tline);
2409 if (tok_is_(tline, ",")) {
2410 tline = tline->next;
2411 continue;
2413 if (!tok_is_(tline, ")")) {
2414 error(ERR_NONFATAL,
2415 "`)' expected to terminate macro template");
2416 free_tlist(origline);
2417 return DIRECTIVE_FOUND;
2419 break;
2421 last = tline;
2422 tline = tline->next;
2424 if (tok_type_(tline, TOK_WHITESPACE))
2425 last = tline, tline = tline->next;
2426 macro_start = NULL;
2427 last->next = NULL;
2428 t = tline;
2429 while (t) {
2430 if (t->type == TOK_ID) {
2431 for (tt = param_start; tt; tt = tt->next)
2432 if (tt->type >= TOK_SMAC_PARAM &&
2433 !strcmp(tt->text, t->text))
2434 t->type = tt->type;
2436 tt = t->next;
2437 t->next = macro_start;
2438 macro_start = t;
2439 t = tt;
2442 * Good. We now have a macro name, a parameter count, and a
2443 * token list (in reverse order) for an expansion. We ought
2444 * to be OK just to create an SMacro, store it, and let
2445 * free_tlist have the rest of the line (which we have
2446 * carefully re-terminated after chopping off the expansion
2447 * from the end).
2449 if (smacro_defined(ctx, mname, nparam, &smac, i == PP_DEFINE)) {
2450 if (!smac) {
2451 error(ERR_WARNING,
2452 "single-line macro `%s' defined both with and"
2453 " without parameters", mname);
2454 free_tlist(origline);
2455 free_tlist(macro_start);
2456 return DIRECTIVE_FOUND;
2457 } else {
2459 * We're redefining, so we have to take over an
2460 * existing SMacro structure. This means freeing
2461 * what was already in it.
2463 nasm_free(smac->name);
2464 free_tlist(smac->expansion);
2466 } else {
2467 smac = nasm_malloc(sizeof(SMacro));
2468 smac->next = *smhead;
2469 *smhead = smac;
2471 smac->name = nasm_strdup(mname);
2472 smac->casesense = ((i == PP_DEFINE) || (i == PP_XDEFINE));
2473 smac->nparam = nparam;
2474 smac->expansion = macro_start;
2475 smac->in_progress = FALSE;
2476 free_tlist(origline);
2477 return DIRECTIVE_FOUND;
2479 case PP_UNDEF:
2480 tline = tline->next;
2481 skip_white_(tline);
2482 tline = expand_id(tline);
2483 if (!tline || (tline->type != TOK_ID &&
2484 (tline->type != TOK_PREPROC_ID ||
2485 tline->text[1] != '$'))) {
2486 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
2487 free_tlist(origline);
2488 return DIRECTIVE_FOUND;
2490 if (tline->next) {
2491 error(ERR_WARNING,
2492 "trailing garbage after macro name ignored");
2495 /* Find the context that symbol belongs to */
2496 ctx = get_ctx(tline->text, FALSE);
2497 if (!ctx)
2498 smhead = &smacros[hash(tline->text)];
2499 else
2500 smhead = &ctx->localmac;
2502 mname = tline->text;
2503 last = tline;
2504 last->next = NULL;
2507 * We now have a macro name... go hunt for it.
2509 while (smacro_defined(ctx, mname, -1, &smac, 1)) {
2510 /* Defined, so we need to find its predecessor and nuke it */
2511 SMacro **s;
2512 for (s = smhead; *s && *s != smac; s = &(*s)->next) ;
2513 if (*s) {
2514 *s = smac->next;
2515 nasm_free(smac->name);
2516 free_tlist(smac->expansion);
2517 nasm_free(smac);
2520 free_tlist(origline);
2521 return DIRECTIVE_FOUND;
2523 case PP_STRLEN:
2524 tline = tline->next;
2525 skip_white_(tline);
2526 tline = expand_id(tline);
2527 if (!tline || (tline->type != TOK_ID &&
2528 (tline->type != TOK_PREPROC_ID ||
2529 tline->text[1] != '$'))) {
2530 error(ERR_NONFATAL,
2531 "`%%strlen' expects a macro identifier as first parameter");
2532 free_tlist(origline);
2533 return DIRECTIVE_FOUND;
2535 ctx = get_ctx(tline->text, FALSE);
2536 if (!ctx)
2537 smhead = &smacros[hash(tline->text)];
2538 else
2539 smhead = &ctx->localmac;
2540 mname = tline->text;
2541 last = tline;
2542 tline = expand_smacro(tline->next);
2543 last->next = NULL;
2545 t = tline;
2546 while (tok_type_(t, TOK_WHITESPACE))
2547 t = t->next;
2548 /* t should now point to the string */
2549 if (t->type != TOK_STRING) {
2550 error(ERR_NONFATAL,
2551 "`%%strlen` requires string as second parameter");
2552 free_tlist(tline);
2553 free_tlist(origline);
2554 return DIRECTIVE_FOUND;
2557 macro_start = nasm_malloc(sizeof(*macro_start));
2558 macro_start->next = NULL;
2559 make_tok_num(macro_start, strlen(t->text) - 2);
2560 macro_start->mac = NULL;
2563 * We now have a macro name, an implicit parameter count of
2564 * zero, and a numeric token to use as an expansion. Create
2565 * and store an SMacro.
2567 if (smacro_defined(ctx, mname, 0, &smac, i == PP_STRLEN)) {
2568 if (!smac)
2569 error(ERR_WARNING,
2570 "single-line macro `%s' defined both with and"
2571 " without parameters", mname);
2572 else {
2574 * We're redefining, so we have to take over an
2575 * existing SMacro structure. This means freeing
2576 * what was already in it.
2578 nasm_free(smac->name);
2579 free_tlist(smac->expansion);
2581 } else {
2582 smac = nasm_malloc(sizeof(SMacro));
2583 smac->next = *smhead;
2584 *smhead = smac;
2586 smac->name = nasm_strdup(mname);
2587 smac->casesense = (i == PP_STRLEN);
2588 smac->nparam = 0;
2589 smac->expansion = macro_start;
2590 smac->in_progress = FALSE;
2591 free_tlist(tline);
2592 free_tlist(origline);
2593 return DIRECTIVE_FOUND;
2595 case PP_SUBSTR:
2596 tline = tline->next;
2597 skip_white_(tline);
2598 tline = expand_id(tline);
2599 if (!tline || (tline->type != TOK_ID &&
2600 (tline->type != TOK_PREPROC_ID ||
2601 tline->text[1] != '$'))) {
2602 error(ERR_NONFATAL,
2603 "`%%substr' expects a macro identifier as first parameter");
2604 free_tlist(origline);
2605 return DIRECTIVE_FOUND;
2607 ctx = get_ctx(tline->text, FALSE);
2608 if (!ctx)
2609 smhead = &smacros[hash(tline->text)];
2610 else
2611 smhead = &ctx->localmac;
2612 mname = tline->text;
2613 last = tline;
2614 tline = expand_smacro(tline->next);
2615 last->next = NULL;
2617 t = tline->next;
2618 while (tok_type_(t, TOK_WHITESPACE))
2619 t = t->next;
2621 /* t should now point to the string */
2622 if (t->type != TOK_STRING) {
2623 error(ERR_NONFATAL,
2624 "`%%substr` requires string as second parameter");
2625 free_tlist(tline);
2626 free_tlist(origline);
2627 return DIRECTIVE_FOUND;
2630 tt = t->next;
2631 tptr = &tt;
2632 tokval.t_type = TOKEN_INVALID;
2633 evalresult =
2634 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2635 if (!evalresult) {
2636 free_tlist(tline);
2637 free_tlist(origline);
2638 return DIRECTIVE_FOUND;
2640 if (!is_simple(evalresult)) {
2641 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
2642 free_tlist(tline);
2643 free_tlist(origline);
2644 return DIRECTIVE_FOUND;
2647 macro_start = nasm_malloc(sizeof(*macro_start));
2648 macro_start->next = NULL;
2649 macro_start->text = nasm_strdup("'''");
2650 if (evalresult->value > 0
2651 && evalresult->value < strlen(t->text) - 1) {
2652 macro_start->text[1] = t->text[evalresult->value];
2653 } else {
2654 macro_start->text[2] = '\0';
2656 macro_start->type = TOK_STRING;
2657 macro_start->mac = NULL;
2660 * We now have a macro name, an implicit parameter count of
2661 * zero, and a numeric token to use as an expansion. Create
2662 * and store an SMacro.
2664 if (smacro_defined(ctx, mname, 0, &smac, i == PP_SUBSTR)) {
2665 if (!smac)
2666 error(ERR_WARNING,
2667 "single-line macro `%s' defined both with and"
2668 " without parameters", mname);
2669 else {
2671 * We're redefining, so we have to take over an
2672 * existing SMacro structure. This means freeing
2673 * what was already in it.
2675 nasm_free(smac->name);
2676 free_tlist(smac->expansion);
2678 } else {
2679 smac = nasm_malloc(sizeof(SMacro));
2680 smac->next = *smhead;
2681 *smhead = smac;
2683 smac->name = nasm_strdup(mname);
2684 smac->casesense = (i == PP_SUBSTR);
2685 smac->nparam = 0;
2686 smac->expansion = macro_start;
2687 smac->in_progress = FALSE;
2688 free_tlist(tline);
2689 free_tlist(origline);
2690 return DIRECTIVE_FOUND;
2692 case PP_ASSIGN:
2693 case PP_IASSIGN:
2694 tline = tline->next;
2695 skip_white_(tline);
2696 tline = expand_id(tline);
2697 if (!tline || (tline->type != TOK_ID &&
2698 (tline->type != TOK_PREPROC_ID ||
2699 tline->text[1] != '$'))) {
2700 error(ERR_NONFATAL,
2701 "`%%%sassign' expects a macro identifier",
2702 (i == PP_IASSIGN ? "i" : ""));
2703 free_tlist(origline);
2704 return DIRECTIVE_FOUND;
2706 ctx = get_ctx(tline->text, FALSE);
2707 if (!ctx)
2708 smhead = &smacros[hash(tline->text)];
2709 else
2710 smhead = &ctx->localmac;
2711 mname = tline->text;
2712 last = tline;
2713 tline = expand_smacro(tline->next);
2714 last->next = NULL;
2716 t = tline;
2717 tptr = &t;
2718 tokval.t_type = TOKEN_INVALID;
2719 evalresult =
2720 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2721 free_tlist(tline);
2722 if (!evalresult) {
2723 free_tlist(origline);
2724 return DIRECTIVE_FOUND;
2727 if (tokval.t_type)
2728 error(ERR_WARNING,
2729 "trailing garbage after expression ignored");
2731 if (!is_simple(evalresult)) {
2732 error(ERR_NONFATAL,
2733 "non-constant value given to `%%%sassign'",
2734 (i == PP_IASSIGN ? "i" : ""));
2735 free_tlist(origline);
2736 return DIRECTIVE_FOUND;
2739 macro_start = nasm_malloc(sizeof(*macro_start));
2740 macro_start->next = NULL;
2741 make_tok_num(macro_start, reloc_value(evalresult));
2742 macro_start->mac = NULL;
2745 * We now have a macro name, an implicit parameter count of
2746 * zero, and a numeric token to use as an expansion. Create
2747 * and store an SMacro.
2749 if (smacro_defined(ctx, mname, 0, &smac, i == PP_ASSIGN)) {
2750 if (!smac)
2751 error(ERR_WARNING,
2752 "single-line macro `%s' defined both with and"
2753 " without parameters", mname);
2754 else {
2756 * We're redefining, so we have to take over an
2757 * existing SMacro structure. This means freeing
2758 * what was already in it.
2760 nasm_free(smac->name);
2761 free_tlist(smac->expansion);
2763 } else {
2764 smac = nasm_malloc(sizeof(SMacro));
2765 smac->next = *smhead;
2766 *smhead = smac;
2768 smac->name = nasm_strdup(mname);
2769 smac->casesense = (i == PP_ASSIGN);
2770 smac->nparam = 0;
2771 smac->expansion = macro_start;
2772 smac->in_progress = FALSE;
2773 free_tlist(origline);
2774 return DIRECTIVE_FOUND;
2776 case PP_LINE:
2778 * Syntax is `%line nnn[+mmm] [filename]'
2780 tline = tline->next;
2781 skip_white_(tline);
2782 if (!tok_type_(tline, TOK_NUMBER)) {
2783 error(ERR_NONFATAL, "`%%line' expects line number");
2784 free_tlist(origline);
2785 return DIRECTIVE_FOUND;
2787 k = readnum(tline->text, &j);
2788 m = 1;
2789 tline = tline->next;
2790 if (tok_is_(tline, "+")) {
2791 tline = tline->next;
2792 if (!tok_type_(tline, TOK_NUMBER)) {
2793 error(ERR_NONFATAL, "`%%line' expects line increment");
2794 free_tlist(origline);
2795 return DIRECTIVE_FOUND;
2797 m = readnum(tline->text, &j);
2798 tline = tline->next;
2800 skip_white_(tline);
2801 src_set_linnum(k);
2802 istk->lineinc = m;
2803 if (tline) {
2804 nasm_free(src_set_fname(detoken(tline, FALSE)));
2806 free_tlist(origline);
2807 return DIRECTIVE_FOUND;
2809 default:
2810 error(ERR_FATAL,
2811 "preprocessor directive `%s' not yet implemented",
2812 directives[i]);
2813 break;
2815 return DIRECTIVE_FOUND;
2819 * Ensure that a macro parameter contains a condition code and
2820 * nothing else. Return the condition code index if so, or -1
2821 * otherwise.
2823 static int find_cc(Token * t)
2825 Token *tt;
2826 int i, j, k, m;
2828 skip_white_(t);
2829 if (t->type != TOK_ID)
2830 return -1;
2831 tt = t->next;
2832 skip_white_(tt);
2833 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
2834 return -1;
2836 i = -1;
2837 j = elements(conditions);
2838 while (j - i > 1) {
2839 k = (j + i) / 2;
2840 m = nasm_stricmp(t->text, conditions[k]);
2841 if (m == 0) {
2842 i = k;
2843 j = -2;
2844 break;
2845 } else if (m < 0) {
2846 j = k;
2847 } else
2848 i = k;
2850 if (j != -2)
2851 return -1;
2852 return i;
2856 * Expand MMacro-local things: parameter references (%0, %n, %+n,
2857 * %-n) and MMacro-local identifiers (%%foo).
2859 static Token *expand_mmac_params(Token * tline)
2861 Token *t, *tt, **tail, *thead;
2863 tail = &thead;
2864 thead = NULL;
2866 while (tline) {
2867 if (tline->type == TOK_PREPROC_ID &&
2868 (((tline->text[1] == '+' || tline->text[1] == '-')
2869 && tline->text[2]) || tline->text[1] == '%'
2870 || (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
2871 char *text = NULL;
2872 int type = 0, cc; /* type = 0 to placate optimisers */
2873 char tmpbuf[30];
2874 int n, i;
2875 MMacro *mac;
2877 t = tline;
2878 tline = tline->next;
2880 mac = istk->mstk;
2881 while (mac && !mac->name) /* avoid mistaking %reps for macros */
2882 mac = mac->next_active;
2883 if (!mac)
2884 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
2885 else
2886 switch (t->text[1]) {
2888 * We have to make a substitution of one of the
2889 * forms %1, %-1, %+1, %%foo, %0.
2891 case '0':
2892 type = TOK_NUMBER;
2893 snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
2894 text = nasm_strdup(tmpbuf);
2895 break;
2896 case '%':
2897 type = TOK_ID;
2898 snprintf(tmpbuf, sizeof(tmpbuf), "..@%lu.",
2899 mac->unique);
2900 text = nasm_strcat(tmpbuf, t->text + 2);
2901 break;
2902 case '-':
2903 n = atoi(t->text + 2) - 1;
2904 if (n >= mac->nparam)
2905 tt = NULL;
2906 else {
2907 if (mac->nparam > 1)
2908 n = (n + mac->rotate) % mac->nparam;
2909 tt = mac->params[n];
2911 cc = find_cc(tt);
2912 if (cc == -1) {
2913 error(ERR_NONFATAL,
2914 "macro parameter %d is not a condition code",
2915 n + 1);
2916 text = NULL;
2917 } else {
2918 type = TOK_ID;
2919 if (inverse_ccs[cc] == -1) {
2920 error(ERR_NONFATAL,
2921 "condition code `%s' is not invertible",
2922 conditions[cc]);
2923 text = NULL;
2924 } else
2925 text =
2926 nasm_strdup(conditions[inverse_ccs[cc]]);
2928 break;
2929 case '+':
2930 n = atoi(t->text + 2) - 1;
2931 if (n >= mac->nparam)
2932 tt = NULL;
2933 else {
2934 if (mac->nparam > 1)
2935 n = (n + mac->rotate) % mac->nparam;
2936 tt = mac->params[n];
2938 cc = find_cc(tt);
2939 if (cc == -1) {
2940 error(ERR_NONFATAL,
2941 "macro parameter %d is not a condition code",
2942 n + 1);
2943 text = NULL;
2944 } else {
2945 type = TOK_ID;
2946 text = nasm_strdup(conditions[cc]);
2948 break;
2949 default:
2950 n = atoi(t->text + 1) - 1;
2951 if (n >= mac->nparam)
2952 tt = NULL;
2953 else {
2954 if (mac->nparam > 1)
2955 n = (n + mac->rotate) % mac->nparam;
2956 tt = mac->params[n];
2958 if (tt) {
2959 for (i = 0; i < mac->paramlen[n]; i++) {
2960 *tail = new_Token(NULL, tt->type, tt->text, 0);
2961 tail = &(*tail)->next;
2962 tt = tt->next;
2965 text = NULL; /* we've done it here */
2966 break;
2968 if (!text) {
2969 delete_Token(t);
2970 } else {
2971 *tail = t;
2972 tail = &t->next;
2973 t->type = type;
2974 nasm_free(t->text);
2975 t->text = text;
2976 t->mac = NULL;
2978 continue;
2979 } else {
2980 t = *tail = tline;
2981 tline = tline->next;
2982 t->mac = NULL;
2983 tail = &t->next;
2986 *tail = NULL;
2987 t = thead;
2988 for (; t && (tt = t->next) != NULL; t = t->next)
2989 switch (t->type) {
2990 case TOK_WHITESPACE:
2991 if (tt->type == TOK_WHITESPACE) {
2992 t->next = delete_Token(tt);
2994 break;
2995 case TOK_ID:
2996 if (tt->type == TOK_ID || tt->type == TOK_NUMBER) {
2997 char *tmp = nasm_strcat(t->text, tt->text);
2998 nasm_free(t->text);
2999 t->text = tmp;
3000 t->next = delete_Token(tt);
3002 break;
3003 case TOK_NUMBER:
3004 if (tt->type == TOK_NUMBER) {
3005 char *tmp = nasm_strcat(t->text, tt->text);
3006 nasm_free(t->text);
3007 t->text = tmp;
3008 t->next = delete_Token(tt);
3010 break;
3013 return thead;
3017 * Expand all single-line macro calls made in the given line.
3018 * Return the expanded version of the line. The original is deemed
3019 * to be destroyed in the process. (In reality we'll just move
3020 * Tokens from input to output a lot of the time, rather than
3021 * actually bothering to destroy and replicate.)
3023 static Token *expand_smacro(Token * tline)
3025 Token *t, *tt, *mstart, **tail, *thead;
3026 SMacro *head = NULL, *m;
3027 Token **params;
3028 int *paramsize;
3029 int nparam, sparam, brackets, rescan;
3030 Token *org_tline = tline;
3031 Context *ctx;
3032 char *mname;
3035 * Trick: we should avoid changing the start token pointer since it can
3036 * be contained in "next" field of other token. Because of this
3037 * we allocate a copy of first token and work with it; at the end of
3038 * routine we copy it back
3040 if (org_tline) {
3041 tline =
3042 new_Token(org_tline->next, org_tline->type, org_tline->text,
3044 tline->mac = org_tline->mac;
3045 nasm_free(org_tline->text);
3046 org_tline->text = NULL;
3049 again:
3050 tail = &thead;
3051 thead = NULL;
3053 while (tline) { /* main token loop */
3054 if ((mname = tline->text)) {
3055 /* if this token is a local macro, look in local context */
3056 if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
3057 ctx = get_ctx(mname, TRUE);
3058 else
3059 ctx = NULL;
3060 if (!ctx)
3061 head = smacros[hash(mname)];
3062 else
3063 head = ctx->localmac;
3065 * We've hit an identifier. As in is_mmacro below, we first
3066 * check whether the identifier is a single-line macro at
3067 * all, then think about checking for parameters if
3068 * necessary.
3070 for (m = head; m; m = m->next)
3071 if (!mstrcmp(m->name, mname, m->casesense))
3072 break;
3073 if (m) {
3074 mstart = tline;
3075 params = NULL;
3076 paramsize = NULL;
3077 if (m->nparam == 0) {
3079 * Simple case: the macro is parameterless. Discard the
3080 * one token that the macro call took, and push the
3081 * expansion back on the to-do stack.
3083 if (!m->expansion) {
3084 if (!strcmp("__FILE__", m->name)) {
3085 long num = 0;
3086 src_get(&num, &(tline->text));
3087 nasm_quote(&(tline->text));
3088 tline->type = TOK_STRING;
3089 continue;
3091 if (!strcmp("__LINE__", m->name)) {
3092 nasm_free(tline->text);
3093 make_tok_num(tline, src_get_linnum());
3094 continue;
3096 tline = delete_Token(tline);
3097 continue;
3099 } else {
3101 * Complicated case: at least one macro with this name
3102 * exists and takes parameters. We must find the
3103 * parameters in the call, count them, find the SMacro
3104 * that corresponds to that form of the macro call, and
3105 * substitute for the parameters when we expand. What a
3106 * pain.
3108 /*tline = tline->next;
3109 skip_white_(tline); */
3110 do {
3111 t = tline->next;
3112 while (tok_type_(t, TOK_SMAC_END)) {
3113 t->mac->in_progress = FALSE;
3114 t->text = NULL;
3115 t = tline->next = delete_Token(t);
3117 tline = t;
3118 } while (tok_type_(tline, TOK_WHITESPACE));
3119 if (!tok_is_(tline, "(")) {
3121 * This macro wasn't called with parameters: ignore
3122 * the call. (Behaviour borrowed from gnu cpp.)
3124 tline = mstart;
3125 m = NULL;
3126 } else {
3127 int paren = 0;
3128 int white = 0;
3129 brackets = 0;
3130 nparam = 0;
3131 sparam = PARAM_DELTA;
3132 params = nasm_malloc(sparam * sizeof(Token *));
3133 params[0] = tline->next;
3134 paramsize = nasm_malloc(sparam * sizeof(int));
3135 paramsize[0] = 0;
3136 while (TRUE) { /* parameter loop */
3138 * For some unusual expansions
3139 * which concatenates function call
3141 t = tline->next;
3142 while (tok_type_(t, TOK_SMAC_END)) {
3143 t->mac->in_progress = FALSE;
3144 t->text = NULL;
3145 t = tline->next = delete_Token(t);
3147 tline = t;
3149 if (!tline) {
3150 error(ERR_NONFATAL,
3151 "macro call expects terminating `)'");
3152 break;
3154 if (tline->type == TOK_WHITESPACE
3155 && brackets <= 0) {
3156 if (paramsize[nparam])
3157 white++;
3158 else
3159 params[nparam] = tline->next;
3160 continue; /* parameter loop */
3162 if (tline->type == TOK_OTHER
3163 && tline->text[1] == 0) {
3164 char ch = tline->text[0];
3165 if (ch == ',' && !paren && brackets <= 0) {
3166 if (++nparam >= sparam) {
3167 sparam += PARAM_DELTA;
3168 params = nasm_realloc(params,
3169 sparam *
3170 sizeof(Token
3171 *));
3172 paramsize =
3173 nasm_realloc(paramsize,
3174 sparam *
3175 sizeof(int));
3177 params[nparam] = tline->next;
3178 paramsize[nparam] = 0;
3179 white = 0;
3180 continue; /* parameter loop */
3182 if (ch == '{' &&
3183 (brackets > 0 || (brackets == 0 &&
3184 !paramsize[nparam])))
3186 if (!(brackets++)) {
3187 params[nparam] = tline->next;
3188 continue; /* parameter loop */
3191 if (ch == '}' && brackets > 0)
3192 if (--brackets == 0) {
3193 brackets = -1;
3194 continue; /* parameter loop */
3196 if (ch == '(' && !brackets)
3197 paren++;
3198 if (ch == ')' && brackets <= 0)
3199 if (--paren < 0)
3200 break;
3202 if (brackets < 0) {
3203 brackets = 0;
3204 error(ERR_NONFATAL, "braces do not "
3205 "enclose all of macro parameter");
3207 paramsize[nparam] += white + 1;
3208 white = 0;
3209 } /* parameter loop */
3210 nparam++;
3211 while (m && (m->nparam != nparam ||
3212 mstrcmp(m->name, mname,
3213 m->casesense)))
3214 m = m->next;
3215 if (!m)
3216 error(ERR_WARNING | ERR_WARN_MNP,
3217 "macro `%s' exists, "
3218 "but not taking %d parameters",
3219 mstart->text, nparam);
3222 if (m && m->in_progress)
3223 m = NULL;
3224 if (!m) { /* in progess or didn't find '(' or wrong nparam */
3226 * Design question: should we handle !tline, which
3227 * indicates missing ')' here, or expand those
3228 * macros anyway, which requires the (t) test a few
3229 * lines down?
3231 nasm_free(params);
3232 nasm_free(paramsize);
3233 tline = mstart;
3234 } else {
3236 * Expand the macro: we are placed on the last token of the
3237 * call, so that we can easily split the call from the
3238 * following tokens. We also start by pushing an SMAC_END
3239 * token for the cycle removal.
3241 t = tline;
3242 if (t) {
3243 tline = t->next;
3244 t->next = NULL;
3246 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
3247 tt->mac = m;
3248 m->in_progress = TRUE;
3249 tline = tt;
3250 for (t = m->expansion; t; t = t->next) {
3251 if (t->type >= TOK_SMAC_PARAM) {
3252 Token *pcopy = tline, **ptail = &pcopy;
3253 Token *ttt, *pt;
3254 int i;
3256 ttt = params[t->type - TOK_SMAC_PARAM];
3257 for (i = paramsize[t->type - TOK_SMAC_PARAM];
3258 --i >= 0;) {
3259 pt = *ptail =
3260 new_Token(tline, ttt->type, ttt->text,
3262 ptail = &pt->next;
3263 ttt = ttt->next;
3265 tline = pcopy;
3266 } else {
3267 tt = new_Token(tline, t->type, t->text, 0);
3268 tline = tt;
3273 * Having done that, get rid of the macro call, and clean
3274 * up the parameters.
3276 nasm_free(params);
3277 nasm_free(paramsize);
3278 free_tlist(mstart);
3279 continue; /* main token loop */
3284 if (tline->type == TOK_SMAC_END) {
3285 tline->mac->in_progress = FALSE;
3286 tline = delete_Token(tline);
3287 } else {
3288 t = *tail = tline;
3289 tline = tline->next;
3290 t->mac = NULL;
3291 t->next = NULL;
3292 tail = &t->next;
3297 * Now scan the entire line and look for successive TOK_IDs that resulted
3298 * after expansion (they can't be produced by tokenise()). The successive
3299 * TOK_IDs should be concatenated.
3300 * Also we look for %+ tokens and concatenate the tokens before and after
3301 * them (without white spaces in between).
3303 t = thead;
3304 rescan = 0;
3305 while (t) {
3306 while (t && t->type != TOK_ID && t->type != TOK_PREPROC_ID)
3307 t = t->next;
3308 if (!t || !t->next)
3309 break;
3310 if (t->next->type == TOK_ID ||
3311 t->next->type == TOK_PREPROC_ID ||
3312 t->next->type == TOK_NUMBER) {
3313 char *p = nasm_strcat(t->text, t->next->text);
3314 nasm_free(t->text);
3315 t->next = delete_Token(t->next);
3316 t->text = p;
3317 rescan = 1;
3318 } else if (t->next->type == TOK_WHITESPACE && t->next->next &&
3319 t->next->next->type == TOK_PREPROC_ID &&
3320 strcmp(t->next->next->text, "%+") == 0) {
3321 /* free the next whitespace, the %+ token and next whitespace */
3322 int i;
3323 for (i = 1; i <= 3; i++) {
3324 if (!t->next
3325 || (i != 2 && t->next->type != TOK_WHITESPACE))
3326 break;
3327 t->next = delete_Token(t->next);
3328 } /* endfor */
3329 } else
3330 t = t->next;
3332 /* If we concatenaded something, re-scan the line for macros */
3333 if (rescan) {
3334 tline = thead;
3335 goto again;
3338 if (org_tline) {
3339 if (thead) {
3340 *org_tline = *thead;
3341 /* since we just gave text to org_line, don't free it */
3342 thead->text = NULL;
3343 delete_Token(thead);
3344 } else {
3345 /* the expression expanded to empty line;
3346 we can't return NULL for some reasons
3347 we just set the line to a single WHITESPACE token. */
3348 memset(org_tline, 0, sizeof(*org_tline));
3349 org_tline->text = NULL;
3350 org_tline->type = TOK_WHITESPACE;
3352 thead = org_tline;
3355 return thead;
3359 * Similar to expand_smacro but used exclusively with macro identifiers
3360 * right before they are fetched in. The reason is that there can be
3361 * identifiers consisting of several subparts. We consider that if there
3362 * are more than one element forming the name, user wants a expansion,
3363 * otherwise it will be left as-is. Example:
3365 * %define %$abc cde
3367 * the identifier %$abc will be left as-is so that the handler for %define
3368 * will suck it and define the corresponding value. Other case:
3370 * %define _%$abc cde
3372 * In this case user wants name to be expanded *before* %define starts
3373 * working, so we'll expand %$abc into something (if it has a value;
3374 * otherwise it will be left as-is) then concatenate all successive
3375 * PP_IDs into one.
3377 static Token *expand_id(Token * tline)
3379 Token *cur, *oldnext = NULL;
3381 if (!tline || !tline->next)
3382 return tline;
3384 cur = tline;
3385 while (cur->next &&
3386 (cur->next->type == TOK_ID ||
3387 cur->next->type == TOK_PREPROC_ID
3388 || cur->next->type == TOK_NUMBER))
3389 cur = cur->next;
3391 /* If identifier consists of just one token, don't expand */
3392 if (cur == tline)
3393 return tline;
3395 if (cur) {
3396 oldnext = cur->next; /* Detach the tail past identifier */
3397 cur->next = NULL; /* so that expand_smacro stops here */
3400 tline = expand_smacro(tline);
3402 if (cur) {
3403 /* expand_smacro possibly changhed tline; re-scan for EOL */
3404 cur = tline;
3405 while (cur && cur->next)
3406 cur = cur->next;
3407 if (cur)
3408 cur->next = oldnext;
3411 return tline;
3415 * Determine whether the given line constitutes a multi-line macro
3416 * call, and return the MMacro structure called if so. Doesn't have
3417 * to check for an initial label - that's taken care of in
3418 * expand_mmacro - but must check numbers of parameters. Guaranteed
3419 * to be called with tline->type == TOK_ID, so the putative macro
3420 * name is easy to find.
3422 static MMacro *is_mmacro(Token * tline, Token *** params_array)
3424 MMacro *head, *m;
3425 Token **params;
3426 int nparam;
3428 head = mmacros[hash(tline->text)];
3431 * Efficiency: first we see if any macro exists with the given
3432 * name. If not, we can return NULL immediately. _Then_ we
3433 * count the parameters, and then we look further along the
3434 * list if necessary to find the proper MMacro.
3436 for (m = head; m; m = m->next)
3437 if (!mstrcmp(m->name, tline->text, m->casesense))
3438 break;
3439 if (!m)
3440 return NULL;
3443 * OK, we have a potential macro. Count and demarcate the
3444 * parameters.
3446 count_mmac_params(tline->next, &nparam, &params);
3449 * So we know how many parameters we've got. Find the MMacro
3450 * structure that handles this number.
3452 while (m) {
3453 if (m->nparam_min <= nparam
3454 && (m->plus || nparam <= m->nparam_max)) {
3456 * This one is right. Just check if cycle removal
3457 * prohibits us using it before we actually celebrate...
3459 if (m->in_progress) {
3460 #if 0
3461 error(ERR_NONFATAL,
3462 "self-reference in multi-line macro `%s'", m->name);
3463 #endif
3464 nasm_free(params);
3465 return NULL;
3468 * It's right, and we can use it. Add its default
3469 * parameters to the end of our list if necessary.
3471 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
3472 params =
3473 nasm_realloc(params,
3474 ((m->nparam_min + m->ndefs +
3475 1) * sizeof(*params)));
3476 while (nparam < m->nparam_min + m->ndefs) {
3477 params[nparam] = m->defaults[nparam - m->nparam_min];
3478 nparam++;
3482 * If we've gone over the maximum parameter count (and
3483 * we're in Plus mode), ignore parameters beyond
3484 * nparam_max.
3486 if (m->plus && nparam > m->nparam_max)
3487 nparam = m->nparam_max;
3489 * Then terminate the parameter list, and leave.
3491 if (!params) { /* need this special case */
3492 params = nasm_malloc(sizeof(*params));
3493 nparam = 0;
3495 params[nparam] = NULL;
3496 *params_array = params;
3497 return m;
3500 * This one wasn't right: look for the next one with the
3501 * same name.
3503 for (m = m->next; m; m = m->next)
3504 if (!mstrcmp(m->name, tline->text, m->casesense))
3505 break;
3509 * After all that, we didn't find one with the right number of
3510 * parameters. Issue a warning, and fail to expand the macro.
3512 error(ERR_WARNING | ERR_WARN_MNP,
3513 "macro `%s' exists, but not taking %d parameters",
3514 tline->text, nparam);
3515 nasm_free(params);
3516 return NULL;
3520 * Expand the multi-line macro call made by the given line, if
3521 * there is one to be expanded. If there is, push the expansion on
3522 * istk->expansion and return 1. Otherwise return 0.
3524 static int expand_mmacro(Token * tline)
3526 Token *startline = tline;
3527 Token *label = NULL;
3528 int dont_prepend = 0;
3529 Token **params, *t, *tt;
3530 MMacro *m;
3531 Line *l, *ll;
3532 int i, nparam, *paramlen;
3534 t = tline;
3535 skip_white_(t);
3536 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
3537 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
3538 return 0;
3539 m = is_mmacro(t, &params);
3540 if (!m) {
3541 Token *last;
3543 * We have an id which isn't a macro call. We'll assume
3544 * it might be a label; we'll also check to see if a
3545 * colon follows it. Then, if there's another id after
3546 * that lot, we'll check it again for macro-hood.
3548 label = last = t;
3549 t = t->next;
3550 if (tok_type_(t, TOK_WHITESPACE))
3551 last = t, t = t->next;
3552 if (tok_is_(t, ":")) {
3553 dont_prepend = 1;
3554 last = t, t = t->next;
3555 if (tok_type_(t, TOK_WHITESPACE))
3556 last = t, t = t->next;
3558 if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
3559 return 0;
3560 last->next = NULL;
3561 tline = t;
3565 * Fix up the parameters: this involves stripping leading and
3566 * trailing whitespace, then stripping braces if they are
3567 * present.
3569 for (nparam = 0; params[nparam]; nparam++) ;
3570 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
3572 for (i = 0; params[i]; i++) {
3573 int brace = FALSE;
3574 int comma = (!m->plus || i < nparam - 1);
3576 t = params[i];
3577 skip_white_(t);
3578 if (tok_is_(t, "{"))
3579 t = t->next, brace = TRUE, comma = FALSE;
3580 params[i] = t;
3581 paramlen[i] = 0;
3582 while (t) {
3583 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
3584 break; /* ... because we have hit a comma */
3585 if (comma && t->type == TOK_WHITESPACE
3586 && tok_is_(t->next, ","))
3587 break; /* ... or a space then a comma */
3588 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
3589 break; /* ... or a brace */
3590 t = t->next;
3591 paramlen[i]++;
3596 * OK, we have a MMacro structure together with a set of
3597 * parameters. We must now go through the expansion and push
3598 * copies of each Line on to istk->expansion. Substitution of
3599 * parameter tokens and macro-local tokens doesn't get done
3600 * until the single-line macro substitution process; this is
3601 * because delaying them allows us to change the semantics
3602 * later through %rotate.
3604 * First, push an end marker on to istk->expansion, mark this
3605 * macro as in progress, and set up its invocation-specific
3606 * variables.
3608 ll = nasm_malloc(sizeof(Line));
3609 ll->next = istk->expansion;
3610 ll->finishes = m;
3611 ll->first = NULL;
3612 istk->expansion = ll;
3614 m->in_progress = TRUE;
3615 m->params = params;
3616 m->iline = tline;
3617 m->nparam = nparam;
3618 m->rotate = 0;
3619 m->paramlen = paramlen;
3620 m->unique = unique++;
3621 m->lineno = 0;
3623 m->next_active = istk->mstk;
3624 istk->mstk = m;
3626 for (l = m->expansion; l; l = l->next) {
3627 Token **tail;
3629 ll = nasm_malloc(sizeof(Line));
3630 ll->finishes = NULL;
3631 ll->next = istk->expansion;
3632 istk->expansion = ll;
3633 tail = &ll->first;
3635 for (t = l->first; t; t = t->next) {
3636 Token *x = t;
3637 if (t->type == TOK_PREPROC_ID &&
3638 t->text[1] == '0' && t->text[2] == '0') {
3639 dont_prepend = -1;
3640 x = label;
3641 if (!x)
3642 continue;
3644 tt = *tail = new_Token(NULL, x->type, x->text, 0);
3645 tail = &tt->next;
3647 *tail = NULL;
3651 * If we had a label, push it on as the first line of
3652 * the macro expansion.
3654 if (label) {
3655 if (dont_prepend < 0)
3656 free_tlist(startline);
3657 else {
3658 ll = nasm_malloc(sizeof(Line));
3659 ll->finishes = NULL;
3660 ll->next = istk->expansion;
3661 istk->expansion = ll;
3662 ll->first = startline;
3663 if (!dont_prepend) {
3664 while (label->next)
3665 label = label->next;
3666 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
3671 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
3673 return 1;
3677 * Since preprocessor always operate only on the line that didn't
3678 * arrived yet, we should always use ERR_OFFBY1. Also since user
3679 * won't want to see same error twice (preprocessing is done once
3680 * per pass) we will want to show errors only during pass one.
3682 static void error(int severity, const char *fmt, ...)
3684 va_list arg;
3685 char buff[1024];
3687 /* If we're in a dead branch of IF or something like it, ignore the error */
3688 if (istk && istk->conds && !emitting(istk->conds->state))
3689 return;
3691 va_start(arg, fmt);
3692 vsnprintf(buff, sizeof(buff), fmt, arg);
3693 va_end(arg);
3695 if (istk && istk->mstk && istk->mstk->name)
3696 _error(severity | ERR_PASS1, "(%s:%d) %s", istk->mstk->name,
3697 istk->mstk->lineno, buff);
3698 else
3699 _error(severity | ERR_PASS1, "%s", buff);
3702 static void
3703 pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
3704 ListGen * listgen)
3706 int h;
3708 _error = errfunc;
3709 cstk = NULL;
3710 istk = nasm_malloc(sizeof(Include));
3711 istk->next = NULL;
3712 istk->conds = NULL;
3713 istk->expansion = NULL;
3714 istk->mstk = NULL;
3715 istk->fp = fopen(file, "r");
3716 istk->fname = NULL;
3717 src_set_fname(nasm_strdup(file));
3718 src_set_linnum(0);
3719 istk->lineinc = 1;
3720 if (!istk->fp)
3721 error(ERR_FATAL | ERR_NOFILE, "unable to open input file `%s'",
3722 file);
3723 defining = NULL;
3724 for (h = 0; h < NHASH; h++) {
3725 mmacros[h] = NULL;
3726 smacros[h] = NULL;
3728 unique = 0;
3729 if (tasm_compatible_mode) {
3730 stdmacpos = stdmac;
3731 } else {
3732 stdmacpos = &stdmac[TASM_MACRO_COUNT];
3734 any_extrastdmac = (extrastdmac != NULL);
3735 list = listgen;
3736 evaluate = eval;
3737 pass = apass;
3740 static char *pp_getline(void)
3742 char *line;
3743 Token *tline;
3745 while (1) {
3747 * Fetch a tokenised line, either from the macro-expansion
3748 * buffer or from the input file.
3750 tline = NULL;
3751 while (istk->expansion && istk->expansion->finishes) {
3752 Line *l = istk->expansion;
3753 if (!l->finishes->name && l->finishes->in_progress > 1) {
3754 Line *ll;
3757 * This is a macro-end marker for a macro with no
3758 * name, which means it's not really a macro at all
3759 * but a %rep block, and the `in_progress' field is
3760 * more than 1, meaning that we still need to
3761 * repeat. (1 means the natural last repetition; 0
3762 * means termination by %exitrep.) We have
3763 * therefore expanded up to the %endrep, and must
3764 * push the whole block on to the expansion buffer
3765 * again. We don't bother to remove the macro-end
3766 * marker: we'd only have to generate another one
3767 * if we did.
3769 l->finishes->in_progress--;
3770 for (l = l->finishes->expansion; l; l = l->next) {
3771 Token *t, *tt, **tail;
3773 ll = nasm_malloc(sizeof(Line));
3774 ll->next = istk->expansion;
3775 ll->finishes = NULL;
3776 ll->first = NULL;
3777 tail = &ll->first;
3779 for (t = l->first; t; t = t->next) {
3780 if (t->text || t->type == TOK_WHITESPACE) {
3781 tt = *tail =
3782 new_Token(NULL, t->type, t->text, 0);
3783 tail = &tt->next;
3787 istk->expansion = ll;
3789 } else {
3791 * Check whether a `%rep' was started and not ended
3792 * within this macro expansion. This can happen and
3793 * should be detected. It's a fatal error because
3794 * I'm too confused to work out how to recover
3795 * sensibly from it.
3797 if (defining) {
3798 if (defining->name)
3799 error(ERR_PANIC,
3800 "defining with name in expansion");
3801 else if (istk->mstk->name)
3802 error(ERR_FATAL,
3803 "`%%rep' without `%%endrep' within"
3804 " expansion of macro `%s'",
3805 istk->mstk->name);
3809 * FIXME: investigate the relationship at this point between
3810 * istk->mstk and l->finishes
3813 MMacro *m = istk->mstk;
3814 istk->mstk = m->next_active;
3815 if (m->name) {
3817 * This was a real macro call, not a %rep, and
3818 * therefore the parameter information needs to
3819 * be freed.
3821 nasm_free(m->params);
3822 free_tlist(m->iline);
3823 nasm_free(m->paramlen);
3824 l->finishes->in_progress = FALSE;
3825 } else
3826 free_mmacro(m);
3828 istk->expansion = l->next;
3829 nasm_free(l);
3830 list->downlevel(LIST_MACRO);
3833 while (1) { /* until we get a line we can use */
3835 if (istk->expansion) { /* from a macro expansion */
3836 char *p;
3837 Line *l = istk->expansion;
3838 if (istk->mstk)
3839 istk->mstk->lineno++;
3840 tline = l->first;
3841 istk->expansion = l->next;
3842 nasm_free(l);
3843 p = detoken(tline, FALSE);
3844 list->line(LIST_MACRO, p);
3845 nasm_free(p);
3846 break;
3848 line = read_line();
3849 if (line) { /* from the current input file */
3850 line = prepreproc(line);
3851 tline = tokenise(line);
3852 nasm_free(line);
3853 break;
3856 * The current file has ended; work down the istk
3859 Include *i = istk;
3860 fclose(i->fp);
3861 if (i->conds)
3862 error(ERR_FATAL,
3863 "expected `%%endif' before end of file");
3864 /* only set line and file name if there's a next node */
3865 if (i->next) {
3866 src_set_linnum(i->lineno);
3867 nasm_free(src_set_fname(i->fname));
3869 istk = i->next;
3870 list->downlevel(LIST_INCLUDE);
3871 nasm_free(i);
3872 if (!istk)
3873 return NULL;
3878 * We must expand MMacro parameters and MMacro-local labels
3879 * _before_ we plunge into directive processing, to cope
3880 * with things like `%define something %1' such as STRUC
3881 * uses. Unless we're _defining_ a MMacro, in which case
3882 * those tokens should be left alone to go into the
3883 * definition; and unless we're in a non-emitting
3884 * condition, in which case we don't want to meddle with
3885 * anything.
3887 if (!defining && !(istk->conds && !emitting(istk->conds->state)))
3888 tline = expand_mmac_params(tline);
3891 * Check the line to see if it's a preprocessor directive.
3893 if (do_directive(tline) == DIRECTIVE_FOUND) {
3894 continue;
3895 } else if (defining) {
3897 * We're defining a multi-line macro. We emit nothing
3898 * at all, and just
3899 * shove the tokenised line on to the macro definition.
3901 Line *l = nasm_malloc(sizeof(Line));
3902 l->next = defining->expansion;
3903 l->first = tline;
3904 l->finishes = FALSE;
3905 defining->expansion = l;
3906 continue;
3907 } else if (istk->conds && !emitting(istk->conds->state)) {
3909 * We're in a non-emitting branch of a condition block.
3910 * Emit nothing at all, not even a blank line: when we
3911 * emerge from the condition we'll give a line-number
3912 * directive so we keep our place correctly.
3914 free_tlist(tline);
3915 continue;
3916 } else if (istk->mstk && !istk->mstk->in_progress) {
3918 * We're in a %rep block which has been terminated, so
3919 * we're walking through to the %endrep without
3920 * emitting anything. Emit nothing at all, not even a
3921 * blank line: when we emerge from the %rep block we'll
3922 * give a line-number directive so we keep our place
3923 * correctly.
3925 free_tlist(tline);
3926 continue;
3927 } else {
3928 tline = expand_smacro(tline);
3929 if (!expand_mmacro(tline)) {
3931 * De-tokenise the line again, and emit it.
3933 line = detoken(tline, TRUE);
3934 free_tlist(tline);
3935 break;
3936 } else {
3937 continue; /* expand_mmacro calls free_tlist */
3942 return line;
3945 static void pp_cleanup(int pass)
3947 int h;
3949 if (defining) {
3950 error(ERR_NONFATAL, "end of file while still defining macro `%s'",
3951 defining->name);
3952 free_mmacro(defining);
3954 while (cstk)
3955 ctx_pop();
3956 for (h = 0; h < NHASH; h++) {
3957 while (mmacros[h]) {
3958 MMacro *m = mmacros[h];
3959 mmacros[h] = mmacros[h]->next;
3960 free_mmacro(m);
3962 while (smacros[h]) {
3963 SMacro *s = smacros[h];
3964 smacros[h] = smacros[h]->next;
3965 nasm_free(s->name);
3966 free_tlist(s->expansion);
3967 nasm_free(s);
3970 while (istk) {
3971 Include *i = istk;
3972 istk = istk->next;
3973 fclose(i->fp);
3974 nasm_free(i->fname);
3975 nasm_free(i);
3977 while (cstk)
3978 ctx_pop();
3979 if (pass == 0) {
3980 free_llist(predef);
3981 delete_Blocks();
3985 void pp_include_path(char *path)
3987 IncPath *i;
3988 /* by alexfru: order of path inclusion fixed (was reverse order) */
3989 i = nasm_malloc(sizeof(IncPath));
3990 i->path = nasm_strdup(path);
3991 i->next = NULL;
3993 if (ipath != NULL) {
3994 IncPath *j = ipath;
3995 while (j->next != NULL)
3996 j = j->next;
3997 j->next = i;
3998 } else {
3999 ipath = i;
4004 * added by alexfru:
4006 * This function is used to "export" the include paths, e.g.
4007 * the paths specified in the '-I' command switch.
4008 * The need for such exporting is due to the 'incbin' directive,
4009 * which includes raw binary files (unlike '%include', which
4010 * includes text source files). It would be real nice to be
4011 * able to specify paths to search for incbin'ned files also.
4012 * So, this is a simple workaround.
4014 * The function use is simple:
4016 * The 1st call (with NULL argument) returns a pointer to the 1st path
4017 * (char** type) or NULL if none include paths available.
4019 * All subsequent calls take as argument the value returned by this
4020 * function last. The return value is either the next path
4021 * (char** type) or NULL if the end of the paths list is reached.
4023 * It is maybe not the best way to do things, but I didn't want
4024 * to export too much, just one or two functions and no types or
4025 * variables exported.
4027 * Can't say I like the current situation with e.g. this path list either,
4028 * it seems to be never deallocated after creation...
4030 char **pp_get_include_path_ptr(char **pPrevPath)
4032 /* This macro returns offset of a member of a structure */
4033 #define GetMemberOffset(StructType,MemberName)\
4034 ((size_t)&((StructType*)0)->MemberName)
4035 IncPath *i;
4037 if (pPrevPath == NULL) {
4038 if (ipath != NULL)
4039 return &ipath->path;
4040 else
4041 return NULL;
4043 i = (IncPath *) ((char *)pPrevPath - GetMemberOffset(IncPath, path));
4044 i = i->next;
4045 if (i != NULL)
4046 return &i->path;
4047 else
4048 return NULL;
4049 #undef GetMemberOffset
4052 void pp_pre_include(char *fname)
4054 Token *inc, *space, *name;
4055 Line *l;
4057 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
4058 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
4059 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
4061 l = nasm_malloc(sizeof(Line));
4062 l->next = predef;
4063 l->first = inc;
4064 l->finishes = FALSE;
4065 predef = l;
4068 void pp_pre_define(char *definition)
4070 Token *def, *space;
4071 Line *l;
4072 char *equals;
4074 equals = strchr(definition, '=');
4075 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4076 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
4077 if (equals)
4078 *equals = ' ';
4079 space->next = tokenise(definition);
4080 if (equals)
4081 *equals = '=';
4083 l = nasm_malloc(sizeof(Line));
4084 l->next = predef;
4085 l->first = def;
4086 l->finishes = FALSE;
4087 predef = l;
4090 void pp_pre_undefine(char *definition)
4092 Token *def, *space;
4093 Line *l;
4095 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4096 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
4097 space->next = tokenise(definition);
4099 l = nasm_malloc(sizeof(Line));
4100 l->next = predef;
4101 l->first = def;
4102 l->finishes = FALSE;
4103 predef = l;
4106 void pp_extra_stdmac(const char **macros)
4108 extrastdmac = macros;
4111 static void make_tok_num(Token * tok, long val)
4113 char numbuf[20];
4114 snprintf(numbuf, sizeof(numbuf), "%ld", val);
4115 tok->text = nasm_strdup(numbuf);
4116 tok->type = TOK_NUMBER;
4119 Preproc nasmpp = {
4120 pp_reset,
4121 pp_getline,
4122 pp_cleanup