Move all the RAA code out of nasmlib
[nasm/autotest.git] / preproc.c
blobb34710d16f1c7cf2f12056aac08745662d625093
1 /* preproc.c macro preprocessor for the Netwide Assembler
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the license given in the file "LICENSE"
6 * distributed in the NASM archive.
8 * initial version 18/iii/97 by Simon Tatham
9 */
11 /* Typical flow of text through preproc
13 * pp_getline gets tokenized lines, either
15 * from a macro expansion
17 * or
18 * {
19 * read_line gets raw text from stdmacpos, or predef, or current input file
20 * tokenize converts to tokens
21 * }
23 * expand_mmac_params is used to expand %1 etc., unless a macro is being
24 * defined or a false conditional is being processed
25 * (%0, %1, %+1, %-1, %%foo
27 * do_directive checks for directives
29 * expand_smacro is used to expand single line macros
31 * expand_mmacro is used to expand multi-line macros
33 * detoken is used to convert the line back to text
36 #include "compiler.h"
38 #include <stdio.h>
39 #include <stdarg.h>
40 #include <stdlib.h>
41 #include <stddef.h>
42 #include <string.h>
43 #include <ctype.h>
44 #include <limits.h>
45 #include <inttypes.h>
47 #include "nasm.h"
48 #include "nasmlib.h"
49 #include "preproc.h"
50 #include "hashtbl.h"
51 #include "quote.h"
52 #include "stdscan.h"
53 #include "tokens.h"
54 #include "tables.h"
56 typedef struct SMacro SMacro;
57 typedef struct MMacro MMacro;
58 typedef struct Context Context;
59 typedef struct Token Token;
60 typedef struct Blocks Blocks;
61 typedef struct Line Line;
62 typedef struct Include Include;
63 typedef struct Cond Cond;
64 typedef struct IncPath IncPath;
67 * Note on the storage of both SMacro and MMacros: the hash table
68 * indexes them case-insensitively, and we then have to go through a
69 * linked list of potential case aliases (and, for MMacros, parameter
70 * ranges); this is to preserve the matching semantics of the earlier
71 * code. If the number of case aliases for a specific macro is a
72 * performance issue, you may want to reconsider your coding style.
76 * Store the definition of a single-line macro.
78 struct SMacro {
79 SMacro *next;
80 char *name;
81 bool casesense;
82 bool in_progress;
83 unsigned int nparam;
84 Token *expansion;
88 * Store the definition of a multi-line macro. This is also used to
89 * store the interiors of `%rep...%endrep' blocks, which are
90 * effectively self-re-invoking multi-line macros which simply
91 * don't have a name or bother to appear in the hash tables. %rep
92 * blocks are signified by having a NULL `name' field.
94 * In a MMacro describing a `%rep' block, the `in_progress' field
95 * isn't merely boolean, but gives the number of repeats left to
96 * run.
98 * The `next' field is used for storing MMacros in hash tables; the
99 * `next_active' field is for stacking them on istk entries.
101 * When a MMacro is being expanded, `params', `iline', `nparam',
102 * `paramlen', `rotate' and `unique' are local to the invocation.
104 struct MMacro {
105 MMacro *next;
106 char *name;
107 int nparam_min, nparam_max;
108 bool casesense;
109 bool plus; /* is the last parameter greedy? */
110 bool nolist; /* is this macro listing-inhibited? */
111 int64_t in_progress;
112 Token *dlist; /* All defaults as one list */
113 Token **defaults; /* Parameter default pointers */
114 int ndefs; /* number of default parameters */
115 Line *expansion;
117 MMacro *next_active;
118 MMacro *rep_nest; /* used for nesting %rep */
119 Token **params; /* actual parameters */
120 Token *iline; /* invocation line */
121 unsigned int nparam, rotate;
122 int *paramlen;
123 uint64_t unique;
124 int lineno; /* Current line number on expansion */
128 * The context stack is composed of a linked list of these.
130 struct Context {
131 Context *next;
132 char *name;
133 struct hash_table localmac;
134 uint32_t number;
138 * This is the internal form which we break input lines up into.
139 * Typically stored in linked lists.
141 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
142 * necessarily used as-is, but is intended to denote the number of
143 * the substituted parameter. So in the definition
145 * %define a(x,y) ( (x) & ~(y) )
147 * the token representing `x' will have its type changed to
148 * TOK_SMAC_PARAM, but the one representing `y' will be
149 * TOK_SMAC_PARAM+1.
151 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
152 * which doesn't need quotes around it. Used in the pre-include
153 * mechanism as an alternative to trying to find a sensible type of
154 * quote to use on the filename we were passed.
156 enum pp_token_type {
157 TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT, TOK_ID,
158 TOK_PREPROC_ID, TOK_STRING,
159 TOK_NUMBER, TOK_FLOAT, TOK_SMAC_END, TOK_OTHER,
160 TOK_INTERNAL_STRING,
161 TOK_PREPROC_Q, TOK_PREPROC_QQ,
162 TOK_SMAC_PARAM, /* MUST BE LAST IN THE LIST!!! */
163 TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
166 struct Token {
167 Token *next;
168 char *text;
169 SMacro *mac; /* associated macro for TOK_SMAC_END */
170 enum pp_token_type type;
174 * Multi-line macro definitions are stored as a linked list of
175 * these, which is essentially a container to allow several linked
176 * lists of Tokens.
178 * Note that in this module, linked lists are treated as stacks
179 * wherever possible. For this reason, Lines are _pushed_ on to the
180 * `expansion' field in MMacro structures, so that the linked list,
181 * if walked, would give the macro lines in reverse order; this
182 * means that we can walk the list when expanding a macro, and thus
183 * push the lines on to the `expansion' field in _istk_ in reverse
184 * order (so that when popped back off they are in the right
185 * order). It may seem cockeyed, and it relies on my design having
186 * an even number of steps in, but it works...
188 * Some of these structures, rather than being actual lines, are
189 * markers delimiting the end of the expansion of a given macro.
190 * This is for use in the cycle-tracking and %rep-handling code.
191 * Such structures have `finishes' non-NULL, and `first' NULL. All
192 * others have `finishes' NULL, but `first' may still be NULL if
193 * the line is blank.
195 struct Line {
196 Line *next;
197 MMacro *finishes;
198 Token *first;
202 * To handle an arbitrary level of file inclusion, we maintain a
203 * stack (ie linked list) of these things.
205 struct Include {
206 Include *next;
207 FILE *fp;
208 Cond *conds;
209 Line *expansion;
210 char *fname;
211 int lineno, lineinc;
212 MMacro *mstk; /* stack of active macros/reps */
216 * Include search path. This is simply a list of strings which get
217 * prepended, in turn, to the name of an include file, in an
218 * attempt to find the file if it's not in the current directory.
220 struct IncPath {
221 IncPath *next;
222 char *path;
226 * Conditional assembly: we maintain a separate stack of these for
227 * each level of file inclusion. (The only reason we keep the
228 * stacks separate is to ensure that a stray `%endif' in a file
229 * included from within the true branch of a `%if' won't terminate
230 * it and cause confusion: instead, rightly, it'll cause an error.)
232 struct Cond {
233 Cond *next;
234 int state;
236 enum {
238 * These states are for use just after %if or %elif: IF_TRUE
239 * means the condition has evaluated to truth so we are
240 * currently emitting, whereas IF_FALSE means we are not
241 * currently emitting but will start doing so if a %else comes
242 * up. In these states, all directives are admissible: %elif,
243 * %else and %endif. (And of course %if.)
245 COND_IF_TRUE, COND_IF_FALSE,
247 * These states come up after a %else: ELSE_TRUE means we're
248 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
249 * any %elif or %else will cause an error.
251 COND_ELSE_TRUE, COND_ELSE_FALSE,
253 * This state means that we're not emitting now, and also that
254 * nothing until %endif will be emitted at all. It's for use in
255 * two circumstances: (i) when we've had our moment of emission
256 * and have now started seeing %elifs, and (ii) when the
257 * condition construct in question is contained within a
258 * non-emitting branch of a larger condition construct.
260 COND_NEVER
262 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
265 * These defines are used as the possible return values for do_directive
267 #define NO_DIRECTIVE_FOUND 0
268 #define DIRECTIVE_FOUND 1
271 * Condition codes. Note that we use c_ prefix not C_ because C_ is
272 * used in nasm.h for the "real" condition codes. At _this_ level,
273 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
274 * ones, so we need a different enum...
276 static const char * const conditions[] = {
277 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
278 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
279 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
281 enum pp_conds {
282 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
283 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
284 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
285 c_none = -1
287 static const enum pp_conds inverse_ccs[] = {
288 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
289 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,
290 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
294 * Directive names.
296 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
297 static int is_condition(enum preproc_token arg)
299 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
302 /* For TASM compatibility we need to be able to recognise TASM compatible
303 * conditional compilation directives. Using the NASM pre-processor does
304 * not work, so we look for them specifically from the following list and
305 * then jam in the equivalent NASM directive into the input stream.
308 enum {
309 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
310 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
313 static const char * const tasm_directives[] = {
314 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
315 "ifndef", "include", "local"
318 static int StackSize = 4;
319 static char *StackPointer = "ebp";
320 static int ArgOffset = 8;
321 static int LocalOffset = 0;
323 static Context *cstk;
324 static Include *istk;
325 static IncPath *ipath = NULL;
327 static efunc _error; /* Pointer to client-provided error reporting function */
328 static evalfunc evaluate;
330 static int pass; /* HACK: pass 0 = generate dependencies only */
331 static StrList **dephead, **deptail; /* Dependency list */
333 static uint64_t unique; /* unique identifier numbers */
335 static Line *predef = NULL;
337 static ListGen *list;
340 * The current set of multi-line macros we have defined.
342 static struct hash_table mmacros;
345 * The current set of single-line macros we have defined.
347 static struct hash_table smacros;
350 * The multi-line macro we are currently defining, or the %rep
351 * block we are currently reading, if any.
353 static MMacro *defining;
356 * The number of macro parameters to allocate space for at a time.
358 #define PARAM_DELTA 16
361 * The standard macro set: defined in macros.c in the array nasm_stdmac.
362 * This gives our position in the macro set, when we're processing it.
364 static const char * const *stdmacpos;
367 * The extra standard macros that come from the object format, if
368 * any.
370 static const char * const *extrastdmac = NULL;
371 bool any_extrastdmac;
374 * Tokens are allocated in blocks to improve speed
376 #define TOKEN_BLOCKSIZE 4096
377 static Token *freeTokens = NULL;
378 struct Blocks {
379 Blocks *next;
380 void *chunk;
383 static Blocks blocks = { NULL, NULL };
386 * Forward declarations.
388 static Token *expand_mmac_params(Token * tline);
389 static Token *expand_smacro(Token * tline);
390 static Token *expand_id(Token * tline);
391 static Context *get_ctx(char *name, bool all_contexts);
392 static void make_tok_num(Token * tok, int64_t val);
393 static void error(int severity, const char *fmt, ...);
394 static void *new_Block(size_t size);
395 static void delete_Blocks(void);
396 static Token *new_Token(Token * next, enum pp_token_type type,
397 const char *text, int txtlen);
398 static Token *delete_Token(Token * t);
401 * Macros for safe checking of token pointers, avoid *(NULL)
403 #define tok_type_(x,t) ((x) && (x)->type == (t))
404 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
405 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
406 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
408 /* Handle TASM specific directives, which do not contain a % in
409 * front of them. We do it here because I could not find any other
410 * place to do it for the moment, and it is a hack (ideally it would
411 * be nice to be able to use the NASM pre-processor to do it).
413 static char *check_tasm_directive(char *line)
415 int32_t i, j, k, m, len;
416 char *p = line, *oldline, oldchar;
418 /* Skip whitespace */
419 while (isspace(*p) && *p != 0)
420 p++;
422 /* Binary search for the directive name */
423 i = -1;
424 j = elements(tasm_directives);
425 len = 0;
426 while (!isspace(p[len]) && p[len] != 0)
427 len++;
428 if (len) {
429 oldchar = p[len];
430 p[len] = 0;
431 while (j - i > 1) {
432 k = (j + i) / 2;
433 m = nasm_stricmp(p, tasm_directives[k]);
434 if (m == 0) {
435 /* We have found a directive, so jam a % in front of it
436 * so that NASM will then recognise it as one if it's own.
438 p[len] = oldchar;
439 len = strlen(p);
440 oldline = line;
441 line = nasm_malloc(len + 2);
442 line[0] = '%';
443 if (k == TM_IFDIFI) {
444 /* NASM does not recognise IFDIFI, so we convert it to
445 * %ifdef BOGUS. This is not used in NASM comaptible
446 * code, but does need to parse for the TASM macro
447 * package.
449 strcpy(line + 1, "ifdef BOGUS");
450 } else {
451 memcpy(line + 1, p, len + 1);
453 nasm_free(oldline);
454 return line;
455 } else if (m < 0) {
456 j = k;
457 } else
458 i = k;
460 p[len] = oldchar;
462 return line;
466 * The pre-preprocessing stage... This function translates line
467 * number indications as they emerge from GNU cpp (`# lineno "file"
468 * flags') into NASM preprocessor line number indications (`%line
469 * lineno file').
471 static char *prepreproc(char *line)
473 int lineno, fnlen;
474 char *fname, *oldline;
476 if (line[0] == '#' && line[1] == ' ') {
477 oldline = line;
478 fname = oldline + 2;
479 lineno = atoi(fname);
480 fname += strspn(fname, "0123456789 ");
481 if (*fname == '"')
482 fname++;
483 fnlen = strcspn(fname, "\"");
484 line = nasm_malloc(20 + fnlen);
485 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
486 nasm_free(oldline);
488 if (tasm_compatible_mode)
489 return check_tasm_directive(line);
490 return line;
494 * Free a linked list of tokens.
496 static void free_tlist(Token * list)
498 while (list) {
499 list = delete_Token(list);
504 * Free a linked list of lines.
506 static void free_llist(Line * list)
508 Line *l;
509 while (list) {
510 l = list;
511 list = list->next;
512 free_tlist(l->first);
513 nasm_free(l);
518 * Free an MMacro
520 static void free_mmacro(MMacro * m)
522 nasm_free(m->name);
523 free_tlist(m->dlist);
524 nasm_free(m->defaults);
525 free_llist(m->expansion);
526 nasm_free(m);
530 * Free all currently defined macros, and free the hash tables
532 static void free_smacro_table(struct hash_table *smt)
534 SMacro *s;
535 const char *key;
536 struct hash_tbl_node *it = NULL;
538 while ((s = hash_iterate(smt, &it, &key)) != NULL) {
539 nasm_free((void *)key);
540 while (s) {
541 SMacro *ns = s->next;
542 nasm_free(s->name);
543 free_tlist(s->expansion);
544 nasm_free(s);
545 s = ns;
548 hash_free(smt);
551 static void free_mmacro_table(struct hash_table *mmt)
553 MMacro *m;
554 const char *key;
555 struct hash_tbl_node *it = NULL;
557 it = NULL;
558 while ((m = hash_iterate(mmt, &it, &key)) != NULL) {
559 nasm_free((void *)key);
560 while (m) {
561 MMacro *nm = m->next;
562 free_mmacro(m);
563 m = nm;
566 hash_free(mmt);
569 static void free_macros(void)
571 free_smacro_table(&smacros);
572 free_mmacro_table(&mmacros);
576 * Initialize the hash tables
578 static void init_macros(void)
580 hash_init(&smacros, HASH_LARGE);
581 hash_init(&mmacros, HASH_LARGE);
585 * Pop the context stack.
587 static void ctx_pop(void)
589 Context *c = cstk;
591 cstk = cstk->next;
592 free_smacro_table(&c->localmac);
593 nasm_free(c->name);
594 nasm_free(c);
598 * Search for a key in the hash index; adding it if necessary
599 * (in which case we initialize the data pointer to NULL.)
601 static void **
602 hash_findi_add(struct hash_table *hash, const char *str)
604 struct hash_insert hi;
605 void **r;
606 char *strx;
608 r = hash_findi(hash, str, &hi);
609 if (r)
610 return r;
612 strx = nasm_strdup(str); /* Use a more efficient allocator here? */
613 return hash_add(&hi, strx, NULL);
617 * Like hash_findi, but returns the data element rather than a pointer
618 * to it. Used only when not adding a new element, hence no third
619 * argument.
621 static void *
622 hash_findix(struct hash_table *hash, const char *str)
624 void **p;
626 p = hash_findi(hash, str, NULL);
627 return p ? *p : NULL;
630 #define BUF_DELTA 512
632 * Read a line from the top file in istk, handling multiple CR/LFs
633 * at the end of the line read, and handling spurious ^Zs. Will
634 * return lines from the standard macro set if this has not already
635 * been done.
637 static char *read_line(void)
639 char *buffer, *p, *q;
640 int bufsize, continued_count;
642 if (stdmacpos) {
643 if (*stdmacpos) {
644 char *ret = nasm_strdup(*stdmacpos++);
645 if (!*stdmacpos && any_extrastdmac) {
646 stdmacpos = extrastdmac;
647 any_extrastdmac = false;
648 return ret;
651 * Nasty hack: here we push the contents of `predef' on
652 * to the top-level expansion stack, since this is the
653 * most convenient way to implement the pre-include and
654 * pre-define features.
656 if (!*stdmacpos) {
657 Line *pd, *l;
658 Token *head, **tail, *t;
660 for (pd = predef; pd; pd = pd->next) {
661 head = NULL;
662 tail = &head;
663 for (t = pd->first; t; t = t->next) {
664 *tail = new_Token(NULL, t->type, t->text, 0);
665 tail = &(*tail)->next;
667 l = nasm_malloc(sizeof(Line));
668 l->next = istk->expansion;
669 l->first = head;
670 l->finishes = false;
671 istk->expansion = l;
674 return ret;
675 } else {
676 stdmacpos = NULL;
680 bufsize = BUF_DELTA;
681 buffer = nasm_malloc(BUF_DELTA);
682 p = buffer;
683 continued_count = 0;
684 while (1) {
685 q = fgets(p, bufsize - (p - buffer), istk->fp);
686 if (!q)
687 break;
688 p += strlen(p);
689 if (p > buffer && p[-1] == '\n') {
690 /* Convert backslash-CRLF line continuation sequences into
691 nothing at all (for DOS and Windows) */
692 if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
693 p -= 3;
694 *p = 0;
695 continued_count++;
697 /* Also convert backslash-LF line continuation sequences into
698 nothing at all (for Unix) */
699 else if (((p - 1) > buffer) && (p[-2] == '\\')) {
700 p -= 2;
701 *p = 0;
702 continued_count++;
703 } else {
704 break;
707 if (p - buffer > bufsize - 10) {
708 int32_t offset = p - buffer;
709 bufsize += BUF_DELTA;
710 buffer = nasm_realloc(buffer, bufsize);
711 p = buffer + offset; /* prevent stale-pointer problems */
715 if (!q && p == buffer) {
716 nasm_free(buffer);
717 return NULL;
720 src_set_linnum(src_get_linnum() + istk->lineinc +
721 (continued_count * istk->lineinc));
724 * Play safe: remove CRs as well as LFs, if any of either are
725 * present at the end of the line.
727 while (--p >= buffer && (*p == '\n' || *p == '\r'))
728 *p = '\0';
731 * Handle spurious ^Z, which may be inserted into source files
732 * by some file transfer utilities.
734 buffer[strcspn(buffer, "\032")] = '\0';
736 list->line(LIST_READ, buffer);
738 return buffer;
742 * Tokenize a line of text. This is a very simple process since we
743 * don't need to parse the value out of e.g. numeric tokens: we
744 * simply split one string into many.
746 static Token *tokenize(char *line)
748 char *p = line;
749 enum pp_token_type type;
750 Token *list = NULL;
751 Token *t, **tail = &list;
753 while (*line) {
754 p = line;
755 if (*p == '%') {
756 p++;
757 if (isdigit(*p) ||
758 ((*p == '-' || *p == '+') && isdigit(p[1])) ||
759 ((*p == '+') && (isspace(p[1]) || !p[1]))) {
760 do {
761 p++;
763 while (isdigit(*p));
764 type = TOK_PREPROC_ID;
765 } else if (*p == '{') {
766 p++;
767 while (*p && *p != '}') {
768 p[-1] = *p;
769 p++;
771 p[-1] = '\0';
772 if (*p)
773 p++;
774 type = TOK_PREPROC_ID;
775 } else if (*p == '?') {
776 type = TOK_PREPROC_Q; /* %? */
777 p++;
778 if (*p == '?') {
779 type = TOK_PREPROC_QQ; /* %?? */
780 p++;
782 } else if (isidchar(*p) ||
783 ((*p == '!' || *p == '%' || *p == '$') &&
784 isidchar(p[1]))) {
785 do {
786 p++;
788 while (isidchar(*p));
789 type = TOK_PREPROC_ID;
790 } else {
791 type = TOK_OTHER;
792 if (*p == '%')
793 p++;
795 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
796 type = TOK_ID;
797 p++;
798 while (*p && isidchar(*p))
799 p++;
800 } else if (*p == '\'' || *p == '"' || *p == '`') {
802 * A string token.
804 type = TOK_STRING;
805 p = nasm_skip_string(p);
807 if (*p) {
808 p++;
809 } else {
810 error(ERR_WARNING, "unterminated string");
811 /* Handling unterminated strings by UNV */
812 /* type = -1; */
814 } else if (isnumstart(*p)) {
815 bool is_hex = false;
816 bool is_float = false;
817 bool has_e = false;
818 char c, *r;
821 * A numeric token.
824 if (*p == '$') {
825 p++;
826 is_hex = true;
829 for (;;) {
830 c = *p++;
832 if (!is_hex && (c == 'e' || c == 'E')) {
833 has_e = true;
834 if (*p == '+' || *p == '-') {
835 /* e can only be followed by +/- if it is either a
836 prefixed hex number or a floating-point number */
837 p++;
838 is_float = true;
840 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
841 is_hex = true;
842 } else if (c == 'P' || c == 'p') {
843 is_float = true;
844 if (*p == '+' || *p == '-')
845 p++;
846 } else if (isnumchar(c) || c == '_')
847 ; /* just advance */
848 else if (c == '.') {
849 /* we need to deal with consequences of the legacy
850 parser, like "1.nolist" being two tokens
851 (TOK_NUMBER, TOK_ID) here; at least give it
852 a shot for now. In the future, we probably need
853 a flex-based scanner with proper pattern matching
854 to do it as well as it can be done. Nothing in
855 the world is going to help the person who wants
856 0x123.p16 interpreted as two tokens, though. */
857 r = p;
858 while (*r == '_')
859 r++;
861 if (isdigit(*r) || (is_hex && isxdigit(*r)) ||
862 (!is_hex && (*r == 'e' || *r == 'E')) ||
863 (*r == 'p' || *r == 'P')) {
864 p = r;
865 is_float = true;
866 } else
867 break; /* Terminate the token */
868 } else
869 break;
871 p--; /* Point to first character beyond number */
873 if (has_e && !is_hex) {
874 /* 1e13 is floating-point, but 1e13h is not */
875 is_float = true;
878 type = is_float ? TOK_FLOAT : TOK_NUMBER;
879 } else if (isspace(*p)) {
880 type = TOK_WHITESPACE;
881 p++;
882 while (*p && isspace(*p))
883 p++;
885 * Whitespace just before end-of-line is discarded by
886 * pretending it's a comment; whitespace just before a
887 * comment gets lumped into the comment.
889 if (!*p || *p == ';') {
890 type = TOK_COMMENT;
891 while (*p)
892 p++;
894 } else if (*p == ';') {
895 type = TOK_COMMENT;
896 while (*p)
897 p++;
898 } else {
900 * Anything else is an operator of some kind. We check
901 * for all the double-character operators (>>, <<, //,
902 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
903 * else is a single-character operator.
905 type = TOK_OTHER;
906 if ((p[0] == '>' && p[1] == '>') ||
907 (p[0] == '<' && p[1] == '<') ||
908 (p[0] == '/' && p[1] == '/') ||
909 (p[0] == '<' && p[1] == '=') ||
910 (p[0] == '>' && p[1] == '=') ||
911 (p[0] == '=' && p[1] == '=') ||
912 (p[0] == '!' && p[1] == '=') ||
913 (p[0] == '<' && p[1] == '>') ||
914 (p[0] == '&' && p[1] == '&') ||
915 (p[0] == '|' && p[1] == '|') ||
916 (p[0] == '^' && p[1] == '^')) {
917 p++;
919 p++;
922 /* Handling unterminated string by UNV */
923 /*if (type == -1)
925 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
926 t->text[p-line] = *line;
927 tail = &t->next;
929 else */
930 if (type != TOK_COMMENT) {
931 *tail = t = new_Token(NULL, type, line, p - line);
932 tail = &t->next;
934 line = p;
936 return list;
940 * this function allocates a new managed block of memory and
941 * returns a pointer to the block. The managed blocks are
942 * deleted only all at once by the delete_Blocks function.
944 static void *new_Block(size_t size)
946 Blocks *b = &blocks;
948 /* first, get to the end of the linked list */
949 while (b->next)
950 b = b->next;
951 /* now allocate the requested chunk */
952 b->chunk = nasm_malloc(size);
954 /* now allocate a new block for the next request */
955 b->next = nasm_malloc(sizeof(Blocks));
956 /* and initialize the contents of the new block */
957 b->next->next = NULL;
958 b->next->chunk = NULL;
959 return b->chunk;
963 * this function deletes all managed blocks of memory
965 static void delete_Blocks(void)
967 Blocks *a, *b = &blocks;
970 * keep in mind that the first block, pointed to by blocks
971 * is a static and not dynamically allocated, so we don't
972 * free it.
974 while (b) {
975 if (b->chunk)
976 nasm_free(b->chunk);
977 a = b;
978 b = b->next;
979 if (a != &blocks)
980 nasm_free(a);
985 * this function creates a new Token and passes a pointer to it
986 * back to the caller. It sets the type and text elements, and
987 * also the mac and next elements to NULL.
989 static Token *new_Token(Token * next, enum pp_token_type type,
990 const char *text, int txtlen)
992 Token *t;
993 int i;
995 if (freeTokens == NULL) {
996 freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
997 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
998 freeTokens[i].next = &freeTokens[i + 1];
999 freeTokens[i].next = NULL;
1001 t = freeTokens;
1002 freeTokens = t->next;
1003 t->next = next;
1004 t->mac = NULL;
1005 t->type = type;
1006 if (type == TOK_WHITESPACE || text == NULL) {
1007 t->text = NULL;
1008 } else {
1009 if (txtlen == 0)
1010 txtlen = strlen(text);
1011 t->text = nasm_malloc(txtlen+1);
1012 memcpy(t->text, text, txtlen);
1013 t->text[txtlen] = '\0';
1015 return t;
1018 static Token *delete_Token(Token * t)
1020 Token *next = t->next;
1021 nasm_free(t->text);
1022 t->next = freeTokens;
1023 freeTokens = t;
1024 return next;
1028 * Convert a line of tokens back into text.
1029 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1030 * will be transformed into ..@ctxnum.xxx
1032 static char *detoken(Token * tlist, bool expand_locals)
1034 Token *t;
1035 int len;
1036 char *line, *p;
1037 const char *q;
1039 len = 0;
1040 for (t = tlist; t; t = t->next) {
1041 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
1042 char *p = getenv(t->text + 2);
1043 nasm_free(t->text);
1044 if (p)
1045 t->text = nasm_strdup(p);
1046 else
1047 t->text = NULL;
1049 /* Expand local macros here and not during preprocessing */
1050 if (expand_locals &&
1051 t->type == TOK_PREPROC_ID && t->text &&
1052 t->text[0] == '%' && t->text[1] == '$') {
1053 Context *ctx = get_ctx(t->text, false);
1054 if (ctx) {
1055 char buffer[40];
1056 char *p, *q = t->text + 2;
1058 q += strspn(q, "$");
1059 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
1060 p = nasm_strcat(buffer, q);
1061 nasm_free(t->text);
1062 t->text = p;
1065 if (t->type == TOK_WHITESPACE) {
1066 len++;
1067 } else if (t->text) {
1068 len += strlen(t->text);
1071 p = line = nasm_malloc(len + 1);
1072 for (t = tlist; t; t = t->next) {
1073 if (t->type == TOK_WHITESPACE) {
1074 *p++ = ' ';
1075 } else if (t->text) {
1076 q = t->text;
1077 while (*q)
1078 *p++ = *q++;
1081 *p = '\0';
1082 return line;
1086 * A scanner, suitable for use by the expression evaluator, which
1087 * operates on a line of Tokens. Expects a pointer to a pointer to
1088 * the first token in the line to be passed in as its private_data
1089 * field.
1091 * FIX: This really needs to be unified with stdscan.
1093 static int ppscan(void *private_data, struct tokenval *tokval)
1095 Token **tlineptr = private_data;
1096 Token *tline;
1097 char ourcopy[MAX_KEYWORD+1], *p, *r, *s;
1099 do {
1100 tline = *tlineptr;
1101 *tlineptr = tline ? tline->next : NULL;
1103 while (tline && (tline->type == TOK_WHITESPACE ||
1104 tline->type == TOK_COMMENT));
1106 if (!tline)
1107 return tokval->t_type = TOKEN_EOS;
1109 tokval->t_charptr = tline->text;
1111 if (tline->text[0] == '$' && !tline->text[1])
1112 return tokval->t_type = TOKEN_HERE;
1113 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
1114 return tokval->t_type = TOKEN_BASE;
1116 if (tline->type == TOK_ID) {
1117 p = tokval->t_charptr = tline->text;
1118 if (p[0] == '$') {
1119 tokval->t_charptr++;
1120 return tokval->t_type = TOKEN_ID;
1123 for (r = p, s = ourcopy; *r; r++) {
1124 if (r >= p+MAX_KEYWORD)
1125 return tokval->t_type = TOKEN_ID; /* Not a keyword */
1126 *s++ = tolower(*r);
1128 *s = '\0';
1129 /* right, so we have an identifier sitting in temp storage. now,
1130 * is it actually a register or instruction name, or what? */
1131 return nasm_token_hash(ourcopy, tokval);
1134 if (tline->type == TOK_NUMBER) {
1135 bool rn_error;
1136 tokval->t_integer = readnum(tline->text, &rn_error);
1137 if (rn_error)
1138 return tokval->t_type = TOKEN_ERRNUM; /* some malformation occurred */
1139 tokval->t_charptr = tline->text;
1140 return tokval->t_type = TOKEN_NUM;
1143 if (tline->type == TOK_FLOAT) {
1144 return tokval->t_type = TOKEN_FLOAT;
1147 if (tline->type == TOK_STRING) {
1148 char bq, *ep;
1149 bool errquote;
1150 bool rn_warn;
1151 size_t l;
1153 bq = tline->text[0];
1154 l = nasm_unquote(tline->text, &ep);
1155 if (ep[0] != bq || ep[1] != '\0')
1156 errquote = true;
1158 if (errquote)
1159 return tokval->t_type = TOKEN_ERRNUM;
1161 tokval->t_integer = readstrnum(tline->text, l, &rn_warn);
1162 if (rn_warn)
1163 error(ERR_WARNING | ERR_PASS1, "character constant too long");
1164 tokval->t_charptr = NULL;
1165 return tokval->t_type = TOKEN_NUM;
1168 if (tline->type == TOK_OTHER) {
1169 if (!strcmp(tline->text, "<<"))
1170 return tokval->t_type = TOKEN_SHL;
1171 if (!strcmp(tline->text, ">>"))
1172 return tokval->t_type = TOKEN_SHR;
1173 if (!strcmp(tline->text, "//"))
1174 return tokval->t_type = TOKEN_SDIV;
1175 if (!strcmp(tline->text, "%%"))
1176 return tokval->t_type = TOKEN_SMOD;
1177 if (!strcmp(tline->text, "=="))
1178 return tokval->t_type = TOKEN_EQ;
1179 if (!strcmp(tline->text, "<>"))
1180 return tokval->t_type = TOKEN_NE;
1181 if (!strcmp(tline->text, "!="))
1182 return tokval->t_type = TOKEN_NE;
1183 if (!strcmp(tline->text, "<="))
1184 return tokval->t_type = TOKEN_LE;
1185 if (!strcmp(tline->text, ">="))
1186 return tokval->t_type = TOKEN_GE;
1187 if (!strcmp(tline->text, "&&"))
1188 return tokval->t_type = TOKEN_DBL_AND;
1189 if (!strcmp(tline->text, "^^"))
1190 return tokval->t_type = TOKEN_DBL_XOR;
1191 if (!strcmp(tline->text, "||"))
1192 return tokval->t_type = TOKEN_DBL_OR;
1196 * We have no other options: just return the first character of
1197 * the token text.
1199 return tokval->t_type = tline->text[0];
1203 * Compare a string to the name of an existing macro; this is a
1204 * simple wrapper which calls either strcmp or nasm_stricmp
1205 * depending on the value of the `casesense' parameter.
1207 static int mstrcmp(const char *p, const char *q, bool casesense)
1209 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
1213 * Compare a string to the name of an existing macro; this is a
1214 * simple wrapper which calls either strcmp or nasm_stricmp
1215 * depending on the value of the `casesense' parameter.
1217 static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
1219 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
1223 * Return the Context structure associated with a %$ token. Return
1224 * NULL, having _already_ reported an error condition, if the
1225 * context stack isn't deep enough for the supplied number of $
1226 * signs.
1227 * If all_contexts == true, contexts that enclose current are
1228 * also scanned for such smacro, until it is found; if not -
1229 * only the context that directly results from the number of $'s
1230 * in variable's name.
1232 static Context *get_ctx(char *name, bool all_contexts)
1234 Context *ctx;
1235 SMacro *m;
1236 int i;
1238 if (!name || name[0] != '%' || name[1] != '$')
1239 return NULL;
1241 if (!cstk) {
1242 error(ERR_NONFATAL, "`%s': context stack is empty", name);
1243 return NULL;
1246 for (i = strspn(name + 2, "$"), ctx = cstk; (i > 0) && ctx; i--) {
1247 ctx = ctx->next;
1248 /* i--; Lino - 02/25/02 */
1250 if (!ctx) {
1251 error(ERR_NONFATAL, "`%s': context stack is only"
1252 " %d level%s deep", name, i - 1, (i == 2 ? "" : "s"));
1253 return NULL;
1255 if (!all_contexts)
1256 return ctx;
1258 do {
1259 /* Search for this smacro in found context */
1260 m = hash_findix(&ctx->localmac, name);
1261 while (m) {
1262 if (!mstrcmp(m->name, name, m->casesense))
1263 return ctx;
1264 m = m->next;
1266 ctx = ctx->next;
1268 while (ctx);
1269 return NULL;
1273 * Check to see if a file is already in a string list
1275 static bool in_list(const StrList *list, const char *str)
1277 while (list) {
1278 if (!strcmp(list->str, str))
1279 return true;
1280 list = list->next;
1282 return false;
1286 * Open an include file. This routine must always return a valid
1287 * file pointer if it returns - it's responsible for throwing an
1288 * ERR_FATAL and bombing out completely if not. It should also try
1289 * the include path one by one until it finds the file or reaches
1290 * the end of the path.
1292 static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail,
1293 bool missing_ok)
1295 FILE *fp;
1296 char *prefix = "";
1297 IncPath *ip = ipath;
1298 int len = strlen(file);
1299 size_t prefix_len = 0;
1300 StrList *sl;
1302 while (1) {
1303 sl = nasm_malloc(prefix_len+len+1+sizeof sl->next);
1304 memcpy(sl->str, prefix, prefix_len);
1305 memcpy(sl->str+prefix_len, file, len+1);
1306 fp = fopen(sl->str, "r");
1307 if (fp && dhead && !in_list(*dhead, sl->str)) {
1308 sl->next = NULL;
1309 **dtail = sl;
1310 *dtail = &sl->next;
1311 } else {
1312 nasm_free(sl);
1314 if (fp)
1315 return fp;
1316 if (!ip) {
1317 if (!missing_ok)
1318 break;
1319 prefix = NULL;
1320 } else {
1321 prefix = ip->path;
1322 ip = ip->next;
1324 if (prefix) {
1325 prefix_len = strlen(prefix);
1326 } else {
1327 /* -MG given and file not found */
1328 if (dhead && !in_list(*dhead, file)) {
1329 sl = nasm_malloc(len+1+sizeof sl->next);
1330 sl->next = NULL;
1331 strcpy(sl->str, file);
1332 **dtail = sl;
1333 *dtail = &sl->next;
1335 return NULL;
1339 error(ERR_FATAL, "unable to open include file `%s'", file);
1340 return NULL; /* never reached - placate compilers */
1344 * Determine if we should warn on defining a single-line macro of
1345 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1346 * return true if _any_ single-line macro of that name is defined.
1347 * Otherwise, will return true if a single-line macro with either
1348 * `nparam' or no parameters is defined.
1350 * If a macro with precisely the right number of parameters is
1351 * defined, or nparam is -1, the address of the definition structure
1352 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1353 * is NULL, no action will be taken regarding its contents, and no
1354 * error will occur.
1356 * Note that this is also called with nparam zero to resolve
1357 * `ifdef'.
1359 * If you already know which context macro belongs to, you can pass
1360 * the context pointer as first parameter; if you won't but name begins
1361 * with %$ the context will be automatically computed. If all_contexts
1362 * is true, macro will be searched in outer contexts as well.
1364 static bool
1365 smacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn,
1366 bool nocase)
1368 struct hash_table *smtbl;
1369 SMacro *m;
1371 if (ctx) {
1372 smtbl = &ctx->localmac;
1373 } else if (name[0] == '%' && name[1] == '$') {
1374 if (cstk)
1375 ctx = get_ctx(name, false);
1376 if (!ctx)
1377 return false; /* got to return _something_ */
1378 smtbl = &ctx->localmac;
1379 } else {
1380 smtbl = &smacros;
1382 m = (SMacro *) hash_findix(smtbl, name);
1384 while (m) {
1385 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
1386 (nparam <= 0 || m->nparam == 0 || nparam == (int) m->nparam)) {
1387 if (defn) {
1388 if (nparam == (int) m->nparam || nparam == -1)
1389 *defn = m;
1390 else
1391 *defn = NULL;
1393 return true;
1395 m = m->next;
1398 return false;
1402 * Count and mark off the parameters in a multi-line macro call.
1403 * This is called both from within the multi-line macro expansion
1404 * code, and also to mark off the default parameters when provided
1405 * in a %macro definition line.
1407 static void count_mmac_params(Token * t, int *nparam, Token *** params)
1409 int paramsize, brace;
1411 *nparam = paramsize = 0;
1412 *params = NULL;
1413 while (t) {
1414 if (*nparam >= paramsize) {
1415 paramsize += PARAM_DELTA;
1416 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1418 skip_white_(t);
1419 brace = false;
1420 if (tok_is_(t, "{"))
1421 brace = true;
1422 (*params)[(*nparam)++] = t;
1423 while (tok_isnt_(t, brace ? "}" : ","))
1424 t = t->next;
1425 if (t) { /* got a comma/brace */
1426 t = t->next;
1427 if (brace) {
1429 * Now we've found the closing brace, look further
1430 * for the comma.
1432 skip_white_(t);
1433 if (tok_isnt_(t, ",")) {
1434 error(ERR_NONFATAL,
1435 "braces do not enclose all of macro parameter");
1436 while (tok_isnt_(t, ","))
1437 t = t->next;
1439 if (t)
1440 t = t->next; /* eat the comma */
1447 * Determine whether one of the various `if' conditions is true or
1448 * not.
1450 * We must free the tline we get passed.
1452 static bool if_condition(Token * tline, enum preproc_token ct)
1454 enum pp_conditional i = PP_COND(ct);
1455 bool j;
1456 Token *t, *tt, **tptr, *origline;
1457 struct tokenval tokval;
1458 expr *evalresult;
1459 enum pp_token_type needtype;
1461 origline = tline;
1463 switch (i) {
1464 case PPC_IFCTX:
1465 j = false; /* have we matched yet? */
1466 while (cstk && tline) {
1467 skip_white_(tline);
1468 if (!tline || tline->type != TOK_ID) {
1469 error(ERR_NONFATAL,
1470 "`%s' expects context identifiers", pp_directives[ct]);
1471 free_tlist(origline);
1472 return -1;
1474 if (!nasm_stricmp(tline->text, cstk->name))
1475 j = true;
1476 tline = tline->next;
1478 break;
1480 case PPC_IFDEF:
1481 j = false; /* have we matched yet? */
1482 while (tline) {
1483 skip_white_(tline);
1484 if (!tline || (tline->type != TOK_ID &&
1485 (tline->type != TOK_PREPROC_ID ||
1486 tline->text[1] != '$'))) {
1487 error(ERR_NONFATAL,
1488 "`%s' expects macro identifiers", pp_directives[ct]);
1489 goto fail;
1491 if (smacro_defined(NULL, tline->text, 0, NULL, true))
1492 j = true;
1493 tline = tline->next;
1495 break;
1497 case PPC_IFIDN:
1498 case PPC_IFIDNI:
1499 tline = expand_smacro(tline);
1500 t = tt = tline;
1501 while (tok_isnt_(tt, ","))
1502 tt = tt->next;
1503 if (!tt) {
1504 error(ERR_NONFATAL,
1505 "`%s' expects two comma-separated arguments",
1506 pp_directives[ct]);
1507 goto fail;
1509 tt = tt->next;
1510 j = true; /* assume equality unless proved not */
1511 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1512 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1513 error(ERR_NONFATAL, "`%s': more than one comma on line",
1514 pp_directives[ct]);
1515 goto fail;
1517 if (t->type == TOK_WHITESPACE) {
1518 t = t->next;
1519 continue;
1521 if (tt->type == TOK_WHITESPACE) {
1522 tt = tt->next;
1523 continue;
1525 if (tt->type != t->type) {
1526 j = false; /* found mismatching tokens */
1527 break;
1529 /* When comparing strings, need to unquote them first */
1530 if (t->type == TOK_STRING) {
1531 size_t l1 = nasm_unquote(t->text, NULL);
1532 size_t l2 = nasm_unquote(tt->text, NULL);
1534 if (l1 != l2) {
1535 j = false;
1536 break;
1538 if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) {
1539 j = false;
1540 break;
1542 } else if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
1543 j = false; /* found mismatching tokens */
1544 break;
1547 t = t->next;
1548 tt = tt->next;
1550 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
1551 j = false; /* trailing gunk on one end or other */
1552 break;
1554 case PPC_IFMACRO:
1556 bool found = false;
1557 MMacro searching, *mmac;
1559 tline = tline->next;
1560 skip_white_(tline);
1561 tline = expand_id(tline);
1562 if (!tok_type_(tline, TOK_ID)) {
1563 error(ERR_NONFATAL,
1564 "`%s' expects a macro name", pp_directives[ct]);
1565 goto fail;
1567 searching.name = nasm_strdup(tline->text);
1568 searching.casesense = true;
1569 searching.plus = false;
1570 searching.nolist = false;
1571 searching.in_progress = 0;
1572 searching.rep_nest = NULL;
1573 searching.nparam_min = 0;
1574 searching.nparam_max = INT_MAX;
1575 tline = expand_smacro(tline->next);
1576 skip_white_(tline);
1577 if (!tline) {
1578 } else if (!tok_type_(tline, TOK_NUMBER)) {
1579 error(ERR_NONFATAL,
1580 "`%s' expects a parameter count or nothing",
1581 pp_directives[ct]);
1582 } else {
1583 searching.nparam_min = searching.nparam_max =
1584 readnum(tline->text, &j);
1585 if (j)
1586 error(ERR_NONFATAL,
1587 "unable to parse parameter count `%s'",
1588 tline->text);
1590 if (tline && tok_is_(tline->next, "-")) {
1591 tline = tline->next->next;
1592 if (tok_is_(tline, "*"))
1593 searching.nparam_max = INT_MAX;
1594 else if (!tok_type_(tline, TOK_NUMBER))
1595 error(ERR_NONFATAL,
1596 "`%s' expects a parameter count after `-'",
1597 pp_directives[ct]);
1598 else {
1599 searching.nparam_max = readnum(tline->text, &j);
1600 if (j)
1601 error(ERR_NONFATAL,
1602 "unable to parse parameter count `%s'",
1603 tline->text);
1604 if (searching.nparam_min > searching.nparam_max)
1605 error(ERR_NONFATAL,
1606 "minimum parameter count exceeds maximum");
1609 if (tline && tok_is_(tline->next, "+")) {
1610 tline = tline->next;
1611 searching.plus = true;
1613 mmac = (MMacro *) hash_findix(&mmacros, searching.name);
1614 while (mmac) {
1615 if (!strcmp(mmac->name, searching.name) &&
1616 (mmac->nparam_min <= searching.nparam_max
1617 || searching.plus)
1618 && (searching.nparam_min <= mmac->nparam_max
1619 || mmac->plus)) {
1620 found = true;
1621 break;
1623 mmac = mmac->next;
1625 nasm_free(searching.name);
1626 j = found;
1627 break;
1630 case PPC_IFID:
1631 needtype = TOK_ID;
1632 goto iftype;
1633 case PPC_IFNUM:
1634 needtype = TOK_NUMBER;
1635 goto iftype;
1636 case PPC_IFSTR:
1637 needtype = TOK_STRING;
1638 goto iftype;
1640 iftype:
1641 t = tline = expand_smacro(tline);
1643 while (tok_type_(t, TOK_WHITESPACE) ||
1644 (needtype == TOK_NUMBER &&
1645 tok_type_(t, TOK_OTHER) &&
1646 (t->text[0] == '-' || t->text[0] == '+') &&
1647 !t->text[1]))
1648 t = t->next;
1650 j = tok_type_(t, needtype);
1651 break;
1653 case PPC_IFTOKEN:
1654 t = tline = expand_smacro(tline);
1655 while (tok_type_(t, TOK_WHITESPACE))
1656 t = t->next;
1658 j = false;
1659 if (t) {
1660 t = t->next; /* Skip the actual token */
1661 while (tok_type_(t, TOK_WHITESPACE))
1662 t = t->next;
1663 j = !t; /* Should be nothing left */
1665 break;
1667 case PPC_IFEMPTY:
1668 t = tline = expand_smacro(tline);
1669 while (tok_type_(t, TOK_WHITESPACE))
1670 t = t->next;
1672 j = !t; /* Should be empty */
1673 break;
1675 case PPC_IF:
1676 t = tline = expand_smacro(tline);
1677 tptr = &t;
1678 tokval.t_type = TOKEN_INVALID;
1679 evalresult = evaluate(ppscan, tptr, &tokval,
1680 NULL, pass | CRITICAL, error, NULL);
1681 if (!evalresult)
1682 return -1;
1683 if (tokval.t_type)
1684 error(ERR_WARNING,
1685 "trailing garbage after expression ignored");
1686 if (!is_simple(evalresult)) {
1687 error(ERR_NONFATAL,
1688 "non-constant value given to `%s'", pp_directives[ct]);
1689 goto fail;
1691 j = reloc_value(evalresult) != 0;
1692 return j;
1694 default:
1695 error(ERR_FATAL,
1696 "preprocessor directive `%s' not yet implemented",
1697 pp_directives[ct]);
1698 goto fail;
1701 free_tlist(origline);
1702 return j ^ PP_NEGATIVE(ct);
1704 fail:
1705 free_tlist(origline);
1706 return -1;
1710 * Expand macros in a string. Used in %error directives (and it should
1711 * almost certainly be removed from there, too.)
1713 * First tokenize the string, apply "expand_smacro" and then de-tokenize back.
1714 * The returned variable should ALWAYS be freed after usage.
1716 void expand_macros_in_string(char **p)
1718 Token *line = tokenize(*p);
1719 line = expand_smacro(line);
1720 *p = detoken(line, false);
1724 * Common code for defining an smacro
1726 static bool define_smacro(Context *ctx, char *mname, bool casesense,
1727 int nparam, Token *expansion)
1729 SMacro *smac, **smhead;
1730 struct hash_table *smtbl;
1732 if (smacro_defined(ctx, mname, nparam, &smac, casesense)) {
1733 if (!smac) {
1734 error(ERR_WARNING,
1735 "single-line macro `%s' defined both with and"
1736 " without parameters", mname);
1738 /* Some instances of the old code considered this a failure,
1739 some others didn't. What is the right thing to do here? */
1740 free_tlist(expansion);
1741 return false; /* Failure */
1742 } else {
1744 * We're redefining, so we have to take over an
1745 * existing SMacro structure. This means freeing
1746 * what was already in it.
1748 nasm_free(smac->name);
1749 free_tlist(smac->expansion);
1751 } else {
1752 smtbl = ctx ? &ctx->localmac : &smacros;
1753 smhead = (SMacro **) hash_findi_add(smtbl, mname);
1754 smac = nasm_malloc(sizeof(SMacro));
1755 smac->next = *smhead;
1756 *smhead = smac;
1758 smac->name = nasm_strdup(mname);
1759 smac->casesense = casesense;
1760 smac->nparam = nparam;
1761 smac->expansion = expansion;
1762 smac->in_progress = false;
1763 return true; /* Success */
1767 * Undefine an smacro
1769 static void undef_smacro(Context *ctx, const char *mname)
1771 SMacro **smhead, *s, **sp;
1772 struct hash_table *smtbl;
1774 smtbl = ctx ? &ctx->localmac : &smacros;
1775 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
1777 if (smhead) {
1779 * We now have a macro name... go hunt for it.
1781 sp = smhead;
1782 while ((s = *sp) != NULL) {
1783 if (!mstrcmp(s->name, mname, s->casesense)) {
1784 *sp = s->next;
1785 nasm_free(s->name);
1786 free_tlist(s->expansion);
1787 nasm_free(s);
1788 } else {
1789 sp = &s->next;
1796 * Decode a size directive
1798 static int parse_size(const char *str) {
1799 static const char *size_names[] =
1800 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
1801 static const int sizes[] =
1802 { 0, 1, 4, 16, 8, 10, 2, 32 };
1804 return sizes[bsii(str, size_names, elements(size_names))+1];
1808 * find and process preprocessor directive in passed line
1809 * Find out if a line contains a preprocessor directive, and deal
1810 * with it if so.
1812 * If a directive _is_ found, it is the responsibility of this routine
1813 * (and not the caller) to free_tlist() the line.
1815 * @param tline a pointer to the current tokeninzed line linked list
1816 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
1819 static int do_directive(Token * tline)
1821 enum preproc_token i;
1822 int j;
1823 bool err;
1824 int nparam;
1825 bool nolist;
1826 bool casesense;
1827 int k, m;
1828 int offset;
1829 char *p, *mname;
1830 Include *inc;
1831 Context *ctx;
1832 Cond *cond;
1833 MMacro *mmac, **mmhead;
1834 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
1835 Line *l;
1836 struct tokenval tokval;
1837 expr *evalresult;
1838 MMacro *tmp_defining; /* Used when manipulating rep_nest */
1839 int64_t count;
1841 origline = tline;
1843 skip_white_(tline);
1844 if (!tline || !tok_type_(tline, TOK_PREPROC_ID) ||
1845 (tline->text[1] == '%' || tline->text[1] == '$'
1846 || tline->text[1] == '!'))
1847 return NO_DIRECTIVE_FOUND;
1849 i = pp_token_hash(tline->text);
1852 * If we're in a non-emitting branch of a condition construct,
1853 * or walking to the end of an already terminated %rep block,
1854 * we should ignore all directives except for condition
1855 * directives.
1857 if (((istk->conds && !emitting(istk->conds->state)) ||
1858 (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
1859 return NO_DIRECTIVE_FOUND;
1863 * If we're defining a macro or reading a %rep block, we should
1864 * ignore all directives except for %macro/%imacro (which
1865 * generate an error), %endm/%endmacro, and (only if we're in a
1866 * %rep block) %endrep. If we're in a %rep block, another %rep
1867 * causes an error, so should be let through.
1869 if (defining && i != PP_MACRO && i != PP_IMACRO &&
1870 i != PP_ENDMACRO && i != PP_ENDM &&
1871 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
1872 return NO_DIRECTIVE_FOUND;
1875 switch (i) {
1876 case PP_INVALID:
1877 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
1878 tline->text);
1879 return NO_DIRECTIVE_FOUND; /* didn't get it */
1881 case PP_STACKSIZE:
1882 /* Directive to tell NASM what the default stack size is. The
1883 * default is for a 16-bit stack, and this can be overriden with
1884 * %stacksize large.
1885 * the following form:
1887 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1889 tline = tline->next;
1890 if (tline && tline->type == TOK_WHITESPACE)
1891 tline = tline->next;
1892 if (!tline || tline->type != TOK_ID) {
1893 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
1894 free_tlist(origline);
1895 return DIRECTIVE_FOUND;
1897 if (nasm_stricmp(tline->text, "flat") == 0) {
1898 /* All subsequent ARG directives are for a 32-bit stack */
1899 StackSize = 4;
1900 StackPointer = "ebp";
1901 ArgOffset = 8;
1902 LocalOffset = 0;
1903 } else if (nasm_stricmp(tline->text, "flat64") == 0) {
1904 /* All subsequent ARG directives are for a 64-bit stack */
1905 StackSize = 8;
1906 StackPointer = "rbp";
1907 ArgOffset = 8;
1908 LocalOffset = 0;
1909 } else if (nasm_stricmp(tline->text, "large") == 0) {
1910 /* All subsequent ARG directives are for a 16-bit stack,
1911 * far function call.
1913 StackSize = 2;
1914 StackPointer = "bp";
1915 ArgOffset = 4;
1916 LocalOffset = 0;
1917 } else if (nasm_stricmp(tline->text, "small") == 0) {
1918 /* All subsequent ARG directives are for a 16-bit stack,
1919 * far function call. We don't support near functions.
1921 StackSize = 2;
1922 StackPointer = "bp";
1923 ArgOffset = 6;
1924 LocalOffset = 0;
1925 } else {
1926 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
1927 free_tlist(origline);
1928 return DIRECTIVE_FOUND;
1930 free_tlist(origline);
1931 return DIRECTIVE_FOUND;
1933 case PP_ARG:
1934 /* TASM like ARG directive to define arguments to functions, in
1935 * the following form:
1937 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1939 offset = ArgOffset;
1940 do {
1941 char *arg, directive[256];
1942 int size = StackSize;
1944 /* Find the argument name */
1945 tline = tline->next;
1946 if (tline && tline->type == TOK_WHITESPACE)
1947 tline = tline->next;
1948 if (!tline || tline->type != TOK_ID) {
1949 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
1950 free_tlist(origline);
1951 return DIRECTIVE_FOUND;
1953 arg = tline->text;
1955 /* Find the argument size type */
1956 tline = tline->next;
1957 if (!tline || tline->type != TOK_OTHER
1958 || tline->text[0] != ':') {
1959 error(ERR_NONFATAL,
1960 "Syntax error processing `%%arg' directive");
1961 free_tlist(origline);
1962 return DIRECTIVE_FOUND;
1964 tline = tline->next;
1965 if (!tline || tline->type != TOK_ID) {
1966 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
1967 free_tlist(origline);
1968 return DIRECTIVE_FOUND;
1971 /* Allow macro expansion of type parameter */
1972 tt = tokenize(tline->text);
1973 tt = expand_smacro(tt);
1974 size = parse_size(tt->text);
1975 if (!size) {
1976 error(ERR_NONFATAL,
1977 "Invalid size type for `%%arg' missing directive");
1978 free_tlist(tt);
1979 free_tlist(origline);
1980 return DIRECTIVE_FOUND;
1982 free_tlist(tt);
1984 /* Round up to even stack slots */
1985 size = (size+StackSize-1) & ~(StackSize-1);
1987 /* Now define the macro for the argument */
1988 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
1989 arg, StackPointer, offset);
1990 do_directive(tokenize(directive));
1991 offset += size;
1993 /* Move to the next argument in the list */
1994 tline = tline->next;
1995 if (tline && tline->type == TOK_WHITESPACE)
1996 tline = tline->next;
1997 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
1998 ArgOffset = offset;
1999 free_tlist(origline);
2000 return DIRECTIVE_FOUND;
2002 case PP_LOCAL:
2003 /* TASM like LOCAL directive to define local variables for a
2004 * function, in the following form:
2006 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2008 * The '= LocalSize' at the end is ignored by NASM, but is
2009 * required by TASM to define the local parameter size (and used
2010 * by the TASM macro package).
2012 offset = LocalOffset;
2013 do {
2014 char *local, directive[256];
2015 int size = StackSize;
2017 /* Find the argument name */
2018 tline = tline->next;
2019 if (tline && tline->type == TOK_WHITESPACE)
2020 tline = tline->next;
2021 if (!tline || tline->type != TOK_ID) {
2022 error(ERR_NONFATAL,
2023 "`%%local' missing argument parameter");
2024 free_tlist(origline);
2025 return DIRECTIVE_FOUND;
2027 local = tline->text;
2029 /* Find the argument size type */
2030 tline = tline->next;
2031 if (!tline || tline->type != TOK_OTHER
2032 || tline->text[0] != ':') {
2033 error(ERR_NONFATAL,
2034 "Syntax error processing `%%local' directive");
2035 free_tlist(origline);
2036 return DIRECTIVE_FOUND;
2038 tline = tline->next;
2039 if (!tline || tline->type != TOK_ID) {
2040 error(ERR_NONFATAL,
2041 "`%%local' missing size type parameter");
2042 free_tlist(origline);
2043 return DIRECTIVE_FOUND;
2046 /* Allow macro expansion of type parameter */
2047 tt = tokenize(tline->text);
2048 tt = expand_smacro(tt);
2049 size = parse_size(tt->text);
2050 if (!size) {
2051 error(ERR_NONFATAL,
2052 "Invalid size type for `%%local' missing directive");
2053 free_tlist(tt);
2054 free_tlist(origline);
2055 return DIRECTIVE_FOUND;
2057 free_tlist(tt);
2059 /* Round up to even stack slots */
2060 size = (size+StackSize-1) & ~(StackSize-1);
2062 offset += size; /* Negative offset, increment before */
2064 /* Now define the macro for the argument */
2065 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
2066 local, StackPointer, offset);
2067 do_directive(tokenize(directive));
2069 /* Now define the assign to setup the enter_c macro correctly */
2070 snprintf(directive, sizeof(directive),
2071 "%%assign %%$localsize %%$localsize+%d", size);
2072 do_directive(tokenize(directive));
2074 /* Move to the next argument in the list */
2075 tline = tline->next;
2076 if (tline && tline->type == TOK_WHITESPACE)
2077 tline = tline->next;
2078 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2079 LocalOffset = offset;
2080 free_tlist(origline);
2081 return DIRECTIVE_FOUND;
2083 case PP_CLEAR:
2084 if (tline->next)
2085 error(ERR_WARNING, "trailing garbage after `%%clear' ignored");
2086 free_macros();
2087 init_macros();
2088 free_tlist(origline);
2089 return DIRECTIVE_FOUND;
2091 case PP_DEPEND:
2092 t = tline->next = expand_smacro(tline->next);
2093 skip_white_(t);
2094 if (!t || (t->type != TOK_STRING &&
2095 t->type != TOK_INTERNAL_STRING)) {
2096 error(ERR_NONFATAL, "`%%depend' expects a file name");
2097 free_tlist(origline);
2098 return DIRECTIVE_FOUND; /* but we did _something_ */
2100 if (t->next)
2101 error(ERR_WARNING,
2102 "trailing garbage after `%%depend' ignored");
2103 p = t->text;
2104 if (t->type != TOK_INTERNAL_STRING)
2105 nasm_unquote(p, NULL);
2106 if (dephead && !in_list(*dephead, p)) {
2107 StrList *sl = nasm_malloc(strlen(p)+1+sizeof sl->next);
2108 sl->next = NULL;
2109 strcpy(sl->str, p);
2110 *deptail = sl;
2111 deptail = &sl->next;
2113 free_tlist(origline);
2114 return DIRECTIVE_FOUND;
2116 case PP_INCLUDE:
2117 t = tline->next = expand_smacro(tline->next);
2118 skip_white_(t);
2120 if (!t || (t->type != TOK_STRING &&
2121 t->type != TOK_INTERNAL_STRING)) {
2122 error(ERR_NONFATAL, "`%%include' expects a file name");
2123 free_tlist(origline);
2124 return DIRECTIVE_FOUND; /* but we did _something_ */
2126 if (t->next)
2127 error(ERR_WARNING,
2128 "trailing garbage after `%%include' ignored");
2129 p = t->text;
2130 if (t->type != TOK_INTERNAL_STRING)
2131 nasm_unquote(p, NULL);
2132 inc = nasm_malloc(sizeof(Include));
2133 inc->next = istk;
2134 inc->conds = NULL;
2135 inc->fp = inc_fopen(p, dephead, &deptail, pass == 0);
2136 if (!inc->fp) {
2137 /* -MG given but file not found */
2138 nasm_free(inc);
2139 } else {
2140 inc->fname = src_set_fname(nasm_strdup(p));
2141 inc->lineno = src_set_linnum(0);
2142 inc->lineinc = 1;
2143 inc->expansion = NULL;
2144 inc->mstk = NULL;
2145 istk = inc;
2146 list->uplevel(LIST_INCLUDE);
2148 free_tlist(origline);
2149 return DIRECTIVE_FOUND;
2151 case PP_PUSH:
2152 tline = tline->next;
2153 skip_white_(tline);
2154 tline = expand_id(tline);
2155 if (!tok_type_(tline, TOK_ID)) {
2156 error(ERR_NONFATAL, "`%%push' expects a context identifier");
2157 free_tlist(origline);
2158 return DIRECTIVE_FOUND; /* but we did _something_ */
2160 if (tline->next)
2161 error(ERR_WARNING, "trailing garbage after `%%push' ignored");
2162 ctx = nasm_malloc(sizeof(Context));
2163 ctx->next = cstk;
2164 hash_init(&ctx->localmac, HASH_SMALL);
2165 ctx->name = nasm_strdup(tline->text);
2166 ctx->number = unique++;
2167 cstk = ctx;
2168 free_tlist(origline);
2169 break;
2171 case PP_REPL:
2172 tline = tline->next;
2173 skip_white_(tline);
2174 tline = expand_id(tline);
2175 if (!tok_type_(tline, TOK_ID)) {
2176 error(ERR_NONFATAL, "`%%repl' expects a context identifier");
2177 free_tlist(origline);
2178 return DIRECTIVE_FOUND; /* but we did _something_ */
2180 if (tline->next)
2181 error(ERR_WARNING, "trailing garbage after `%%repl' ignored");
2182 if (!cstk)
2183 error(ERR_NONFATAL, "`%%repl': context stack is empty");
2184 else {
2185 nasm_free(cstk->name);
2186 cstk->name = nasm_strdup(tline->text);
2188 free_tlist(origline);
2189 break;
2191 case PP_POP:
2192 if (tline->next)
2193 error(ERR_WARNING, "trailing garbage after `%%pop' ignored");
2194 if (!cstk)
2195 error(ERR_NONFATAL, "`%%pop': context stack is already empty");
2196 else
2197 ctx_pop();
2198 free_tlist(origline);
2199 break;
2201 case PP_ERROR:
2202 tline->next = expand_smacro(tline->next);
2203 tline = tline->next;
2204 skip_white_(tline);
2205 if (tok_type_(tline, TOK_STRING)) {
2206 p = tline->text;
2207 nasm_unquote(p, NULL);
2208 expand_macros_in_string(&p); /* WHY? */
2209 error(ERR_NONFATAL, "%s", p);
2210 nasm_free(p);
2211 } else {
2212 p = detoken(tline, false);
2213 error(ERR_WARNING, "%s", p); /* WARNING!??!! */
2214 nasm_free(p);
2216 free_tlist(origline);
2217 break;
2219 CASE_PP_IF:
2220 if (istk->conds && !emitting(istk->conds->state))
2221 j = COND_NEVER;
2222 else {
2223 j = if_condition(tline->next, i);
2224 tline->next = NULL; /* it got freed */
2225 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2227 cond = nasm_malloc(sizeof(Cond));
2228 cond->next = istk->conds;
2229 cond->state = j;
2230 istk->conds = cond;
2231 free_tlist(origline);
2232 return DIRECTIVE_FOUND;
2234 CASE_PP_ELIF:
2235 if (!istk->conds)
2236 error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
2237 if (emitting(istk->conds->state)
2238 || istk->conds->state == COND_NEVER)
2239 istk->conds->state = COND_NEVER;
2240 else {
2242 * IMPORTANT: In the case of %if, we will already have
2243 * called expand_mmac_params(); however, if we're
2244 * processing an %elif we must have been in a
2245 * non-emitting mode, which would have inhibited
2246 * the normal invocation of expand_mmac_params(). Therefore,
2247 * we have to do it explicitly here.
2249 j = if_condition(expand_mmac_params(tline->next), i);
2250 tline->next = NULL; /* it got freed */
2251 istk->conds->state =
2252 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2254 free_tlist(origline);
2255 return DIRECTIVE_FOUND;
2257 case PP_ELSE:
2258 if (tline->next)
2259 error(ERR_WARNING, "trailing garbage after `%%else' ignored");
2260 if (!istk->conds)
2261 error(ERR_FATAL, "`%%else': no matching `%%if'");
2262 if (emitting(istk->conds->state)
2263 || istk->conds->state == COND_NEVER)
2264 istk->conds->state = COND_ELSE_FALSE;
2265 else
2266 istk->conds->state = COND_ELSE_TRUE;
2267 free_tlist(origline);
2268 return DIRECTIVE_FOUND;
2270 case PP_ENDIF:
2271 if (tline->next)
2272 error(ERR_WARNING, "trailing garbage after `%%endif' ignored");
2273 if (!istk->conds)
2274 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2275 cond = istk->conds;
2276 istk->conds = cond->next;
2277 nasm_free(cond);
2278 free_tlist(origline);
2279 return DIRECTIVE_FOUND;
2281 case PP_MACRO:
2282 case PP_IMACRO:
2283 if (defining)
2284 error(ERR_FATAL,
2285 "`%%%smacro': already defining a macro",
2286 (i == PP_IMACRO ? "i" : ""));
2287 tline = tline->next;
2288 skip_white_(tline);
2289 tline = expand_id(tline);
2290 if (!tok_type_(tline, TOK_ID)) {
2291 error(ERR_NONFATAL,
2292 "`%%%smacro' expects a macro name",
2293 (i == PP_IMACRO ? "i" : ""));
2294 return DIRECTIVE_FOUND;
2296 defining = nasm_malloc(sizeof(MMacro));
2297 defining->name = nasm_strdup(tline->text);
2298 defining->casesense = (i == PP_MACRO);
2299 defining->plus = false;
2300 defining->nolist = false;
2301 defining->in_progress = 0;
2302 defining->rep_nest = NULL;
2303 tline = expand_smacro(tline->next);
2304 skip_white_(tline);
2305 if (!tok_type_(tline, TOK_NUMBER)) {
2306 error(ERR_NONFATAL,
2307 "`%%%smacro' expects a parameter count",
2308 (i == PP_IMACRO ? "i" : ""));
2309 defining->nparam_min = defining->nparam_max = 0;
2310 } else {
2311 defining->nparam_min = defining->nparam_max =
2312 readnum(tline->text, &err);
2313 if (err)
2314 error(ERR_NONFATAL,
2315 "unable to parse parameter count `%s'", tline->text);
2317 if (tline && tok_is_(tline->next, "-")) {
2318 tline = tline->next->next;
2319 if (tok_is_(tline, "*"))
2320 defining->nparam_max = INT_MAX;
2321 else if (!tok_type_(tline, TOK_NUMBER))
2322 error(ERR_NONFATAL,
2323 "`%%%smacro' expects a parameter count after `-'",
2324 (i == PP_IMACRO ? "i" : ""));
2325 else {
2326 defining->nparam_max = readnum(tline->text, &err);
2327 if (err)
2328 error(ERR_NONFATAL,
2329 "unable to parse parameter count `%s'",
2330 tline->text);
2331 if (defining->nparam_min > defining->nparam_max)
2332 error(ERR_NONFATAL,
2333 "minimum parameter count exceeds maximum");
2336 if (tline && tok_is_(tline->next, "+")) {
2337 tline = tline->next;
2338 defining->plus = true;
2340 if (tline && tok_type_(tline->next, TOK_ID) &&
2341 !nasm_stricmp(tline->next->text, ".nolist")) {
2342 tline = tline->next;
2343 defining->nolist = true;
2345 mmac = (MMacro *) hash_findix(&mmacros, defining->name);
2346 while (mmac) {
2347 if (!strcmp(mmac->name, defining->name) &&
2348 (mmac->nparam_min <= defining->nparam_max
2349 || defining->plus)
2350 && (defining->nparam_min <= mmac->nparam_max
2351 || mmac->plus)) {
2352 error(ERR_WARNING,
2353 "redefining multi-line macro `%s'", defining->name);
2354 break;
2356 mmac = mmac->next;
2359 * Handle default parameters.
2361 if (tline && tline->next) {
2362 defining->dlist = tline->next;
2363 tline->next = NULL;
2364 count_mmac_params(defining->dlist, &defining->ndefs,
2365 &defining->defaults);
2366 } else {
2367 defining->dlist = NULL;
2368 defining->defaults = NULL;
2370 defining->expansion = NULL;
2371 free_tlist(origline);
2372 return DIRECTIVE_FOUND;
2374 case PP_ENDM:
2375 case PP_ENDMACRO:
2376 if (!defining) {
2377 error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2378 return DIRECTIVE_FOUND;
2380 mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
2381 defining->next = *mmhead;
2382 *mmhead = defining;
2383 defining = NULL;
2384 free_tlist(origline);
2385 return DIRECTIVE_FOUND;
2387 case PP_ROTATE:
2388 if (tline->next && tline->next->type == TOK_WHITESPACE)
2389 tline = tline->next;
2390 if (tline->next == NULL) {
2391 free_tlist(origline);
2392 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
2393 return DIRECTIVE_FOUND;
2395 t = expand_smacro(tline->next);
2396 tline->next = NULL;
2397 free_tlist(origline);
2398 tline = t;
2399 tptr = &t;
2400 tokval.t_type = TOKEN_INVALID;
2401 evalresult =
2402 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2403 free_tlist(tline);
2404 if (!evalresult)
2405 return DIRECTIVE_FOUND;
2406 if (tokval.t_type)
2407 error(ERR_WARNING,
2408 "trailing garbage after expression ignored");
2409 if (!is_simple(evalresult)) {
2410 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2411 return DIRECTIVE_FOUND;
2413 mmac = istk->mstk;
2414 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2415 mmac = mmac->next_active;
2416 if (!mmac) {
2417 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
2418 } else if (mmac->nparam == 0) {
2419 error(ERR_NONFATAL,
2420 "`%%rotate' invoked within macro without parameters");
2421 } else {
2422 int rotate = mmac->rotate + reloc_value(evalresult);
2424 rotate %= (int)mmac->nparam;
2425 if (rotate < 0)
2426 rotate += mmac->nparam;
2428 mmac->rotate = rotate;
2430 return DIRECTIVE_FOUND;
2432 case PP_REP:
2433 nolist = false;
2434 do {
2435 tline = tline->next;
2436 } while (tok_type_(tline, TOK_WHITESPACE));
2438 if (tok_type_(tline, TOK_ID) &&
2439 nasm_stricmp(tline->text, ".nolist") == 0) {
2440 nolist = true;
2441 do {
2442 tline = tline->next;
2443 } while (tok_type_(tline, TOK_WHITESPACE));
2446 if (tline) {
2447 t = expand_smacro(tline);
2448 tptr = &t;
2449 tokval.t_type = TOKEN_INVALID;
2450 evalresult =
2451 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2452 if (!evalresult) {
2453 free_tlist(origline);
2454 return DIRECTIVE_FOUND;
2456 if (tokval.t_type)
2457 error(ERR_WARNING,
2458 "trailing garbage after expression ignored");
2459 if (!is_simple(evalresult)) {
2460 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2461 return DIRECTIVE_FOUND;
2463 count = reloc_value(evalresult) + 1;
2464 } else {
2465 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
2466 count = 0;
2468 free_tlist(origline);
2470 tmp_defining = defining;
2471 defining = nasm_malloc(sizeof(MMacro));
2472 defining->name = NULL; /* flags this macro as a %rep block */
2473 defining->casesense = false;
2474 defining->plus = false;
2475 defining->nolist = nolist;
2476 defining->in_progress = count;
2477 defining->nparam_min = defining->nparam_max = 0;
2478 defining->defaults = NULL;
2479 defining->dlist = NULL;
2480 defining->expansion = NULL;
2481 defining->next_active = istk->mstk;
2482 defining->rep_nest = tmp_defining;
2483 return DIRECTIVE_FOUND;
2485 case PP_ENDREP:
2486 if (!defining || defining->name) {
2487 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2488 return DIRECTIVE_FOUND;
2492 * Now we have a "macro" defined - although it has no name
2493 * and we won't be entering it in the hash tables - we must
2494 * push a macro-end marker for it on to istk->expansion.
2495 * After that, it will take care of propagating itself (a
2496 * macro-end marker line for a macro which is really a %rep
2497 * block will cause the macro to be re-expanded, complete
2498 * with another macro-end marker to ensure the process
2499 * continues) until the whole expansion is forcibly removed
2500 * from istk->expansion by a %exitrep.
2502 l = nasm_malloc(sizeof(Line));
2503 l->next = istk->expansion;
2504 l->finishes = defining;
2505 l->first = NULL;
2506 istk->expansion = l;
2508 istk->mstk = defining;
2510 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2511 tmp_defining = defining;
2512 defining = defining->rep_nest;
2513 free_tlist(origline);
2514 return DIRECTIVE_FOUND;
2516 case PP_EXITREP:
2518 * We must search along istk->expansion until we hit a
2519 * macro-end marker for a macro with no name. Then we set
2520 * its `in_progress' flag to 0.
2522 for (l = istk->expansion; l; l = l->next)
2523 if (l->finishes && !l->finishes->name)
2524 break;
2526 if (l)
2527 l->finishes->in_progress = 0;
2528 else
2529 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2530 free_tlist(origline);
2531 return DIRECTIVE_FOUND;
2533 case PP_XDEFINE:
2534 case PP_IXDEFINE:
2535 case PP_DEFINE:
2536 case PP_IDEFINE:
2537 casesense = (i == PP_DEFINE || i == PP_XDEFINE);
2539 tline = tline->next;
2540 skip_white_(tline);
2541 tline = expand_id(tline);
2542 if (!tline || (tline->type != TOK_ID &&
2543 (tline->type != TOK_PREPROC_ID ||
2544 tline->text[1] != '$'))) {
2545 error(ERR_NONFATAL, "`%s' expects a macro identifier",
2546 pp_directives[i]);
2547 free_tlist(origline);
2548 return DIRECTIVE_FOUND;
2551 ctx = get_ctx(tline->text, false);
2553 mname = tline->text;
2554 last = tline;
2555 param_start = tline = tline->next;
2556 nparam = 0;
2558 /* Expand the macro definition now for %xdefine and %ixdefine */
2559 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2560 tline = expand_smacro(tline);
2562 if (tok_is_(tline, "(")) {
2564 * This macro has parameters.
2567 tline = tline->next;
2568 while (1) {
2569 skip_white_(tline);
2570 if (!tline) {
2571 error(ERR_NONFATAL, "parameter identifier expected");
2572 free_tlist(origline);
2573 return DIRECTIVE_FOUND;
2575 if (tline->type != TOK_ID) {
2576 error(ERR_NONFATAL,
2577 "`%s': parameter identifier expected",
2578 tline->text);
2579 free_tlist(origline);
2580 return DIRECTIVE_FOUND;
2582 tline->type = TOK_SMAC_PARAM + nparam++;
2583 tline = tline->next;
2584 skip_white_(tline);
2585 if (tok_is_(tline, ",")) {
2586 tline = tline->next;
2587 continue;
2589 if (!tok_is_(tline, ")")) {
2590 error(ERR_NONFATAL,
2591 "`)' expected to terminate macro template");
2592 free_tlist(origline);
2593 return DIRECTIVE_FOUND;
2595 break;
2597 last = tline;
2598 tline = tline->next;
2600 if (tok_type_(tline, TOK_WHITESPACE))
2601 last = tline, tline = tline->next;
2602 macro_start = NULL;
2603 last->next = NULL;
2604 t = tline;
2605 while (t) {
2606 if (t->type == TOK_ID) {
2607 for (tt = param_start; tt; tt = tt->next)
2608 if (tt->type >= TOK_SMAC_PARAM &&
2609 !strcmp(tt->text, t->text))
2610 t->type = tt->type;
2612 tt = t->next;
2613 t->next = macro_start;
2614 macro_start = t;
2615 t = tt;
2618 * Good. We now have a macro name, a parameter count, and a
2619 * token list (in reverse order) for an expansion. We ought
2620 * to be OK just to create an SMacro, store it, and let
2621 * free_tlist have the rest of the line (which we have
2622 * carefully re-terminated after chopping off the expansion
2623 * from the end).
2625 define_smacro(ctx, mname, casesense, nparam, macro_start);
2626 free_tlist(origline);
2627 return DIRECTIVE_FOUND;
2629 case PP_UNDEF:
2630 tline = tline->next;
2631 skip_white_(tline);
2632 tline = expand_id(tline);
2633 if (!tline || (tline->type != TOK_ID &&
2634 (tline->type != TOK_PREPROC_ID ||
2635 tline->text[1] != '$'))) {
2636 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
2637 free_tlist(origline);
2638 return DIRECTIVE_FOUND;
2640 if (tline->next) {
2641 error(ERR_WARNING,
2642 "trailing garbage after macro name ignored");
2645 /* Find the context that symbol belongs to */
2646 ctx = get_ctx(tline->text, false);
2647 undef_smacro(ctx, tline->text);
2648 free_tlist(origline);
2649 return DIRECTIVE_FOUND;
2651 case PP_DEFSTR:
2652 case PP_IDEFSTR:
2653 casesense = (i == PP_DEFSTR);
2655 tline = tline->next;
2656 skip_white_(tline);
2657 tline = expand_id(tline);
2658 if (!tline || (tline->type != TOK_ID &&
2659 (tline->type != TOK_PREPROC_ID ||
2660 tline->text[1] != '$'))) {
2661 error(ERR_NONFATAL, "`%s' expects a macro identifier",
2662 pp_directives[i]);
2663 free_tlist(origline);
2664 return DIRECTIVE_FOUND;
2667 ctx = get_ctx(tline->text, false);
2669 mname = tline->text;
2670 last = tline;
2671 tline = expand_smacro(tline->next);
2672 last->next = NULL;
2674 while (tok_type_(tline, TOK_WHITESPACE))
2675 tline = delete_Token(tline);
2677 p = detoken(tline, false);
2678 macro_start = nasm_malloc(sizeof(*macro_start));
2679 macro_start->next = NULL;
2680 macro_start->text = nasm_quote(p, strlen(p));
2681 macro_start->type = TOK_STRING;
2682 macro_start->mac = NULL;
2683 nasm_free(p);
2686 * We now have a macro name, an implicit parameter count of
2687 * zero, and a string token to use as an expansion. Create
2688 * and store an SMacro.
2690 define_smacro(ctx, mname, casesense, 0, macro_start);
2691 free_tlist(origline);
2692 return DIRECTIVE_FOUND;
2694 case PP_PATHSEARCH:
2696 FILE *fp;
2697 StrList *xsl = NULL;
2698 StrList **xst = &xsl;
2700 casesense = true;
2702 tline = tline->next;
2703 skip_white_(tline);
2704 tline = expand_id(tline);
2705 if (!tline || (tline->type != TOK_ID &&
2706 (tline->type != TOK_PREPROC_ID ||
2707 tline->text[1] != '$'))) {
2708 error(ERR_NONFATAL,
2709 "`%%pathsearch' expects a macro identifier as first parameter");
2710 free_tlist(origline);
2711 return DIRECTIVE_FOUND;
2713 ctx = get_ctx(tline->text, false);
2715 mname = tline->text;
2716 last = tline;
2717 tline = expand_smacro(tline->next);
2718 last->next = NULL;
2720 t = tline;
2721 while (tok_type_(t, TOK_WHITESPACE))
2722 t = t->next;
2724 if (!t || (t->type != TOK_STRING &&
2725 t->type != TOK_INTERNAL_STRING)) {
2726 error(ERR_NONFATAL, "`%%pathsearch' expects a file name");
2727 free_tlist(tline);
2728 free_tlist(origline);
2729 return DIRECTIVE_FOUND; /* but we did _something_ */
2731 if (t->next)
2732 error(ERR_WARNING,
2733 "trailing garbage after `%%pathsearch' ignored");
2734 p = t->text;
2735 if (t->type != TOK_INTERNAL_STRING)
2736 nasm_unquote(p, NULL);
2738 fp = inc_fopen(p, &xsl, &xst, true);
2739 if (fp) {
2740 p = xsl->str;
2741 fclose(fp); /* Don't actually care about the file */
2743 macro_start = nasm_malloc(sizeof(*macro_start));
2744 macro_start->next = NULL;
2745 macro_start->text = nasm_quote(p, strlen(p));
2746 macro_start->type = TOK_STRING;
2747 macro_start->mac = NULL;
2748 if (xsl)
2749 nasm_free(xsl);
2752 * We now have a macro name, an implicit parameter count of
2753 * zero, and a string token to use as an expansion. Create
2754 * and store an SMacro.
2756 define_smacro(ctx, mname, casesense, 0, macro_start);
2757 free_tlist(tline);
2758 free_tlist(origline);
2759 return DIRECTIVE_FOUND;
2762 case PP_STRLEN:
2763 casesense = true;
2765 tline = tline->next;
2766 skip_white_(tline);
2767 tline = expand_id(tline);
2768 if (!tline || (tline->type != TOK_ID &&
2769 (tline->type != TOK_PREPROC_ID ||
2770 tline->text[1] != '$'))) {
2771 error(ERR_NONFATAL,
2772 "`%%strlen' expects a macro identifier as first parameter");
2773 free_tlist(origline);
2774 return DIRECTIVE_FOUND;
2776 ctx = get_ctx(tline->text, false);
2778 mname = tline->text;
2779 last = tline;
2780 tline = expand_smacro(tline->next);
2781 last->next = NULL;
2783 t = tline;
2784 while (tok_type_(t, TOK_WHITESPACE))
2785 t = t->next;
2786 /* t should now point to the string */
2787 if (t->type != TOK_STRING) {
2788 error(ERR_NONFATAL,
2789 "`%%strlen` requires string as second parameter");
2790 free_tlist(tline);
2791 free_tlist(origline);
2792 return DIRECTIVE_FOUND;
2795 macro_start = nasm_malloc(sizeof(*macro_start));
2796 macro_start->next = NULL;
2797 make_tok_num(macro_start, nasm_unquote(t->text, NULL));
2798 macro_start->mac = NULL;
2801 * We now have a macro name, an implicit parameter count of
2802 * zero, and a numeric token to use as an expansion. Create
2803 * and store an SMacro.
2805 define_smacro(ctx, mname, casesense, 0, macro_start);
2806 free_tlist(tline);
2807 free_tlist(origline);
2808 return DIRECTIVE_FOUND;
2810 case PP_SUBSTR:
2812 int64_t a1, a2;
2813 size_t len;
2815 casesense = true;
2817 tline = tline->next;
2818 skip_white_(tline);
2819 tline = expand_id(tline);
2820 if (!tline || (tline->type != TOK_ID &&
2821 (tline->type != TOK_PREPROC_ID ||
2822 tline->text[1] != '$'))) {
2823 error(ERR_NONFATAL,
2824 "`%%substr' expects a macro identifier as first parameter");
2825 free_tlist(origline);
2826 return DIRECTIVE_FOUND;
2828 ctx = get_ctx(tline->text, false);
2830 mname = tline->text;
2831 last = tline;
2832 tline = expand_smacro(tline->next);
2833 last->next = NULL;
2835 t = tline->next;
2836 while (tok_type_(t, TOK_WHITESPACE))
2837 t = t->next;
2839 /* t should now point to the string */
2840 if (t->type != TOK_STRING) {
2841 error(ERR_NONFATAL,
2842 "`%%substr` requires string as second parameter");
2843 free_tlist(tline);
2844 free_tlist(origline);
2845 return DIRECTIVE_FOUND;
2848 tt = t->next;
2849 tptr = &tt;
2850 tokval.t_type = TOKEN_INVALID;
2851 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
2852 pass, error, NULL);
2853 if (!evalresult) {
2854 free_tlist(tline);
2855 free_tlist(origline);
2856 return DIRECTIVE_FOUND;
2857 } else if (!is_simple(evalresult)) {
2858 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
2859 free_tlist(tline);
2860 free_tlist(origline);
2861 return DIRECTIVE_FOUND;
2863 a1 = evalresult->value-1;
2865 while (tok_type_(tt, TOK_WHITESPACE))
2866 tt = tt->next;
2867 if (!tt) {
2868 a2 = 1; /* Backwards compatibility: one character */
2869 } else {
2870 tokval.t_type = TOKEN_INVALID;
2871 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
2872 pass, error, NULL);
2873 if (!evalresult) {
2874 free_tlist(tline);
2875 free_tlist(origline);
2876 return DIRECTIVE_FOUND;
2877 } else if (!is_simple(evalresult)) {
2878 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
2879 free_tlist(tline);
2880 free_tlist(origline);
2881 return DIRECTIVE_FOUND;
2883 a2 = evalresult->value;
2886 len = nasm_unquote(t->text, NULL);
2887 if (a2 < 0)
2888 a2 = a2+1+len-a1;
2889 if (a1+a2 > (int64_t)len)
2890 a2 = len-a1;
2892 macro_start = nasm_malloc(sizeof(*macro_start));
2893 macro_start->next = NULL;
2894 macro_start->text = nasm_quote((a1 < 0) ? "" : t->text+a1, a2);
2895 macro_start->type = TOK_STRING;
2896 macro_start->mac = NULL;
2899 * We now have a macro name, an implicit parameter count of
2900 * zero, and a numeric token to use as an expansion. Create
2901 * and store an SMacro.
2903 define_smacro(ctx, mname, casesense, 0, macro_start);
2904 free_tlist(tline);
2905 free_tlist(origline);
2906 return DIRECTIVE_FOUND;
2909 case PP_ASSIGN:
2910 case PP_IASSIGN:
2911 casesense = (i == PP_ASSIGN);
2913 tline = tline->next;
2914 skip_white_(tline);
2915 tline = expand_id(tline);
2916 if (!tline || (tline->type != TOK_ID &&
2917 (tline->type != TOK_PREPROC_ID ||
2918 tline->text[1] != '$'))) {
2919 error(ERR_NONFATAL,
2920 "`%%%sassign' expects a macro identifier",
2921 (i == PP_IASSIGN ? "i" : ""));
2922 free_tlist(origline);
2923 return DIRECTIVE_FOUND;
2925 ctx = get_ctx(tline->text, false);
2927 mname = tline->text;
2928 last = tline;
2929 tline = expand_smacro(tline->next);
2930 last->next = NULL;
2932 t = tline;
2933 tptr = &t;
2934 tokval.t_type = TOKEN_INVALID;
2935 evalresult =
2936 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2937 free_tlist(tline);
2938 if (!evalresult) {
2939 free_tlist(origline);
2940 return DIRECTIVE_FOUND;
2943 if (tokval.t_type)
2944 error(ERR_WARNING,
2945 "trailing garbage after expression ignored");
2947 if (!is_simple(evalresult)) {
2948 error(ERR_NONFATAL,
2949 "non-constant value given to `%%%sassign'",
2950 (i == PP_IASSIGN ? "i" : ""));
2951 free_tlist(origline);
2952 return DIRECTIVE_FOUND;
2955 macro_start = nasm_malloc(sizeof(*macro_start));
2956 macro_start->next = NULL;
2957 make_tok_num(macro_start, reloc_value(evalresult));
2958 macro_start->mac = NULL;
2961 * We now have a macro name, an implicit parameter count of
2962 * zero, and a numeric token to use as an expansion. Create
2963 * and store an SMacro.
2965 define_smacro(ctx, mname, casesense, 0, macro_start);
2966 free_tlist(origline);
2967 return DIRECTIVE_FOUND;
2969 case PP_LINE:
2971 * Syntax is `%line nnn[+mmm] [filename]'
2973 tline = tline->next;
2974 skip_white_(tline);
2975 if (!tok_type_(tline, TOK_NUMBER)) {
2976 error(ERR_NONFATAL, "`%%line' expects line number");
2977 free_tlist(origline);
2978 return DIRECTIVE_FOUND;
2980 k = readnum(tline->text, &err);
2981 m = 1;
2982 tline = tline->next;
2983 if (tok_is_(tline, "+")) {
2984 tline = tline->next;
2985 if (!tok_type_(tline, TOK_NUMBER)) {
2986 error(ERR_NONFATAL, "`%%line' expects line increment");
2987 free_tlist(origline);
2988 return DIRECTIVE_FOUND;
2990 m = readnum(tline->text, &err);
2991 tline = tline->next;
2993 skip_white_(tline);
2994 src_set_linnum(k);
2995 istk->lineinc = m;
2996 if (tline) {
2997 nasm_free(src_set_fname(detoken(tline, false)));
2999 free_tlist(origline);
3000 return DIRECTIVE_FOUND;
3002 default:
3003 error(ERR_FATAL,
3004 "preprocessor directive `%s' not yet implemented",
3005 pp_directives[i]);
3006 break;
3008 return DIRECTIVE_FOUND;
3012 * Ensure that a macro parameter contains a condition code and
3013 * nothing else. Return the condition code index if so, or -1
3014 * otherwise.
3016 static int find_cc(Token * t)
3018 Token *tt;
3019 int i, j, k, m;
3021 if (!t)
3022 return -1; /* Probably a %+ without a space */
3024 skip_white_(t);
3025 if (t->type != TOK_ID)
3026 return -1;
3027 tt = t->next;
3028 skip_white_(tt);
3029 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
3030 return -1;
3032 i = -1;
3033 j = elements(conditions);
3034 while (j - i > 1) {
3035 k = (j + i) / 2;
3036 m = nasm_stricmp(t->text, conditions[k]);
3037 if (m == 0) {
3038 i = k;
3039 j = -2;
3040 break;
3041 } else if (m < 0) {
3042 j = k;
3043 } else
3044 i = k;
3046 if (j != -2)
3047 return -1;
3048 return i;
3052 * Expand MMacro-local things: parameter references (%0, %n, %+n,
3053 * %-n) and MMacro-local identifiers (%%foo).
3055 static Token *expand_mmac_params(Token * tline)
3057 Token *t, *tt, **tail, *thead;
3059 tail = &thead;
3060 thead = NULL;
3062 while (tline) {
3063 if (tline->type == TOK_PREPROC_ID &&
3064 (((tline->text[1] == '+' || tline->text[1] == '-')
3065 && tline->text[2]) || tline->text[1] == '%'
3066 || (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
3067 char *text = NULL;
3068 int type = 0, cc; /* type = 0 to placate optimisers */
3069 char tmpbuf[30];
3070 unsigned int n;
3071 int i;
3072 MMacro *mac;
3074 t = tline;
3075 tline = tline->next;
3077 mac = istk->mstk;
3078 while (mac && !mac->name) /* avoid mistaking %reps for macros */
3079 mac = mac->next_active;
3080 if (!mac)
3081 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
3082 else
3083 switch (t->text[1]) {
3085 * We have to make a substitution of one of the
3086 * forms %1, %-1, %+1, %%foo, %0.
3088 case '0':
3089 type = TOK_NUMBER;
3090 snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
3091 text = nasm_strdup(tmpbuf);
3092 break;
3093 case '%':
3094 type = TOK_ID;
3095 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
3096 mac->unique);
3097 text = nasm_strcat(tmpbuf, t->text + 2);
3098 break;
3099 case '-':
3100 n = atoi(t->text + 2) - 1;
3101 if (n >= mac->nparam)
3102 tt = NULL;
3103 else {
3104 if (mac->nparam > 1)
3105 n = (n + mac->rotate) % mac->nparam;
3106 tt = mac->params[n];
3108 cc = find_cc(tt);
3109 if (cc == -1) {
3110 error(ERR_NONFATAL,
3111 "macro parameter %d is not a condition code",
3112 n + 1);
3113 text = NULL;
3114 } else {
3115 type = TOK_ID;
3116 if (inverse_ccs[cc] == -1) {
3117 error(ERR_NONFATAL,
3118 "condition code `%s' is not invertible",
3119 conditions[cc]);
3120 text = NULL;
3121 } else
3122 text =
3123 nasm_strdup(conditions[inverse_ccs[cc]]);
3125 break;
3126 case '+':
3127 n = atoi(t->text + 2) - 1;
3128 if (n >= mac->nparam)
3129 tt = NULL;
3130 else {
3131 if (mac->nparam > 1)
3132 n = (n + mac->rotate) % mac->nparam;
3133 tt = mac->params[n];
3135 cc = find_cc(tt);
3136 if (cc == -1) {
3137 error(ERR_NONFATAL,
3138 "macro parameter %d is not a condition code",
3139 n + 1);
3140 text = NULL;
3141 } else {
3142 type = TOK_ID;
3143 text = nasm_strdup(conditions[cc]);
3145 break;
3146 default:
3147 n = atoi(t->text + 1) - 1;
3148 if (n >= mac->nparam)
3149 tt = NULL;
3150 else {
3151 if (mac->nparam > 1)
3152 n = (n + mac->rotate) % mac->nparam;
3153 tt = mac->params[n];
3155 if (tt) {
3156 for (i = 0; i < mac->paramlen[n]; i++) {
3157 *tail = new_Token(NULL, tt->type, tt->text, 0);
3158 tail = &(*tail)->next;
3159 tt = tt->next;
3162 text = NULL; /* we've done it here */
3163 break;
3165 if (!text) {
3166 delete_Token(t);
3167 } else {
3168 *tail = t;
3169 tail = &t->next;
3170 t->type = type;
3171 nasm_free(t->text);
3172 t->text = text;
3173 t->mac = NULL;
3175 continue;
3176 } else {
3177 t = *tail = tline;
3178 tline = tline->next;
3179 t->mac = NULL;
3180 tail = &t->next;
3183 *tail = NULL;
3184 t = thead;
3185 for (; t && (tt = t->next) != NULL; t = t->next)
3186 switch (t->type) {
3187 case TOK_WHITESPACE:
3188 if (tt->type == TOK_WHITESPACE) {
3189 t->next = delete_Token(tt);
3191 break;
3192 case TOK_ID:
3193 if (tt->type == TOK_ID || tt->type == TOK_NUMBER) {
3194 char *tmp = nasm_strcat(t->text, tt->text);
3195 nasm_free(t->text);
3196 t->text = tmp;
3197 t->next = delete_Token(tt);
3199 break;
3200 case TOK_NUMBER:
3201 if (tt->type == TOK_NUMBER) {
3202 char *tmp = nasm_strcat(t->text, tt->text);
3203 nasm_free(t->text);
3204 t->text = tmp;
3205 t->next = delete_Token(tt);
3207 break;
3208 default:
3209 break;
3212 return thead;
3216 * Expand all single-line macro calls made in the given line.
3217 * Return the expanded version of the line. The original is deemed
3218 * to be destroyed in the process. (In reality we'll just move
3219 * Tokens from input to output a lot of the time, rather than
3220 * actually bothering to destroy and replicate.)
3222 #define DEADMAN_LIMIT (1 << 20)
3224 static Token *expand_smacro(Token * tline)
3226 Token *t, *tt, *mstart, **tail, *thead;
3227 struct hash_table *smtbl;
3228 SMacro *head = NULL, *m;
3229 Token **params;
3230 int *paramsize;
3231 unsigned int nparam, sparam;
3232 int brackets, rescan;
3233 Token *org_tline = tline;
3234 Context *ctx;
3235 char *mname;
3236 int deadman = DEADMAN_LIMIT;
3239 * Trick: we should avoid changing the start token pointer since it can
3240 * be contained in "next" field of other token. Because of this
3241 * we allocate a copy of first token and work with it; at the end of
3242 * routine we copy it back
3244 if (org_tline) {
3245 tline =
3246 new_Token(org_tline->next, org_tline->type, org_tline->text,
3248 tline->mac = org_tline->mac;
3249 nasm_free(org_tline->text);
3250 org_tline->text = NULL;
3253 again:
3254 tail = &thead;
3255 thead = NULL;
3257 while (tline) { /* main token loop */
3258 if (!--deadman) {
3259 error(ERR_NONFATAL, "interminable macro recursion");
3260 break;
3263 if ((mname = tline->text)) {
3264 /* if this token is a local macro, look in local context */
3265 ctx = NULL;
3266 smtbl = &smacros;
3267 if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID) {
3268 ctx = get_ctx(mname, true);
3269 if (ctx)
3270 smtbl = &ctx->localmac;
3272 head = (SMacro *) hash_findix(smtbl, mname);
3275 * We've hit an identifier. As in is_mmacro below, we first
3276 * check whether the identifier is a single-line macro at
3277 * all, then think about checking for parameters if
3278 * necessary.
3280 for (m = head; m; m = m->next)
3281 if (!mstrcmp(m->name, mname, m->casesense))
3282 break;
3283 if (m) {
3284 mstart = tline;
3285 params = NULL;
3286 paramsize = NULL;
3287 if (m->nparam == 0) {
3289 * Simple case: the macro is parameterless. Discard the
3290 * one token that the macro call took, and push the
3291 * expansion back on the to-do stack.
3293 if (!m->expansion) {
3294 if (!strcmp("__FILE__", m->name)) {
3295 int32_t num = 0;
3296 char *file;
3297 src_get(&num, &file);
3298 tline->text = nasm_quote(file, strlen(file));
3299 tline->type = TOK_STRING;
3300 nasm_free(file);
3301 continue;
3303 if (!strcmp("__LINE__", m->name)) {
3304 nasm_free(tline->text);
3305 make_tok_num(tline, src_get_linnum());
3306 continue;
3308 if (!strcmp("__BITS__", m->name)) {
3309 nasm_free(tline->text);
3310 make_tok_num(tline, globalbits);
3311 continue;
3313 tline = delete_Token(tline);
3314 continue;
3316 } else {
3318 * Complicated case: at least one macro with this name
3319 * exists and takes parameters. We must find the
3320 * parameters in the call, count them, find the SMacro
3321 * that corresponds to that form of the macro call, and
3322 * substitute for the parameters when we expand. What a
3323 * pain.
3325 /*tline = tline->next;
3326 skip_white_(tline); */
3327 do {
3328 t = tline->next;
3329 while (tok_type_(t, TOK_SMAC_END)) {
3330 t->mac->in_progress = false;
3331 t->text = NULL;
3332 t = tline->next = delete_Token(t);
3334 tline = t;
3335 } while (tok_type_(tline, TOK_WHITESPACE));
3336 if (!tok_is_(tline, "(")) {
3338 * This macro wasn't called with parameters: ignore
3339 * the call. (Behaviour borrowed from gnu cpp.)
3341 tline = mstart;
3342 m = NULL;
3343 } else {
3344 int paren = 0;
3345 int white = 0;
3346 brackets = 0;
3347 nparam = 0;
3348 sparam = PARAM_DELTA;
3349 params = nasm_malloc(sparam * sizeof(Token *));
3350 params[0] = tline->next;
3351 paramsize = nasm_malloc(sparam * sizeof(int));
3352 paramsize[0] = 0;
3353 while (true) { /* parameter loop */
3355 * For some unusual expansions
3356 * which concatenates function call
3358 t = tline->next;
3359 while (tok_type_(t, TOK_SMAC_END)) {
3360 t->mac->in_progress = false;
3361 t->text = NULL;
3362 t = tline->next = delete_Token(t);
3364 tline = t;
3366 if (!tline) {
3367 error(ERR_NONFATAL,
3368 "macro call expects terminating `)'");
3369 break;
3371 if (tline->type == TOK_WHITESPACE
3372 && brackets <= 0) {
3373 if (paramsize[nparam])
3374 white++;
3375 else
3376 params[nparam] = tline->next;
3377 continue; /* parameter loop */
3379 if (tline->type == TOK_OTHER
3380 && tline->text[1] == 0) {
3381 char ch = tline->text[0];
3382 if (ch == ',' && !paren && brackets <= 0) {
3383 if (++nparam >= sparam) {
3384 sparam += PARAM_DELTA;
3385 params = nasm_realloc(params,
3386 sparam *
3387 sizeof(Token
3388 *));
3389 paramsize =
3390 nasm_realloc(paramsize,
3391 sparam *
3392 sizeof(int));
3394 params[nparam] = tline->next;
3395 paramsize[nparam] = 0;
3396 white = 0;
3397 continue; /* parameter loop */
3399 if (ch == '{' &&
3400 (brackets > 0 || (brackets == 0 &&
3401 !paramsize[nparam])))
3403 if (!(brackets++)) {
3404 params[nparam] = tline->next;
3405 continue; /* parameter loop */
3408 if (ch == '}' && brackets > 0)
3409 if (--brackets == 0) {
3410 brackets = -1;
3411 continue; /* parameter loop */
3413 if (ch == '(' && !brackets)
3414 paren++;
3415 if (ch == ')' && brackets <= 0)
3416 if (--paren < 0)
3417 break;
3419 if (brackets < 0) {
3420 brackets = 0;
3421 error(ERR_NONFATAL, "braces do not "
3422 "enclose all of macro parameter");
3424 paramsize[nparam] += white + 1;
3425 white = 0;
3426 } /* parameter loop */
3427 nparam++;
3428 while (m && (m->nparam != nparam ||
3429 mstrcmp(m->name, mname,
3430 m->casesense)))
3431 m = m->next;
3432 if (!m)
3433 error(ERR_WARNING | ERR_WARN_MNP,
3434 "macro `%s' exists, "
3435 "but not taking %d parameters",
3436 mstart->text, nparam);
3439 if (m && m->in_progress)
3440 m = NULL;
3441 if (!m) { /* in progess or didn't find '(' or wrong nparam */
3443 * Design question: should we handle !tline, which
3444 * indicates missing ')' here, or expand those
3445 * macros anyway, which requires the (t) test a few
3446 * lines down?
3448 nasm_free(params);
3449 nasm_free(paramsize);
3450 tline = mstart;
3451 } else {
3453 * Expand the macro: we are placed on the last token of the
3454 * call, so that we can easily split the call from the
3455 * following tokens. We also start by pushing an SMAC_END
3456 * token for the cycle removal.
3458 t = tline;
3459 if (t) {
3460 tline = t->next;
3461 t->next = NULL;
3463 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
3464 tt->mac = m;
3465 m->in_progress = true;
3466 tline = tt;
3467 for (t = m->expansion; t; t = t->next) {
3468 if (t->type >= TOK_SMAC_PARAM) {
3469 Token *pcopy = tline, **ptail = &pcopy;
3470 Token *ttt, *pt;
3471 int i;
3473 ttt = params[t->type - TOK_SMAC_PARAM];
3474 for (i = paramsize[t->type - TOK_SMAC_PARAM];
3475 --i >= 0;) {
3476 pt = *ptail =
3477 new_Token(tline, ttt->type, ttt->text,
3479 ptail = &pt->next;
3480 ttt = ttt->next;
3482 tline = pcopy;
3483 } else if (t->type == TOK_PREPROC_Q) {
3484 tt = new_Token(tline, TOK_ID, mname, 0);
3485 tline = tt;
3486 } else if (t->type == TOK_PREPROC_QQ) {
3487 tt = new_Token(tline, TOK_ID, m->name, 0);
3488 tline = tt;
3489 } else {
3490 tt = new_Token(tline, t->type, t->text, 0);
3491 tline = tt;
3496 * Having done that, get rid of the macro call, and clean
3497 * up the parameters.
3499 nasm_free(params);
3500 nasm_free(paramsize);
3501 free_tlist(mstart);
3502 continue; /* main token loop */
3507 if (tline->type == TOK_SMAC_END) {
3508 tline->mac->in_progress = false;
3509 tline = delete_Token(tline);
3510 } else {
3511 t = *tail = tline;
3512 tline = tline->next;
3513 t->mac = NULL;
3514 t->next = NULL;
3515 tail = &t->next;
3520 * Now scan the entire line and look for successive TOK_IDs that resulted
3521 * after expansion (they can't be produced by tokenize()). The successive
3522 * TOK_IDs should be concatenated.
3523 * Also we look for %+ tokens and concatenate the tokens before and after
3524 * them (without white spaces in between).
3526 t = thead;
3527 rescan = 0;
3528 while (t) {
3529 while (t && t->type != TOK_ID && t->type != TOK_PREPROC_ID)
3530 t = t->next;
3531 if (!t || !t->next)
3532 break;
3533 if (t->next->type == TOK_ID ||
3534 t->next->type == TOK_PREPROC_ID ||
3535 t->next->type == TOK_NUMBER) {
3536 char *p = nasm_strcat(t->text, t->next->text);
3537 nasm_free(t->text);
3538 t->next = delete_Token(t->next);
3539 t->text = p;
3540 rescan = 1;
3541 } else if (t->next->type == TOK_WHITESPACE && t->next->next &&
3542 t->next->next->type == TOK_PREPROC_ID &&
3543 strcmp(t->next->next->text, "%+") == 0) {
3544 /* free the next whitespace, the %+ token and next whitespace */
3545 int i;
3546 for (i = 1; i <= 3; i++) {
3547 if (!t->next
3548 || (i != 2 && t->next->type != TOK_WHITESPACE))
3549 break;
3550 t->next = delete_Token(t->next);
3551 } /* endfor */
3552 } else
3553 t = t->next;
3555 /* If we concatenaded something, re-scan the line for macros */
3556 if (rescan) {
3557 tline = thead;
3558 goto again;
3561 if (org_tline) {
3562 if (thead) {
3563 *org_tline = *thead;
3564 /* since we just gave text to org_line, don't free it */
3565 thead->text = NULL;
3566 delete_Token(thead);
3567 } else {
3568 /* the expression expanded to empty line;
3569 we can't return NULL for some reasons
3570 we just set the line to a single WHITESPACE token. */
3571 memset(org_tline, 0, sizeof(*org_tline));
3572 org_tline->text = NULL;
3573 org_tline->type = TOK_WHITESPACE;
3575 thead = org_tline;
3578 return thead;
3582 * Similar to expand_smacro but used exclusively with macro identifiers
3583 * right before they are fetched in. The reason is that there can be
3584 * identifiers consisting of several subparts. We consider that if there
3585 * are more than one element forming the name, user wants a expansion,
3586 * otherwise it will be left as-is. Example:
3588 * %define %$abc cde
3590 * the identifier %$abc will be left as-is so that the handler for %define
3591 * will suck it and define the corresponding value. Other case:
3593 * %define _%$abc cde
3595 * In this case user wants name to be expanded *before* %define starts
3596 * working, so we'll expand %$abc into something (if it has a value;
3597 * otherwise it will be left as-is) then concatenate all successive
3598 * PP_IDs into one.
3600 static Token *expand_id(Token * tline)
3602 Token *cur, *oldnext = NULL;
3604 if (!tline || !tline->next)
3605 return tline;
3607 cur = tline;
3608 while (cur->next &&
3609 (cur->next->type == TOK_ID ||
3610 cur->next->type == TOK_PREPROC_ID
3611 || cur->next->type == TOK_NUMBER))
3612 cur = cur->next;
3614 /* If identifier consists of just one token, don't expand */
3615 if (cur == tline)
3616 return tline;
3618 if (cur) {
3619 oldnext = cur->next; /* Detach the tail past identifier */
3620 cur->next = NULL; /* so that expand_smacro stops here */
3623 tline = expand_smacro(tline);
3625 if (cur) {
3626 /* expand_smacro possibly changhed tline; re-scan for EOL */
3627 cur = tline;
3628 while (cur && cur->next)
3629 cur = cur->next;
3630 if (cur)
3631 cur->next = oldnext;
3634 return tline;
3638 * Determine whether the given line constitutes a multi-line macro
3639 * call, and return the MMacro structure called if so. Doesn't have
3640 * to check for an initial label - that's taken care of in
3641 * expand_mmacro - but must check numbers of parameters. Guaranteed
3642 * to be called with tline->type == TOK_ID, so the putative macro
3643 * name is easy to find.
3645 static MMacro *is_mmacro(Token * tline, Token *** params_array)
3647 MMacro *head, *m;
3648 Token **params;
3649 int nparam;
3651 head = (MMacro *) hash_findix(&mmacros, tline->text);
3654 * Efficiency: first we see if any macro exists with the given
3655 * name. If not, we can return NULL immediately. _Then_ we
3656 * count the parameters, and then we look further along the
3657 * list if necessary to find the proper MMacro.
3659 for (m = head; m; m = m->next)
3660 if (!mstrcmp(m->name, tline->text, m->casesense))
3661 break;
3662 if (!m)
3663 return NULL;
3666 * OK, we have a potential macro. Count and demarcate the
3667 * parameters.
3669 count_mmac_params(tline->next, &nparam, &params);
3672 * So we know how many parameters we've got. Find the MMacro
3673 * structure that handles this number.
3675 while (m) {
3676 if (m->nparam_min <= nparam
3677 && (m->plus || nparam <= m->nparam_max)) {
3679 * This one is right. Just check if cycle removal
3680 * prohibits us using it before we actually celebrate...
3682 if (m->in_progress) {
3683 #if 0
3684 error(ERR_NONFATAL,
3685 "self-reference in multi-line macro `%s'", m->name);
3686 #endif
3687 nasm_free(params);
3688 return NULL;
3691 * It's right, and we can use it. Add its default
3692 * parameters to the end of our list if necessary.
3694 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
3695 params =
3696 nasm_realloc(params,
3697 ((m->nparam_min + m->ndefs +
3698 1) * sizeof(*params)));
3699 while (nparam < m->nparam_min + m->ndefs) {
3700 params[nparam] = m->defaults[nparam - m->nparam_min];
3701 nparam++;
3705 * If we've gone over the maximum parameter count (and
3706 * we're in Plus mode), ignore parameters beyond
3707 * nparam_max.
3709 if (m->plus && nparam > m->nparam_max)
3710 nparam = m->nparam_max;
3712 * Then terminate the parameter list, and leave.
3714 if (!params) { /* need this special case */
3715 params = nasm_malloc(sizeof(*params));
3716 nparam = 0;
3718 params[nparam] = NULL;
3719 *params_array = params;
3720 return m;
3723 * This one wasn't right: look for the next one with the
3724 * same name.
3726 for (m = m->next; m; m = m->next)
3727 if (!mstrcmp(m->name, tline->text, m->casesense))
3728 break;
3732 * After all that, we didn't find one with the right number of
3733 * parameters. Issue a warning, and fail to expand the macro.
3735 error(ERR_WARNING | ERR_WARN_MNP,
3736 "macro `%s' exists, but not taking %d parameters",
3737 tline->text, nparam);
3738 nasm_free(params);
3739 return NULL;
3743 * Expand the multi-line macro call made by the given line, if
3744 * there is one to be expanded. If there is, push the expansion on
3745 * istk->expansion and return 1. Otherwise return 0.
3747 static int expand_mmacro(Token * tline)
3749 Token *startline = tline;
3750 Token *label = NULL;
3751 int dont_prepend = 0;
3752 Token **params, *t, *mtok, *tt;
3753 MMacro *m;
3754 Line *l, *ll;
3755 int i, nparam, *paramlen;
3756 const char *mname;
3758 t = tline;
3759 skip_white_(t);
3760 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
3761 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
3762 return 0;
3763 mtok = t;
3764 m = is_mmacro(t, &params);
3765 if (m) {
3766 mname = t->text;
3767 } else {
3768 Token *last;
3770 * We have an id which isn't a macro call. We'll assume
3771 * it might be a label; we'll also check to see if a
3772 * colon follows it. Then, if there's another id after
3773 * that lot, we'll check it again for macro-hood.
3775 label = last = t;
3776 t = t->next;
3777 if (tok_type_(t, TOK_WHITESPACE))
3778 last = t, t = t->next;
3779 if (tok_is_(t, ":")) {
3780 dont_prepend = 1;
3781 last = t, t = t->next;
3782 if (tok_type_(t, TOK_WHITESPACE))
3783 last = t, t = t->next;
3785 if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
3786 return 0;
3787 last->next = NULL;
3788 mname = t->text;
3789 tline = t;
3793 * Fix up the parameters: this involves stripping leading and
3794 * trailing whitespace, then stripping braces if they are
3795 * present.
3797 for (nparam = 0; params[nparam]; nparam++) ;
3798 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
3800 for (i = 0; params[i]; i++) {
3801 int brace = false;
3802 int comma = (!m->plus || i < nparam - 1);
3804 t = params[i];
3805 skip_white_(t);
3806 if (tok_is_(t, "{"))
3807 t = t->next, brace = true, comma = false;
3808 params[i] = t;
3809 paramlen[i] = 0;
3810 while (t) {
3811 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
3812 break; /* ... because we have hit a comma */
3813 if (comma && t->type == TOK_WHITESPACE
3814 && tok_is_(t->next, ","))
3815 break; /* ... or a space then a comma */
3816 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
3817 break; /* ... or a brace */
3818 t = t->next;
3819 paramlen[i]++;
3824 * OK, we have a MMacro structure together with a set of
3825 * parameters. We must now go through the expansion and push
3826 * copies of each Line on to istk->expansion. Substitution of
3827 * parameter tokens and macro-local tokens doesn't get done
3828 * until the single-line macro substitution process; this is
3829 * because delaying them allows us to change the semantics
3830 * later through %rotate.
3832 * First, push an end marker on to istk->expansion, mark this
3833 * macro as in progress, and set up its invocation-specific
3834 * variables.
3836 ll = nasm_malloc(sizeof(Line));
3837 ll->next = istk->expansion;
3838 ll->finishes = m;
3839 ll->first = NULL;
3840 istk->expansion = ll;
3842 m->in_progress = true;
3843 m->params = params;
3844 m->iline = tline;
3845 m->nparam = nparam;
3846 m->rotate = 0;
3847 m->paramlen = paramlen;
3848 m->unique = unique++;
3849 m->lineno = 0;
3851 m->next_active = istk->mstk;
3852 istk->mstk = m;
3854 for (l = m->expansion; l; l = l->next) {
3855 Token **tail;
3857 ll = nasm_malloc(sizeof(Line));
3858 ll->finishes = NULL;
3859 ll->next = istk->expansion;
3860 istk->expansion = ll;
3861 tail = &ll->first;
3863 for (t = l->first; t; t = t->next) {
3864 Token *x = t;
3865 switch (t->type) {
3866 case TOK_PREPROC_Q:
3867 tt = *tail = new_Token(NULL, TOK_ID, mname, 0);
3868 break;
3869 case TOK_PREPROC_QQ:
3870 tt = *tail = new_Token(NULL, TOK_ID, m->name, 0);
3871 break;
3872 case TOK_PREPROC_ID:
3873 if (t->text[1] == '0' && t->text[2] == '0') {
3874 dont_prepend = -1;
3875 x = label;
3876 if (!x)
3877 continue;
3879 /* fall through */
3880 default:
3881 tt = *tail = new_Token(NULL, x->type, x->text, 0);
3882 break;
3884 tail = &tt->next;
3886 *tail = NULL;
3890 * If we had a label, push it on as the first line of
3891 * the macro expansion.
3893 if (label) {
3894 if (dont_prepend < 0)
3895 free_tlist(startline);
3896 else {
3897 ll = nasm_malloc(sizeof(Line));
3898 ll->finishes = NULL;
3899 ll->next = istk->expansion;
3900 istk->expansion = ll;
3901 ll->first = startline;
3902 if (!dont_prepend) {
3903 while (label->next)
3904 label = label->next;
3905 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
3910 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
3912 return 1;
3916 * Since preprocessor always operate only on the line that didn't
3917 * arrived yet, we should always use ERR_OFFBY1. Also since user
3918 * won't want to see same error twice (preprocessing is done once
3919 * per pass) we will want to show errors only during pass one.
3921 static void error(int severity, const char *fmt, ...)
3923 va_list arg;
3924 char buff[1024];
3926 /* If we're in a dead branch of IF or something like it, ignore the error */
3927 if (istk && istk->conds && !emitting(istk->conds->state))
3928 return;
3930 va_start(arg, fmt);
3931 vsnprintf(buff, sizeof(buff), fmt, arg);
3932 va_end(arg);
3934 if (istk && istk->mstk && istk->mstk->name)
3935 _error(severity | ERR_PASS1, "(%s:%d) %s", istk->mstk->name,
3936 istk->mstk->lineno, buff);
3937 else
3938 _error(severity | ERR_PASS1, "%s", buff);
3941 static void
3942 pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
3943 ListGen * listgen, StrList **deplist)
3945 _error = errfunc;
3946 cstk = NULL;
3947 istk = nasm_malloc(sizeof(Include));
3948 istk->next = NULL;
3949 istk->conds = NULL;
3950 istk->expansion = NULL;
3951 istk->mstk = NULL;
3952 istk->fp = fopen(file, "r");
3953 istk->fname = NULL;
3954 src_set_fname(nasm_strdup(file));
3955 src_set_linnum(0);
3956 istk->lineinc = 1;
3957 if (!istk->fp)
3958 error(ERR_FATAL | ERR_NOFILE, "unable to open input file `%s'",
3959 file);
3960 defining = NULL;
3961 init_macros();
3962 unique = 0;
3963 if (tasm_compatible_mode) {
3964 stdmacpos = nasm_stdmac;
3965 } else {
3966 stdmacpos = nasm_stdmac_after_tasm;
3968 any_extrastdmac = (extrastdmac != NULL);
3969 list = listgen;
3970 evaluate = eval;
3971 pass = apass;
3972 dephead = deptail = deplist;
3973 if (deplist) {
3974 StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
3975 sl->next = NULL;
3976 strcpy(sl->str, file);
3977 *deptail = sl;
3978 deptail = &sl->next;
3982 static char *pp_getline(void)
3984 char *line;
3985 Token *tline;
3987 while (1) {
3989 * Fetch a tokenized line, either from the macro-expansion
3990 * buffer or from the input file.
3992 tline = NULL;
3993 while (istk->expansion && istk->expansion->finishes) {
3994 Line *l = istk->expansion;
3995 if (!l->finishes->name && l->finishes->in_progress > 1) {
3996 Line *ll;
3999 * This is a macro-end marker for a macro with no
4000 * name, which means it's not really a macro at all
4001 * but a %rep block, and the `in_progress' field is
4002 * more than 1, meaning that we still need to
4003 * repeat. (1 means the natural last repetition; 0
4004 * means termination by %exitrep.) We have
4005 * therefore expanded up to the %endrep, and must
4006 * push the whole block on to the expansion buffer
4007 * again. We don't bother to remove the macro-end
4008 * marker: we'd only have to generate another one
4009 * if we did.
4011 l->finishes->in_progress--;
4012 for (l = l->finishes->expansion; l; l = l->next) {
4013 Token *t, *tt, **tail;
4015 ll = nasm_malloc(sizeof(Line));
4016 ll->next = istk->expansion;
4017 ll->finishes = NULL;
4018 ll->first = NULL;
4019 tail = &ll->first;
4021 for (t = l->first; t; t = t->next) {
4022 if (t->text || t->type == TOK_WHITESPACE) {
4023 tt = *tail =
4024 new_Token(NULL, t->type, t->text, 0);
4025 tail = &tt->next;
4029 istk->expansion = ll;
4031 } else {
4033 * Check whether a `%rep' was started and not ended
4034 * within this macro expansion. This can happen and
4035 * should be detected. It's a fatal error because
4036 * I'm too confused to work out how to recover
4037 * sensibly from it.
4039 if (defining) {
4040 if (defining->name)
4041 error(ERR_PANIC,
4042 "defining with name in expansion");
4043 else if (istk->mstk->name)
4044 error(ERR_FATAL,
4045 "`%%rep' without `%%endrep' within"
4046 " expansion of macro `%s'",
4047 istk->mstk->name);
4051 * FIXME: investigate the relationship at this point between
4052 * istk->mstk and l->finishes
4055 MMacro *m = istk->mstk;
4056 istk->mstk = m->next_active;
4057 if (m->name) {
4059 * This was a real macro call, not a %rep, and
4060 * therefore the parameter information needs to
4061 * be freed.
4063 nasm_free(m->params);
4064 free_tlist(m->iline);
4065 nasm_free(m->paramlen);
4066 l->finishes->in_progress = false;
4067 } else
4068 free_mmacro(m);
4070 istk->expansion = l->next;
4071 nasm_free(l);
4072 list->downlevel(LIST_MACRO);
4075 while (1) { /* until we get a line we can use */
4077 if (istk->expansion) { /* from a macro expansion */
4078 char *p;
4079 Line *l = istk->expansion;
4080 if (istk->mstk)
4081 istk->mstk->lineno++;
4082 tline = l->first;
4083 istk->expansion = l->next;
4084 nasm_free(l);
4085 p = detoken(tline, false);
4086 list->line(LIST_MACRO, p);
4087 nasm_free(p);
4088 break;
4090 line = read_line();
4091 if (line) { /* from the current input file */
4092 line = prepreproc(line);
4093 tline = tokenize(line);
4094 nasm_free(line);
4095 break;
4098 * The current file has ended; work down the istk
4101 Include *i = istk;
4102 fclose(i->fp);
4103 if (i->conds)
4104 error(ERR_FATAL,
4105 "expected `%%endif' before end of file");
4106 /* only set line and file name if there's a next node */
4107 if (i->next) {
4108 src_set_linnum(i->lineno);
4109 nasm_free(src_set_fname(i->fname));
4111 istk = i->next;
4112 list->downlevel(LIST_INCLUDE);
4113 nasm_free(i);
4114 if (!istk)
4115 return NULL;
4120 * We must expand MMacro parameters and MMacro-local labels
4121 * _before_ we plunge into directive processing, to cope
4122 * with things like `%define something %1' such as STRUC
4123 * uses. Unless we're _defining_ a MMacro, in which case
4124 * those tokens should be left alone to go into the
4125 * definition; and unless we're in a non-emitting
4126 * condition, in which case we don't want to meddle with
4127 * anything.
4129 if (!defining && !(istk->conds && !emitting(istk->conds->state)))
4130 tline = expand_mmac_params(tline);
4133 * Check the line to see if it's a preprocessor directive.
4135 if (do_directive(tline) == DIRECTIVE_FOUND) {
4136 continue;
4137 } else if (defining) {
4139 * We're defining a multi-line macro. We emit nothing
4140 * at all, and just
4141 * shove the tokenized line on to the macro definition.
4143 Line *l = nasm_malloc(sizeof(Line));
4144 l->next = defining->expansion;
4145 l->first = tline;
4146 l->finishes = false;
4147 defining->expansion = l;
4148 continue;
4149 } else if (istk->conds && !emitting(istk->conds->state)) {
4151 * We're in a non-emitting branch of a condition block.
4152 * Emit nothing at all, not even a blank line: when we
4153 * emerge from the condition we'll give a line-number
4154 * directive so we keep our place correctly.
4156 free_tlist(tline);
4157 continue;
4158 } else if (istk->mstk && !istk->mstk->in_progress) {
4160 * We're in a %rep block which has been terminated, so
4161 * we're walking through to the %endrep without
4162 * emitting anything. Emit nothing at all, not even a
4163 * blank line: when we emerge from the %rep block we'll
4164 * give a line-number directive so we keep our place
4165 * correctly.
4167 free_tlist(tline);
4168 continue;
4169 } else {
4170 tline = expand_smacro(tline);
4171 if (!expand_mmacro(tline)) {
4173 * De-tokenize the line again, and emit it.
4175 line = detoken(tline, true);
4176 free_tlist(tline);
4177 break;
4178 } else {
4179 continue; /* expand_mmacro calls free_tlist */
4184 return line;
4187 static void pp_cleanup(int pass)
4189 if (defining) {
4190 error(ERR_NONFATAL, "end of file while still defining macro `%s'",
4191 defining->name);
4192 free_mmacro(defining);
4194 while (cstk)
4195 ctx_pop();
4196 free_macros();
4197 while (istk) {
4198 Include *i = istk;
4199 istk = istk->next;
4200 fclose(i->fp);
4201 nasm_free(i->fname);
4202 nasm_free(i);
4204 while (cstk)
4205 ctx_pop();
4206 if (pass == 0) {
4207 free_llist(predef);
4208 delete_Blocks();
4212 void pp_include_path(char *path)
4214 IncPath *i;
4216 i = nasm_malloc(sizeof(IncPath));
4217 i->path = path ? nasm_strdup(path) : NULL;
4218 i->next = NULL;
4220 if (ipath != NULL) {
4221 IncPath *j = ipath;
4222 while (j->next != NULL)
4223 j = j->next;
4224 j->next = i;
4225 } else {
4226 ipath = i;
4230 void pp_pre_include(char *fname)
4232 Token *inc, *space, *name;
4233 Line *l;
4235 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
4236 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
4237 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
4239 l = nasm_malloc(sizeof(Line));
4240 l->next = predef;
4241 l->first = inc;
4242 l->finishes = false;
4243 predef = l;
4246 void pp_pre_define(char *definition)
4248 Token *def, *space;
4249 Line *l;
4250 char *equals;
4252 equals = strchr(definition, '=');
4253 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4254 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
4255 if (equals)
4256 *equals = ' ';
4257 space->next = tokenize(definition);
4258 if (equals)
4259 *equals = '=';
4261 l = nasm_malloc(sizeof(Line));
4262 l->next = predef;
4263 l->first = def;
4264 l->finishes = false;
4265 predef = l;
4268 void pp_pre_undefine(char *definition)
4270 Token *def, *space;
4271 Line *l;
4273 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4274 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
4275 space->next = tokenize(definition);
4277 l = nasm_malloc(sizeof(Line));
4278 l->next = predef;
4279 l->first = def;
4280 l->finishes = false;
4281 predef = l;
4285 * Added by Keith Kanios:
4287 * This function is used to assist with "runtime" preprocessor
4288 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
4290 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
4291 * PASS A VALID STRING TO THIS FUNCTION!!!!!
4294 void pp_runtime(char *definition)
4296 Token *def;
4298 def = tokenize(definition);
4299 if(do_directive(def) == NO_DIRECTIVE_FOUND)
4300 free_tlist(def);
4304 void pp_extra_stdmac(const char **macros)
4306 extrastdmac = macros;
4309 static void make_tok_num(Token * tok, int64_t val)
4311 char numbuf[20];
4312 snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
4313 tok->text = nasm_strdup(numbuf);
4314 tok->type = TOK_NUMBER;
4317 Preproc nasmpp = {
4318 pp_reset,
4319 pp_getline,
4320 pp_cleanup