BR 2826669: update licensing information in README
[nasm.git] / preproc.c
blob357a1b5784377cc9c8c57ff698a803c73339197b
1 /* ----------------------------------------------------------------------- *
2 *
3 * Copyright 1996-2009 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
35 * preproc.c macro preprocessor for the Netwide Assembler
38 /* Typical flow of text through preproc
40 * pp_getline gets tokenized lines, either
42 * from a macro expansion
44 * or
45 * {
46 * read_line gets raw text from stdmacpos, or predef, or current input file
47 * tokenize converts to tokens
48 * }
50 * expand_mmac_params is used to expand %1 etc., unless a macro is being
51 * defined or a false conditional is being processed
52 * (%0, %1, %+1, %-1, %%foo
54 * do_directive checks for directives
56 * expand_smacro is used to expand single line macros
58 * expand_mmacro is used to expand multi-line macros
60 * detoken is used to convert the line back to text
63 #include "compiler.h"
65 #include <stdio.h>
66 #include <stdarg.h>
67 #include <stdlib.h>
68 #include <stddef.h>
69 #include <string.h>
70 #include <ctype.h>
71 #include <limits.h>
72 #include <inttypes.h>
74 #include "nasm.h"
75 #include "nasmlib.h"
76 #include "preproc.h"
77 #include "hashtbl.h"
78 #include "quote.h"
79 #include "stdscan.h"
80 #include "tokens.h"
81 #include "tables.h"
83 typedef struct SMacro SMacro;
84 typedef struct MMacro MMacro;
85 typedef struct Context Context;
86 typedef struct Token Token;
87 typedef struct Blocks Blocks;
88 typedef struct Line Line;
89 typedef struct Include Include;
90 typedef struct Cond Cond;
91 typedef struct IncPath IncPath;
94 * Note on the storage of both SMacro and MMacros: the hash table
95 * indexes them case-insensitively, and we then have to go through a
96 * linked list of potential case aliases (and, for MMacros, parameter
97 * ranges); this is to preserve the matching semantics of the earlier
98 * code. If the number of case aliases for a specific macro is a
99 * performance issue, you may want to reconsider your coding style.
103 * Store the definition of a single-line macro.
105 struct SMacro {
106 SMacro *next;
107 char *name;
108 bool casesense;
109 bool in_progress;
110 unsigned int nparam;
111 Token *expansion;
115 * Store the definition of a multi-line macro. This is also used to
116 * store the interiors of `%rep...%endrep' blocks, which are
117 * effectively self-re-invoking multi-line macros which simply
118 * don't have a name or bother to appear in the hash tables. %rep
119 * blocks are signified by having a NULL `name' field.
121 * In a MMacro describing a `%rep' block, the `in_progress' field
122 * isn't merely boolean, but gives the number of repeats left to
123 * run.
125 * The `next' field is used for storing MMacros in hash tables; the
126 * `next_active' field is for stacking them on istk entries.
128 * When a MMacro is being expanded, `params', `iline', `nparam',
129 * `paramlen', `rotate' and `unique' are local to the invocation.
131 struct MMacro {
132 MMacro *next;
133 char *name;
134 int nparam_min, nparam_max;
135 bool casesense;
136 bool plus; /* is the last parameter greedy? */
137 bool nolist; /* is this macro listing-inhibited? */
138 int64_t in_progress;
139 Token *dlist; /* All defaults as one list */
140 Token **defaults; /* Parameter default pointers */
141 int ndefs; /* number of default parameters */
142 Line *expansion;
144 MMacro *next_active;
145 MMacro *rep_nest; /* used for nesting %rep */
146 Token **params; /* actual parameters */
147 Token *iline; /* invocation line */
148 unsigned int nparam, rotate;
149 int *paramlen;
150 uint64_t unique;
151 int lineno; /* Current line number on expansion */
155 * The context stack is composed of a linked list of these.
157 struct Context {
158 Context *next;
159 char *name;
160 struct hash_table localmac;
161 uint32_t number;
165 * This is the internal form which we break input lines up into.
166 * Typically stored in linked lists.
168 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
169 * necessarily used as-is, but is intended to denote the number of
170 * the substituted parameter. So in the definition
172 * %define a(x,y) ( (x) & ~(y) )
174 * the token representing `x' will have its type changed to
175 * TOK_SMAC_PARAM, but the one representing `y' will be
176 * TOK_SMAC_PARAM+1.
178 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
179 * which doesn't need quotes around it. Used in the pre-include
180 * mechanism as an alternative to trying to find a sensible type of
181 * quote to use on the filename we were passed.
183 enum pp_token_type {
184 TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT, TOK_ID,
185 TOK_PREPROC_ID, TOK_STRING,
186 TOK_NUMBER, TOK_FLOAT, TOK_SMAC_END, TOK_OTHER,
187 TOK_INTERNAL_STRING,
188 TOK_PREPROC_Q, TOK_PREPROC_QQ,
189 TOK_PASTE, /* %+ */
190 TOK_INDIRECT, /* %[...] */
191 TOK_SMAC_PARAM, /* MUST BE LAST IN THE LIST!!! */
192 TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
195 struct Token {
196 Token *next;
197 char *text;
198 union {
199 SMacro *mac; /* associated macro for TOK_SMAC_END */
200 size_t len; /* scratch length field */
201 } a; /* Auxiliary data */
202 enum pp_token_type type;
206 * Multi-line macro definitions are stored as a linked list of
207 * these, which is essentially a container to allow several linked
208 * lists of Tokens.
210 * Note that in this module, linked lists are treated as stacks
211 * wherever possible. For this reason, Lines are _pushed_ on to the
212 * `expansion' field in MMacro structures, so that the linked list,
213 * if walked, would give the macro lines in reverse order; this
214 * means that we can walk the list when expanding a macro, and thus
215 * push the lines on to the `expansion' field in _istk_ in reverse
216 * order (so that when popped back off they are in the right
217 * order). It may seem cockeyed, and it relies on my design having
218 * an even number of steps in, but it works...
220 * Some of these structures, rather than being actual lines, are
221 * markers delimiting the end of the expansion of a given macro.
222 * This is for use in the cycle-tracking and %rep-handling code.
223 * Such structures have `finishes' non-NULL, and `first' NULL. All
224 * others have `finishes' NULL, but `first' may still be NULL if
225 * the line is blank.
227 struct Line {
228 Line *next;
229 MMacro *finishes;
230 Token *first;
234 * To handle an arbitrary level of file inclusion, we maintain a
235 * stack (ie linked list) of these things.
237 struct Include {
238 Include *next;
239 FILE *fp;
240 Cond *conds;
241 Line *expansion;
242 char *fname;
243 int lineno, lineinc;
244 MMacro *mstk; /* stack of active macros/reps */
248 * Include search path. This is simply a list of strings which get
249 * prepended, in turn, to the name of an include file, in an
250 * attempt to find the file if it's not in the current directory.
252 struct IncPath {
253 IncPath *next;
254 char *path;
258 * Conditional assembly: we maintain a separate stack of these for
259 * each level of file inclusion. (The only reason we keep the
260 * stacks separate is to ensure that a stray `%endif' in a file
261 * included from within the true branch of a `%if' won't terminate
262 * it and cause confusion: instead, rightly, it'll cause an error.)
264 struct Cond {
265 Cond *next;
266 int state;
268 enum {
270 * These states are for use just after %if or %elif: IF_TRUE
271 * means the condition has evaluated to truth so we are
272 * currently emitting, whereas IF_FALSE means we are not
273 * currently emitting but will start doing so if a %else comes
274 * up. In these states, all directives are admissible: %elif,
275 * %else and %endif. (And of course %if.)
277 COND_IF_TRUE, COND_IF_FALSE,
279 * These states come up after a %else: ELSE_TRUE means we're
280 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
281 * any %elif or %else will cause an error.
283 COND_ELSE_TRUE, COND_ELSE_FALSE,
285 * These states mean that we're not emitting now, and also that
286 * nothing until %endif will be emitted at all. COND_DONE is
287 * used when we've had our moment of emission
288 * and have now started seeing %elifs. COND_NEVER is used when
289 * the condition construct in question is contained within a
290 * non-emitting branch of a larger condition construct,
291 * or if there is an error.
293 COND_DONE, COND_NEVER
295 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
298 * These defines are used as the possible return values for do_directive
300 #define NO_DIRECTIVE_FOUND 0
301 #define DIRECTIVE_FOUND 1
304 * Condition codes. Note that we use c_ prefix not C_ because C_ is
305 * used in nasm.h for the "real" condition codes. At _this_ level,
306 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
307 * ones, so we need a different enum...
309 static const char * const conditions[] = {
310 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
311 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
312 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
314 enum pp_conds {
315 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
316 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
317 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
318 c_none = -1
320 static const enum pp_conds inverse_ccs[] = {
321 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
322 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,
323 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
327 * Directive names.
329 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
330 static int is_condition(enum preproc_token arg)
332 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
335 /* For TASM compatibility we need to be able to recognise TASM compatible
336 * conditional compilation directives. Using the NASM pre-processor does
337 * not work, so we look for them specifically from the following list and
338 * then jam in the equivalent NASM directive into the input stream.
341 enum {
342 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
343 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
346 static const char * const tasm_directives[] = {
347 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
348 "ifndef", "include", "local"
351 static int StackSize = 4;
352 static char *StackPointer = "ebp";
353 static int ArgOffset = 8;
354 static int LocalOffset = 0;
356 static Context *cstk;
357 static Include *istk;
358 static IncPath *ipath = NULL;
360 static efunc _error; /* Pointer to client-provided error reporting function */
361 static evalfunc evaluate;
363 static int pass; /* HACK: pass 0 = generate dependencies only */
364 static StrList **dephead, **deptail; /* Dependency list */
366 static uint64_t unique; /* unique identifier numbers */
368 static Line *predef = NULL;
369 static bool do_predef;
371 static ListGen *list;
374 * The current set of multi-line macros we have defined.
376 static struct hash_table mmacros;
379 * The current set of single-line macros we have defined.
381 static struct hash_table smacros;
384 * The multi-line macro we are currently defining, or the %rep
385 * block we are currently reading, if any.
387 static MMacro *defining;
389 static uint64_t nested_mac_count;
390 static uint64_t nested_rep_count;
393 * The number of macro parameters to allocate space for at a time.
395 #define PARAM_DELTA 16
398 * The standard macro set: defined in macros.c in the array nasm_stdmac.
399 * This gives our position in the macro set, when we're processing it.
401 static macros_t *stdmacpos;
404 * The extra standard macros that come from the object format, if
405 * any.
407 static macros_t *extrastdmac = NULL;
408 static bool any_extrastdmac;
411 * Tokens are allocated in blocks to improve speed
413 #define TOKEN_BLOCKSIZE 4096
414 static Token *freeTokens = NULL;
415 struct Blocks {
416 Blocks *next;
417 void *chunk;
420 static Blocks blocks = { NULL, NULL };
423 * Forward declarations.
425 static Token *expand_mmac_params(Token * tline);
426 static Token *expand_smacro(Token * tline);
427 static Token *expand_id(Token * tline);
428 static Context *get_ctx(const char *name, const char **namep,
429 bool all_contexts);
430 static void make_tok_num(Token * tok, int64_t val);
431 static void error(int severity, const char *fmt, ...);
432 static void error_precond(int severity, const char *fmt, ...);
433 static void *new_Block(size_t size);
434 static void delete_Blocks(void);
435 static Token *new_Token(Token * next, enum pp_token_type type,
436 const char *text, int txtlen);
437 static Token *delete_Token(Token * t);
440 * Macros for safe checking of token pointers, avoid *(NULL)
442 #define tok_type_(x,t) ((x) && (x)->type == (t))
443 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
444 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
445 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
447 /* Handle TASM specific directives, which do not contain a % in
448 * front of them. We do it here because I could not find any other
449 * place to do it for the moment, and it is a hack (ideally it would
450 * be nice to be able to use the NASM pre-processor to do it).
452 static char *check_tasm_directive(char *line)
454 int32_t i, j, k, m, len;
455 char *p = line, *oldline, oldchar;
457 /* Skip whitespace */
458 while (nasm_isspace(*p) && *p != 0)
459 p++;
461 /* Binary search for the directive name */
462 i = -1;
463 j = elements(tasm_directives);
464 len = 0;
465 while (!nasm_isspace(p[len]) && p[len] != 0)
466 len++;
467 if (len) {
468 oldchar = p[len];
469 p[len] = 0;
470 while (j - i > 1) {
471 k = (j + i) / 2;
472 m = nasm_stricmp(p, tasm_directives[k]);
473 if (m == 0) {
474 /* We have found a directive, so jam a % in front of it
475 * so that NASM will then recognise it as one if it's own.
477 p[len] = oldchar;
478 len = strlen(p);
479 oldline = line;
480 line = nasm_malloc(len + 2);
481 line[0] = '%';
482 if (k == TM_IFDIFI) {
484 * NASM does not recognise IFDIFI, so we convert
485 * it to %if 0. This is not used in NASM
486 * compatible code, but does need to parse for the
487 * TASM macro package.
489 strcpy(line + 1, "if 0");
490 } else {
491 memcpy(line + 1, p, len + 1);
493 nasm_free(oldline);
494 return line;
495 } else if (m < 0) {
496 j = k;
497 } else
498 i = k;
500 p[len] = oldchar;
502 return line;
506 * The pre-preprocessing stage... This function translates line
507 * number indications as they emerge from GNU cpp (`# lineno "file"
508 * flags') into NASM preprocessor line number indications (`%line
509 * lineno file').
511 static char *prepreproc(char *line)
513 int lineno, fnlen;
514 char *fname, *oldline;
516 if (line[0] == '#' && line[1] == ' ') {
517 oldline = line;
518 fname = oldline + 2;
519 lineno = atoi(fname);
520 fname += strspn(fname, "0123456789 ");
521 if (*fname == '"')
522 fname++;
523 fnlen = strcspn(fname, "\"");
524 line = nasm_malloc(20 + fnlen);
525 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
526 nasm_free(oldline);
528 if (tasm_compatible_mode)
529 return check_tasm_directive(line);
530 return line;
534 * Free a linked list of tokens.
536 static void free_tlist(Token * list)
538 while (list) {
539 list = delete_Token(list);
544 * Free a linked list of lines.
546 static void free_llist(Line * list)
548 Line *l;
549 while (list) {
550 l = list;
551 list = list->next;
552 free_tlist(l->first);
553 nasm_free(l);
558 * Free an MMacro
560 static void free_mmacro(MMacro * m)
562 nasm_free(m->name);
563 free_tlist(m->dlist);
564 nasm_free(m->defaults);
565 free_llist(m->expansion);
566 nasm_free(m);
570 * Free all currently defined macros, and free the hash tables
572 static void free_smacro_table(struct hash_table *smt)
574 SMacro *s;
575 const char *key;
576 struct hash_tbl_node *it = NULL;
578 while ((s = hash_iterate(smt, &it, &key)) != NULL) {
579 nasm_free((void *)key);
580 while (s) {
581 SMacro *ns = s->next;
582 nasm_free(s->name);
583 free_tlist(s->expansion);
584 nasm_free(s);
585 s = ns;
588 hash_free(smt);
591 static void free_mmacro_table(struct hash_table *mmt)
593 MMacro *m;
594 const char *key;
595 struct hash_tbl_node *it = NULL;
597 it = NULL;
598 while ((m = hash_iterate(mmt, &it, &key)) != NULL) {
599 nasm_free((void *)key);
600 while (m) {
601 MMacro *nm = m->next;
602 free_mmacro(m);
603 m = nm;
606 hash_free(mmt);
609 static void free_macros(void)
611 free_smacro_table(&smacros);
612 free_mmacro_table(&mmacros);
616 * Initialize the hash tables
618 static void init_macros(void)
620 hash_init(&smacros, HASH_LARGE);
621 hash_init(&mmacros, HASH_LARGE);
625 * Pop the context stack.
627 static void ctx_pop(void)
629 Context *c = cstk;
631 cstk = cstk->next;
632 free_smacro_table(&c->localmac);
633 nasm_free(c->name);
634 nasm_free(c);
638 * Search for a key in the hash index; adding it if necessary
639 * (in which case we initialize the data pointer to NULL.)
641 static void **
642 hash_findi_add(struct hash_table *hash, const char *str)
644 struct hash_insert hi;
645 void **r;
646 char *strx;
648 r = hash_findi(hash, str, &hi);
649 if (r)
650 return r;
652 strx = nasm_strdup(str); /* Use a more efficient allocator here? */
653 return hash_add(&hi, strx, NULL);
657 * Like hash_findi, but returns the data element rather than a pointer
658 * to it. Used only when not adding a new element, hence no third
659 * argument.
661 static void *
662 hash_findix(struct hash_table *hash, const char *str)
664 void **p;
666 p = hash_findi(hash, str, NULL);
667 return p ? *p : NULL;
670 #define BUF_DELTA 512
672 * Read a line from the top file in istk, handling multiple CR/LFs
673 * at the end of the line read, and handling spurious ^Zs. Will
674 * return lines from the standard macro set if this has not already
675 * been done.
677 static char *read_line(void)
679 char *buffer, *p, *q;
680 int bufsize, continued_count;
682 if (stdmacpos) {
683 unsigned char c;
684 const unsigned char *p = stdmacpos;
685 char *ret, *q;
686 size_t len = 0;
687 while ((c = *p++)) {
688 if (c >= 0x80)
689 len += pp_directives_len[c-0x80]+1;
690 else
691 len++;
693 ret = nasm_malloc(len+1);
694 q = ret;
695 while ((c = *stdmacpos++)) {
696 if (c >= 0x80) {
697 memcpy(q, pp_directives[c-0x80], pp_directives_len[c-0x80]);
698 q += pp_directives_len[c-0x80];
699 *q++ = ' ';
700 } else {
701 *q++ = c;
704 stdmacpos = p;
705 *q = '\0';
707 if (!*stdmacpos) {
708 /* This was the last of the standard macro chain... */
709 stdmacpos = NULL;
710 if (any_extrastdmac) {
711 stdmacpos = extrastdmac;
712 any_extrastdmac = false;
713 } else if (do_predef) {
714 Line *pd, *l;
715 Token *head, **tail, *t;
718 * Nasty hack: here we push the contents of
719 * `predef' on to the top-level expansion stack,
720 * since this is the most convenient way to
721 * implement the pre-include and pre-define
722 * features.
724 for (pd = predef; pd; pd = pd->next) {
725 head = NULL;
726 tail = &head;
727 for (t = pd->first; t; t = t->next) {
728 *tail = new_Token(NULL, t->type, t->text, 0);
729 tail = &(*tail)->next;
731 l = nasm_malloc(sizeof(Line));
732 l->next = istk->expansion;
733 l->first = head;
734 l->finishes = NULL;
735 istk->expansion = l;
737 do_predef = false;
740 return ret;
743 bufsize = BUF_DELTA;
744 buffer = nasm_malloc(BUF_DELTA);
745 p = buffer;
746 continued_count = 0;
747 while (1) {
748 q = fgets(p, bufsize - (p - buffer), istk->fp);
749 if (!q)
750 break;
751 p += strlen(p);
752 if (p > buffer && p[-1] == '\n') {
753 /* Convert backslash-CRLF line continuation sequences into
754 nothing at all (for DOS and Windows) */
755 if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
756 p -= 3;
757 *p = 0;
758 continued_count++;
760 /* Also convert backslash-LF line continuation sequences into
761 nothing at all (for Unix) */
762 else if (((p - 1) > buffer) && (p[-2] == '\\')) {
763 p -= 2;
764 *p = 0;
765 continued_count++;
766 } else {
767 break;
770 if (p - buffer > bufsize - 10) {
771 int32_t offset = p - buffer;
772 bufsize += BUF_DELTA;
773 buffer = nasm_realloc(buffer, bufsize);
774 p = buffer + offset; /* prevent stale-pointer problems */
778 if (!q && p == buffer) {
779 nasm_free(buffer);
780 return NULL;
783 src_set_linnum(src_get_linnum() + istk->lineinc +
784 (continued_count * istk->lineinc));
787 * Play safe: remove CRs as well as LFs, if any of either are
788 * present at the end of the line.
790 while (--p >= buffer && (*p == '\n' || *p == '\r'))
791 *p = '\0';
794 * Handle spurious ^Z, which may be inserted into source files
795 * by some file transfer utilities.
797 buffer[strcspn(buffer, "\032")] = '\0';
799 list->line(LIST_READ, buffer);
801 return buffer;
805 * Tokenize a line of text. This is a very simple process since we
806 * don't need to parse the value out of e.g. numeric tokens: we
807 * simply split one string into many.
809 static Token *tokenize(char *line)
811 char c, *p = line;
812 enum pp_token_type type;
813 Token *list = NULL;
814 Token *t, **tail = &list;
816 while (*line) {
817 p = line;
818 if (*p == '%') {
819 p++;
820 if (*p == '+' && !nasm_isdigit(p[1])) {
821 p++;
822 type = TOK_PASTE;
823 } else if (nasm_isdigit(*p) ||
824 ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
825 do {
826 p++;
828 while (nasm_isdigit(*p));
829 type = TOK_PREPROC_ID;
830 } else if (*p == '{') {
831 p++;
832 while (*p && *p != '}') {
833 p[-1] = *p;
834 p++;
836 p[-1] = '\0';
837 if (*p)
838 p++;
839 type = TOK_PREPROC_ID;
840 } else if (*p == '[') {
841 int lvl = 1;
842 line += 2; /* Skip the leading %[ */
843 p++;
844 while (lvl && (c = *p++)) {
845 switch (c) {
846 case ']':
847 lvl--;
848 break;
849 case '%':
850 if (*p == '[')
851 lvl++;
852 break;
853 case '\'':
854 case '\"':
855 case '`':
856 p = nasm_skip_string(p)+1;
857 break;
858 default:
859 break;
862 p--;
863 if (*p)
864 *p++ = '\0';
865 if (lvl)
866 error(ERR_NONFATAL, "unterminated %[ construct");
867 type = TOK_INDIRECT;
868 } else if (*p == '?') {
869 type = TOK_PREPROC_Q; /* %? */
870 p++;
871 if (*p == '?') {
872 type = TOK_PREPROC_QQ; /* %?? */
873 p++;
875 } else if (isidchar(*p) ||
876 ((*p == '!' || *p == '%' || *p == '$') &&
877 isidchar(p[1]))) {
878 do {
879 p++;
881 while (isidchar(*p));
882 type = TOK_PREPROC_ID;
883 } else {
884 type = TOK_OTHER;
885 if (*p == '%')
886 p++;
888 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
889 type = TOK_ID;
890 p++;
891 while (*p && isidchar(*p))
892 p++;
893 } else if (*p == '\'' || *p == '"' || *p == '`') {
895 * A string token.
897 type = TOK_STRING;
898 p = nasm_skip_string(p);
900 if (*p) {
901 p++;
902 } else {
903 error(ERR_WARNING|ERR_PASS1, "unterminated string");
904 /* Handling unterminated strings by UNV */
905 /* type = -1; */
907 } else if (p[0] == '$' && p[1] == '$') {
908 type = TOK_OTHER; /* TOKEN_BASE */
909 p += 2;
910 } else if (isnumstart(*p)) {
911 bool is_hex = false;
912 bool is_float = false;
913 bool has_e = false;
914 char c, *r;
917 * A numeric token.
920 if (*p == '$') {
921 p++;
922 is_hex = true;
925 for (;;) {
926 c = *p++;
928 if (!is_hex && (c == 'e' || c == 'E')) {
929 has_e = true;
930 if (*p == '+' || *p == '-') {
931 /* e can only be followed by +/- if it is either a
932 prefixed hex number or a floating-point number */
933 p++;
934 is_float = true;
936 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
937 is_hex = true;
938 } else if (c == 'P' || c == 'p') {
939 is_float = true;
940 if (*p == '+' || *p == '-')
941 p++;
942 } else if (isnumchar(c) || c == '_')
943 ; /* just advance */
944 else if (c == '.') {
945 /* we need to deal with consequences of the legacy
946 parser, like "1.nolist" being two tokens
947 (TOK_NUMBER, TOK_ID) here; at least give it
948 a shot for now. In the future, we probably need
949 a flex-based scanner with proper pattern matching
950 to do it as well as it can be done. Nothing in
951 the world is going to help the person who wants
952 0x123.p16 interpreted as two tokens, though. */
953 r = p;
954 while (*r == '_')
955 r++;
957 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
958 (!is_hex && (*r == 'e' || *r == 'E')) ||
959 (*r == 'p' || *r == 'P')) {
960 p = r;
961 is_float = true;
962 } else
963 break; /* Terminate the token */
964 } else
965 break;
967 p--; /* Point to first character beyond number */
969 if (p == line+1 && *line == '$') {
970 type = TOK_OTHER; /* TOKEN_HERE */
971 } else {
972 if (has_e && !is_hex) {
973 /* 1e13 is floating-point, but 1e13h is not */
974 is_float = true;
977 type = is_float ? TOK_FLOAT : TOK_NUMBER;
979 } else if (nasm_isspace(*p)) {
980 type = TOK_WHITESPACE;
981 p++;
982 while (*p && nasm_isspace(*p))
983 p++;
985 * Whitespace just before end-of-line is discarded by
986 * pretending it's a comment; whitespace just before a
987 * comment gets lumped into the comment.
989 if (!*p || *p == ';') {
990 type = TOK_COMMENT;
991 while (*p)
992 p++;
994 } else if (*p == ';') {
995 type = TOK_COMMENT;
996 while (*p)
997 p++;
998 } else {
1000 * Anything else is an operator of some kind. We check
1001 * for all the double-character operators (>>, <<, //,
1002 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1003 * else is a single-character operator.
1005 type = TOK_OTHER;
1006 if ((p[0] == '>' && p[1] == '>') ||
1007 (p[0] == '<' && p[1] == '<') ||
1008 (p[0] == '/' && p[1] == '/') ||
1009 (p[0] == '<' && p[1] == '=') ||
1010 (p[0] == '>' && p[1] == '=') ||
1011 (p[0] == '=' && p[1] == '=') ||
1012 (p[0] == '!' && p[1] == '=') ||
1013 (p[0] == '<' && p[1] == '>') ||
1014 (p[0] == '&' && p[1] == '&') ||
1015 (p[0] == '|' && p[1] == '|') ||
1016 (p[0] == '^' && p[1] == '^')) {
1017 p++;
1019 p++;
1022 /* Handling unterminated string by UNV */
1023 /*if (type == -1)
1025 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1026 t->text[p-line] = *line;
1027 tail = &t->next;
1029 else */
1030 if (type != TOK_COMMENT) {
1031 *tail = t = new_Token(NULL, type, line, p - line);
1032 tail = &t->next;
1034 line = p;
1036 return list;
1040 * this function allocates a new managed block of memory and
1041 * returns a pointer to the block. The managed blocks are
1042 * deleted only all at once by the delete_Blocks function.
1044 static void *new_Block(size_t size)
1046 Blocks *b = &blocks;
1048 /* first, get to the end of the linked list */
1049 while (b->next)
1050 b = b->next;
1051 /* now allocate the requested chunk */
1052 b->chunk = nasm_malloc(size);
1054 /* now allocate a new block for the next request */
1055 b->next = nasm_malloc(sizeof(Blocks));
1056 /* and initialize the contents of the new block */
1057 b->next->next = NULL;
1058 b->next->chunk = NULL;
1059 return b->chunk;
1063 * this function deletes all managed blocks of memory
1065 static void delete_Blocks(void)
1067 Blocks *a, *b = &blocks;
1070 * keep in mind that the first block, pointed to by blocks
1071 * is a static and not dynamically allocated, so we don't
1072 * free it.
1074 while (b) {
1075 if (b->chunk)
1076 nasm_free(b->chunk);
1077 a = b;
1078 b = b->next;
1079 if (a != &blocks)
1080 nasm_free(a);
1085 * this function creates a new Token and passes a pointer to it
1086 * back to the caller. It sets the type and text elements, and
1087 * also the a.mac and next elements to NULL.
1089 static Token *new_Token(Token * next, enum pp_token_type type,
1090 const char *text, int txtlen)
1092 Token *t;
1093 int i;
1095 if (freeTokens == NULL) {
1096 freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
1097 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
1098 freeTokens[i].next = &freeTokens[i + 1];
1099 freeTokens[i].next = NULL;
1101 t = freeTokens;
1102 freeTokens = t->next;
1103 t->next = next;
1104 t->a.mac = NULL;
1105 t->type = type;
1106 if (type == TOK_WHITESPACE || text == NULL) {
1107 t->text = NULL;
1108 } else {
1109 if (txtlen == 0)
1110 txtlen = strlen(text);
1111 t->text = nasm_malloc(txtlen+1);
1112 memcpy(t->text, text, txtlen);
1113 t->text[txtlen] = '\0';
1115 return t;
1118 static Token *delete_Token(Token * t)
1120 Token *next = t->next;
1121 nasm_free(t->text);
1122 t->next = freeTokens;
1123 freeTokens = t;
1124 return next;
1128 * Convert a line of tokens back into text.
1129 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1130 * will be transformed into ..@ctxnum.xxx
1132 static char *detoken(Token * tlist, bool expand_locals)
1134 Token *t;
1135 int len;
1136 char *line, *p;
1137 const char *q;
1139 len = 0;
1140 for (t = tlist; t; t = t->next) {
1141 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
1142 char *p = getenv(t->text + 2);
1143 nasm_free(t->text);
1144 if (p)
1145 t->text = nasm_strdup(p);
1146 else
1147 t->text = NULL;
1149 /* Expand local macros here and not during preprocessing */
1150 if (expand_locals &&
1151 t->type == TOK_PREPROC_ID && t->text &&
1152 t->text[0] == '%' && t->text[1] == '$') {
1153 const char *q;
1154 char *p;
1155 Context *ctx = get_ctx(t->text, &q, false);
1156 if (ctx) {
1157 char buffer[40];
1158 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
1159 p = nasm_strcat(buffer, q);
1160 nasm_free(t->text);
1161 t->text = p;
1164 if (t->type == TOK_WHITESPACE) {
1165 len++;
1166 } else if (t->text) {
1167 len += strlen(t->text);
1170 p = line = nasm_malloc(len + 1);
1171 for (t = tlist; t; t = t->next) {
1172 if (t->type == TOK_WHITESPACE) {
1173 *p++ = ' ';
1174 } else if (t->text) {
1175 q = t->text;
1176 while (*q)
1177 *p++ = *q++;
1180 *p = '\0';
1181 return line;
1185 * A scanner, suitable for use by the expression evaluator, which
1186 * operates on a line of Tokens. Expects a pointer to a pointer to
1187 * the first token in the line to be passed in as its private_data
1188 * field.
1190 * FIX: This really needs to be unified with stdscan.
1192 static int ppscan(void *private_data, struct tokenval *tokval)
1194 Token **tlineptr = private_data;
1195 Token *tline;
1196 char ourcopy[MAX_KEYWORD+1], *p, *r, *s;
1198 do {
1199 tline = *tlineptr;
1200 *tlineptr = tline ? tline->next : NULL;
1202 while (tline && (tline->type == TOK_WHITESPACE ||
1203 tline->type == TOK_COMMENT));
1205 if (!tline)
1206 return tokval->t_type = TOKEN_EOS;
1208 tokval->t_charptr = tline->text;
1210 if (tline->text[0] == '$' && !tline->text[1])
1211 return tokval->t_type = TOKEN_HERE;
1212 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
1213 return tokval->t_type = TOKEN_BASE;
1215 if (tline->type == TOK_ID) {
1216 p = tokval->t_charptr = tline->text;
1217 if (p[0] == '$') {
1218 tokval->t_charptr++;
1219 return tokval->t_type = TOKEN_ID;
1222 for (r = p, s = ourcopy; *r; r++) {
1223 if (r >= p+MAX_KEYWORD)
1224 return tokval->t_type = TOKEN_ID; /* Not a keyword */
1225 *s++ = nasm_tolower(*r);
1227 *s = '\0';
1228 /* right, so we have an identifier sitting in temp storage. now,
1229 * is it actually a register or instruction name, or what? */
1230 return nasm_token_hash(ourcopy, tokval);
1233 if (tline->type == TOK_NUMBER) {
1234 bool rn_error;
1235 tokval->t_integer = readnum(tline->text, &rn_error);
1236 tokval->t_charptr = tline->text;
1237 if (rn_error)
1238 return tokval->t_type = TOKEN_ERRNUM;
1239 else
1240 return tokval->t_type = TOKEN_NUM;
1243 if (tline->type == TOK_FLOAT) {
1244 return tokval->t_type = TOKEN_FLOAT;
1247 if (tline->type == TOK_STRING) {
1248 char bq, *ep;
1250 bq = tline->text[0];
1251 tokval->t_charptr = tline->text;
1252 tokval->t_inttwo = nasm_unquote(tline->text, &ep);
1254 if (ep[0] != bq || ep[1] != '\0')
1255 return tokval->t_type = TOKEN_ERRSTR;
1256 else
1257 return tokval->t_type = TOKEN_STR;
1260 if (tline->type == TOK_OTHER) {
1261 if (!strcmp(tline->text, "<<"))
1262 return tokval->t_type = TOKEN_SHL;
1263 if (!strcmp(tline->text, ">>"))
1264 return tokval->t_type = TOKEN_SHR;
1265 if (!strcmp(tline->text, "//"))
1266 return tokval->t_type = TOKEN_SDIV;
1267 if (!strcmp(tline->text, "%%"))
1268 return tokval->t_type = TOKEN_SMOD;
1269 if (!strcmp(tline->text, "=="))
1270 return tokval->t_type = TOKEN_EQ;
1271 if (!strcmp(tline->text, "<>"))
1272 return tokval->t_type = TOKEN_NE;
1273 if (!strcmp(tline->text, "!="))
1274 return tokval->t_type = TOKEN_NE;
1275 if (!strcmp(tline->text, "<="))
1276 return tokval->t_type = TOKEN_LE;
1277 if (!strcmp(tline->text, ">="))
1278 return tokval->t_type = TOKEN_GE;
1279 if (!strcmp(tline->text, "&&"))
1280 return tokval->t_type = TOKEN_DBL_AND;
1281 if (!strcmp(tline->text, "^^"))
1282 return tokval->t_type = TOKEN_DBL_XOR;
1283 if (!strcmp(tline->text, "||"))
1284 return tokval->t_type = TOKEN_DBL_OR;
1288 * We have no other options: just return the first character of
1289 * the token text.
1291 return tokval->t_type = tline->text[0];
1295 * Compare a string to the name of an existing macro; this is a
1296 * simple wrapper which calls either strcmp or nasm_stricmp
1297 * depending on the value of the `casesense' parameter.
1299 static int mstrcmp(const char *p, const char *q, bool casesense)
1301 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
1305 * Compare a string to the name of an existing macro; this is a
1306 * simple wrapper which calls either strcmp or nasm_stricmp
1307 * depending on the value of the `casesense' parameter.
1309 static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
1311 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
1315 * Return the Context structure associated with a %$ token. Return
1316 * NULL, having _already_ reported an error condition, if the
1317 * context stack isn't deep enough for the supplied number of $
1318 * signs.
1319 * If all_contexts == true, contexts that enclose current are
1320 * also scanned for such smacro, until it is found; if not -
1321 * only the context that directly results from the number of $'s
1322 * in variable's name.
1324 * If "namep" is non-NULL, set it to the pointer to the macro name
1325 * tail, i.e. the part beyond %$...
1327 static Context *get_ctx(const char *name, const char **namep,
1328 bool all_contexts)
1330 Context *ctx;
1331 SMacro *m;
1332 int i;
1334 if (namep)
1335 *namep = name;
1337 if (!name || name[0] != '%' || name[1] != '$')
1338 return NULL;
1340 if (!cstk) {
1341 error(ERR_NONFATAL, "`%s': context stack is empty", name);
1342 return NULL;
1345 name += 2;
1346 ctx = cstk;
1347 i = 0;
1348 while (ctx && *name == '$') {
1349 name++;
1350 i++;
1351 ctx = ctx->next;
1353 if (!ctx) {
1354 error(ERR_NONFATAL, "`%s': context stack is only"
1355 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
1356 return NULL;
1359 if (namep)
1360 *namep = name;
1362 if (!all_contexts)
1363 return ctx;
1365 do {
1366 /* Search for this smacro in found context */
1367 m = hash_findix(&ctx->localmac, name);
1368 while (m) {
1369 if (!mstrcmp(m->name, name, m->casesense))
1370 return ctx;
1371 m = m->next;
1373 ctx = ctx->next;
1375 while (ctx);
1376 return NULL;
1380 * Check to see if a file is already in a string list
1382 static bool in_list(const StrList *list, const char *str)
1384 while (list) {
1385 if (!strcmp(list->str, str))
1386 return true;
1387 list = list->next;
1389 return false;
1393 * Open an include file. This routine must always return a valid
1394 * file pointer if it returns - it's responsible for throwing an
1395 * ERR_FATAL and bombing out completely if not. It should also try
1396 * the include path one by one until it finds the file or reaches
1397 * the end of the path.
1399 static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail,
1400 bool missing_ok)
1402 FILE *fp;
1403 char *prefix = "";
1404 IncPath *ip = ipath;
1405 int len = strlen(file);
1406 size_t prefix_len = 0;
1407 StrList *sl;
1409 while (1) {
1410 sl = nasm_malloc(prefix_len+len+1+sizeof sl->next);
1411 memcpy(sl->str, prefix, prefix_len);
1412 memcpy(sl->str+prefix_len, file, len+1);
1413 fp = fopen(sl->str, "r");
1414 if (fp && dhead && !in_list(*dhead, sl->str)) {
1415 sl->next = NULL;
1416 **dtail = sl;
1417 *dtail = &sl->next;
1418 } else {
1419 nasm_free(sl);
1421 if (fp)
1422 return fp;
1423 if (!ip) {
1424 if (!missing_ok)
1425 break;
1426 prefix = NULL;
1427 } else {
1428 prefix = ip->path;
1429 ip = ip->next;
1431 if (prefix) {
1432 prefix_len = strlen(prefix);
1433 } else {
1434 /* -MG given and file not found */
1435 if (dhead && !in_list(*dhead, file)) {
1436 sl = nasm_malloc(len+1+sizeof sl->next);
1437 sl->next = NULL;
1438 strcpy(sl->str, file);
1439 **dtail = sl;
1440 *dtail = &sl->next;
1442 return NULL;
1446 error(ERR_FATAL, "unable to open include file `%s'", file);
1447 return NULL; /* never reached - placate compilers */
1451 * Determine if we should warn on defining a single-line macro of
1452 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1453 * return true if _any_ single-line macro of that name is defined.
1454 * Otherwise, will return true if a single-line macro with either
1455 * `nparam' or no parameters is defined.
1457 * If a macro with precisely the right number of parameters is
1458 * defined, or nparam is -1, the address of the definition structure
1459 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1460 * is NULL, no action will be taken regarding its contents, and no
1461 * error will occur.
1463 * Note that this is also called with nparam zero to resolve
1464 * `ifdef'.
1466 * If you already know which context macro belongs to, you can pass
1467 * the context pointer as first parameter; if you won't but name begins
1468 * with %$ the context will be automatically computed. If all_contexts
1469 * is true, macro will be searched in outer contexts as well.
1471 static bool
1472 smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
1473 bool nocase)
1475 struct hash_table *smtbl;
1476 SMacro *m;
1478 if (ctx) {
1479 smtbl = &ctx->localmac;
1480 } else if (name[0] == '%' && name[1] == '$') {
1481 if (cstk)
1482 ctx = get_ctx(name, &name, false);
1483 if (!ctx)
1484 return false; /* got to return _something_ */
1485 smtbl = &ctx->localmac;
1486 } else {
1487 smtbl = &smacros;
1489 m = (SMacro *) hash_findix(smtbl, name);
1491 while (m) {
1492 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
1493 (nparam <= 0 || m->nparam == 0 || nparam == (int) m->nparam)) {
1494 if (defn) {
1495 if (nparam == (int) m->nparam || nparam == -1)
1496 *defn = m;
1497 else
1498 *defn = NULL;
1500 return true;
1502 m = m->next;
1505 return false;
1509 * Count and mark off the parameters in a multi-line macro call.
1510 * This is called both from within the multi-line macro expansion
1511 * code, and also to mark off the default parameters when provided
1512 * in a %macro definition line.
1514 static void count_mmac_params(Token * t, int *nparam, Token *** params)
1516 int paramsize, brace;
1518 *nparam = paramsize = 0;
1519 *params = NULL;
1520 while (t) {
1521 /* +1: we need space for the final NULL */
1522 if (*nparam+1 >= paramsize) {
1523 paramsize += PARAM_DELTA;
1524 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1526 skip_white_(t);
1527 brace = false;
1528 if (tok_is_(t, "{"))
1529 brace = true;
1530 (*params)[(*nparam)++] = t;
1531 while (tok_isnt_(t, brace ? "}" : ","))
1532 t = t->next;
1533 if (t) { /* got a comma/brace */
1534 t = t->next;
1535 if (brace) {
1537 * Now we've found the closing brace, look further
1538 * for the comma.
1540 skip_white_(t);
1541 if (tok_isnt_(t, ",")) {
1542 error(ERR_NONFATAL,
1543 "braces do not enclose all of macro parameter");
1544 while (tok_isnt_(t, ","))
1545 t = t->next;
1547 if (t)
1548 t = t->next; /* eat the comma */
1555 * Determine whether one of the various `if' conditions is true or
1556 * not.
1558 * We must free the tline we get passed.
1560 static bool if_condition(Token * tline, enum preproc_token ct)
1562 enum pp_conditional i = PP_COND(ct);
1563 bool j;
1564 Token *t, *tt, **tptr, *origline;
1565 struct tokenval tokval;
1566 expr *evalresult;
1567 enum pp_token_type needtype;
1569 origline = tline;
1571 switch (i) {
1572 case PPC_IFCTX:
1573 j = false; /* have we matched yet? */
1574 while (true) {
1575 skip_white_(tline);
1576 if (!tline)
1577 break;
1578 if (tline->type != TOK_ID) {
1579 error(ERR_NONFATAL,
1580 "`%s' expects context identifiers", pp_directives[ct]);
1581 free_tlist(origline);
1582 return -1;
1584 if (cstk && cstk->name && !nasm_stricmp(tline->text, cstk->name))
1585 j = true;
1586 tline = tline->next;
1588 break;
1590 case PPC_IFDEF:
1591 j = false; /* have we matched yet? */
1592 while (tline) {
1593 skip_white_(tline);
1594 if (!tline || (tline->type != TOK_ID &&
1595 (tline->type != TOK_PREPROC_ID ||
1596 tline->text[1] != '$'))) {
1597 error(ERR_NONFATAL,
1598 "`%s' expects macro identifiers", pp_directives[ct]);
1599 goto fail;
1601 if (smacro_defined(NULL, tline->text, 0, NULL, true))
1602 j = true;
1603 tline = tline->next;
1605 break;
1607 case PPC_IFIDN:
1608 case PPC_IFIDNI:
1609 tline = expand_smacro(tline);
1610 t = tt = tline;
1611 while (tok_isnt_(tt, ","))
1612 tt = tt->next;
1613 if (!tt) {
1614 error(ERR_NONFATAL,
1615 "`%s' expects two comma-separated arguments",
1616 pp_directives[ct]);
1617 goto fail;
1619 tt = tt->next;
1620 j = true; /* assume equality unless proved not */
1621 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1622 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1623 error(ERR_NONFATAL, "`%s': more than one comma on line",
1624 pp_directives[ct]);
1625 goto fail;
1627 if (t->type == TOK_WHITESPACE) {
1628 t = t->next;
1629 continue;
1631 if (tt->type == TOK_WHITESPACE) {
1632 tt = tt->next;
1633 continue;
1635 if (tt->type != t->type) {
1636 j = false; /* found mismatching tokens */
1637 break;
1639 /* When comparing strings, need to unquote them first */
1640 if (t->type == TOK_STRING) {
1641 size_t l1 = nasm_unquote(t->text, NULL);
1642 size_t l2 = nasm_unquote(tt->text, NULL);
1644 if (l1 != l2) {
1645 j = false;
1646 break;
1648 if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) {
1649 j = false;
1650 break;
1652 } else if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
1653 j = false; /* found mismatching tokens */
1654 break;
1657 t = t->next;
1658 tt = tt->next;
1660 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
1661 j = false; /* trailing gunk on one end or other */
1662 break;
1664 case PPC_IFMACRO:
1666 bool found = false;
1667 MMacro searching, *mmac;
1669 skip_white_(tline);
1670 tline = expand_id(tline);
1671 if (!tok_type_(tline, TOK_ID)) {
1672 error(ERR_NONFATAL,
1673 "`%s' expects a macro name", pp_directives[ct]);
1674 goto fail;
1676 searching.name = nasm_strdup(tline->text);
1677 searching.casesense = true;
1678 searching.plus = false;
1679 searching.nolist = false;
1680 searching.in_progress = 0;
1681 searching.rep_nest = NULL;
1682 searching.nparam_min = 0;
1683 searching.nparam_max = INT_MAX;
1684 tline = expand_smacro(tline->next);
1685 skip_white_(tline);
1686 if (!tline) {
1687 } else if (!tok_type_(tline, TOK_NUMBER)) {
1688 error(ERR_NONFATAL,
1689 "`%s' expects a parameter count or nothing",
1690 pp_directives[ct]);
1691 } else {
1692 searching.nparam_min = searching.nparam_max =
1693 readnum(tline->text, &j);
1694 if (j)
1695 error(ERR_NONFATAL,
1696 "unable to parse parameter count `%s'",
1697 tline->text);
1699 if (tline && tok_is_(tline->next, "-")) {
1700 tline = tline->next->next;
1701 if (tok_is_(tline, "*"))
1702 searching.nparam_max = INT_MAX;
1703 else if (!tok_type_(tline, TOK_NUMBER))
1704 error(ERR_NONFATAL,
1705 "`%s' expects a parameter count after `-'",
1706 pp_directives[ct]);
1707 else {
1708 searching.nparam_max = readnum(tline->text, &j);
1709 if (j)
1710 error(ERR_NONFATAL,
1711 "unable to parse parameter count `%s'",
1712 tline->text);
1713 if (searching.nparam_min > searching.nparam_max)
1714 error(ERR_NONFATAL,
1715 "minimum parameter count exceeds maximum");
1718 if (tline && tok_is_(tline->next, "+")) {
1719 tline = tline->next;
1720 searching.plus = true;
1722 mmac = (MMacro *) hash_findix(&mmacros, searching.name);
1723 while (mmac) {
1724 if (!strcmp(mmac->name, searching.name) &&
1725 (mmac->nparam_min <= searching.nparam_max
1726 || searching.plus)
1727 && (searching.nparam_min <= mmac->nparam_max
1728 || mmac->plus)) {
1729 found = true;
1730 break;
1732 mmac = mmac->next;
1734 if(tline && tline->next)
1735 error(ERR_WARNING|ERR_PASS1,
1736 "trailing garbage after %%ifmacro ignored");
1737 nasm_free(searching.name);
1738 j = found;
1739 break;
1742 case PPC_IFID:
1743 needtype = TOK_ID;
1744 goto iftype;
1745 case PPC_IFNUM:
1746 needtype = TOK_NUMBER;
1747 goto iftype;
1748 case PPC_IFSTR:
1749 needtype = TOK_STRING;
1750 goto iftype;
1752 iftype:
1753 t = tline = expand_smacro(tline);
1755 while (tok_type_(t, TOK_WHITESPACE) ||
1756 (needtype == TOK_NUMBER &&
1757 tok_type_(t, TOK_OTHER) &&
1758 (t->text[0] == '-' || t->text[0] == '+') &&
1759 !t->text[1]))
1760 t = t->next;
1762 j = tok_type_(t, needtype);
1763 break;
1765 case PPC_IFTOKEN:
1766 t = tline = expand_smacro(tline);
1767 while (tok_type_(t, TOK_WHITESPACE))
1768 t = t->next;
1770 j = false;
1771 if (t) {
1772 t = t->next; /* Skip the actual token */
1773 while (tok_type_(t, TOK_WHITESPACE))
1774 t = t->next;
1775 j = !t; /* Should be nothing left */
1777 break;
1779 case PPC_IFEMPTY:
1780 t = tline = expand_smacro(tline);
1781 while (tok_type_(t, TOK_WHITESPACE))
1782 t = t->next;
1784 j = !t; /* Should be empty */
1785 break;
1787 case PPC_IF:
1788 t = tline = expand_smacro(tline);
1789 tptr = &t;
1790 tokval.t_type = TOKEN_INVALID;
1791 evalresult = evaluate(ppscan, tptr, &tokval,
1792 NULL, pass | CRITICAL, error, NULL);
1793 if (!evalresult)
1794 return -1;
1795 if (tokval.t_type)
1796 error(ERR_WARNING|ERR_PASS1,
1797 "trailing garbage after expression ignored");
1798 if (!is_simple(evalresult)) {
1799 error(ERR_NONFATAL,
1800 "non-constant value given to `%s'", pp_directives[ct]);
1801 goto fail;
1803 j = reloc_value(evalresult) != 0;
1804 break;
1806 default:
1807 error(ERR_FATAL,
1808 "preprocessor directive `%s' not yet implemented",
1809 pp_directives[ct]);
1810 goto fail;
1813 free_tlist(origline);
1814 return j ^ PP_NEGATIVE(ct);
1816 fail:
1817 free_tlist(origline);
1818 return -1;
1822 * Common code for defining an smacro
1824 static bool define_smacro(Context *ctx, const char *mname, bool casesense,
1825 int nparam, Token *expansion)
1827 SMacro *smac, **smhead;
1828 struct hash_table *smtbl;
1830 if (smacro_defined(ctx, mname, nparam, &smac, casesense)) {
1831 if (!smac) {
1832 error(ERR_WARNING|ERR_PASS1,
1833 "single-line macro `%s' defined both with and"
1834 " without parameters", mname);
1836 /* Some instances of the old code considered this a failure,
1837 some others didn't. What is the right thing to do here? */
1838 free_tlist(expansion);
1839 return false; /* Failure */
1840 } else {
1842 * We're redefining, so we have to take over an
1843 * existing SMacro structure. This means freeing
1844 * what was already in it.
1846 nasm_free(smac->name);
1847 free_tlist(smac->expansion);
1849 } else {
1850 smtbl = ctx ? &ctx->localmac : &smacros;
1851 smhead = (SMacro **) hash_findi_add(smtbl, mname);
1852 smac = nasm_malloc(sizeof(SMacro));
1853 smac->next = *smhead;
1854 *smhead = smac;
1856 smac->name = nasm_strdup(mname);
1857 smac->casesense = casesense;
1858 smac->nparam = nparam;
1859 smac->expansion = expansion;
1860 smac->in_progress = false;
1861 return true; /* Success */
1865 * Undefine an smacro
1867 static void undef_smacro(Context *ctx, const char *mname)
1869 SMacro **smhead, *s, **sp;
1870 struct hash_table *smtbl;
1872 smtbl = ctx ? &ctx->localmac : &smacros;
1873 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
1875 if (smhead) {
1877 * We now have a macro name... go hunt for it.
1879 sp = smhead;
1880 while ((s = *sp) != NULL) {
1881 if (!mstrcmp(s->name, mname, s->casesense)) {
1882 *sp = s->next;
1883 nasm_free(s->name);
1884 free_tlist(s->expansion);
1885 nasm_free(s);
1886 } else {
1887 sp = &s->next;
1894 * Parse a mmacro specification.
1896 static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
1898 bool err;
1900 tline = tline->next;
1901 skip_white_(tline);
1902 tline = expand_id(tline);
1903 if (!tok_type_(tline, TOK_ID)) {
1904 error(ERR_NONFATAL, "`%s' expects a macro name", directive);
1905 return false;
1908 def->name = nasm_strdup(tline->text);
1909 def->plus = false;
1910 def->nolist = false;
1911 def->in_progress = 0;
1912 def->rep_nest = NULL;
1913 def->nparam_min = 0;
1914 def->nparam_max = 0;
1916 tline = expand_smacro(tline->next);
1917 skip_white_(tline);
1918 if (!tok_type_(tline, TOK_NUMBER)) {
1919 error(ERR_NONFATAL, "`%s' expects a parameter count", directive);
1920 } else {
1921 def->nparam_min = def->nparam_max =
1922 readnum(tline->text, &err);
1923 if (err)
1924 error(ERR_NONFATAL,
1925 "unable to parse parameter count `%s'", tline->text);
1927 if (tline && tok_is_(tline->next, "-")) {
1928 tline = tline->next->next;
1929 if (tok_is_(tline, "*")) {
1930 def->nparam_max = INT_MAX;
1931 } else if (!tok_type_(tline, TOK_NUMBER)) {
1932 error(ERR_NONFATAL,
1933 "`%s' expects a parameter count after `-'", directive);
1934 } else {
1935 def->nparam_max = readnum(tline->text, &err);
1936 if (err) {
1937 error(ERR_NONFATAL, "unable to parse parameter count `%s'",
1938 tline->text);
1940 if (def->nparam_min > def->nparam_max) {
1941 error(ERR_NONFATAL, "minimum parameter count exceeds maximum");
1945 if (tline && tok_is_(tline->next, "+")) {
1946 tline = tline->next;
1947 def->plus = true;
1949 if (tline && tok_type_(tline->next, TOK_ID) &&
1950 !nasm_stricmp(tline->next->text, ".nolist")) {
1951 tline = tline->next;
1952 def->nolist = true;
1956 * Handle default parameters.
1958 if (tline && tline->next) {
1959 def->dlist = tline->next;
1960 tline->next = NULL;
1961 count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
1962 } else {
1963 def->dlist = NULL;
1964 def->defaults = NULL;
1966 def->expansion = NULL;
1968 if(def->defaults &&
1969 def->ndefs > def->nparam_max - def->nparam_min &&
1970 !def->plus)
1971 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MDP,
1972 "too many default macro parameters");
1974 return true;
1979 * Decode a size directive
1981 static int parse_size(const char *str) {
1982 static const char *size_names[] =
1983 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
1984 static const int sizes[] =
1985 { 0, 1, 4, 16, 8, 10, 2, 32 };
1987 return sizes[bsii(str, size_names, elements(size_names))+1];
1991 * find and process preprocessor directive in passed line
1992 * Find out if a line contains a preprocessor directive, and deal
1993 * with it if so.
1995 * If a directive _is_ found, it is the responsibility of this routine
1996 * (and not the caller) to free_tlist() the line.
1998 * @param tline a pointer to the current tokeninzed line linked list
1999 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2002 static int do_directive(Token * tline)
2004 enum preproc_token i;
2005 int j;
2006 bool err;
2007 int nparam;
2008 bool nolist;
2009 bool casesense;
2010 int k, m;
2011 int offset;
2012 char *p, *pp;
2013 const char *mname;
2014 Include *inc;
2015 Context *ctx;
2016 Cond *cond;
2017 MMacro *mmac, **mmhead;
2018 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
2019 Line *l;
2020 struct tokenval tokval;
2021 expr *evalresult;
2022 MMacro *tmp_defining; /* Used when manipulating rep_nest */
2023 int64_t count;
2024 size_t len;
2025 int severity;
2027 origline = tline;
2029 skip_white_(tline);
2030 if (!tline || !tok_type_(tline, TOK_PREPROC_ID) ||
2031 (tline->text[1] == '%' || tline->text[1] == '$'
2032 || tline->text[1] == '!'))
2033 return NO_DIRECTIVE_FOUND;
2035 i = pp_token_hash(tline->text);
2038 * If we're in a non-emitting branch of a condition construct,
2039 * or walking to the end of an already terminated %rep block,
2040 * we should ignore all directives except for condition
2041 * directives.
2043 if (((istk->conds && !emitting(istk->conds->state)) ||
2044 (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
2045 return NO_DIRECTIVE_FOUND;
2049 * If we're defining a macro or reading a %rep block, we should
2050 * ignore all directives except for %macro/%imacro (which nest),
2051 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2052 * If we're in a %rep block, another %rep nests, so should be let through.
2054 if (defining && i != PP_MACRO && i != PP_IMACRO &&
2055 i != PP_ENDMACRO && i != PP_ENDM &&
2056 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
2057 return NO_DIRECTIVE_FOUND;
2060 if (defining) {
2061 if (i == PP_MACRO || i == PP_IMACRO) {
2062 nested_mac_count++;
2063 return NO_DIRECTIVE_FOUND;
2064 } else if (nested_mac_count > 0) {
2065 if (i == PP_ENDMACRO) {
2066 nested_mac_count--;
2067 return NO_DIRECTIVE_FOUND;
2070 if (!defining->name) {
2071 if (i == PP_REP) {
2072 nested_rep_count++;
2073 return NO_DIRECTIVE_FOUND;
2074 } else if (nested_rep_count > 0) {
2075 if (i == PP_ENDREP) {
2076 nested_rep_count--;
2077 return NO_DIRECTIVE_FOUND;
2083 switch (i) {
2084 case PP_INVALID:
2085 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
2086 tline->text);
2087 return NO_DIRECTIVE_FOUND; /* didn't get it */
2089 case PP_STACKSIZE:
2090 /* Directive to tell NASM what the default stack size is. The
2091 * default is for a 16-bit stack, and this can be overriden with
2092 * %stacksize large.
2093 * the following form:
2095 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2097 tline = tline->next;
2098 if (tline && tline->type == TOK_WHITESPACE)
2099 tline = tline->next;
2100 if (!tline || tline->type != TOK_ID) {
2101 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
2102 free_tlist(origline);
2103 return DIRECTIVE_FOUND;
2105 if (nasm_stricmp(tline->text, "flat") == 0) {
2106 /* All subsequent ARG directives are for a 32-bit stack */
2107 StackSize = 4;
2108 StackPointer = "ebp";
2109 ArgOffset = 8;
2110 LocalOffset = 0;
2111 } else if (nasm_stricmp(tline->text, "flat64") == 0) {
2112 /* All subsequent ARG directives are for a 64-bit stack */
2113 StackSize = 8;
2114 StackPointer = "rbp";
2115 ArgOffset = 8;
2116 LocalOffset = 0;
2117 } else if (nasm_stricmp(tline->text, "large") == 0) {
2118 /* All subsequent ARG directives are for a 16-bit stack,
2119 * far function call.
2121 StackSize = 2;
2122 StackPointer = "bp";
2123 ArgOffset = 4;
2124 LocalOffset = 0;
2125 } else if (nasm_stricmp(tline->text, "small") == 0) {
2126 /* All subsequent ARG directives are for a 16-bit stack,
2127 * far function call. We don't support near functions.
2129 StackSize = 2;
2130 StackPointer = "bp";
2131 ArgOffset = 6;
2132 LocalOffset = 0;
2133 } else {
2134 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
2135 free_tlist(origline);
2136 return DIRECTIVE_FOUND;
2138 free_tlist(origline);
2139 return DIRECTIVE_FOUND;
2141 case PP_ARG:
2142 /* TASM like ARG directive to define arguments to functions, in
2143 * the following form:
2145 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2147 offset = ArgOffset;
2148 do {
2149 char *arg, directive[256];
2150 int size = StackSize;
2152 /* Find the argument name */
2153 tline = tline->next;
2154 if (tline && tline->type == TOK_WHITESPACE)
2155 tline = tline->next;
2156 if (!tline || tline->type != TOK_ID) {
2157 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
2158 free_tlist(origline);
2159 return DIRECTIVE_FOUND;
2161 arg = tline->text;
2163 /* Find the argument size type */
2164 tline = tline->next;
2165 if (!tline || tline->type != TOK_OTHER
2166 || tline->text[0] != ':') {
2167 error(ERR_NONFATAL,
2168 "Syntax error processing `%%arg' directive");
2169 free_tlist(origline);
2170 return DIRECTIVE_FOUND;
2172 tline = tline->next;
2173 if (!tline || tline->type != TOK_ID) {
2174 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
2175 free_tlist(origline);
2176 return DIRECTIVE_FOUND;
2179 /* Allow macro expansion of type parameter */
2180 tt = tokenize(tline->text);
2181 tt = expand_smacro(tt);
2182 size = parse_size(tt->text);
2183 if (!size) {
2184 error(ERR_NONFATAL,
2185 "Invalid size type for `%%arg' missing directive");
2186 free_tlist(tt);
2187 free_tlist(origline);
2188 return DIRECTIVE_FOUND;
2190 free_tlist(tt);
2192 /* Round up to even stack slots */
2193 size = (size+StackSize-1) & ~(StackSize-1);
2195 /* Now define the macro for the argument */
2196 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
2197 arg, StackPointer, offset);
2198 do_directive(tokenize(directive));
2199 offset += size;
2201 /* Move to the next argument in the list */
2202 tline = tline->next;
2203 if (tline && tline->type == TOK_WHITESPACE)
2204 tline = tline->next;
2205 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2206 ArgOffset = offset;
2207 free_tlist(origline);
2208 return DIRECTIVE_FOUND;
2210 case PP_LOCAL:
2211 /* TASM like LOCAL directive to define local variables for a
2212 * function, in the following form:
2214 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2216 * The '= LocalSize' at the end is ignored by NASM, but is
2217 * required by TASM to define the local parameter size (and used
2218 * by the TASM macro package).
2220 offset = LocalOffset;
2221 do {
2222 char *local, directive[256];
2223 int size = StackSize;
2225 /* Find the argument name */
2226 tline = tline->next;
2227 if (tline && tline->type == TOK_WHITESPACE)
2228 tline = tline->next;
2229 if (!tline || tline->type != TOK_ID) {
2230 error(ERR_NONFATAL,
2231 "`%%local' missing argument parameter");
2232 free_tlist(origline);
2233 return DIRECTIVE_FOUND;
2235 local = tline->text;
2237 /* Find the argument size type */
2238 tline = tline->next;
2239 if (!tline || tline->type != TOK_OTHER
2240 || tline->text[0] != ':') {
2241 error(ERR_NONFATAL,
2242 "Syntax error processing `%%local' directive");
2243 free_tlist(origline);
2244 return DIRECTIVE_FOUND;
2246 tline = tline->next;
2247 if (!tline || tline->type != TOK_ID) {
2248 error(ERR_NONFATAL,
2249 "`%%local' missing size type parameter");
2250 free_tlist(origline);
2251 return DIRECTIVE_FOUND;
2254 /* Allow macro expansion of type parameter */
2255 tt = tokenize(tline->text);
2256 tt = expand_smacro(tt);
2257 size = parse_size(tt->text);
2258 if (!size) {
2259 error(ERR_NONFATAL,
2260 "Invalid size type for `%%local' missing directive");
2261 free_tlist(tt);
2262 free_tlist(origline);
2263 return DIRECTIVE_FOUND;
2265 free_tlist(tt);
2267 /* Round up to even stack slots */
2268 size = (size+StackSize-1) & ~(StackSize-1);
2270 offset += size; /* Negative offset, increment before */
2272 /* Now define the macro for the argument */
2273 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
2274 local, StackPointer, offset);
2275 do_directive(tokenize(directive));
2277 /* Now define the assign to setup the enter_c macro correctly */
2278 snprintf(directive, sizeof(directive),
2279 "%%assign %%$localsize %%$localsize+%d", size);
2280 do_directive(tokenize(directive));
2282 /* Move to the next argument in the list */
2283 tline = tline->next;
2284 if (tline && tline->type == TOK_WHITESPACE)
2285 tline = tline->next;
2286 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2287 LocalOffset = offset;
2288 free_tlist(origline);
2289 return DIRECTIVE_FOUND;
2291 case PP_CLEAR:
2292 if (tline->next)
2293 error(ERR_WARNING|ERR_PASS1,
2294 "trailing garbage after `%%clear' ignored");
2295 free_macros();
2296 init_macros();
2297 free_tlist(origline);
2298 return DIRECTIVE_FOUND;
2300 case PP_DEPEND:
2301 t = tline->next = expand_smacro(tline->next);
2302 skip_white_(t);
2303 if (!t || (t->type != TOK_STRING &&
2304 t->type != TOK_INTERNAL_STRING)) {
2305 error(ERR_NONFATAL, "`%%depend' expects a file name");
2306 free_tlist(origline);
2307 return DIRECTIVE_FOUND; /* but we did _something_ */
2309 if (t->next)
2310 error(ERR_WARNING|ERR_PASS1,
2311 "trailing garbage after `%%depend' ignored");
2312 p = t->text;
2313 if (t->type != TOK_INTERNAL_STRING)
2314 nasm_unquote(p, NULL);
2315 if (dephead && !in_list(*dephead, p)) {
2316 StrList *sl = nasm_malloc(strlen(p)+1+sizeof sl->next);
2317 sl->next = NULL;
2318 strcpy(sl->str, p);
2319 *deptail = sl;
2320 deptail = &sl->next;
2322 free_tlist(origline);
2323 return DIRECTIVE_FOUND;
2325 case PP_INCLUDE:
2326 t = tline->next = expand_smacro(tline->next);
2327 skip_white_(t);
2329 if (!t || (t->type != TOK_STRING &&
2330 t->type != TOK_INTERNAL_STRING)) {
2331 error(ERR_NONFATAL, "`%%include' expects a file name");
2332 free_tlist(origline);
2333 return DIRECTIVE_FOUND; /* but we did _something_ */
2335 if (t->next)
2336 error(ERR_WARNING|ERR_PASS1,
2337 "trailing garbage after `%%include' ignored");
2338 p = t->text;
2339 if (t->type != TOK_INTERNAL_STRING)
2340 nasm_unquote(p, NULL);
2341 inc = nasm_malloc(sizeof(Include));
2342 inc->next = istk;
2343 inc->conds = NULL;
2344 inc->fp = inc_fopen(p, dephead, &deptail, pass == 0);
2345 if (!inc->fp) {
2346 /* -MG given but file not found */
2347 nasm_free(inc);
2348 } else {
2349 inc->fname = src_set_fname(nasm_strdup(p));
2350 inc->lineno = src_set_linnum(0);
2351 inc->lineinc = 1;
2352 inc->expansion = NULL;
2353 inc->mstk = NULL;
2354 istk = inc;
2355 list->uplevel(LIST_INCLUDE);
2357 free_tlist(origline);
2358 return DIRECTIVE_FOUND;
2360 case PP_USE:
2362 static macros_t *use_pkg;
2363 const char *pkg_macro;
2365 tline = tline->next;
2366 skip_white_(tline);
2367 tline = expand_id(tline);
2369 if (!tline || (tline->type != TOK_STRING &&
2370 tline->type != TOK_INTERNAL_STRING &&
2371 tline->type != TOK_ID)) {
2372 error(ERR_NONFATAL, "`%%use' expects a package name");
2373 free_tlist(origline);
2374 return DIRECTIVE_FOUND; /* but we did _something_ */
2376 if (tline->next)
2377 error(ERR_WARNING|ERR_PASS1,
2378 "trailing garbage after `%%use' ignored");
2379 if (tline->type == TOK_STRING)
2380 nasm_unquote(tline->text, NULL);
2381 use_pkg = nasm_stdmac_find_package(tline->text);
2382 if (!use_pkg)
2383 error(ERR_NONFATAL, "unknown `%%use' package: %s", tline->text);
2384 /* The first string will be <%define>__USE_*__ */
2385 pkg_macro = (char *)use_pkg + 1;
2386 if (!smacro_defined(NULL, pkg_macro, 0, NULL, true)) {
2387 /* Not already included, go ahead and include it */
2388 stdmacpos = use_pkg;
2390 free_tlist(origline);
2391 return DIRECTIVE_FOUND;
2393 case PP_PUSH:
2394 case PP_REPL:
2395 case PP_POP:
2396 tline = tline->next;
2397 skip_white_(tline);
2398 tline = expand_id(tline);
2399 if (tline) {
2400 if (!tok_type_(tline, TOK_ID)) {
2401 error(ERR_NONFATAL, "`%s' expects a context identifier",
2402 pp_directives[i]);
2403 free_tlist(origline);
2404 return DIRECTIVE_FOUND; /* but we did _something_ */
2406 if (tline->next)
2407 error(ERR_WARNING|ERR_PASS1,
2408 "trailing garbage after `%s' ignored",
2409 pp_directives[i]);
2410 p = nasm_strdup(tline->text);
2411 } else {
2412 p = NULL; /* Anonymous */
2415 if (i == PP_PUSH) {
2416 ctx = nasm_malloc(sizeof(Context));
2417 ctx->next = cstk;
2418 hash_init(&ctx->localmac, HASH_SMALL);
2419 ctx->name = p;
2420 ctx->number = unique++;
2421 cstk = ctx;
2422 } else {
2423 /* %pop or %repl */
2424 if (!cstk) {
2425 error(ERR_NONFATAL, "`%s': context stack is empty",
2426 pp_directives[i]);
2427 } else if (i == PP_POP) {
2428 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
2429 error(ERR_NONFATAL, "`%%pop' in wrong context: %s, "
2430 "expected %s",
2431 cstk->name ? cstk->name : "anonymous", p);
2432 else
2433 ctx_pop();
2434 } else {
2435 /* i == PP_REPL */
2436 nasm_free(cstk->name);
2437 cstk->name = p;
2438 p = NULL;
2440 nasm_free(p);
2442 free_tlist(origline);
2443 return DIRECTIVE_FOUND;
2444 case PP_FATAL:
2445 severity = ERR_FATAL;
2446 goto issue_error;
2447 case PP_ERROR:
2448 severity = ERR_NONFATAL;
2449 goto issue_error;
2450 case PP_WARNING:
2451 severity = ERR_WARNING|ERR_WARN_USER;
2452 goto issue_error;
2454 issue_error:
2456 /* Only error out if this is the final pass */
2457 if (pass != 2 && i != PP_FATAL)
2458 return DIRECTIVE_FOUND;
2460 tline->next = expand_smacro(tline->next);
2461 tline = tline->next;
2462 skip_white_(tline);
2463 t = tline ? tline->next : NULL;
2464 skip_white_(t);
2465 if (tok_type_(tline, TOK_STRING) && !t) {
2466 /* The line contains only a quoted string */
2467 p = tline->text;
2468 nasm_unquote(p, NULL);
2469 error(severity, "%s", p);
2470 } else {
2471 /* Not a quoted string, or more than a quoted string */
2472 p = detoken(tline, false);
2473 error(severity, "%s", p);
2474 nasm_free(p);
2476 free_tlist(origline);
2477 return DIRECTIVE_FOUND;
2480 CASE_PP_IF:
2481 if (istk->conds && !emitting(istk->conds->state))
2482 j = COND_NEVER;
2483 else {
2484 j = if_condition(tline->next, i);
2485 tline->next = NULL; /* it got freed */
2486 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2488 cond = nasm_malloc(sizeof(Cond));
2489 cond->next = istk->conds;
2490 cond->state = j;
2491 istk->conds = cond;
2492 free_tlist(origline);
2493 return DIRECTIVE_FOUND;
2495 CASE_PP_ELIF:
2496 if (!istk->conds)
2497 error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
2498 switch(istk->conds->state) {
2499 case COND_IF_TRUE:
2500 istk->conds->state = COND_DONE;
2501 break;
2503 case COND_DONE:
2504 case COND_NEVER:
2505 break;
2507 case COND_ELSE_TRUE:
2508 case COND_ELSE_FALSE:
2509 error_precond(ERR_WARNING|ERR_PASS1,
2510 "`%%elif' after `%%else' ignored");
2511 istk->conds->state = COND_NEVER;
2512 break;
2514 case COND_IF_FALSE:
2516 * IMPORTANT: In the case of %if, we will already have
2517 * called expand_mmac_params(); however, if we're
2518 * processing an %elif we must have been in a
2519 * non-emitting mode, which would have inhibited
2520 * the normal invocation of expand_mmac_params().
2521 * Therefore, we have to do it explicitly here.
2523 j = if_condition(expand_mmac_params(tline->next), i);
2524 tline->next = NULL; /* it got freed */
2525 istk->conds->state =
2526 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2527 break;
2529 free_tlist(origline);
2530 return DIRECTIVE_FOUND;
2532 case PP_ELSE:
2533 if (tline->next)
2534 error_precond(ERR_WARNING|ERR_PASS1,
2535 "trailing garbage after `%%else' ignored");
2536 if (!istk->conds)
2537 error(ERR_FATAL, "`%%else': no matching `%%if'");
2538 switch(istk->conds->state) {
2539 case COND_IF_TRUE:
2540 case COND_DONE:
2541 istk->conds->state = COND_ELSE_FALSE;
2542 break;
2544 case COND_NEVER:
2545 break;
2547 case COND_IF_FALSE:
2548 istk->conds->state = COND_ELSE_TRUE;
2549 break;
2551 case COND_ELSE_TRUE:
2552 case COND_ELSE_FALSE:
2553 error_precond(ERR_WARNING|ERR_PASS1,
2554 "`%%else' after `%%else' ignored.");
2555 istk->conds->state = COND_NEVER;
2556 break;
2558 free_tlist(origline);
2559 return DIRECTIVE_FOUND;
2561 case PP_ENDIF:
2562 if (tline->next)
2563 error_precond(ERR_WARNING|ERR_PASS1,
2564 "trailing garbage after `%%endif' ignored");
2565 if (!istk->conds)
2566 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2567 cond = istk->conds;
2568 istk->conds = cond->next;
2569 nasm_free(cond);
2570 free_tlist(origline);
2571 return DIRECTIVE_FOUND;
2573 case PP_MACRO:
2574 case PP_IMACRO:
2575 if (defining) {
2576 error(ERR_FATAL,
2577 "`%%%smacro': already defining a macro",
2578 (i == PP_IMACRO ? "i" : ""));
2579 return DIRECTIVE_FOUND;
2581 defining = nasm_malloc(sizeof(MMacro));
2582 defining->casesense = (i == PP_MACRO);
2583 if (!parse_mmacro_spec(tline, defining, pp_directives[i])) {
2584 nasm_free(defining);
2585 defining = NULL;
2586 return DIRECTIVE_FOUND;
2589 mmac = (MMacro *) hash_findix(&mmacros, defining->name);
2590 while (mmac) {
2591 if (!strcmp(mmac->name, defining->name) &&
2592 (mmac->nparam_min <= defining->nparam_max
2593 || defining->plus)
2594 && (defining->nparam_min <= mmac->nparam_max
2595 || mmac->plus)) {
2596 error(ERR_WARNING|ERR_PASS1,
2597 "redefining multi-line macro `%s'", defining->name);
2598 return DIRECTIVE_FOUND;
2600 mmac = mmac->next;
2602 free_tlist(origline);
2603 return DIRECTIVE_FOUND;
2605 case PP_ENDM:
2606 case PP_ENDMACRO:
2607 if (! (defining && defining->name)) {
2608 error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2609 return DIRECTIVE_FOUND;
2611 mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
2612 defining->next = *mmhead;
2613 *mmhead = defining;
2614 defining = NULL;
2615 free_tlist(origline);
2616 return DIRECTIVE_FOUND;
2618 case PP_UNMACRO:
2619 case PP_UNIMACRO:
2621 MMacro **mmac_p;
2622 MMacro spec;
2624 spec.casesense = (i == PP_UNMACRO);
2625 if (!parse_mmacro_spec(tline, &spec, pp_directives[i])) {
2626 return DIRECTIVE_FOUND;
2628 mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
2629 while (mmac_p && *mmac_p) {
2630 mmac = *mmac_p;
2631 if (mmac->casesense == spec.casesense &&
2632 !mstrcmp(mmac->name, spec.name, spec.casesense) &&
2633 mmac->nparam_min == spec.nparam_min &&
2634 mmac->nparam_max == spec.nparam_max &&
2635 mmac->plus == spec.plus) {
2636 *mmac_p = mmac->next;
2637 free_mmacro(mmac);
2638 } else {
2639 mmac_p = &mmac->next;
2642 free_tlist(origline);
2643 free_tlist(spec.dlist);
2644 return DIRECTIVE_FOUND;
2647 case PP_ROTATE:
2648 if (tline->next && tline->next->type == TOK_WHITESPACE)
2649 tline = tline->next;
2650 if (tline->next == NULL) {
2651 free_tlist(origline);
2652 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
2653 return DIRECTIVE_FOUND;
2655 t = expand_smacro(tline->next);
2656 tline->next = NULL;
2657 free_tlist(origline);
2658 tline = t;
2659 tptr = &t;
2660 tokval.t_type = TOKEN_INVALID;
2661 evalresult =
2662 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2663 free_tlist(tline);
2664 if (!evalresult)
2665 return DIRECTIVE_FOUND;
2666 if (tokval.t_type)
2667 error(ERR_WARNING|ERR_PASS1,
2668 "trailing garbage after expression ignored");
2669 if (!is_simple(evalresult)) {
2670 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2671 return DIRECTIVE_FOUND;
2673 mmac = istk->mstk;
2674 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2675 mmac = mmac->next_active;
2676 if (!mmac) {
2677 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
2678 } else if (mmac->nparam == 0) {
2679 error(ERR_NONFATAL,
2680 "`%%rotate' invoked within macro without parameters");
2681 } else {
2682 int rotate = mmac->rotate + reloc_value(evalresult);
2684 rotate %= (int)mmac->nparam;
2685 if (rotate < 0)
2686 rotate += mmac->nparam;
2688 mmac->rotate = rotate;
2690 return DIRECTIVE_FOUND;
2692 case PP_REP:
2693 nolist = false;
2694 do {
2695 tline = tline->next;
2696 } while (tok_type_(tline, TOK_WHITESPACE));
2698 if (tok_type_(tline, TOK_ID) &&
2699 nasm_stricmp(tline->text, ".nolist") == 0) {
2700 nolist = true;
2701 do {
2702 tline = tline->next;
2703 } while (tok_type_(tline, TOK_WHITESPACE));
2706 if (tline) {
2707 t = expand_smacro(tline);
2708 tptr = &t;
2709 tokval.t_type = TOKEN_INVALID;
2710 evalresult =
2711 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2712 if (!evalresult) {
2713 free_tlist(origline);
2714 return DIRECTIVE_FOUND;
2716 if (tokval.t_type)
2717 error(ERR_WARNING|ERR_PASS1,
2718 "trailing garbage after expression ignored");
2719 if (!is_simple(evalresult)) {
2720 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2721 return DIRECTIVE_FOUND;
2723 count = reloc_value(evalresult) + 1;
2724 } else {
2725 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
2726 count = 0;
2728 free_tlist(origline);
2730 tmp_defining = defining;
2731 defining = nasm_malloc(sizeof(MMacro));
2732 defining->name = NULL; /* flags this macro as a %rep block */
2733 defining->casesense = false;
2734 defining->plus = false;
2735 defining->nolist = nolist;
2736 defining->in_progress = count;
2737 defining->nparam_min = defining->nparam_max = 0;
2738 defining->defaults = NULL;
2739 defining->dlist = NULL;
2740 defining->expansion = NULL;
2741 defining->next_active = istk->mstk;
2742 defining->rep_nest = tmp_defining;
2743 return DIRECTIVE_FOUND;
2745 case PP_ENDREP:
2746 if (!defining || defining->name) {
2747 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2748 return DIRECTIVE_FOUND;
2752 * Now we have a "macro" defined - although it has no name
2753 * and we won't be entering it in the hash tables - we must
2754 * push a macro-end marker for it on to istk->expansion.
2755 * After that, it will take care of propagating itself (a
2756 * macro-end marker line for a macro which is really a %rep
2757 * block will cause the macro to be re-expanded, complete
2758 * with another macro-end marker to ensure the process
2759 * continues) until the whole expansion is forcibly removed
2760 * from istk->expansion by a %exitrep.
2762 l = nasm_malloc(sizeof(Line));
2763 l->next = istk->expansion;
2764 l->finishes = defining;
2765 l->first = NULL;
2766 istk->expansion = l;
2768 istk->mstk = defining;
2770 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2771 tmp_defining = defining;
2772 defining = defining->rep_nest;
2773 free_tlist(origline);
2774 return DIRECTIVE_FOUND;
2776 case PP_EXITREP:
2778 * We must search along istk->expansion until we hit a
2779 * macro-end marker for a macro with no name. Then we set
2780 * its `in_progress' flag to 0.
2782 for (l = istk->expansion; l; l = l->next)
2783 if (l->finishes && !l->finishes->name)
2784 break;
2786 if (l)
2787 l->finishes->in_progress = 1;
2788 else
2789 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2790 free_tlist(origline);
2791 return DIRECTIVE_FOUND;
2793 case PP_XDEFINE:
2794 case PP_IXDEFINE:
2795 case PP_DEFINE:
2796 case PP_IDEFINE:
2797 casesense = (i == PP_DEFINE || i == PP_XDEFINE);
2799 tline = tline->next;
2800 skip_white_(tline);
2801 tline = expand_id(tline);
2802 if (!tline || (tline->type != TOK_ID &&
2803 (tline->type != TOK_PREPROC_ID ||
2804 tline->text[1] != '$'))) {
2805 error(ERR_NONFATAL, "`%s' expects a macro identifier",
2806 pp_directives[i]);
2807 free_tlist(origline);
2808 return DIRECTIVE_FOUND;
2811 ctx = get_ctx(tline->text, &mname, false);
2812 last = tline;
2813 param_start = tline = tline->next;
2814 nparam = 0;
2816 /* Expand the macro definition now for %xdefine and %ixdefine */
2817 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2818 tline = expand_smacro(tline);
2820 if (tok_is_(tline, "(")) {
2822 * This macro has parameters.
2825 tline = tline->next;
2826 while (1) {
2827 skip_white_(tline);
2828 if (!tline) {
2829 error(ERR_NONFATAL, "parameter identifier expected");
2830 free_tlist(origline);
2831 return DIRECTIVE_FOUND;
2833 if (tline->type != TOK_ID) {
2834 error(ERR_NONFATAL,
2835 "`%s': parameter identifier expected",
2836 tline->text);
2837 free_tlist(origline);
2838 return DIRECTIVE_FOUND;
2840 tline->type = TOK_SMAC_PARAM + nparam++;
2841 tline = tline->next;
2842 skip_white_(tline);
2843 if (tok_is_(tline, ",")) {
2844 tline = tline->next;
2845 } else {
2846 if (!tok_is_(tline, ")")) {
2847 error(ERR_NONFATAL,
2848 "`)' expected to terminate macro template");
2849 free_tlist(origline);
2850 return DIRECTIVE_FOUND;
2852 break;
2855 last = tline;
2856 tline = tline->next;
2858 if (tok_type_(tline, TOK_WHITESPACE))
2859 last = tline, tline = tline->next;
2860 macro_start = NULL;
2861 last->next = NULL;
2862 t = tline;
2863 while (t) {
2864 if (t->type == TOK_ID) {
2865 for (tt = param_start; tt; tt = tt->next)
2866 if (tt->type >= TOK_SMAC_PARAM &&
2867 !strcmp(tt->text, t->text))
2868 t->type = tt->type;
2870 tt = t->next;
2871 t->next = macro_start;
2872 macro_start = t;
2873 t = tt;
2876 * Good. We now have a macro name, a parameter count, and a
2877 * token list (in reverse order) for an expansion. We ought
2878 * to be OK just to create an SMacro, store it, and let
2879 * free_tlist have the rest of the line (which we have
2880 * carefully re-terminated after chopping off the expansion
2881 * from the end).
2883 define_smacro(ctx, mname, casesense, nparam, macro_start);
2884 free_tlist(origline);
2885 return DIRECTIVE_FOUND;
2887 case PP_UNDEF:
2888 tline = tline->next;
2889 skip_white_(tline);
2890 tline = expand_id(tline);
2891 if (!tline || (tline->type != TOK_ID &&
2892 (tline->type != TOK_PREPROC_ID ||
2893 tline->text[1] != '$'))) {
2894 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
2895 free_tlist(origline);
2896 return DIRECTIVE_FOUND;
2898 if (tline->next) {
2899 error(ERR_WARNING|ERR_PASS1,
2900 "trailing garbage after macro name ignored");
2903 /* Find the context that symbol belongs to */
2904 ctx = get_ctx(tline->text, &mname, false);
2905 undef_smacro(ctx, mname);
2906 free_tlist(origline);
2907 return DIRECTIVE_FOUND;
2909 case PP_DEFSTR:
2910 case PP_IDEFSTR:
2911 casesense = (i == PP_DEFSTR);
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, "`%s' expects a macro identifier",
2920 pp_directives[i]);
2921 free_tlist(origline);
2922 return DIRECTIVE_FOUND;
2925 ctx = get_ctx(tline->text, &mname, false);
2926 last = tline;
2927 tline = expand_smacro(tline->next);
2928 last->next = NULL;
2930 while (tok_type_(tline, TOK_WHITESPACE))
2931 tline = delete_Token(tline);
2933 p = detoken(tline, false);
2934 macro_start = nasm_malloc(sizeof(*macro_start));
2935 macro_start->next = NULL;
2936 macro_start->text = nasm_quote(p, strlen(p));
2937 macro_start->type = TOK_STRING;
2938 macro_start->a.mac = NULL;
2939 nasm_free(p);
2942 * We now have a macro name, an implicit parameter count of
2943 * zero, and a string token to use as an expansion. Create
2944 * and store an SMacro.
2946 define_smacro(ctx, mname, casesense, 0, macro_start);
2947 free_tlist(origline);
2948 return DIRECTIVE_FOUND;
2950 case PP_PATHSEARCH:
2952 FILE *fp;
2953 StrList *xsl = NULL;
2954 StrList **xst = &xsl;
2956 casesense = true;
2958 tline = tline->next;
2959 skip_white_(tline);
2960 tline = expand_id(tline);
2961 if (!tline || (tline->type != TOK_ID &&
2962 (tline->type != TOK_PREPROC_ID ||
2963 tline->text[1] != '$'))) {
2964 error(ERR_NONFATAL,
2965 "`%%pathsearch' expects a macro identifier as first parameter");
2966 free_tlist(origline);
2967 return DIRECTIVE_FOUND;
2969 ctx = get_ctx(tline->text, &mname, false);
2970 last = tline;
2971 tline = expand_smacro(tline->next);
2972 last->next = NULL;
2974 t = tline;
2975 while (tok_type_(t, TOK_WHITESPACE))
2976 t = t->next;
2978 if (!t || (t->type != TOK_STRING &&
2979 t->type != TOK_INTERNAL_STRING)) {
2980 error(ERR_NONFATAL, "`%%pathsearch' expects a file name");
2981 free_tlist(tline);
2982 free_tlist(origline);
2983 return DIRECTIVE_FOUND; /* but we did _something_ */
2985 if (t->next)
2986 error(ERR_WARNING|ERR_PASS1,
2987 "trailing garbage after `%%pathsearch' ignored");
2988 p = t->text;
2989 if (t->type != TOK_INTERNAL_STRING)
2990 nasm_unquote(p, NULL);
2992 fp = inc_fopen(p, &xsl, &xst, true);
2993 if (fp) {
2994 p = xsl->str;
2995 fclose(fp); /* Don't actually care about the file */
2997 macro_start = nasm_malloc(sizeof(*macro_start));
2998 macro_start->next = NULL;
2999 macro_start->text = nasm_quote(p, strlen(p));
3000 macro_start->type = TOK_STRING;
3001 macro_start->a.mac = NULL;
3002 if (xsl)
3003 nasm_free(xsl);
3006 * We now have a macro name, an implicit parameter count of
3007 * zero, and a string token to use as an expansion. Create
3008 * and store an SMacro.
3010 define_smacro(ctx, mname, casesense, 0, macro_start);
3011 free_tlist(tline);
3012 free_tlist(origline);
3013 return DIRECTIVE_FOUND;
3016 case PP_STRLEN:
3017 casesense = true;
3019 tline = tline->next;
3020 skip_white_(tline);
3021 tline = expand_id(tline);
3022 if (!tline || (tline->type != TOK_ID &&
3023 (tline->type != TOK_PREPROC_ID ||
3024 tline->text[1] != '$'))) {
3025 error(ERR_NONFATAL,
3026 "`%%strlen' expects a macro identifier as first parameter");
3027 free_tlist(origline);
3028 return DIRECTIVE_FOUND;
3030 ctx = get_ctx(tline->text, &mname, false);
3031 last = tline;
3032 tline = expand_smacro(tline->next);
3033 last->next = NULL;
3035 t = tline;
3036 while (tok_type_(t, TOK_WHITESPACE))
3037 t = t->next;
3038 /* t should now point to the string */
3039 if (t->type != TOK_STRING) {
3040 error(ERR_NONFATAL,
3041 "`%%strlen` requires string as second parameter");
3042 free_tlist(tline);
3043 free_tlist(origline);
3044 return DIRECTIVE_FOUND;
3047 macro_start = nasm_malloc(sizeof(*macro_start));
3048 macro_start->next = NULL;
3049 make_tok_num(macro_start, nasm_unquote(t->text, NULL));
3050 macro_start->a.mac = NULL;
3053 * We now have a macro name, an implicit parameter count of
3054 * zero, and a numeric token to use as an expansion. Create
3055 * and store an SMacro.
3057 define_smacro(ctx, mname, casesense, 0, macro_start);
3058 free_tlist(tline);
3059 free_tlist(origline);
3060 return DIRECTIVE_FOUND;
3062 case PP_STRCAT:
3063 casesense = true;
3065 tline = tline->next;
3066 skip_white_(tline);
3067 tline = expand_id(tline);
3068 if (!tline || (tline->type != TOK_ID &&
3069 (tline->type != TOK_PREPROC_ID ||
3070 tline->text[1] != '$'))) {
3071 error(ERR_NONFATAL,
3072 "`%%strcat' expects a macro identifier as first parameter");
3073 free_tlist(origline);
3074 return DIRECTIVE_FOUND;
3076 ctx = get_ctx(tline->text, &mname, false);
3077 last = tline;
3078 tline = expand_smacro(tline->next);
3079 last->next = NULL;
3081 len = 0;
3082 for (t = tline; t; t = t->next) {
3083 switch (t->type) {
3084 case TOK_WHITESPACE:
3085 break;
3086 case TOK_STRING:
3087 len += t->a.len = nasm_unquote(t->text, NULL);
3088 break;
3089 case TOK_OTHER:
3090 if (!strcmp(t->text, ",")) /* permit comma separators */
3091 break;
3092 /* else fall through */
3093 default:
3094 error(ERR_NONFATAL,
3095 "non-string passed to `%%strcat' (%d)", t->type);
3096 free_tlist(tline);
3097 free_tlist(origline);
3098 return DIRECTIVE_FOUND;
3102 p = pp = nasm_malloc(len);
3103 t = tline;
3104 for (t = tline; t; t = t->next) {
3105 if (t->type == TOK_STRING) {
3106 memcpy(p, t->text, t->a.len);
3107 p += t->a.len;
3112 * We now have a macro name, an implicit parameter count of
3113 * zero, and a numeric token to use as an expansion. Create
3114 * and store an SMacro.
3116 macro_start = new_Token(NULL, TOK_STRING, NULL, 0);
3117 macro_start->text = nasm_quote(pp, len);
3118 nasm_free(pp);
3119 define_smacro(ctx, mname, casesense, 0, macro_start);
3120 free_tlist(tline);
3121 free_tlist(origline);
3122 return DIRECTIVE_FOUND;
3124 case PP_SUBSTR:
3126 int64_t a1, a2;
3127 size_t len;
3129 casesense = true;
3131 tline = tline->next;
3132 skip_white_(tline);
3133 tline = expand_id(tline);
3134 if (!tline || (tline->type != TOK_ID &&
3135 (tline->type != TOK_PREPROC_ID ||
3136 tline->text[1] != '$'))) {
3137 error(ERR_NONFATAL,
3138 "`%%substr' expects a macro identifier as first parameter");
3139 free_tlist(origline);
3140 return DIRECTIVE_FOUND;
3142 ctx = get_ctx(tline->text, &mname, false);
3143 last = tline;
3144 tline = expand_smacro(tline->next);
3145 last->next = NULL;
3147 t = tline->next;
3148 while (tok_type_(t, TOK_WHITESPACE))
3149 t = t->next;
3151 /* t should now point to the string */
3152 if (t->type != TOK_STRING) {
3153 error(ERR_NONFATAL,
3154 "`%%substr` requires string as second parameter");
3155 free_tlist(tline);
3156 free_tlist(origline);
3157 return DIRECTIVE_FOUND;
3160 tt = t->next;
3161 tptr = &tt;
3162 tokval.t_type = TOKEN_INVALID;
3163 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3164 pass, error, NULL);
3165 if (!evalresult) {
3166 free_tlist(tline);
3167 free_tlist(origline);
3168 return DIRECTIVE_FOUND;
3169 } else if (!is_simple(evalresult)) {
3170 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3171 free_tlist(tline);
3172 free_tlist(origline);
3173 return DIRECTIVE_FOUND;
3175 a1 = evalresult->value-1;
3177 while (tok_type_(tt, TOK_WHITESPACE))
3178 tt = tt->next;
3179 if (!tt) {
3180 a2 = 1; /* Backwards compatibility: one character */
3181 } else {
3182 tokval.t_type = TOKEN_INVALID;
3183 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3184 pass, error, NULL);
3185 if (!evalresult) {
3186 free_tlist(tline);
3187 free_tlist(origline);
3188 return DIRECTIVE_FOUND;
3189 } else if (!is_simple(evalresult)) {
3190 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3191 free_tlist(tline);
3192 free_tlist(origline);
3193 return DIRECTIVE_FOUND;
3195 a2 = evalresult->value;
3198 len = nasm_unquote(t->text, NULL);
3199 if (a2 < 0)
3200 a2 = a2+1+len-a1;
3201 if (a1+a2 > (int64_t)len)
3202 a2 = len-a1;
3204 macro_start = nasm_malloc(sizeof(*macro_start));
3205 macro_start->next = NULL;
3206 macro_start->text = nasm_quote((a1 < 0) ? "" : t->text+a1, a2);
3207 macro_start->type = TOK_STRING;
3208 macro_start->a.mac = NULL;
3211 * We now have a macro name, an implicit parameter count of
3212 * zero, and a numeric token to use as an expansion. Create
3213 * and store an SMacro.
3215 define_smacro(ctx, mname, casesense, 0, macro_start);
3216 free_tlist(tline);
3217 free_tlist(origline);
3218 return DIRECTIVE_FOUND;
3221 case PP_ASSIGN:
3222 case PP_IASSIGN:
3223 casesense = (i == PP_ASSIGN);
3225 tline = tline->next;
3226 skip_white_(tline);
3227 tline = expand_id(tline);
3228 if (!tline || (tline->type != TOK_ID &&
3229 (tline->type != TOK_PREPROC_ID ||
3230 tline->text[1] != '$'))) {
3231 error(ERR_NONFATAL,
3232 "`%%%sassign' expects a macro identifier",
3233 (i == PP_IASSIGN ? "i" : ""));
3234 free_tlist(origline);
3235 return DIRECTIVE_FOUND;
3237 ctx = get_ctx(tline->text, &mname, false);
3238 last = tline;
3239 tline = expand_smacro(tline->next);
3240 last->next = NULL;
3242 t = tline;
3243 tptr = &t;
3244 tokval.t_type = TOKEN_INVALID;
3245 evalresult =
3246 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3247 free_tlist(tline);
3248 if (!evalresult) {
3249 free_tlist(origline);
3250 return DIRECTIVE_FOUND;
3253 if (tokval.t_type)
3254 error(ERR_WARNING|ERR_PASS1,
3255 "trailing garbage after expression ignored");
3257 if (!is_simple(evalresult)) {
3258 error(ERR_NONFATAL,
3259 "non-constant value given to `%%%sassign'",
3260 (i == PP_IASSIGN ? "i" : ""));
3261 free_tlist(origline);
3262 return DIRECTIVE_FOUND;
3265 macro_start = nasm_malloc(sizeof(*macro_start));
3266 macro_start->next = NULL;
3267 make_tok_num(macro_start, reloc_value(evalresult));
3268 macro_start->a.mac = NULL;
3271 * We now have a macro name, an implicit parameter count of
3272 * zero, and a numeric token to use as an expansion. Create
3273 * and store an SMacro.
3275 define_smacro(ctx, mname, casesense, 0, macro_start);
3276 free_tlist(origline);
3277 return DIRECTIVE_FOUND;
3279 case PP_LINE:
3281 * Syntax is `%line nnn[+mmm] [filename]'
3283 tline = tline->next;
3284 skip_white_(tline);
3285 if (!tok_type_(tline, TOK_NUMBER)) {
3286 error(ERR_NONFATAL, "`%%line' expects line number");
3287 free_tlist(origline);
3288 return DIRECTIVE_FOUND;
3290 k = readnum(tline->text, &err);
3291 m = 1;
3292 tline = tline->next;
3293 if (tok_is_(tline, "+")) {
3294 tline = tline->next;
3295 if (!tok_type_(tline, TOK_NUMBER)) {
3296 error(ERR_NONFATAL, "`%%line' expects line increment");
3297 free_tlist(origline);
3298 return DIRECTIVE_FOUND;
3300 m = readnum(tline->text, &err);
3301 tline = tline->next;
3303 skip_white_(tline);
3304 src_set_linnum(k);
3305 istk->lineinc = m;
3306 if (tline) {
3307 nasm_free(src_set_fname(detoken(tline, false)));
3309 free_tlist(origline);
3310 return DIRECTIVE_FOUND;
3312 default:
3313 error(ERR_FATAL,
3314 "preprocessor directive `%s' not yet implemented",
3315 pp_directives[i]);
3316 return DIRECTIVE_FOUND;
3321 * Ensure that a macro parameter contains a condition code and
3322 * nothing else. Return the condition code index if so, or -1
3323 * otherwise.
3325 static int find_cc(Token * t)
3327 Token *tt;
3328 int i, j, k, m;
3330 if (!t)
3331 return -1; /* Probably a %+ without a space */
3333 skip_white_(t);
3334 if (t->type != TOK_ID)
3335 return -1;
3336 tt = t->next;
3337 skip_white_(tt);
3338 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
3339 return -1;
3341 i = -1;
3342 j = elements(conditions);
3343 while (j - i > 1) {
3344 k = (j + i) / 2;
3345 m = nasm_stricmp(t->text, conditions[k]);
3346 if (m == 0) {
3347 i = k;
3348 j = -2;
3349 break;
3350 } else if (m < 0) {
3351 j = k;
3352 } else
3353 i = k;
3355 if (j != -2)
3356 return -1;
3357 return i;
3360 static bool paste_tokens(Token **head, bool handle_paste_tokens)
3362 Token **tail, *t, *tt;
3363 Token **paste_head;
3364 bool did_paste = false;
3365 char *tmp;
3367 /* Now handle token pasting... */
3368 paste_head = NULL;
3369 tail = head;
3370 while ((t = *tail) && (tt = t->next)) {
3371 switch (t->type) {
3372 case TOK_WHITESPACE:
3373 if (tt->type == TOK_WHITESPACE) {
3374 /* Zap adjacent whitespace tokens */
3375 t->next = delete_Token(tt);
3376 } else {
3377 /* Do not advance paste_head here */
3378 tail = &t->next;
3380 break;
3381 case TOK_ID:
3382 case TOK_PREPROC_ID:
3383 case TOK_NUMBER:
3384 case TOK_FLOAT:
3386 size_t len = 0;
3387 char *tmp, *p;
3389 while (tt && (tt->type == TOK_ID || tt->type == TOK_PREPROC_ID ||
3390 tt->type == TOK_NUMBER || tt->type == TOK_FLOAT ||
3391 tt->type == TOK_OTHER)) {
3392 len += strlen(tt->text);
3393 tt = tt->next;
3396 /* Now tt points to the first token after the potential
3397 paste area... */
3398 if (tt != t->next) {
3399 /* We have at least two tokens... */
3400 len += strlen(t->text);
3401 p = tmp = nasm_malloc(len+1);
3403 while (t != tt) {
3404 strcpy(p, t->text);
3405 p = strchr(p, '\0');
3406 t = delete_Token(t);
3409 t = *tail = tokenize(tmp);
3410 nasm_free(tmp);
3412 while (t->next) {
3413 tail = &t->next;
3414 t = t->next;
3416 t->next = tt; /* Attach the remaining token chain */
3418 did_paste = true;
3420 paste_head = tail;
3421 tail = &t->next;
3422 break;
3424 case TOK_PASTE: /* %+ */
3425 if (handle_paste_tokens) {
3426 /* Zap %+ and whitespace tokens to the right */
3427 while (t && (t->type == TOK_WHITESPACE ||
3428 t->type == TOK_PASTE))
3429 t = *tail = delete_Token(t);
3430 if (!paste_head || !t)
3431 break; /* Nothing to paste with */
3432 tail = paste_head;
3433 t = *tail;
3434 tt = t->next;
3435 while (tok_type_(tt, TOK_WHITESPACE))
3436 tt = t->next = delete_Token(tt);
3438 if (tt) {
3439 tmp = nasm_strcat(t->text, tt->text);
3440 delete_Token(t);
3441 tt = delete_Token(tt);
3442 t = *tail = tokenize(tmp);
3443 nasm_free(tmp);
3444 while (t->next) {
3445 tail = &t->next;
3446 t = t->next;
3448 t->next = tt; /* Attach the remaining token chain */
3449 did_paste = true;
3451 paste_head = tail;
3452 tail = &t->next;
3453 break;
3455 /* else fall through */
3456 default:
3457 tail = paste_head = &t->next;
3458 break;
3461 return did_paste;
3464 * Expand MMacro-local things: parameter references (%0, %n, %+n,
3465 * %-n) and MMacro-local identifiers (%%foo) as well as
3466 * macro indirection (%[...]).
3468 static Token *expand_mmac_params(Token * tline)
3470 Token *t, *tt, **tail, *thead;
3471 bool changed = false;
3473 tail = &thead;
3474 thead = NULL;
3476 while (tline) {
3477 if (tline->type == TOK_PREPROC_ID &&
3478 (((tline->text[1] == '+' || tline->text[1] == '-')
3479 && tline->text[2]) || tline->text[1] == '%'
3480 || (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
3481 char *text = NULL;
3482 int type = 0, cc; /* type = 0 to placate optimisers */
3483 char tmpbuf[30];
3484 unsigned int n;
3485 int i;
3486 MMacro *mac;
3488 t = tline;
3489 tline = tline->next;
3491 mac = istk->mstk;
3492 while (mac && !mac->name) /* avoid mistaking %reps for macros */
3493 mac = mac->next_active;
3494 if (!mac)
3495 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
3496 else
3497 switch (t->text[1]) {
3499 * We have to make a substitution of one of the
3500 * forms %1, %-1, %+1, %%foo, %0.
3502 case '0':
3503 type = TOK_NUMBER;
3504 snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
3505 text = nasm_strdup(tmpbuf);
3506 break;
3507 case '%':
3508 type = TOK_ID;
3509 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
3510 mac->unique);
3511 text = nasm_strcat(tmpbuf, t->text + 2);
3512 break;
3513 case '-':
3514 n = atoi(t->text + 2) - 1;
3515 if (n >= mac->nparam)
3516 tt = NULL;
3517 else {
3518 if (mac->nparam > 1)
3519 n = (n + mac->rotate) % mac->nparam;
3520 tt = mac->params[n];
3522 cc = find_cc(tt);
3523 if (cc == -1) {
3524 error(ERR_NONFATAL,
3525 "macro parameter %d is not a condition code",
3526 n + 1);
3527 text = NULL;
3528 } else {
3529 type = TOK_ID;
3530 if (inverse_ccs[cc] == -1) {
3531 error(ERR_NONFATAL,
3532 "condition code `%s' is not invertible",
3533 conditions[cc]);
3534 text = NULL;
3535 } else
3536 text = nasm_strdup(conditions[inverse_ccs[cc]]);
3538 break;
3539 case '+':
3540 n = atoi(t->text + 2) - 1;
3541 if (n >= mac->nparam)
3542 tt = NULL;
3543 else {
3544 if (mac->nparam > 1)
3545 n = (n + mac->rotate) % mac->nparam;
3546 tt = mac->params[n];
3548 cc = find_cc(tt);
3549 if (cc == -1) {
3550 error(ERR_NONFATAL,
3551 "macro parameter %d is not a condition code",
3552 n + 1);
3553 text = NULL;
3554 } else {
3555 type = TOK_ID;
3556 text = nasm_strdup(conditions[cc]);
3558 break;
3559 default:
3560 n = atoi(t->text + 1) - 1;
3561 if (n >= mac->nparam)
3562 tt = NULL;
3563 else {
3564 if (mac->nparam > 1)
3565 n = (n + mac->rotate) % mac->nparam;
3566 tt = mac->params[n];
3568 if (tt) {
3569 for (i = 0; i < mac->paramlen[n]; i++) {
3570 *tail = new_Token(NULL, tt->type, tt->text, 0);
3571 tail = &(*tail)->next;
3572 tt = tt->next;
3575 text = NULL; /* we've done it here */
3576 break;
3578 if (!text) {
3579 delete_Token(t);
3580 } else {
3581 *tail = t;
3582 tail = &t->next;
3583 t->type = type;
3584 nasm_free(t->text);
3585 t->text = text;
3586 t->a.mac = NULL;
3588 changed = true;
3589 continue;
3590 } else if (tline->type == TOK_INDIRECT) {
3591 t = tline;
3592 tline = tline->next;
3593 tt = tokenize(t->text);
3594 tt = expand_mmac_params(tt);
3595 tt = expand_smacro(tt);
3596 *tail = tt;
3597 while (tt) {
3598 tt->a.mac = NULL; /* Necessary? */
3599 tail = &tt->next;
3600 tt = tt->next;
3602 delete_Token(t);
3603 changed = true;
3604 } else {
3605 t = *tail = tline;
3606 tline = tline->next;
3607 t->a.mac = NULL;
3608 tail = &t->next;
3611 *tail = NULL;
3613 if (changed)
3614 paste_tokens(&thead, false);
3616 return thead;
3620 * Expand all single-line macro calls made in the given line.
3621 * Return the expanded version of the line. The original is deemed
3622 * to be destroyed in the process. (In reality we'll just move
3623 * Tokens from input to output a lot of the time, rather than
3624 * actually bothering to destroy and replicate.)
3626 #define DEADMAN_LIMIT (1 << 20)
3628 static Token *expand_smacro(Token * tline)
3630 Token *t, *tt, *mstart, **tail, *thead;
3631 struct hash_table *smtbl;
3632 SMacro *head = NULL, *m;
3633 Token **params;
3634 int *paramsize;
3635 unsigned int nparam, sparam;
3636 int brackets;
3637 Token *org_tline = tline;
3638 Context *ctx;
3639 const char *mname;
3640 int deadman = DEADMAN_LIMIT;
3641 bool expanded;
3644 * Trick: we should avoid changing the start token pointer since it can
3645 * be contained in "next" field of other token. Because of this
3646 * we allocate a copy of first token and work with it; at the end of
3647 * routine we copy it back
3649 if (org_tline) {
3650 tline =
3651 new_Token(org_tline->next, org_tline->type, org_tline->text,
3653 tline->a.mac = org_tline->a.mac;
3654 nasm_free(org_tline->text);
3655 org_tline->text = NULL;
3658 expanded = true; /* Always expand %+ at least once */
3660 again:
3661 tail = &thead;
3662 thead = NULL;
3664 while (tline) { /* main token loop */
3665 if (!--deadman) {
3666 error(ERR_NONFATAL, "interminable macro recursion");
3667 break;
3670 if ((mname = tline->text)) {
3671 /* if this token is a local macro, look in local context */
3672 if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
3673 ctx = get_ctx(mname, &mname, true);
3674 else
3675 ctx = NULL;
3676 smtbl = ctx ? &ctx->localmac : &smacros;
3677 head = (SMacro *) hash_findix(smtbl, mname);
3680 * We've hit an identifier. As in is_mmacro below, we first
3681 * check whether the identifier is a single-line macro at
3682 * all, then think about checking for parameters if
3683 * necessary.
3685 for (m = head; m; m = m->next)
3686 if (!mstrcmp(m->name, mname, m->casesense))
3687 break;
3688 if (m) {
3689 mstart = tline;
3690 params = NULL;
3691 paramsize = NULL;
3692 if (m->nparam == 0) {
3694 * Simple case: the macro is parameterless. Discard the
3695 * one token that the macro call took, and push the
3696 * expansion back on the to-do stack.
3698 if (!m->expansion) {
3699 if (!strcmp("__FILE__", m->name)) {
3700 int32_t num = 0;
3701 char *file = NULL;
3702 src_get(&num, &file);
3703 tline->text = nasm_quote(file, strlen(file));
3704 tline->type = TOK_STRING;
3705 nasm_free(file);
3706 continue;
3708 if (!strcmp("__LINE__", m->name)) {
3709 nasm_free(tline->text);
3710 make_tok_num(tline, src_get_linnum());
3711 continue;
3713 if (!strcmp("__BITS__", m->name)) {
3714 nasm_free(tline->text);
3715 make_tok_num(tline, globalbits);
3716 continue;
3718 tline = delete_Token(tline);
3719 continue;
3721 } else {
3723 * Complicated case: at least one macro with this name
3724 * exists and takes parameters. We must find the
3725 * parameters in the call, count them, find the SMacro
3726 * that corresponds to that form of the macro call, and
3727 * substitute for the parameters when we expand. What a
3728 * pain.
3730 /*tline = tline->next;
3731 skip_white_(tline); */
3732 do {
3733 t = tline->next;
3734 while (tok_type_(t, TOK_SMAC_END)) {
3735 t->a.mac->in_progress = false;
3736 t->text = NULL;
3737 t = tline->next = delete_Token(t);
3739 tline = t;
3740 } while (tok_type_(tline, TOK_WHITESPACE));
3741 if (!tok_is_(tline, "(")) {
3743 * This macro wasn't called with parameters: ignore
3744 * the call. (Behaviour borrowed from gnu cpp.)
3746 tline = mstart;
3747 m = NULL;
3748 } else {
3749 int paren = 0;
3750 int white = 0;
3751 brackets = 0;
3752 nparam = 0;
3753 sparam = PARAM_DELTA;
3754 params = nasm_malloc(sparam * sizeof(Token *));
3755 params[0] = tline->next;
3756 paramsize = nasm_malloc(sparam * sizeof(int));
3757 paramsize[0] = 0;
3758 while (true) { /* parameter loop */
3760 * For some unusual expansions
3761 * which concatenates function call
3763 t = tline->next;
3764 while (tok_type_(t, TOK_SMAC_END)) {
3765 t->a.mac->in_progress = false;
3766 t->text = NULL;
3767 t = tline->next = delete_Token(t);
3769 tline = t;
3771 if (!tline) {
3772 error(ERR_NONFATAL,
3773 "macro call expects terminating `)'");
3774 break;
3776 if (tline->type == TOK_WHITESPACE
3777 && brackets <= 0) {
3778 if (paramsize[nparam])
3779 white++;
3780 else
3781 params[nparam] = tline->next;
3782 continue; /* parameter loop */
3784 if (tline->type == TOK_OTHER
3785 && tline->text[1] == 0) {
3786 char ch = tline->text[0];
3787 if (ch == ',' && !paren && brackets <= 0) {
3788 if (++nparam >= sparam) {
3789 sparam += PARAM_DELTA;
3790 params = nasm_realloc(params,
3791 sparam *
3792 sizeof(Token
3793 *));
3794 paramsize =
3795 nasm_realloc(paramsize,
3796 sparam *
3797 sizeof(int));
3799 params[nparam] = tline->next;
3800 paramsize[nparam] = 0;
3801 white = 0;
3802 continue; /* parameter loop */
3804 if (ch == '{' &&
3805 (brackets > 0 || (brackets == 0 &&
3806 !paramsize[nparam])))
3808 if (!(brackets++)) {
3809 params[nparam] = tline->next;
3810 continue; /* parameter loop */
3813 if (ch == '}' && brackets > 0)
3814 if (--brackets == 0) {
3815 brackets = -1;
3816 continue; /* parameter loop */
3818 if (ch == '(' && !brackets)
3819 paren++;
3820 if (ch == ')' && brackets <= 0)
3821 if (--paren < 0)
3822 break;
3824 if (brackets < 0) {
3825 brackets = 0;
3826 error(ERR_NONFATAL, "braces do not "
3827 "enclose all of macro parameter");
3829 paramsize[nparam] += white + 1;
3830 white = 0;
3831 } /* parameter loop */
3832 nparam++;
3833 while (m && (m->nparam != nparam ||
3834 mstrcmp(m->name, mname,
3835 m->casesense)))
3836 m = m->next;
3837 if (!m)
3838 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
3839 "macro `%s' exists, "
3840 "but not taking %d parameters",
3841 mstart->text, nparam);
3844 if (m && m->in_progress)
3845 m = NULL;
3846 if (!m) { /* in progess or didn't find '(' or wrong nparam */
3848 * Design question: should we handle !tline, which
3849 * indicates missing ')' here, or expand those
3850 * macros anyway, which requires the (t) test a few
3851 * lines down?
3853 nasm_free(params);
3854 nasm_free(paramsize);
3855 tline = mstart;
3856 } else {
3858 * Expand the macro: we are placed on the last token of the
3859 * call, so that we can easily split the call from the
3860 * following tokens. We also start by pushing an SMAC_END
3861 * token for the cycle removal.
3863 t = tline;
3864 if (t) {
3865 tline = t->next;
3866 t->next = NULL;
3868 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
3869 tt->a.mac = m;
3870 m->in_progress = true;
3871 tline = tt;
3872 for (t = m->expansion; t; t = t->next) {
3873 if (t->type >= TOK_SMAC_PARAM) {
3874 Token *pcopy = tline, **ptail = &pcopy;
3875 Token *ttt, *pt;
3876 int i;
3878 ttt = params[t->type - TOK_SMAC_PARAM];
3879 for (i = paramsize[t->type - TOK_SMAC_PARAM];
3880 --i >= 0;) {
3881 pt = *ptail =
3882 new_Token(tline, ttt->type, ttt->text,
3884 ptail = &pt->next;
3885 ttt = ttt->next;
3887 tline = pcopy;
3888 } else if (t->type == TOK_PREPROC_Q) {
3889 tt = new_Token(tline, TOK_ID, mname, 0);
3890 tline = tt;
3891 } else if (t->type == TOK_PREPROC_QQ) {
3892 tt = new_Token(tline, TOK_ID, m->name, 0);
3893 tline = tt;
3894 } else {
3895 tt = new_Token(tline, t->type, t->text, 0);
3896 tline = tt;
3901 * Having done that, get rid of the macro call, and clean
3902 * up the parameters.
3904 nasm_free(params);
3905 nasm_free(paramsize);
3906 free_tlist(mstart);
3907 expanded = true;
3908 continue; /* main token loop */
3913 if (tline->type == TOK_SMAC_END) {
3914 tline->a.mac->in_progress = false;
3915 tline = delete_Token(tline);
3916 } else {
3917 t = *tail = tline;
3918 tline = tline->next;
3919 t->a.mac = NULL;
3920 t->next = NULL;
3921 tail = &t->next;
3926 * Now scan the entire line and look for successive TOK_IDs that resulted
3927 * after expansion (they can't be produced by tokenize()). The successive
3928 * TOK_IDs should be concatenated.
3929 * Also we look for %+ tokens and concatenate the tokens before and after
3930 * them (without white spaces in between).
3932 if (expanded && paste_tokens(&thead, true)) {
3934 * If we concatenated something, *and* we had previously expanded
3935 * an actual macro, scan the lines again for macros...
3937 tline = thead;
3938 expanded = false;
3939 goto again;
3942 if (org_tline) {
3943 if (thead) {
3944 *org_tline = *thead;
3945 /* since we just gave text to org_line, don't free it */
3946 thead->text = NULL;
3947 delete_Token(thead);
3948 } else {
3949 /* the expression expanded to empty line;
3950 we can't return NULL for some reasons
3951 we just set the line to a single WHITESPACE token. */
3952 memset(org_tline, 0, sizeof(*org_tline));
3953 org_tline->text = NULL;
3954 org_tline->type = TOK_WHITESPACE;
3956 thead = org_tline;
3959 return thead;
3963 * Similar to expand_smacro but used exclusively with macro identifiers
3964 * right before they are fetched in. The reason is that there can be
3965 * identifiers consisting of several subparts. We consider that if there
3966 * are more than one element forming the name, user wants a expansion,
3967 * otherwise it will be left as-is. Example:
3969 * %define %$abc cde
3971 * the identifier %$abc will be left as-is so that the handler for %define
3972 * will suck it and define the corresponding value. Other case:
3974 * %define _%$abc cde
3976 * In this case user wants name to be expanded *before* %define starts
3977 * working, so we'll expand %$abc into something (if it has a value;
3978 * otherwise it will be left as-is) then concatenate all successive
3979 * PP_IDs into one.
3981 static Token *expand_id(Token * tline)
3983 Token *cur, *oldnext = NULL;
3985 if (!tline || !tline->next)
3986 return tline;
3988 cur = tline;
3989 while (cur->next &&
3990 (cur->next->type == TOK_ID ||
3991 cur->next->type == TOK_PREPROC_ID
3992 || cur->next->type == TOK_NUMBER))
3993 cur = cur->next;
3995 /* If identifier consists of just one token, don't expand */
3996 if (cur == tline)
3997 return tline;
3999 if (cur) {
4000 oldnext = cur->next; /* Detach the tail past identifier */
4001 cur->next = NULL; /* so that expand_smacro stops here */
4004 tline = expand_smacro(tline);
4006 if (cur) {
4007 /* expand_smacro possibly changhed tline; re-scan for EOL */
4008 cur = tline;
4009 while (cur && cur->next)
4010 cur = cur->next;
4011 if (cur)
4012 cur->next = oldnext;
4015 return tline;
4019 * Determine whether the given line constitutes a multi-line macro
4020 * call, and return the MMacro structure called if so. Doesn't have
4021 * to check for an initial label - that's taken care of in
4022 * expand_mmacro - but must check numbers of parameters. Guaranteed
4023 * to be called with tline->type == TOK_ID, so the putative macro
4024 * name is easy to find.
4026 static MMacro *is_mmacro(Token * tline, Token *** params_array)
4028 MMacro *head, *m;
4029 Token **params;
4030 int nparam;
4032 head = (MMacro *) hash_findix(&mmacros, tline->text);
4035 * Efficiency: first we see if any macro exists with the given
4036 * name. If not, we can return NULL immediately. _Then_ we
4037 * count the parameters, and then we look further along the
4038 * list if necessary to find the proper MMacro.
4040 for (m = head; m; m = m->next)
4041 if (!mstrcmp(m->name, tline->text, m->casesense))
4042 break;
4043 if (!m)
4044 return NULL;
4047 * OK, we have a potential macro. Count and demarcate the
4048 * parameters.
4050 count_mmac_params(tline->next, &nparam, &params);
4053 * So we know how many parameters we've got. Find the MMacro
4054 * structure that handles this number.
4056 while (m) {
4057 if (m->nparam_min <= nparam
4058 && (m->plus || nparam <= m->nparam_max)) {
4060 * This one is right. Just check if cycle removal
4061 * prohibits us using it before we actually celebrate...
4063 if (m->in_progress) {
4064 #if 0
4065 error(ERR_NONFATAL,
4066 "self-reference in multi-line macro `%s'", m->name);
4067 #endif
4068 nasm_free(params);
4069 return NULL;
4072 * It's right, and we can use it. Add its default
4073 * parameters to the end of our list if necessary.
4075 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
4076 params =
4077 nasm_realloc(params,
4078 ((m->nparam_min + m->ndefs +
4079 1) * sizeof(*params)));
4080 while (nparam < m->nparam_min + m->ndefs) {
4081 params[nparam] = m->defaults[nparam - m->nparam_min];
4082 nparam++;
4086 * If we've gone over the maximum parameter count (and
4087 * we're in Plus mode), ignore parameters beyond
4088 * nparam_max.
4090 if (m->plus && nparam > m->nparam_max)
4091 nparam = m->nparam_max;
4093 * Then terminate the parameter list, and leave.
4095 if (!params) { /* need this special case */
4096 params = nasm_malloc(sizeof(*params));
4097 nparam = 0;
4099 params[nparam] = NULL;
4100 *params_array = params;
4101 return m;
4104 * This one wasn't right: look for the next one with the
4105 * same name.
4107 for (m = m->next; m; m = m->next)
4108 if (!mstrcmp(m->name, tline->text, m->casesense))
4109 break;
4113 * After all that, we didn't find one with the right number of
4114 * parameters. Issue a warning, and fail to expand the macro.
4116 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
4117 "macro `%s' exists, but not taking %d parameters",
4118 tline->text, nparam);
4119 nasm_free(params);
4120 return NULL;
4124 * Expand the multi-line macro call made by the given line, if
4125 * there is one to be expanded. If there is, push the expansion on
4126 * istk->expansion and return 1. Otherwise return 0.
4128 static int expand_mmacro(Token * tline)
4130 Token *startline = tline;
4131 Token *label = NULL;
4132 int dont_prepend = 0;
4133 Token **params, *t, *mtok, *tt;
4134 MMacro *m;
4135 Line *l, *ll;
4136 int i, nparam, *paramlen;
4137 const char *mname;
4139 t = tline;
4140 skip_white_(t);
4141 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4142 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
4143 return 0;
4144 mtok = t;
4145 m = is_mmacro(t, &params);
4146 if (m) {
4147 mname = t->text;
4148 } else {
4149 Token *last;
4151 * We have an id which isn't a macro call. We'll assume
4152 * it might be a label; we'll also check to see if a
4153 * colon follows it. Then, if there's another id after
4154 * that lot, we'll check it again for macro-hood.
4156 label = last = t;
4157 t = t->next;
4158 if (tok_type_(t, TOK_WHITESPACE))
4159 last = t, t = t->next;
4160 if (tok_is_(t, ":")) {
4161 dont_prepend = 1;
4162 last = t, t = t->next;
4163 if (tok_type_(t, TOK_WHITESPACE))
4164 last = t, t = t->next;
4166 if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
4167 return 0;
4168 last->next = NULL;
4169 mname = t->text;
4170 tline = t;
4174 * Fix up the parameters: this involves stripping leading and
4175 * trailing whitespace, then stripping braces if they are
4176 * present.
4178 for (nparam = 0; params[nparam]; nparam++) ;
4179 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
4181 for (i = 0; params[i]; i++) {
4182 int brace = false;
4183 int comma = (!m->plus || i < nparam - 1);
4185 t = params[i];
4186 skip_white_(t);
4187 if (tok_is_(t, "{"))
4188 t = t->next, brace = true, comma = false;
4189 params[i] = t;
4190 paramlen[i] = 0;
4191 while (t) {
4192 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
4193 break; /* ... because we have hit a comma */
4194 if (comma && t->type == TOK_WHITESPACE
4195 && tok_is_(t->next, ","))
4196 break; /* ... or a space then a comma */
4197 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
4198 break; /* ... or a brace */
4199 t = t->next;
4200 paramlen[i]++;
4205 * OK, we have a MMacro structure together with a set of
4206 * parameters. We must now go through the expansion and push
4207 * copies of each Line on to istk->expansion. Substitution of
4208 * parameter tokens and macro-local tokens doesn't get done
4209 * until the single-line macro substitution process; this is
4210 * because delaying them allows us to change the semantics
4211 * later through %rotate.
4213 * First, push an end marker on to istk->expansion, mark this
4214 * macro as in progress, and set up its invocation-specific
4215 * variables.
4217 ll = nasm_malloc(sizeof(Line));
4218 ll->next = istk->expansion;
4219 ll->finishes = m;
4220 ll->first = NULL;
4221 istk->expansion = ll;
4223 m->in_progress = true;
4224 m->params = params;
4225 m->iline = tline;
4226 m->nparam = nparam;
4227 m->rotate = 0;
4228 m->paramlen = paramlen;
4229 m->unique = unique++;
4230 m->lineno = 0;
4232 m->next_active = istk->mstk;
4233 istk->mstk = m;
4235 for (l = m->expansion; l; l = l->next) {
4236 Token **tail;
4238 ll = nasm_malloc(sizeof(Line));
4239 ll->finishes = NULL;
4240 ll->next = istk->expansion;
4241 istk->expansion = ll;
4242 tail = &ll->first;
4244 for (t = l->first; t; t = t->next) {
4245 Token *x = t;
4246 switch (t->type) {
4247 case TOK_PREPROC_Q:
4248 tt = *tail = new_Token(NULL, TOK_ID, mname, 0);
4249 break;
4250 case TOK_PREPROC_QQ:
4251 tt = *tail = new_Token(NULL, TOK_ID, m->name, 0);
4252 break;
4253 case TOK_PREPROC_ID:
4254 if (t->text[1] == '0' && t->text[2] == '0') {
4255 dont_prepend = -1;
4256 x = label;
4257 if (!x)
4258 continue;
4260 /* fall through */
4261 default:
4262 tt = *tail = new_Token(NULL, x->type, x->text, 0);
4263 break;
4265 tail = &tt->next;
4267 *tail = NULL;
4271 * If we had a label, push it on as the first line of
4272 * the macro expansion.
4274 if (label) {
4275 if (dont_prepend < 0)
4276 free_tlist(startline);
4277 else {
4278 ll = nasm_malloc(sizeof(Line));
4279 ll->finishes = NULL;
4280 ll->next = istk->expansion;
4281 istk->expansion = ll;
4282 ll->first = startline;
4283 if (!dont_prepend) {
4284 while (label->next)
4285 label = label->next;
4286 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
4291 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
4293 return 1;
4296 /* The function that actually does the error reporting */
4297 static void verror(int severity, const char *fmt, va_list arg)
4299 char buff[1024];
4301 vsnprintf(buff, sizeof(buff), fmt, arg);
4303 if (istk && istk->mstk && istk->mstk->name)
4304 _error(severity, "(%s:%d) %s", istk->mstk->name,
4305 istk->mstk->lineno, buff);
4306 else
4307 _error(severity, "%s", buff);
4311 * Since preprocessor always operate only on the line that didn't
4312 * arrived yet, we should always use ERR_OFFBY1.
4314 static void error(int severity, const char *fmt, ...)
4316 va_list arg;
4318 /* If we're in a dead branch of IF or something like it, ignore the error */
4319 if (istk && istk->conds && !emitting(istk->conds->state))
4320 return;
4322 va_start(arg, fmt);
4323 verror(severity, fmt, arg);
4324 va_end(arg);
4328 * Because %else etc are evaluated in the state context
4329 * of the previous branch, errors might get lost with error():
4330 * %if 0 ... %else trailing garbage ... %endif
4331 * So %else etc should report errors with this function.
4333 static void error_precond(int severity, const char *fmt, ...)
4335 va_list arg;
4337 /* Only ignore the error if it's really in a dead branch */
4338 if (istk && istk->conds && istk->conds->state == COND_NEVER)
4339 return;
4341 va_start(arg, fmt);
4342 verror(severity, fmt, arg);
4343 va_end(arg);
4346 static void
4347 pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
4348 ListGen * listgen, StrList **deplist)
4350 Token *t;
4352 _error = errfunc;
4353 cstk = NULL;
4354 istk = nasm_malloc(sizeof(Include));
4355 istk->next = NULL;
4356 istk->conds = NULL;
4357 istk->expansion = NULL;
4358 istk->mstk = NULL;
4359 istk->fp = fopen(file, "r");
4360 istk->fname = NULL;
4361 src_set_fname(nasm_strdup(file));
4362 src_set_linnum(0);
4363 istk->lineinc = 1;
4364 if (!istk->fp)
4365 error(ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'",
4366 file);
4367 defining = NULL;
4368 nested_mac_count = 0;
4369 nested_rep_count = 0;
4370 init_macros();
4371 unique = 0;
4372 if (tasm_compatible_mode) {
4373 stdmacpos = nasm_stdmac;
4374 } else {
4375 stdmacpos = nasm_stdmac_after_tasm;
4377 any_extrastdmac = extrastdmac && *extrastdmac;
4378 do_predef = true;
4379 list = listgen;
4380 evaluate = eval;
4383 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
4384 * The caller, however, will also pass in 3 for preprocess-only so
4385 * we can set __PASS__ accordingly.
4387 pass = apass > 2 ? 2 : apass;
4389 dephead = deptail = deplist;
4390 if (deplist) {
4391 StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
4392 sl->next = NULL;
4393 strcpy(sl->str, file);
4394 *deptail = sl;
4395 deptail = &sl->next;
4399 * Define the __PASS__ macro. This is defined here unlike
4400 * all the other builtins, because it is special -- it varies between
4401 * passes.
4403 t = nasm_malloc(sizeof(*t));
4404 t->next = NULL;
4405 make_tok_num(t, apass);
4406 t->a.mac = NULL;
4407 define_smacro(NULL, "__PASS__", true, 0, t);
4410 static char *pp_getline(void)
4412 char *line;
4413 Token *tline;
4415 while (1) {
4417 * Fetch a tokenized line, either from the macro-expansion
4418 * buffer or from the input file.
4420 tline = NULL;
4421 while (istk->expansion && istk->expansion->finishes) {
4422 Line *l = istk->expansion;
4423 if (!l->finishes->name && l->finishes->in_progress > 1) {
4424 Line *ll;
4427 * This is a macro-end marker for a macro with no
4428 * name, which means it's not really a macro at all
4429 * but a %rep block, and the `in_progress' field is
4430 * more than 1, meaning that we still need to
4431 * repeat. (1 means the natural last repetition; 0
4432 * means termination by %exitrep.) We have
4433 * therefore expanded up to the %endrep, and must
4434 * push the whole block on to the expansion buffer
4435 * again. We don't bother to remove the macro-end
4436 * marker: we'd only have to generate another one
4437 * if we did.
4439 l->finishes->in_progress--;
4440 for (l = l->finishes->expansion; l; l = l->next) {
4441 Token *t, *tt, **tail;
4443 ll = nasm_malloc(sizeof(Line));
4444 ll->next = istk->expansion;
4445 ll->finishes = NULL;
4446 ll->first = NULL;
4447 tail = &ll->first;
4449 for (t = l->first; t; t = t->next) {
4450 if (t->text || t->type == TOK_WHITESPACE) {
4451 tt = *tail =
4452 new_Token(NULL, t->type, t->text, 0);
4453 tail = &tt->next;
4457 istk->expansion = ll;
4459 } else {
4461 * Check whether a `%rep' was started and not ended
4462 * within this macro expansion. This can happen and
4463 * should be detected. It's a fatal error because
4464 * I'm too confused to work out how to recover
4465 * sensibly from it.
4467 if (defining) {
4468 if (defining->name)
4469 error(ERR_PANIC,
4470 "defining with name in expansion");
4471 else if (istk->mstk->name)
4472 error(ERR_FATAL,
4473 "`%%rep' without `%%endrep' within"
4474 " expansion of macro `%s'",
4475 istk->mstk->name);
4479 * FIXME: investigate the relationship at this point between
4480 * istk->mstk and l->finishes
4483 MMacro *m = istk->mstk;
4484 istk->mstk = m->next_active;
4485 if (m->name) {
4487 * This was a real macro call, not a %rep, and
4488 * therefore the parameter information needs to
4489 * be freed.
4491 nasm_free(m->params);
4492 free_tlist(m->iline);
4493 nasm_free(m->paramlen);
4494 l->finishes->in_progress = false;
4495 } else
4496 free_mmacro(m);
4498 istk->expansion = l->next;
4499 nasm_free(l);
4500 list->downlevel(LIST_MACRO);
4503 while (1) { /* until we get a line we can use */
4505 if (istk->expansion) { /* from a macro expansion */
4506 char *p;
4507 Line *l = istk->expansion;
4508 if (istk->mstk)
4509 istk->mstk->lineno++;
4510 tline = l->first;
4511 istk->expansion = l->next;
4512 nasm_free(l);
4513 p = detoken(tline, false);
4514 list->line(LIST_MACRO, p);
4515 nasm_free(p);
4516 break;
4518 line = read_line();
4519 if (line) { /* from the current input file */
4520 line = prepreproc(line);
4521 tline = tokenize(line);
4522 nasm_free(line);
4523 break;
4526 * The current file has ended; work down the istk
4529 Include *i = istk;
4530 fclose(i->fp);
4531 if (i->conds)
4532 error(ERR_FATAL,
4533 "expected `%%endif' before end of file");
4534 /* only set line and file name if there's a next node */
4535 if (i->next) {
4536 src_set_linnum(i->lineno);
4537 nasm_free(src_set_fname(i->fname));
4539 istk = i->next;
4540 list->downlevel(LIST_INCLUDE);
4541 nasm_free(i);
4542 if (!istk)
4543 return NULL;
4544 if (istk->expansion && istk->expansion->finishes)
4545 break;
4550 * We must expand MMacro parameters and MMacro-local labels
4551 * _before_ we plunge into directive processing, to cope
4552 * with things like `%define something %1' such as STRUC
4553 * uses. Unless we're _defining_ a MMacro, in which case
4554 * those tokens should be left alone to go into the
4555 * definition; and unless we're in a non-emitting
4556 * condition, in which case we don't want to meddle with
4557 * anything.
4559 if (!defining && !(istk->conds && !emitting(istk->conds->state))
4560 && !(istk->mstk && !istk->mstk->in_progress)) {
4561 tline = expand_mmac_params(tline);
4565 * Check the line to see if it's a preprocessor directive.
4567 if (do_directive(tline) == DIRECTIVE_FOUND) {
4568 continue;
4569 } else if (defining) {
4571 * We're defining a multi-line macro. We emit nothing
4572 * at all, and just
4573 * shove the tokenized line on to the macro definition.
4575 Line *l = nasm_malloc(sizeof(Line));
4576 l->next = defining->expansion;
4577 l->first = tline;
4578 l->finishes = NULL;
4579 defining->expansion = l;
4580 continue;
4581 } else if (istk->conds && !emitting(istk->conds->state)) {
4583 * We're in a non-emitting branch of a condition block.
4584 * Emit nothing at all, not even a blank line: when we
4585 * emerge from the condition we'll give a line-number
4586 * directive so we keep our place correctly.
4588 free_tlist(tline);
4589 continue;
4590 } else if (istk->mstk && !istk->mstk->in_progress) {
4592 * We're in a %rep block which has been terminated, so
4593 * we're walking through to the %endrep without
4594 * emitting anything. Emit nothing at all, not even a
4595 * blank line: when we emerge from the %rep block we'll
4596 * give a line-number directive so we keep our place
4597 * correctly.
4599 free_tlist(tline);
4600 continue;
4601 } else {
4602 tline = expand_smacro(tline);
4603 if (!expand_mmacro(tline)) {
4605 * De-tokenize the line again, and emit it.
4607 line = detoken(tline, true);
4608 free_tlist(tline);
4609 break;
4610 } else {
4611 continue; /* expand_mmacro calls free_tlist */
4616 return line;
4619 static void pp_cleanup(int pass)
4621 if (defining) {
4622 if(defining->name) {
4623 error(ERR_NONFATAL,
4624 "end of file while still defining macro `%s'",
4625 defining->name);
4626 } else {
4627 error(ERR_NONFATAL, "end of file while still in %%rep");
4630 free_mmacro(defining);
4632 while (cstk)
4633 ctx_pop();
4634 free_macros();
4635 while (istk) {
4636 Include *i = istk;
4637 istk = istk->next;
4638 fclose(i->fp);
4639 nasm_free(i->fname);
4640 nasm_free(i);
4642 while (cstk)
4643 ctx_pop();
4644 nasm_free(src_set_fname(NULL));
4645 if (pass == 0) {
4646 IncPath *i;
4647 free_llist(predef);
4648 delete_Blocks();
4649 while ((i = ipath)) {
4650 ipath = i->next;
4651 if (i->path)
4652 nasm_free(i->path);
4653 nasm_free(i);
4658 void pp_include_path(char *path)
4660 IncPath *i;
4662 i = nasm_malloc(sizeof(IncPath));
4663 i->path = path ? nasm_strdup(path) : NULL;
4664 i->next = NULL;
4666 if (ipath != NULL) {
4667 IncPath *j = ipath;
4668 while (j->next != NULL)
4669 j = j->next;
4670 j->next = i;
4671 } else {
4672 ipath = i;
4676 void pp_pre_include(char *fname)
4678 Token *inc, *space, *name;
4679 Line *l;
4681 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
4682 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
4683 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
4685 l = nasm_malloc(sizeof(Line));
4686 l->next = predef;
4687 l->first = inc;
4688 l->finishes = NULL;
4689 predef = l;
4692 void pp_pre_define(char *definition)
4694 Token *def, *space;
4695 Line *l;
4696 char *equals;
4698 equals = strchr(definition, '=');
4699 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4700 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
4701 if (equals)
4702 *equals = ' ';
4703 space->next = tokenize(definition);
4704 if (equals)
4705 *equals = '=';
4707 l = nasm_malloc(sizeof(Line));
4708 l->next = predef;
4709 l->first = def;
4710 l->finishes = NULL;
4711 predef = l;
4714 void pp_pre_undefine(char *definition)
4716 Token *def, *space;
4717 Line *l;
4719 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4720 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
4721 space->next = tokenize(definition);
4723 l = nasm_malloc(sizeof(Line));
4724 l->next = predef;
4725 l->first = def;
4726 l->finishes = NULL;
4727 predef = l;
4731 * Added by Keith Kanios:
4733 * This function is used to assist with "runtime" preprocessor
4734 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
4736 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
4737 * PASS A VALID STRING TO THIS FUNCTION!!!!!
4740 void pp_runtime(char *definition)
4742 Token *def;
4744 def = tokenize(definition);
4745 if(do_directive(def) == NO_DIRECTIVE_FOUND)
4746 free_tlist(def);
4750 void pp_extra_stdmac(macros_t *macros)
4752 extrastdmac = macros;
4755 static void make_tok_num(Token * tok, int64_t val)
4757 char numbuf[20];
4758 snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
4759 tok->text = nasm_strdup(numbuf);
4760 tok->type = TOK_NUMBER;
4763 Preproc nasmpp = {
4764 pp_reset,
4765 pp_getline,
4766 pp_cleanup