BR 3392652: hold smacro expansion warnings until we are sure
[nasm.git] / asm / preproc.c
blob82b3825e54d0edaa0e9a0b258c9034e80ae8ed1a
1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2020 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 "nctype.h"
67 #include "nasm.h"
68 #include "nasmlib.h"
69 #include "error.h"
70 #include "preproc.h"
71 #include "hashtbl.h"
72 #include "quote.h"
73 #include "stdscan.h"
74 #include "eval.h"
75 #include "tokens.h"
76 #include "tables.h"
77 #include "listing.h"
79 typedef struct SMacro SMacro;
80 typedef struct MMacro MMacro;
81 typedef struct MMacroInvocation MMacroInvocation;
82 typedef struct Context Context;
83 typedef struct Token Token;
84 typedef struct Line Line;
85 typedef struct Include Include;
86 typedef struct Cond Cond;
89 * This is the internal form which we break input lines up into.
90 * Typically stored in linked lists.
92 * Note that `type' serves a double meaning: TOK_SMAC_START_PARAMS is
93 * not necessarily used as-is, but is also used to encode the number
94 * and expansion type of substituted parameter. So in the definition
96 * %define a(x,=y) ( (x) & ~(y) )
98 * the token representing `x' will have its type changed to
99 * tok_smac_param(0) but the one representing `y' will be
100 * tok_smac_param(1); see the accessor functions below.
102 * TOK_INTERNAL_STRING is a string which has been unquoted, but should
103 * be treated as if it was a quoted string. The code is free to change
104 * one into the other at will. TOK_NAKED_STRING is a text token which
105 * should be treated as a string, but which MUST NOT be turned into a
106 * quoted string. TOK_INTERNAL_STRINGs can contain any character,
107 * including NUL, but TOK_NAKED_STRING must be a valid C string.
109 enum pp_token_type {
110 TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT,
111 TOK_CORRUPT, /* Token text modified in an unsafe manner, now bogus */
112 TOK_BLOCK, /* Storage block pointer, not a real token */
113 TOK_ID,
114 TOK_PREPROC_ID, TOK_MMACRO_PARAM, TOK_LOCAL_SYMBOL,
115 TOK_LOCAL_MACRO, TOK_ENVIRON, TOK_STRING,
116 TOK_NUMBER, TOK_FLOAT, TOK_OTHER,
117 TOK_INTERNAL_STRING, TOK_NAKED_STRING,
118 TOK_PREPROC_Q, TOK_PREPROC_QQ,
119 TOK_PASTE, /* %+ */
120 TOK_COND_COMMA, /* %, */
121 TOK_INDIRECT, /* %[...] */
122 TOK_XDEF_PARAM, /* Used during %xdefine processing */
123 TOK_SMAC_START_PARAMS, /* MUST BE LAST IN THE LIST!!! */
124 TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
127 static inline enum pp_token_type tok_smac_param(int param)
129 return TOK_SMAC_START_PARAMS + param;
131 static int smac_nparam(enum pp_token_type toktype)
133 return toktype - TOK_SMAC_START_PARAMS;
135 static bool is_smac_param(enum pp_token_type toktype)
137 return toktype >= TOK_SMAC_START_PARAMS;
140 #define PP_CONCAT_MASK(x) (1U << (x))
142 struct tokseq_match {
143 int mask_head;
144 int mask_tail;
148 * This is tuned so struct Token should be 64 bytes on 64-bit
149 * systems and 32 bytes on 32-bit systems. It enables them
150 * to be nicely cache aligned, and the text to still be kept
151 * inline for nearly all tokens.
153 * We prohibit tokens of length > MAX_TEXT even though
154 * length here is an unsigned int; this avoids problems
155 * if the length is passed through an interface with type "int",
156 * and is absurdly large anyway.
158 * For the text mode, in pointer mode the pointer is stored at the end
159 * of the union and the pad field is cleared. This allows short tokens
160 * to be unconditionally tested for by only looking at the first text
161 * bytes and not examining the type or len fields.
163 #define INLINE_TEXT (7*sizeof(char *)-sizeof(enum pp_token_type)-sizeof(unsigned int)-1)
164 #define MAX_TEXT (INT_MAX-2)
166 struct Token {
167 Token *next;
168 enum pp_token_type type;
169 unsigned int len;
170 union {
171 char a[INLINE_TEXT+1];
172 struct {
173 char pad[INLINE_TEXT+1 - sizeof(char *)];
174 char *ptr;
175 } p;
176 } text;
180 * Note on the storage of both SMacro and MMacros: the hash table
181 * indexes them case-insensitively, and we then have to go through a
182 * linked list of potential case aliases (and, for MMacros, parameter
183 * ranges); this is to preserve the matching semantics of the earlier
184 * code. If the number of case aliases for a specific macro is a
185 * performance issue, you may want to reconsider your coding style.
189 * Function call tp obtain the expansion of an smacro
191 typedef Token *(*ExpandSMacro)(const SMacro *s, Token **params, int nparams);
194 * Store the definition of a single-line macro.
196 enum sparmflags {
197 SPARM_PLAIN = 0,
198 SPARM_EVAL = 1, /* Evaluate as a numeric expression (=) */
199 SPARM_STR = 2, /* Convert to quoted string ($) */
200 SPARM_NOSTRIP = 4, /* Don't strip braces (!) */
201 SPARM_GREEDY = 8 /* Greedy final parameter (+) */
204 struct smac_param {
205 Token name;
206 enum sparmflags flags;
209 struct SMacro {
210 SMacro *next; /* MUST BE FIRST - see free_smacro() */
211 char *name;
212 Token *expansion;
213 ExpandSMacro expand;
214 intorptr expandpvt;
215 struct smac_param *params;
216 int nparam;
217 bool greedy;
218 bool casesense;
219 bool in_progress;
220 bool alias; /* This is an alias macro */
224 * Store the definition of a multi-line macro. This is also used to
225 * store the interiors of `%rep...%endrep' blocks, which are
226 * effectively self-re-invoking multi-line macros which simply
227 * don't have a name or bother to appear in the hash tables. %rep
228 * blocks are signified by having a NULL `name' field.
230 * In a MMacro describing a `%rep' block, the `in_progress' field
231 * isn't merely boolean, but gives the number of repeats left to
232 * run.
234 * The `next' field is used for storing MMacros in hash tables; the
235 * `next_active' field is for stacking them on istk entries.
237 * When a MMacro is being expanded, `params', `iline', `nparam',
238 * `paramlen', `rotate' and `unique' are local to the invocation.
242 * Expansion stack. Note that .mmac can point back to the macro itself,
243 * whereas .mstk cannot.
245 struct mstk {
246 MMacro *mstk; /* Any expansion, real macro or not */
247 MMacro *mmac; /* Highest level actual mmacro */
250 struct MMacro {
251 MMacro *next;
252 #if 0
253 MMacroInvocation *prev; /* previous invocation */
254 #endif
255 char *name;
256 int nparam_min, nparam_max;
257 bool casesense;
258 bool plus; /* is the last parameter greedy? */
259 bool nolist; /* is this macro listing-inhibited? */
260 bool capture_label; /* macro definition has %00; capture label */
261 int32_t in_progress; /* is this macro currently being expanded? */
262 int32_t max_depth; /* maximum number of recursive expansions allowed */
263 Token *dlist; /* All defaults as one list */
264 Token **defaults; /* Parameter default pointers */
265 int ndefs; /* number of default parameters */
266 Line *expansion;
268 struct mstk mstk; /* Macro expansion stack */
269 struct mstk dstk; /* Macro definitions stack */
270 Token **params; /* actual parameters */
271 Token *iline; /* invocation line */
272 unsigned int nparam, rotate;
273 char *iname; /* name invoked as */
274 int *paramlen;
275 uint64_t unique;
276 int lineno; /* Current line number on expansion */
277 uint64_t condcnt; /* number of if blocks... */
279 const char *fname; /* File where defined */
280 int32_t xline; /* First line in macro */
284 /* Store the definition of a multi-line macro, as defined in a
285 * previous recursive macro expansion.
287 #if 0
289 struct MMacroInvocation {
290 MMacroInvocation *prev; /* previous invocation */
291 Token **params; /* actual parameters */
292 Token *iline; /* invocation line */
293 unsigned int nparam, rotate;
294 int *paramlen;
295 uint64_t unique;
296 uint64_t condcnt;
299 #endif
302 * The context stack is composed of a linked list of these.
304 struct Context {
305 Context *next;
306 const char *name;
307 struct hash_table localmac;
308 uint64_t number;
309 unsigned int depth;
313 static inline const char *tok_text(const struct Token *t)
315 return (t->len <= INLINE_TEXT) ? t->text.a : t->text.p.ptr;
319 * Returns a mutable pointer to the text buffer. The text can be changed,
320 * but the length MUST NOT CHANGE, in either direction; nor is it permitted
321 * to pad with null characters to create an artificially shorter string.
323 static inline char *tok_text_buf(struct Token *t)
325 return (t->len <= INLINE_TEXT) ? t->text.a : t->text.p.ptr;
328 static inline unsigned int tok_check_len(size_t len)
330 if (unlikely(len > MAX_TEXT))
331 nasm_fatal("impossibly large token");
333 return len;
336 static inline bool tok_text_match(const struct Token *a, const struct Token *b)
338 return a->len == b->len && !memcmp(tok_text(a), tok_text(b), a->len);
341 static inline bool tok_match(const struct Token *a, const struct Token *b)
343 return a->type == b->type && tok_text_match(a, b);
346 /* strlen() variant useful for set_text() and its variants */
347 static size_t tok_strlen(const char *str)
349 return strnlen(str, MAX_TEXT+1);
353 * Set the text field to a copy of the given string; the length if
354 * not given should be obtained with tok_strlen().
356 static Token *set_text(struct Token *t, const char *text, size_t len)
358 char *textp;
360 if (t->len > INLINE_TEXT)
361 nasm_free(t->text.p.ptr);
363 nasm_zero(t->text.a);
365 t->len = tok_check_len(len);
366 textp = (len > INLINE_TEXT)
367 ? (t->text.p.ptr = nasm_malloc(len+1)) : t->text.a;
368 memcpy(textp, text, len+1);
369 return t;
373 * Set the text field to the existing pre-allocated string, either
374 * taking over or freeing the allocation in the process.
376 static Token *set_text_free(struct Token *t, char *text, unsigned int len)
378 if (t->len > INLINE_TEXT)
379 nasm_free(t->text.p.ptr);
381 nasm_zero(t->text.a);
383 t->len = tok_check_len(len);
384 if (len > INLINE_TEXT) {
385 t->text.p.ptr = text;
386 } else {
387 memcpy(t->text.a, text, len+1);
388 nasm_free(text);
391 return t;
395 * Allocate a new buffer containing a copy of the text field
396 * of the token.
398 static char *dup_text(const struct Token *t)
400 size_t size = t->len + 1;
401 char *p = nasm_malloc(size);
403 return memcpy(p, tok_text(t), size);
407 * Multi-line macro definitions are stored as a linked list of
408 * these, which is essentially a container to allow several linked
409 * lists of Tokens.
411 * Note that in this module, linked lists are treated as stacks
412 * wherever possible. For this reason, Lines are _pushed_ on to the
413 * `expansion' field in MMacro structures, so that the linked list,
414 * if walked, would give the macro lines in reverse order; this
415 * means that we can walk the list when expanding a macro, and thus
416 * push the lines on to the `expansion' field in _istk_ in reverse
417 * order (so that when popped back off they are in the right
418 * order). It may seem cockeyed, and it relies on my design having
419 * an even number of steps in, but it works...
421 * Some of these structures, rather than being actual lines, are
422 * markers delimiting the end of the expansion of a given macro.
423 * This is for use in the cycle-tracking and %rep-handling code.
424 * Such structures have `finishes' non-NULL, and `first' NULL. All
425 * others have `finishes' NULL, but `first' may still be NULL if
426 * the line is blank.
428 struct Line {
429 Line *next;
430 MMacro *finishes;
431 Token *first;
435 * To handle an arbitrary level of file inclusion, we maintain a
436 * stack (ie linked list) of these things.
438 struct Include {
439 Include *next;
440 FILE *fp;
441 Cond *conds;
442 Line *expansion;
443 const char *fname;
444 struct mstk mstk;
445 int lineno, lineinc;
446 bool nolist;
450 * File real name hash, so we don't have to re-search the include
451 * path for every pass (and potentially more than that if a file
452 * is used more than once.)
454 struct hash_table FileHash;
457 * Counters to trap on insane macro recursion or processing.
458 * Note: for smacros these count *down*, for mmacros they count *up*.
460 struct deadman {
461 int64_t total; /* Total number of macros/tokens */
462 int64_t levels; /* Descent depth across all macros */
463 bool triggered; /* Already triggered, no need for error msg */
466 static struct deadman smacro_deadman, mmacro_deadman;
469 * Conditional assembly: we maintain a separate stack of these for
470 * each level of file inclusion. (The only reason we keep the
471 * stacks separate is to ensure that a stray `%endif' in a file
472 * included from within the true branch of a `%if' won't terminate
473 * it and cause confusion: instead, rightly, it'll cause an error.)
475 enum cond_state {
477 * These states are for use just after %if or %elif: IF_TRUE
478 * means the condition has evaluated to truth so we are
479 * currently emitting, whereas IF_FALSE means we are not
480 * currently emitting but will start doing so if a %else comes
481 * up. In these states, all directives are admissible: %elif,
482 * %else and %endif. (And of course %if.)
484 COND_IF_TRUE, COND_IF_FALSE,
486 * These states come up after a %else: ELSE_TRUE means we're
487 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
488 * any %elif or %else will cause an error.
490 COND_ELSE_TRUE, COND_ELSE_FALSE,
492 * These states mean that we're not emitting now, and also that
493 * nothing until %endif will be emitted at all. COND_DONE is
494 * used when we've had our moment of emission
495 * and have now started seeing %elifs. COND_NEVER is used when
496 * the condition construct in question is contained within a
497 * non-emitting branch of a larger condition construct,
498 * or if there is an error.
500 COND_DONE, COND_NEVER
502 struct Cond {
503 Cond *next;
504 enum cond_state state;
506 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
509 * These defines are used as the possible return values for do_directive
511 #define NO_DIRECTIVE_FOUND 0
512 #define DIRECTIVE_FOUND 1
515 * Condition codes. Note that we use c_ prefix not C_ because C_ is
516 * used in nasm.h for the "real" condition codes. At _this_ level,
517 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
518 * ones, so we need a different enum...
520 static const char * const conditions[] = {
521 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
522 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
523 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
525 enum pp_conds {
526 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
527 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
528 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
529 c_none = -1
531 static const enum pp_conds inverse_ccs[] = {
532 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
533 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,
534 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
538 * Directive names.
540 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
541 static int is_condition(enum preproc_token arg)
543 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
546 /* For TASM compatibility we need to be able to recognise TASM compatible
547 * conditional compilation directives. Using the NASM pre-processor does
548 * not work, so we look for them specifically from the following list and
549 * then jam in the equivalent NASM directive into the input stream.
552 enum {
553 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
554 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
557 static const char * const tasm_directives[] = {
558 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
559 "ifndef", "include", "local"
562 static int StackSize = 4;
563 static const char *StackPointer = "ebp";
564 static int ArgOffset = 8;
565 static int LocalOffset = 0;
567 static Context *cstk;
568 static Include *istk;
569 static const struct strlist *ipath_list;
570 static bool do_aliases;
572 static struct strlist *deplist;
574 static uint64_t unique; /* unique identifier numbers */
576 static Line *predef = NULL;
577 static bool do_predef;
578 static enum preproc_mode pp_mode;
581 * The current set of multi-line macros we have defined.
583 static struct hash_table mmacros;
586 * The current set of single-line macros we have defined.
588 static struct hash_table smacros;
591 * The multi-line macro we are currently defining, or the %rep
592 * block we are currently reading, if any.
594 static MMacro *defining;
596 static uint64_t nested_mac_count;
597 static uint64_t nested_rep_count;
600 * The number of macro parameters to allocate space for at a time.
602 #define PARAM_DELTA 16
605 * The standard macro set: defined in macros.c in a set of arrays.
606 * This gives our position in any macro set, while we are processing it.
607 * The stdmacset is an array of such macro sets.
609 static macros_t *stdmacpos;
610 static macros_t **stdmacnext;
611 static macros_t *stdmacros[8];
612 static macros_t *extrastdmac;
615 * Map of which %use packages have been loaded
617 static bool *use_loaded;
620 * Forward declarations.
622 static void pp_add_stdmac(macros_t *macros);
623 static Token *expand_mmac_params(Token * tline);
624 static Token *expand_smacro(Token * tline);
625 static Token *expand_id(Token * tline);
626 static Context *get_ctx(const char *name, const char **namep);
627 static Token *make_tok_num(Token *next, int64_t val);
628 static Token *make_tok_qstr(Token *next, const char *str);
629 static Token *make_tok_qstr_len(Token *next, const char *str, size_t len);
630 static Token *make_tok_char(Token *next, char op);
631 static Token *new_Token(Token * next, enum pp_token_type type,
632 const char *text, size_t txtlen);
633 static Token *new_Token_free(Token * next, enum pp_token_type type,
634 char *text, size_t txtlen);
635 static Token *dup_Token(Token *next, const Token *src);
636 static Token *new_White(Token *next);
637 static Token *delete_Token(Token *t);
638 static Token *steal_Token(Token *dst, Token *src);
639 static const struct use_package *
640 get_use_pkg(Token *t, const char *dname, const char **name);
641 static void mark_smac_params(Token *tline, const SMacro *tmpl,
642 enum pp_token_type type);
644 /* Safe test for token type, false on x == NULL */
645 static inline bool tok_type(const Token *x, enum pp_token_type t)
647 return x && x->type == t;
650 /* Whitespace token? */
651 static inline bool tok_white(const Token *x)
653 return tok_type(x, TOK_WHITESPACE);
656 /* Skip past any whitespace */
657 static inline Token *skip_white(Token *x)
659 while (tok_white(x))
660 x = x->next;
662 return x;
665 /* Delete any whitespace */
666 static Token *zap_white(Token *x)
668 while (tok_white(x))
669 x = delete_Token(x);
671 return x;
675 * Single special character tests. The use of & rather than && is intentional; it
676 * tells the compiler that it is safe to access text.a[1] unconditionally; hopefully
677 * a smart compiler should turn it into a 16-bit memory reference.
679 static inline bool tok_is(const Token *x, char c)
681 return x && ((x->text.a[0] == c) & !x->text.a[1]);
684 /* True if any other kind of token that "c", but not NULL */
685 static inline bool tok_isnt(const Token *x, char c)
687 return x && !((x->text.a[0] == c) & !x->text.a[1]);
691 * Unquote a token if it is a string, and set its type to
692 * TOK_INTERNAL_STRING.
694 static const char *unquote_token(Token *t)
696 if (t->type != TOK_STRING)
697 return tok_text(t);
699 t->type = TOK_INTERNAL_STRING;
701 if (t->len > INLINE_TEXT) {
702 char *p = t->text.p.ptr;
704 t->len = nasm_unquote(p, NULL);
706 if (t->len <= INLINE_TEXT) {
707 nasm_zero(t->text.a);
708 memcpy(t->text.a, p, t->len);
709 nasm_free(p);
710 return t->text.a;
711 } else {
712 return p;
714 } else {
715 t->len = nasm_unquote(t->text.a, NULL);
716 return t->text.a;
721 * Same as unquote_token(), but error out if the resulting string
722 * contains unacceptable control characters.
724 static const char *unquote_token_cstr(Token *t)
726 if (t->type != TOK_STRING)
727 return tok_text(t);
729 t->type = TOK_INTERNAL_STRING;
731 if (t->len > INLINE_TEXT) {
732 char *p = t->text.p.ptr;
734 t->len = nasm_unquote_cstr(p, NULL);
736 if (t->len <= INLINE_TEXT) {
737 nasm_zero(t->text.a);
738 memcpy(t->text.a, p, t->len);
739 nasm_free(p);
740 return t->text.a;
741 } else {
742 return p;
744 } else {
745 t->len = nasm_unquote_cstr(t->text.a, NULL);
746 return t->text.a;
751 * Convert a TOK_INTERNAL_STRING token to a quoted
752 * TOK_STRING tokens.
754 static Token *quote_any_token(Token *t);
755 static inline Token *quote_token(Token *t)
757 if (likely(!tok_is(t, TOK_INTERNAL_STRING)))
758 return t;
760 return quote_any_token(t);
764 * Convert *any* kind of token to a quoted
765 * TOK_STRING token.
767 static Token *quote_any_token(Token *t)
769 size_t len;
770 char *p;
772 p = nasm_quote(tok_text(t), &len);
773 t->type = TOK_STRING;
774 return set_text_free(t, p, len);
778 * In-place reverse a list of tokens.
780 static Token *reverse_tokens(Token *t)
782 Token *prev = NULL;
783 Token *next;
785 while (t) {
786 next = t->next;
787 t->next = prev;
788 prev = t;
789 t = next;
792 return prev;
796 * getenv() variant operating on an input token
798 static const char *pp_getenv(const Token *t, bool warn)
800 const char *txt = tok_text(t);
801 const char *v;
802 char *buf = NULL;
803 bool is_string = false;
805 if (!t)
806 return NULL;
808 switch (t->type) {
809 case TOK_ENVIRON:
810 txt += 2; /* Skip leading %! */
811 is_string = nasm_isquote(*txt);
812 break;
814 case TOK_STRING:
815 is_string = true;
816 break;
818 case TOK_INTERNAL_STRING:
819 case TOK_NAKED_STRING:
820 case TOK_ID:
821 is_string = false;
822 break;
824 default:
825 return NULL;
828 if (is_string) {
829 buf = nasm_strdup(txt);
830 nasm_unquote_cstr(buf, NULL);
831 txt = buf;
834 v = getenv(txt);
835 if (warn && !v) {
837 *!environment [on] nonexistent environment variable
838 *! warns if a nonexistent environment variable
839 *! is accessed using the \c{%!} preprocessor
840 *! construct (see \k{getenv}.) Such environment
841 *! variables are treated as empty (with this
842 *! warning issued) starting in NASM 2.15;
843 *! earlier versions of NASM would treat this as
844 *! an error.
846 nasm_warn(WARN_ENVIRONMENT, "nonexistent environment variable `%s'", txt);
847 v = "";
850 if (buf)
851 nasm_free(buf);
853 return v;
857 * Handle TASM specific directives, which do not contain a % in
858 * front of them. We do it here because I could not find any other
859 * place to do it for the moment, and it is a hack (ideally it would
860 * be nice to be able to use the NASM pre-processor to do it).
862 static char *check_tasm_directive(char *line)
864 int32_t i, j, k, m, len;
865 char *p, *q, *oldline, oldchar;
867 p = nasm_skip_spaces(line);
869 /* Binary search for the directive name */
870 i = -1;
871 j = ARRAY_SIZE(tasm_directives);
872 q = nasm_skip_word(p);
873 len = q - p;
874 if (len) {
875 oldchar = p[len];
876 p[len] = 0;
877 while (j - i > 1) {
878 k = (j + i) / 2;
879 m = nasm_stricmp(p, tasm_directives[k]);
880 if (m == 0) {
881 /* We have found a directive, so jam a % in front of it
882 * so that NASM will then recognise it as one if it's own.
884 p[len] = oldchar;
885 len = strlen(p);
886 oldline = line;
887 line = nasm_malloc(len + 2);
888 line[0] = '%';
889 if (k == TM_IFDIFI) {
891 * NASM does not recognise IFDIFI, so we convert
892 * it to %if 0. This is not used in NASM
893 * compatible code, but does need to parse for the
894 * TASM macro package.
896 strcpy(line + 1, "if 0");
897 } else {
898 memcpy(line + 1, p, len + 1);
900 nasm_free(oldline);
901 return line;
902 } else if (m < 0) {
903 j = k;
904 } else
905 i = k;
907 p[len] = oldchar;
909 return line;
913 * The pre-preprocessing stage... This function translates line
914 * number indications as they emerge from GNU cpp (`# lineno "file"
915 * flags') into NASM preprocessor line number indications (`%line
916 * lineno file').
918 static char *prepreproc(char *line)
920 int lineno, fnlen;
921 char *fname, *oldline;
923 if (line[0] == '#' && line[1] == ' ') {
924 oldline = line;
925 fname = oldline + 2;
926 lineno = atoi(fname);
927 fname += strspn(fname, "0123456789 ");
928 if (*fname == '"')
929 fname++;
930 fnlen = strcspn(fname, "\"");
931 line = nasm_malloc(20 + fnlen);
932 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
933 nasm_free(oldline);
935 if (tasm_compatible_mode)
936 return check_tasm_directive(line);
937 return line;
941 * Free a linked list of tokens.
943 static void free_tlist(Token * list)
945 while (list)
946 list = delete_Token(list);
950 * Free a linked list of lines.
952 static void free_llist(Line * list)
954 Line *l, *tmp;
955 list_for_each_safe(l, tmp, list) {
956 free_tlist(l->first);
957 nasm_free(l);
962 * Free an array of linked lists of tokens
964 static void free_tlist_array(Token **array, size_t nlists)
966 Token **listp = array;
968 while (nlists--)
969 free_tlist(*listp++);
971 nasm_free(array);
975 * Duplicate a linked list of tokens.
977 static Token *dup_tlist(const Token *list, Token ***tailp)
979 Token *newlist = NULL;
980 Token **tailpp = &newlist;
981 const Token *t;
983 list_for_each(t, list) {
984 Token *nt;
985 *tailpp = nt = dup_Token(NULL, t);
986 tailpp = &nt->next;
989 if (tailp) {
990 **tailp = newlist;
991 *tailp = tailpp;
994 return newlist;
998 * Duplicate a linked list of tokens with a maximum count
1000 static Token *dup_tlistn(const Token *list, size_t cnt, Token ***tailp)
1002 Token *newlist = NULL;
1003 Token **tailpp = &newlist;
1004 const Token *t;
1006 list_for_each(t, list) {
1007 Token *nt;
1008 if (!cnt--)
1009 break;
1010 *tailpp = nt = dup_Token(NULL, t);
1011 tailpp = &nt->next;
1014 if (tailp) {
1015 **tailp = newlist;
1016 if (newlist)
1017 *tailp = tailpp;
1020 return newlist;
1024 * Duplicate a linked list of tokens in reverse order
1026 static Token *dup_tlist_reverse(const Token *list, Token *tail)
1028 const Token *t;
1030 list_for_each(t, list)
1031 tail = dup_Token(tail, t);
1033 return tail;
1037 * Free an MMacro
1039 static void free_mmacro(MMacro * m)
1041 nasm_free(m->name);
1042 free_tlist(m->dlist);
1043 nasm_free(m->defaults);
1044 free_llist(m->expansion);
1045 nasm_free(m);
1049 * Clear or free an SMacro
1051 static void free_smacro_members(SMacro *s)
1053 if (s->params) {
1054 int i;
1055 for (i = 0; i < s->nparam; i++) {
1056 if (s->params[i].name.len > INLINE_TEXT)
1057 nasm_free(s->params[i].name.text.p.ptr);
1059 nasm_free(s->params);
1061 nasm_free(s->name);
1062 free_tlist(s->expansion);
1065 static void clear_smacro(SMacro *s)
1067 free_smacro_members(s);
1068 /* Wipe everything except the next pointer */
1069 memset(&s->next + 1, 0, sizeof *s - sizeof s->next);
1073 * Free an SMacro
1075 static void free_smacro(SMacro *s)
1077 free_smacro_members(s);
1078 nasm_free(s);
1082 * Free all currently defined macros, and free the hash tables
1084 static void free_smacro_table(struct hash_table *smt)
1086 struct hash_iterator it;
1087 const struct hash_node *np;
1089 hash_for_each(smt, it, np) {
1090 SMacro *tmp;
1091 SMacro *s = np->data;
1092 nasm_free((void *)np->key);
1093 list_for_each_safe(s, tmp, s)
1094 free_smacro(s);
1096 hash_free(smt);
1099 static void free_mmacro_table(struct hash_table *mmt)
1101 struct hash_iterator it;
1102 const struct hash_node *np;
1104 hash_for_each(mmt, it, np) {
1105 MMacro *tmp;
1106 MMacro *m = np->data;
1107 nasm_free((void *)np->key);
1108 list_for_each_safe(m, tmp, m)
1109 free_mmacro(m);
1111 hash_free(mmt);
1114 static void free_macros(void)
1116 free_smacro_table(&smacros);
1117 free_mmacro_table(&mmacros);
1121 * Initialize the hash tables
1123 static void init_macros(void)
1128 * Pop the context stack.
1130 static void ctx_pop(void)
1132 Context *c = cstk;
1134 cstk = cstk->next;
1135 free_smacro_table(&c->localmac);
1136 nasm_free((char *)c->name);
1137 nasm_free(c);
1141 * Search for a key in the hash index; adding it if necessary
1142 * (in which case we initialize the data pointer to NULL.)
1144 static void **
1145 hash_findi_add(struct hash_table *hash, const char *str)
1147 struct hash_insert hi;
1148 void **r;
1149 char *strx;
1150 size_t l = strlen(str) + 1;
1152 r = hash_findib(hash, str, l, &hi);
1153 if (r)
1154 return r;
1156 strx = nasm_malloc(l); /* Use a more efficient allocator here? */
1157 memcpy(strx, str, l);
1158 return hash_add(&hi, strx, NULL);
1162 * Like hash_findi, but returns the data element rather than a pointer
1163 * to it. Used only when not adding a new element, hence no third
1164 * argument.
1166 static void *
1167 hash_findix(struct hash_table *hash, const char *str)
1169 void **p;
1171 p = hash_findi(hash, str, NULL);
1172 return p ? *p : NULL;
1176 * read line from standart macros set,
1177 * if there no more left -- return NULL
1179 static char *line_from_stdmac(void)
1181 unsigned char c;
1182 const unsigned char *p = stdmacpos;
1183 char *line, *q;
1184 size_t len = 0;
1186 if (!stdmacpos)
1187 return NULL;
1190 * 32-126 is ASCII, 127 is end of line, 128-31 are directives
1191 * (allowed to wrap around) corresponding to PP_* tokens 0-159.
1193 while ((c = *p++) != 127) {
1194 uint8_t ndir = c - 128;
1195 if (ndir < 256-96)
1196 len += pp_directives_len[ndir] + 1;
1197 else
1198 len++;
1201 line = nasm_malloc(len + 1);
1202 q = line;
1204 while ((c = *stdmacpos++) != 127) {
1205 uint8_t ndir = c - 128;
1206 if (ndir < 256-96) {
1207 memcpy(q, pp_directives[ndir], pp_directives_len[ndir]);
1208 q += pp_directives_len[ndir];
1209 *q++ = ' ';
1210 } else {
1211 *q++ = c;
1214 stdmacpos = p;
1215 *q = '\0';
1217 if (*stdmacpos == 127) {
1218 /* This was the last of this particular macro set */
1219 stdmacpos = NULL;
1220 if (*stdmacnext) {
1221 stdmacpos = *stdmacnext++;
1222 } else if (do_predef) {
1223 Line *pd, *l;
1226 * Nasty hack: here we push the contents of
1227 * `predef' on to the top-level expansion stack,
1228 * since this is the most convenient way to
1229 * implement the pre-include and pre-define
1230 * features.
1232 list_for_each(pd, predef) {
1233 nasm_new(l);
1234 l->next = istk->expansion;
1235 l->first = dup_tlist(pd->first, NULL);
1236 l->finishes = NULL;
1238 istk->expansion = l;
1240 do_predef = false;
1244 return line;
1248 * Read a line from a file. Return NULL on end of file.
1250 static char *line_from_file(FILE *f)
1252 int c;
1253 unsigned int size, next;
1254 const unsigned int delta = 512;
1255 const unsigned int pad = 8;
1256 unsigned int nr_cont = 0;
1257 bool cont = false;
1258 char *buffer, *p;
1259 int32_t lineno;
1261 size = delta;
1262 p = buffer = nasm_malloc(size);
1264 do {
1265 c = fgetc(f);
1267 switch (c) {
1268 case EOF:
1269 if (p == buffer) {
1270 nasm_free(buffer);
1271 return NULL;
1273 c = 0;
1274 break;
1276 case '\r':
1277 next = fgetc(f);
1278 if (next != '\n')
1279 ungetc(next, f);
1280 if (cont) {
1281 cont = false;
1282 continue;
1284 c = 0;
1285 break;
1287 case '\n':
1288 if (cont) {
1289 cont = false;
1290 continue;
1292 c = 0;
1293 break;
1295 case 032: /* ^Z = legacy MS-DOS end of file mark */
1296 c = 0;
1297 break;
1299 case '\\':
1300 next = fgetc(f);
1301 ungetc(next, f);
1302 if (next == '\r' || next == '\n') {
1303 cont = true;
1304 nr_cont++;
1305 continue;
1307 break;
1310 if (p >= (buffer + size - pad)) {
1311 buffer = nasm_realloc(buffer, size + delta);
1312 p = buffer + size - pad;
1313 size += delta;
1316 *p++ = c;
1317 } while (c);
1319 lineno = src_get_linnum() + istk->lineinc +
1320 (nr_cont * istk->lineinc);
1321 src_set_linnum(lineno);
1323 return buffer;
1327 * Common read routine regardless of source
1329 static char *read_line(void)
1331 char *line;
1332 FILE *f = istk->fp;
1334 if (f)
1335 line = line_from_file(f);
1336 else
1337 line = line_from_stdmac();
1339 if (!line)
1340 return NULL;
1342 if (!istk->nolist)
1343 lfmt->line(LIST_READ, src_get_linnum(), line);
1345 return line;
1349 * Tokenize a line of text. This is a very simple process since we
1350 * don't need to parse the value out of e.g. numeric tokens: we
1351 * simply split one string into many.
1353 static Token *tokenize(const char *line)
1355 enum pp_token_type type;
1356 Token *list = NULL;
1357 Token *t, **tail = &list;
1359 while (*line) {
1360 const char *p = line;
1361 const char *ep = NULL; /* End of token, for trimming the end */
1362 size_t toklen;
1363 char firstchar = *p; /* Can be used to override the first char */
1365 if (*p == '%') {
1367 * Preprocessor construct; find the end of the token.
1368 * Classification is handled later, because %{...} can be
1369 * used to create any preprocessor token.
1371 p++;
1372 if (*p == '+' && !nasm_isdigit(p[1])) {
1373 /* Paste token */
1374 p++;
1375 } else if (nasm_isdigit(*p) ||
1376 ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
1377 do {
1378 p++;
1380 while (nasm_isdigit(*p));
1381 } else if (*p == '{' || *p == '[') {
1382 /* %{...} or %[...] */
1383 char firstchar = *p;
1384 char endchar = *p + 2; /* } or ] */
1385 int lvl = 1;
1386 line += (*p++ == '{'); /* Skip { but not [ (yet) */
1387 while (lvl) {
1388 if (*p == firstchar) {
1389 lvl++;
1390 } else if (*p == endchar) {
1391 lvl--;
1392 } else if (nasm_isquote(*p)) {
1393 p = nasm_skip_string(p);
1397 * *p can have been advanced to a null character by
1398 * nasm_skip_string()
1400 if (!*p) {
1401 nasm_warn(WARN_OTHER, "unterminated %%%c construct",
1402 firstchar);
1403 break;
1405 p++;
1407 ep = lvl ? p : p-1; /* Terminal character not part of token */
1408 } else if (*p == '?') {
1409 /* %? or %?? */
1410 p++;
1411 if (*p == '?')
1412 p++;
1413 } else if (*p == '!') {
1414 /* Environment variable reference */
1415 p++;
1416 if (nasm_isidchar(*p)) {
1417 do {
1418 p++;
1420 while (nasm_isidchar(*p));
1421 } else if (nasm_isquote(*p)) {
1422 p = nasm_skip_string(p);
1423 if (*p)
1424 p++;
1425 else
1426 nasm_nonfatalf(ERR_PASS1, "unterminated %%! string");
1427 } else {
1428 /* %! without anything else... */
1430 } else if (*p == ',') {
1431 /* Conditional comma */
1432 p++;
1433 } else if (nasm_isidchar(*p) ||
1434 ((*p == '%' || *p == '$') && nasm_isidchar(p[1]))) {
1435 /* Identifier or some sort */
1436 do {
1437 p++;
1439 while (nasm_isidchar(*p));
1440 } else if (*p == '%') {
1441 /* %% operator */
1442 p++;
1445 if (!ep)
1446 ep = p;
1447 toklen = ep - line;
1449 /* Classify here, to handle %{...} correctly */
1450 if (toklen < 2) {
1451 type = TOK_OTHER; /* % operator */
1452 } else {
1453 char c0 = line[1];
1455 switch (c0) {
1456 case '+':
1457 type = (toklen == 2) ? TOK_PASTE : TOK_MMACRO_PARAM;
1458 break;
1460 case '-':
1461 type = TOK_MMACRO_PARAM;
1462 break;
1464 case '?':
1465 if (toklen == 2)
1466 type = TOK_PREPROC_Q;
1467 else if (toklen == 3 && line[2] == '?')
1468 type = TOK_PREPROC_QQ;
1469 else
1470 type = TOK_PREPROC_ID;
1471 break;
1473 case '!':
1474 type = (toklen == 2) ? TOK_OTHER : TOK_ENVIRON;
1475 break;
1477 case '%':
1478 type = (toklen == 2) ? TOK_OTHER : TOK_LOCAL_SYMBOL;
1479 break;
1481 case '$':
1482 type = (toklen == 2) ? TOK_OTHER : TOK_LOCAL_MACRO;
1483 break;
1485 case '[':
1486 line += 2; /* Skip %[ */
1487 firstchar = *line; /* Don't clobber */
1488 toklen -= 2;
1489 type = TOK_INDIRECT;
1490 break;
1492 case ',':
1493 type = (toklen == 2) ? TOK_COND_COMMA : TOK_PREPROC_ID;
1494 break;
1496 case '\'':
1497 case '\"':
1498 case '`':
1499 /* %{'string'} */
1500 type = TOK_PREPROC_ID;
1501 break;
1503 case ':':
1504 type = TOK_MMACRO_PARAM; /* %{:..} */
1505 break;
1507 default:
1508 if (nasm_isdigit(c0))
1509 type = TOK_MMACRO_PARAM;
1510 else if (nasm_isidchar(c0) || toklen > 2)
1511 type = TOK_PREPROC_ID;
1512 else
1513 type = TOK_OTHER;
1514 break;
1517 } else if (nasm_isidstart(*p) || (*p == '$' && nasm_isidstart(p[1]))) {
1519 * An identifier. This includes the ? operator, which is
1520 * treated as a keyword, not as a special character
1521 * operator
1523 type = TOK_ID;
1524 while (nasm_isidchar(*++p))
1526 } else if (nasm_isquote(*p)) {
1528 * A string token.
1530 type = TOK_STRING;
1531 p = nasm_skip_string(p);
1533 if (*p) {
1534 p++;
1535 } else {
1536 nasm_warn(WARN_OTHER, "unterminated string");
1537 /* Handling unterminated strings by UNV */
1538 /* type = -1; */
1540 } else if (p[0] == '$' && p[1] == '$') {
1541 type = TOK_OTHER; /* TOKEN_BASE */
1542 p += 2;
1543 } else if (nasm_isnumstart(*p)) {
1544 bool is_hex = false;
1545 bool is_float = false;
1546 bool has_e = false;
1547 char c;
1550 * A numeric token.
1553 if (*p == '$') {
1554 p++;
1555 is_hex = true;
1558 for (;;) {
1559 c = *p++;
1561 if (!is_hex && (c == 'e' || c == 'E')) {
1562 has_e = true;
1563 if (*p == '+' || *p == '-') {
1565 * e can only be followed by +/- if it is either a
1566 * prefixed hex number or a floating-point number
1568 p++;
1569 is_float = true;
1571 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
1572 is_hex = true;
1573 } else if (c == 'P' || c == 'p') {
1574 is_float = true;
1575 if (*p == '+' || *p == '-')
1576 p++;
1577 } else if (nasm_isnumchar(c))
1578 ; /* just advance */
1579 else if (c == '.') {
1581 * we need to deal with consequences of the legacy
1582 * parser, like "1.nolist" being two tokens
1583 * (TOK_NUMBER, TOK_ID) here; at least give it
1584 * a shot for now. In the future, we probably need
1585 * a flex-based scanner with proper pattern matching
1586 * to do it as well as it can be done. Nothing in
1587 * the world is going to help the person who wants
1588 * 0x123.p16 interpreted as two tokens, though.
1590 const char *r = p;
1591 while (*r == '_')
1592 r++;
1594 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
1595 (!is_hex && (*r == 'e' || *r == 'E')) ||
1596 (*r == 'p' || *r == 'P')) {
1597 p = r;
1598 is_float = true;
1599 } else
1600 break; /* Terminate the token */
1601 } else
1602 break;
1604 p--; /* Point to first character beyond number */
1606 if (p == line+1 && *line == '$') {
1607 type = TOK_OTHER; /* TOKEN_HERE */
1608 } else {
1609 if (has_e && !is_hex) {
1610 /* 1e13 is floating-point, but 1e13h is not */
1611 is_float = true;
1614 type = is_float ? TOK_FLOAT : TOK_NUMBER;
1616 } else if (nasm_isspace(*p)) {
1617 type = TOK_WHITESPACE;
1618 p = nasm_skip_spaces(p);
1620 * Whitespace just before end-of-line is discarded by
1621 * pretending it's a comment; whitespace just before a
1622 * comment gets lumped into the comment.
1624 if (!*p || *p == ';') {
1625 type = TOK_COMMENT;
1626 while (*p)
1627 p++;
1629 } else if (*p == ';') {
1630 type = TOK_COMMENT;
1631 while (*p)
1632 p++;
1633 } else {
1635 * Anything else is an operator of some kind. We check
1636 * for all the double-character operators (>>, <<, //,
1637 * %%, <=, >=, ==, !=, <>, &&, ||, ^^) and the triple-
1638 * character operators (<<<, >>>, <=>) but anything
1639 * else is a single-character operator.
1641 type = TOK_OTHER;
1642 switch (*p++) {
1643 case '>':
1644 if (*p == '>') {
1645 p++;
1646 if (*p == '>')
1647 p++;
1648 } else if (*p == '=') {
1649 p++;
1651 break;
1653 case '<':
1654 if (*p == '<') {
1655 p++;
1656 if (*p == '<')
1657 p++;
1658 } else if (*p == '=') {
1659 p++;
1660 if (*p == '>')
1661 p++;
1662 } else if (*p == '>') {
1663 p++;
1665 break;
1667 case '!':
1668 if (*p == '=')
1669 p++;
1670 break;
1672 case '/':
1673 case '=':
1674 case '&':
1675 case '|':
1676 case '^':
1677 /* These operators can be doubled but nothing else */
1678 if (*p == p[-1])
1679 p++;
1680 break;
1682 default:
1683 break;
1687 if (type == TOK_WHITESPACE) {
1688 *tail = t = new_White(NULL);
1689 tail = &t->next;
1690 } else if (type != TOK_COMMENT) {
1691 if (!ep)
1692 ep = p;
1693 *tail = t = new_Token(NULL, type, line, ep - line);
1694 *tok_text_buf(t) = firstchar; /* E.g. %{foo} -> {foo -> %foo */
1695 tail = &t->next;
1697 line = p;
1699 return list;
1703 * Tokens are allocated in blocks to improve speed. Set the blocksize
1704 * to 0 to use regular nasm_malloc(); this is useful for debugging.
1706 * alloc_Token() returns a zero-initialized token structure.
1708 #define TOKEN_BLOCKSIZE 4096
1710 #if TOKEN_BLOCKSIZE
1712 static Token *freeTokens = NULL;
1713 static Token *tokenblocks = NULL;
1715 static Token *alloc_Token(void)
1717 Token *t = freeTokens;
1719 if (unlikely(!t)) {
1720 Token *block;
1721 size_t i;
1723 nasm_newn(block, TOKEN_BLOCKSIZE);
1726 * The first entry in each array are a linked list of
1727 * block allocations and is not used for data.
1729 block[0].next = tokenblocks;
1730 block[0].type = TOK_BLOCK;
1731 tokenblocks = block;
1734 * Add the rest to the free list
1736 for (i = 2; i < TOKEN_BLOCKSIZE - 1; i++)
1737 block[i].next = &block[i+1];
1739 freeTokens = &block[2];
1742 * Return the topmost usable token
1744 return &block[1];
1747 freeTokens = t->next;
1748 t->next = NULL;
1749 return t;
1752 static Token *delete_Token(Token *t)
1754 Token *next = t->next;
1756 nasm_zero(*t);
1757 t->next = freeTokens;
1758 freeTokens = t;
1760 return next;
1763 static void delete_Blocks(void)
1765 Token *block, *blocktmp;
1767 list_for_each_safe(block, blocktmp, tokenblocks)
1768 nasm_free(block);
1770 freeTokens = tokenblocks = NULL;
1773 #else
1775 static inline Token *alloc_Token(void)
1777 Token *t;
1778 nasm_new(*t);
1779 return t;
1782 static Token *delete_Token(Token *t)
1784 Token *next = t->next;
1785 nasm_free(t);
1786 return next;
1789 static inline void delete_Blocks(void)
1791 /* Nothing to do */
1794 #endif
1797 * this function creates a new Token and passes a pointer to it
1798 * back to the caller. It sets the type, text, and next pointer elements.
1800 static Token *new_Token(Token * next, enum pp_token_type type,
1801 const char *text, size_t txtlen)
1803 Token *t = alloc_Token();
1804 char *textp;
1806 t->next = next;
1807 t->type = type;
1808 if (type == TOK_WHITESPACE) {
1809 t->len = 1;
1810 t->text.a[0] = ' ';
1811 } else {
1812 if (text && text[0] && !txtlen)
1813 txtlen = tok_strlen(text);
1815 t->len = tok_check_len(txtlen);
1817 if (text) {
1818 textp = (txtlen > INLINE_TEXT)
1819 ? (t->text.p.ptr = nasm_malloc(txtlen+1)) : t->text.a;
1820 memcpy(textp, text, txtlen);
1821 textp[txtlen] = '\0'; /* In case we needed malloc() */
1822 } else {
1824 * Allocate a buffer but do not fill it. The caller
1825 * can fill in text, but must not change the length.
1826 * The filled in text must be exactly txtlen once
1827 * the buffer is filled and before the token is added
1828 * to any line lists.
1830 if (txtlen > INLINE_TEXT)
1831 t->text.p.ptr = nasm_zalloc(txtlen+1);
1834 return t;
1838 * Same as new_Token(), but text belongs to the new token and is
1839 * either taken over or freed. This function MUST be called
1840 * with valid txt and txtlen, unlike new_Token().
1842 static Token *new_Token_free(Token * next, enum pp_token_type type,
1843 char *text, size_t txtlen)
1845 Token *t = alloc_Token();
1847 t->next = next;
1848 t->type = type;
1849 t->len = tok_check_len(txtlen);
1851 if (txtlen <= INLINE_TEXT) {
1852 memcpy(t->text.a, text, txtlen);
1853 free(text);
1854 } else {
1855 t->text.p.ptr = text;
1858 return t;
1861 static Token *dup_Token(Token *next, const Token *src)
1863 Token *t = alloc_Token();
1865 memcpy(t, src, sizeof *src);
1866 t->next = next;
1868 if (t->len > INLINE_TEXT) {
1869 t->text.p.ptr = nasm_malloc(t->len + 1);
1870 memcpy(t->text.p.ptr, src->text.p.ptr, t->len+1);
1873 return t;
1876 static Token *new_White(Token *next)
1878 Token *t = alloc_Token();
1880 t->next = next;
1881 t->type = TOK_WHITESPACE;
1882 t->len = 1;
1883 t->text.a[0] = ' ';
1885 return t;
1889 * This *transfers* the content from one token to another, leaving the
1890 * next pointer of the latter intact. Unlike dup_Token(), the old
1891 * token is destroyed, except for its next pointer, and the text
1892 * pointer allocation, if any, is simply transferred.
1894 static Token *steal_Token(Token *dst, Token *src)
1896 /* Overwrite everything except the next pointers */
1897 memcpy((char *)dst + sizeof(Token *), (char *)src + sizeof(Token *),
1898 sizeof(Token) - sizeof(Token *));
1900 /* Clear the donor token */
1901 memset((char *)src + sizeof(Token *), 0, sizeof(Token) - sizeof(Token *));
1903 return dst;
1907 * Convert a line of tokens back into text. This modifies the list
1908 * by expanding environment variables.
1910 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1911 * are also transformed into ..@ctxnum.xxx
1913 static char *detoken(Token * tlist, bool expand_locals)
1915 Token *t;
1916 char *line, *p;
1917 int len = 0;
1919 list_for_each(t, tlist) {
1920 switch (t->type) {
1921 case TOK_ENVIRON:
1923 const char *v = pp_getenv(t, true);
1924 set_text(t, v, tok_strlen(v));
1925 t->type = TOK_NAKED_STRING;
1926 break;
1929 case TOK_LOCAL_MACRO:
1930 case TOK_LOCAL_SYMBOL:
1931 if (expand_locals) {
1932 const char *q;
1933 char *p;
1934 Context *ctx = get_ctx(tok_text(t), &q);
1935 if (ctx) {
1936 p = nasm_asprintf("..@%"PRIu64".%s", ctx->number, q);
1937 set_text_free(t, p, nasm_last_string_len());
1938 t->type = TOK_ID;
1941 break;
1943 default:
1944 break; /* No modifications */
1947 if (debug_level(2)) {
1948 unsigned int t_len = t->len;
1949 unsigned int s_len = tok_strlen(tok_text(t));
1950 if (t_len != s_len) {
1951 nasm_panic("assertion failed: token \"%s\" type %u len %u has t->len %u\n",
1952 tok_text(t), t->type, s_len, t_len);
1953 t->len = s_len;
1957 len += t->len;
1960 p = line = nasm_malloc(len + 1);
1962 list_for_each(t, tlist)
1963 p = mempcpy(p, tok_text(t), t->len);
1964 *p = '\0';
1966 return line;
1970 * A scanner, suitable for use by the expression evaluator, which
1971 * operates on a line of Tokens. Expects a pointer to a pointer to
1972 * the first token in the line to be passed in as its private_data
1973 * field.
1975 * FIX: This really needs to be unified with stdscan.
1977 struct ppscan {
1978 Token *tptr;
1979 int ntokens;
1982 static int ppscan(void *private_data, struct tokenval *tokval)
1984 struct ppscan *pps = private_data;
1985 Token *tline;
1986 const char *txt;
1988 do {
1989 if (pps->ntokens && (tline = pps->tptr)) {
1990 pps->ntokens--;
1991 pps->tptr = tline->next;
1992 } else {
1993 pps->tptr = NULL;
1994 pps->ntokens = 0;
1995 return tokval->t_type = TOKEN_EOS;
1997 } while (tline->type == TOK_WHITESPACE || tline->type == TOK_COMMENT);
1999 txt = tok_text(tline);
2000 tokval->t_charptr = (char *)txt; /* Fix this */
2002 if (txt[0] == '$') {
2003 if (!txt[1]) {
2004 return tokval->t_type = TOKEN_HERE;
2005 } else if (txt[1] == '$' && !txt[2]) {
2006 return tokval->t_type = TOKEN_BASE;
2007 } else if (tline->type == TOK_ID) {
2008 tokval->t_charptr++;
2009 return tokval->t_type = TOKEN_ID;
2013 switch (tline->type) {
2014 default:
2015 if (tline->len == 1)
2016 return tokval->t_type = txt[0];
2017 /* fall through */
2018 case TOK_ID:
2019 return nasm_token_hash(txt, tokval);
2021 case TOK_NUMBER:
2023 bool rn_error;
2024 tokval->t_integer = readnum(txt, &rn_error);
2025 if (rn_error)
2026 return tokval->t_type = TOKEN_ERRNUM;
2027 else
2028 return tokval->t_type = TOKEN_NUM;
2031 case TOK_FLOAT:
2032 return tokval->t_type = TOKEN_FLOAT;
2034 case TOK_STRING:
2035 tokval->t_charptr = (char *)unquote_token(tline);
2036 tokval->t_inttwo = tline->len;
2037 return tokval->t_type = TOKEN_STR;
2042 * 1. An expression (true if nonzero 0)
2043 * 2. The keywords true, on, yes for true
2044 * 3. The keywords false, off, no for false
2045 * 4. An empty line, for true
2047 * On error, return defval (usually the previous value)
2049 static bool pp_get_boolean_option(Token *tline, bool defval)
2051 static const char * const noyes[] = {
2052 "no", "yes",
2053 "false", "true",
2054 "off", "on"
2056 struct ppscan pps;
2057 struct tokenval tokval;
2058 expr *evalresult;
2060 tline = skip_white(tline);
2061 if (!tline)
2062 return true;
2064 if (tline->type == TOK_ID) {
2065 size_t i;
2066 const char *txt = tok_text(tline);
2068 for (i = 0; i < ARRAY_SIZE(noyes); i++)
2069 if (!nasm_stricmp(txt, noyes[i]))
2070 return i & 1;
2073 pps.tptr = NULL;
2074 pps.tptr = tline;
2075 pps.ntokens = -1;
2076 tokval.t_type = TOKEN_INVALID;
2077 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
2079 if (!evalresult)
2080 return true;
2082 if (tokval.t_type)
2083 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
2084 if (!is_really_simple(evalresult)) {
2085 nasm_nonfatal("boolean flag expression must be a constant");
2086 return defval;
2089 return reloc_value(evalresult) != 0;
2093 * Compare a string to the name of an existing macro; this is a
2094 * simple wrapper which calls either strcmp or nasm_stricmp
2095 * depending on the value of the `casesense' parameter.
2097 static int mstrcmp(const char *p, const char *q, bool casesense)
2099 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
2103 * Compare a string to the name of an existing macro; this is a
2104 * simple wrapper which calls either strcmp or nasm_stricmp
2105 * depending on the value of the `casesense' parameter.
2107 static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
2109 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
2113 * Return the Context structure associated with a %$ token. Return
2114 * NULL, having _already_ reported an error condition, if the
2115 * context stack isn't deep enough for the supplied number of $
2116 * signs.
2118 * If "namep" is non-NULL, set it to the pointer to the macro name
2119 * tail, i.e. the part beyond %$...
2121 static Context *get_ctx(const char *name, const char **namep)
2123 Context *ctx;
2124 int i;
2126 if (namep)
2127 *namep = name;
2129 if (!name || name[0] != '%' || name[1] != '$')
2130 return NULL;
2132 if (!cstk) {
2133 nasm_nonfatal("`%s': context stack is empty", name);
2134 return NULL;
2137 name += 2;
2138 ctx = cstk;
2139 i = 0;
2140 while (ctx && *name == '$') {
2141 name++;
2142 i++;
2143 ctx = ctx->next;
2145 if (!ctx) {
2146 nasm_nonfatal("`%s': context stack is only"
2147 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
2148 return NULL;
2151 if (namep)
2152 *namep = name;
2154 return ctx;
2158 * Open an include file. This routine must always return a valid
2159 * file pointer if it returns - it's responsible for throwing an
2160 * ERR_FATAL and bombing out completely if not. It should also try
2161 * the include path one by one until it finds the file or reaches
2162 * the end of the path.
2164 * Note: for INC_PROBE the function returns NULL at all times;
2165 * instead look for the
2167 enum incopen_mode {
2168 INC_NEEDED, /* File must exist */
2169 INC_OPTIONAL, /* Missing is OK */
2170 INC_PROBE /* Only an existence probe */
2173 /* This is conducts a full pathname search */
2174 static FILE *inc_fopen_search(const char *file, char **slpath,
2175 enum incopen_mode omode, enum file_flags fmode)
2177 const struct strlist_entry *ip = strlist_head(ipath_list);
2178 FILE *fp;
2179 const char *prefix = "";
2180 char *sp;
2181 bool found;
2183 while (1) {
2184 sp = nasm_catfile(prefix, file);
2185 if (omode == INC_PROBE) {
2186 fp = NULL;
2187 found = nasm_file_exists(sp);
2188 } else {
2189 fp = nasm_open_read(sp, fmode);
2190 found = (fp != NULL);
2192 if (found) {
2193 *slpath = sp;
2194 return fp;
2197 nasm_free(sp);
2199 if (!ip) {
2200 *slpath = NULL;
2201 return NULL;
2204 prefix = ip->str;
2205 ip = ip->next;
2210 * Open a file, or test for the presence of one (depending on omode),
2211 * considering the include path.
2213 static FILE *inc_fopen(const char *file,
2214 struct strlist *dhead,
2215 const char **found_path,
2216 enum incopen_mode omode,
2217 enum file_flags fmode)
2219 struct hash_insert hi;
2220 void **hp;
2221 char *path;
2222 FILE *fp = NULL;
2224 hp = hash_find(&FileHash, file, &hi);
2225 if (hp) {
2226 path = *hp;
2227 if (path || omode != INC_NEEDED) {
2228 strlist_add(dhead, path ? path : file);
2230 } else {
2231 /* Need to do the actual path search */
2232 fp = inc_fopen_search(file, &path, omode, fmode);
2234 /* Positive or negative result */
2235 hash_add(&hi, nasm_strdup(file), path);
2238 * Add file to dependency path.
2240 if (path || omode != INC_NEEDED)
2241 strlist_add(dhead, file);
2244 if (path && !fp && omode != INC_PROBE)
2245 fp = nasm_open_read(path, fmode);
2247 if (omode == INC_NEEDED && !fp) {
2248 if (!path)
2249 errno = ENOENT;
2251 nasm_nonfatal("unable to open include file `%s': %s",
2252 file, strerror(errno));
2255 if (found_path)
2256 *found_path = path;
2258 return fp;
2262 * Opens an include or input file. Public version, for use by modules
2263 * that get a file:lineno pair and need to look at the file again
2264 * (e.g. the CodeView debug backend). Returns NULL on failure.
2266 FILE *pp_input_fopen(const char *filename, enum file_flags mode)
2268 return inc_fopen(filename, NULL, NULL, INC_OPTIONAL, mode);
2272 * Determine if we should warn on defining a single-line macro of
2273 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
2274 * return true if _any_ single-line macro of that name is defined.
2275 * Otherwise, will return true if a single-line macro with either
2276 * `nparam' or no parameters is defined.
2278 * If a macro with precisely the right number of parameters is
2279 * defined, or nparam is -1, the address of the definition structure
2280 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
2281 * is NULL, no action will be taken regarding its contents, and no
2282 * error will occur.
2284 * Note that this is also called with nparam zero to resolve
2285 * `ifdef'.
2287 static bool
2288 smacro_defined(Context *ctx, const char *name, int nparam, SMacro **defn,
2289 bool nocase, bool find_alias)
2291 struct hash_table *smtbl;
2292 SMacro *m;
2294 smtbl = ctx ? &ctx->localmac : &smacros;
2296 restart:
2297 m = (SMacro *) hash_findix(smtbl, name);
2299 while (m) {
2300 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
2301 (nparam <= 0 || m->nparam == 0 || nparam == m->nparam ||
2302 (m->greedy && nparam >= m->nparam-1))) {
2303 if (m->alias && !find_alias) {
2304 if (do_aliases) {
2305 name = tok_text(m->expansion);
2306 goto restart;
2307 } else {
2308 continue;
2311 if (defn) {
2312 *defn = (nparam == m->nparam || nparam == -1) ? m : NULL;
2314 return true;
2316 m = m->next;
2319 return false;
2322 /* param should be a natural number [0; INT_MAX] */
2323 static int read_param_count(const char *str)
2325 int result;
2326 bool err;
2328 result = readnum(str, &err);
2329 if (result < 0 || result > INT_MAX) {
2330 result = 0;
2331 nasm_nonfatal("parameter count `%s' is out of bounds [%d; %d]",
2332 str, 0, INT_MAX);
2333 } else if (err)
2334 nasm_nonfatal("unable to parse parameter count `%s'", str);
2335 return result;
2339 * Count and mark off the parameters in a multi-line macro call.
2340 * This is called both from within the multi-line macro expansion
2341 * code, and also to mark off the default parameters when provided
2342 * in a %macro definition line.
2344 * Note that we need space in the params array for parameter 0 being
2345 * a possible captured label as well as the final NULL.
2347 static void count_mmac_params(Token * t, int *nparamp, Token ***paramsp)
2349 int paramsize;
2350 int nparam = 0;
2351 Token **params;
2353 paramsize = PARAM_DELTA;
2354 params = nasm_malloc(paramsize * sizeof(*params));
2355 params[0] = NULL;
2357 while ((t = skip_white(t))) {
2358 /* 2 slots for captured label and NULL */
2359 if (nparam+2 >= paramsize) {
2360 paramsize += PARAM_DELTA;
2361 params = nasm_realloc(params, sizeof(*params) * paramsize);
2363 params[++nparam] = t;
2364 if (tok_is(t, '{')) {
2365 int brace = 1;
2366 while (brace && (t = t->next)) {
2367 brace += tok_is(t, '{');
2368 brace -= tok_is(t, '}');
2371 if (t) {
2373 * Now we've found the closing brace, look further
2374 * for the comma.
2376 t = skip_white(t->next);
2377 if (tok_isnt(t, ','))
2378 nasm_nonfatal("braces do not enclose all of macro parameter");
2379 } else {
2380 nasm_nonfatal("expecting closing brace in macro parameter");
2384 while (tok_isnt(t, ','))
2385 t = t->next;
2387 if (t) /* got a comma */
2388 t = t->next; /* eat the comma */
2391 params[nparam+1] = NULL;
2392 *paramsp = params;
2393 *nparamp = nparam;
2397 * Determine whether one of the various `if' conditions is true or
2398 * not.
2400 * We must free the tline we get passed.
2402 static enum cond_state if_condition(Token * tline, enum preproc_token ct)
2404 bool j;
2405 Token *t, *tt, *origline;
2406 struct ppscan pps;
2407 struct tokenval tokval;
2408 expr *evalresult;
2409 enum pp_token_type needtype;
2410 const char *dname = pp_directives[ct];
2411 bool casesense = true;
2412 enum preproc_token cond = PP_COND(ct);
2414 origline = tline;
2416 switch (cond) {
2417 case PP_IFCTX:
2418 j = false; /* have we matched yet? */
2419 while (true) {
2420 tline = skip_white(tline);
2421 if (!tline)
2422 break;
2423 if (tline->type != TOK_ID) {
2424 nasm_nonfatal("`%s' expects context identifiers",
2425 dname);
2426 goto fail;
2428 if (cstk && cstk->name && !nasm_stricmp(tok_text(tline), cstk->name))
2429 j = true;
2430 tline = tline->next;
2432 break;
2434 case PP_IFDEF:
2435 case PP_IFDEFALIAS:
2437 bool alias = cond == PP_IFDEFALIAS;
2438 SMacro *smac;
2439 Context *ctx;
2440 const char *mname;
2442 j = false; /* have we matched yet? */
2443 while (tline) {
2444 tline = skip_white(tline);
2445 if (!tline || (tline->type != TOK_ID &&
2446 tline->type != TOK_LOCAL_MACRO)) {
2447 nasm_nonfatal("`%s' expects macro identifiers",
2448 dname);
2449 goto fail;
2452 mname = tok_text(tline);
2453 ctx = get_ctx(mname, &mname);
2454 if (smacro_defined(ctx, mname, 0, &smac, true, alias) && smac
2455 && smac->alias == alias) {
2456 j = true;
2457 break;
2459 tline = tline->next;
2461 break;
2464 case PP_IFENV:
2465 tline = expand_smacro(tline);
2466 j = false; /* have we matched yet? */
2467 while (tline) {
2468 tline = skip_white(tline);
2469 if (!tline || (tline->type != TOK_ID &&
2470 tline->type != TOK_STRING &&
2471 tline->type != TOK_INTERNAL_STRING &&
2472 tline->type != TOK_ENVIRON)) {
2473 nasm_nonfatal("`%s' expects environment variable names",
2474 dname);
2475 goto fail;
2478 j |= !!pp_getenv(tline, false);
2479 tline = tline->next;
2481 break;
2483 case PP_IFIDNI:
2484 casesense = false;
2485 /* fall through */
2486 case PP_IFIDN:
2487 tline = expand_smacro(tline);
2488 t = tt = tline;
2489 while (tok_isnt(tt, ','))
2490 tt = tt->next;
2491 if (!tt) {
2492 nasm_nonfatal("`%s' expects two comma-separated arguments",
2493 dname);
2494 goto fail;
2496 tt = tt->next;
2497 j = true; /* assume equality unless proved not */
2498 while (tok_isnt(t, ',') && tt) {
2499 unsigned int l1, l2;
2500 const char *t1, *t2;
2502 if (tok_is(tt, ',')) {
2503 nasm_nonfatal("`%s': more than one comma on line",
2504 dname);
2505 goto fail;
2507 if (t->type == TOK_WHITESPACE) {
2508 t = t->next;
2509 continue;
2511 if (tt->type == TOK_WHITESPACE) {
2512 tt = tt->next;
2513 continue;
2515 if (tt->type != t->type) {
2516 j = false; /* found mismatching tokens */
2517 break;
2520 t1 = unquote_token(t);
2521 t2 = unquote_token(tt);
2522 l1 = t->len;
2523 l2 = tt->len;
2525 if (l1 != l2 || mmemcmp(t1, t2, l1, casesense)) {
2526 j = false;
2527 break;
2530 t = t->next;
2531 tt = tt->next;
2533 if (!tok_is(t, ',') || tt)
2534 j = false; /* trailing gunk on one end or other */
2535 break;
2537 case PP_IFMACRO:
2539 bool found = false;
2540 MMacro searching, *mmac;
2542 tline = skip_white(tline);
2543 tline = expand_id(tline);
2544 if (!tok_type(tline, TOK_ID)) {
2545 nasm_nonfatal("`%s' expects a macro name", dname);
2546 goto fail;
2548 nasm_zero(searching);
2549 searching.name = dup_text(tline);
2550 searching.casesense = true;
2551 searching.nparam_min = 0;
2552 searching.nparam_max = INT_MAX;
2553 tline = expand_smacro(tline->next);
2554 tline = skip_white(tline);
2555 if (!tline) {
2556 } else if (!tok_type(tline, TOK_NUMBER)) {
2557 nasm_nonfatal("`%s' expects a parameter count or nothing",
2558 dname);
2559 } else {
2560 searching.nparam_min = searching.nparam_max =
2561 read_param_count(tok_text(tline));
2563 if (tline && tok_is(tline->next, '-')) {
2564 tline = tline->next->next;
2565 if (tok_is(tline, '*'))
2566 searching.nparam_max = INT_MAX;
2567 else if (!tok_type(tline, TOK_NUMBER))
2568 nasm_nonfatal("`%s' expects a parameter count after `-'",
2569 dname);
2570 else {
2571 searching.nparam_max = read_param_count(tok_text(tline));
2572 if (searching.nparam_min > searching.nparam_max) {
2573 nasm_nonfatal("minimum parameter count exceeds maximum");
2574 searching.nparam_max = searching.nparam_min;
2578 if (tline && tok_is(tline->next, '+')) {
2579 tline = tline->next;
2580 searching.plus = true;
2582 mmac = (MMacro *) hash_findix(&mmacros, searching.name);
2583 while (mmac) {
2584 if (!strcmp(mmac->name, searching.name) &&
2585 (mmac->nparam_min <= searching.nparam_max
2586 || searching.plus)
2587 && (searching.nparam_min <= mmac->nparam_max
2588 || mmac->plus)) {
2589 found = true;
2590 break;
2592 mmac = mmac->next;
2594 if (tline && tline->next)
2595 nasm_warn(WARN_OTHER, "trailing garbage after %%ifmacro ignored");
2596 nasm_free(searching.name);
2597 j = found;
2598 break;
2601 case PP_IFID:
2602 needtype = TOK_ID;
2603 goto iftype;
2604 case PP_IFNUM:
2605 needtype = TOK_NUMBER;
2606 goto iftype;
2607 case PP_IFSTR:
2608 needtype = TOK_STRING;
2609 goto iftype;
2611 iftype:
2612 t = tline = expand_smacro(tline);
2614 while (tok_white(t) ||
2615 (needtype == TOK_NUMBER && (tok_is(t, '-') | tok_is(t, '+'))))
2616 t = t->next;
2618 j = tok_type(t, needtype);
2619 break;
2621 case PP_IFTOKEN:
2622 tline = expand_smacro(tline);
2623 t = skip_white(tline);
2625 j = false;
2626 if (t) {
2627 t = skip_white(t->next); /* Skip the actual token + whitespace */
2628 j = !t;
2630 break;
2632 case PP_IFEMPTY:
2633 tline = expand_smacro(tline);
2634 t = skip_white(tline);
2635 j = !t; /* Should be empty */
2636 break;
2638 case PP_IF:
2639 pps.tptr = tline = expand_smacro(tline);
2640 pps.ntokens = -1;
2641 tokval.t_type = TOKEN_INVALID;
2642 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
2643 if (!evalresult)
2644 return -1;
2645 if (tokval.t_type)
2646 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
2647 if (!is_simple(evalresult)) {
2648 nasm_nonfatal("non-constant value given to `%s'",
2649 dname);
2650 goto fail;
2652 j = reloc_value(evalresult) != 0;
2653 break;
2655 case PP_IFUSING:
2656 case PP_IFUSABLE:
2658 const struct use_package *pkg;
2659 const char *name;
2661 pkg = get_use_pkg(tline, dname, &name);
2662 if (!name)
2663 goto fail;
2665 j = pkg && ((cond == PP_IFUSABLE) | use_loaded[pkg->index]);
2666 break;
2669 default:
2670 nasm_nonfatal("unknown preprocessor directive `%s'", dname);
2671 goto fail;
2674 free_tlist(origline);
2675 return (j ^ PP_COND_NEGATIVE(ct)) ? COND_IF_TRUE : COND_IF_FALSE;
2677 fail:
2678 free_tlist(origline);
2679 return COND_NEVER;
2683 * Default smacro expansion routine: just returns a copy of the
2684 * expansion list.
2686 static Token *
2687 smacro_expand_default(const SMacro *s, Token **params, int nparams)
2689 (void)params;
2690 (void)nparams;
2692 return dup_tlist(s->expansion, NULL);
2696 * Emit a macro defintion or undef to the listing file, if
2697 * desired. This is similar to detoken(), but it handles the reverse
2698 * expansion list, does not expand %! or local variable tokens, and
2699 * does some special handling for macro parameters.
2701 static void
2702 list_smacro_def(enum preproc_token op, const Context *ctx, const SMacro *m)
2704 Token *t;
2705 size_t namelen, size;
2706 char *def, *p;
2707 char *context_prefix = NULL;
2708 size_t context_len;
2710 namelen = strlen(m->name);
2711 size = namelen + 2; /* Include room for space after name + NUL */
2713 if (ctx) {
2714 int context_depth = cstk->depth - ctx->depth + 1;
2715 context_prefix =
2716 nasm_asprintf("[%s::%"PRIu64"] %%%-*s",
2717 ctx->name ? ctx->name : "",
2718 ctx->number, context_depth, "");
2720 context_len = nasm_last_string_len();
2721 memset(context_prefix + context_len - context_depth,
2722 '$', context_depth);
2723 size += context_len;
2726 list_for_each(t, m->expansion)
2727 size += t->len;
2729 if (m->nparam) {
2731 * Space for ( and either , or ) around each
2732 * parameter, plus up to 4 flags.
2734 int i;
2736 size += 1 + 4 * m->nparam;
2737 for (i = 0; i < m->nparam; i++)
2738 size += m->params[i].name.len;
2741 def = nasm_malloc(size);
2742 p = def+size;
2743 *--p = '\0';
2745 list_for_each(t, m->expansion) {
2746 p -= t->len;
2747 memcpy(p, tok_text(t), t->len);
2750 *--p = ' ';
2752 if (m->nparam) {
2753 int i;
2755 *--p = ')';
2756 for (i = m->nparam-1; i >= 0; i--) {
2757 enum sparmflags flags = m->params[i].flags;
2758 if (flags & SPARM_GREEDY)
2759 *--p = '+';
2760 p -= m->params[i].name.len;
2761 memcpy(p, tok_text(&m->params[i].name), m->params[i].name.len);
2763 if (flags & SPARM_NOSTRIP)
2764 *--p = '!';
2765 if (flags & SPARM_STR)
2766 *--p = '&';
2767 if (flags & SPARM_EVAL)
2768 *--p = '=';
2769 *--p = ',';
2771 *p = '('; /* First parameter starts with ( not , */
2774 p -= namelen;
2775 memcpy(p, m->name, namelen);
2777 if (context_prefix) {
2778 p -= context_len;
2779 memcpy(p, context_prefix, context_len);
2780 nasm_free(context_prefix);
2783 nasm_listmsg("%s %s", pp_directives[op], p);
2784 nasm_free(def);
2788 * Parse smacro arguments, return argument count. If the tmpl argument
2789 * is set, set the nparam, greedy and params field in the template.
2790 * *tpp is updated to point to the pointer to the first token after the
2791 * prototype.
2793 * The text values from any argument tokens are "stolen" and the
2794 * corresponding text fields set to NULL.
2796 static int parse_smacro_template(Token ***tpp, SMacro *tmpl)
2798 int nparam = 0;
2799 enum sparmflags flags;
2800 struct smac_param *params = NULL;
2801 bool err, done;
2802 bool greedy = false;
2803 Token **tn = *tpp;
2804 Token *t = *tn;
2805 Token *name;
2808 * DO NOT skip whitespace here, or we won't be able to distinguish:
2810 * %define foo (a,b) ; no arguments, (a,b) is the expansion
2811 * %define bar(a,b) ; two arguments, empty expansion
2813 * This ambiguity was inherited from C.
2816 if (!tok_is(t, '('))
2817 goto finish;
2819 if (tmpl) {
2820 Token *tx = t;
2821 Token **txpp = &tx;
2822 int sparam;
2824 /* Count parameters first */
2825 sparam = parse_smacro_template(&txpp, NULL);
2826 if (!sparam)
2827 goto finish; /* No parameters, we're done */
2828 nasm_newn(params, sparam);
2831 /* Skip leading paren */
2832 tn = &t->next;
2833 t = *tn;
2835 name = NULL;
2836 flags = 0;
2837 err = done = false;
2839 while (!done) {
2840 if (!t || !t->type) {
2841 if (name || flags)
2842 nasm_nonfatal("`)' expected to terminate macro template");
2843 else
2844 nasm_nonfatal("parameter identifier expected");
2845 break;
2848 switch (t->type) {
2849 case TOK_ID:
2850 if (name)
2851 goto bad;
2852 name = t;
2853 break;
2855 case TOK_OTHER:
2856 if (t->len != 1)
2857 goto bad;
2858 switch (t->text.a[0]) {
2859 case '=':
2860 flags |= SPARM_EVAL;
2861 break;
2862 case '&':
2863 flags |= SPARM_STR;
2864 break;
2865 case '!':
2866 flags |= SPARM_NOSTRIP;
2867 break;
2868 case '+':
2869 flags |= SPARM_GREEDY;
2870 greedy = true;
2871 break;
2872 case ',':
2873 if (greedy)
2874 nasm_nonfatal("greedy parameter must be last");
2875 /* fall through */
2876 case ')':
2877 if (params) {
2878 if (name)
2879 steal_Token(&params[nparam].name, name);
2880 params[nparam].flags = flags;
2882 nparam++;
2883 name = NULL;
2884 flags = 0;
2885 done = t->text.a[0] == ')';
2886 break;
2887 default:
2888 goto bad;
2890 break;
2892 case TOK_WHITESPACE:
2893 break;
2895 default:
2896 bad:
2897 if (!err) {
2898 nasm_nonfatal("garbage `%s' in macro parameter list", tok_text(t));
2899 err = true;
2901 break;
2904 tn = &t->next;
2905 t = *tn;
2908 finish:
2909 while (t && t->type == TOK_WHITESPACE) {
2910 tn = &t->next;
2911 t = t->next;
2913 *tpp = tn;
2914 if (tmpl) {
2915 tmpl->nparam = nparam;
2916 tmpl->greedy = greedy;
2917 tmpl->params = params;
2919 return nparam;
2923 * Common code for defining an smacro. The tmpl argument, if not NULL,
2924 * contains any macro parameters that aren't explicit arguments;
2925 * those are the more uncommon macro variants.
2927 static SMacro *define_smacro(const char *mname, bool casesense,
2928 Token *expansion, SMacro *tmpl)
2930 SMacro *smac, **smhead;
2931 struct hash_table *smtbl;
2932 Context *ctx;
2933 bool defining_alias = false;
2934 unsigned int nparam = 0;
2936 if (tmpl) {
2937 defining_alias = tmpl->alias;
2938 nparam = tmpl->nparam;
2939 if (nparam && !defining_alias)
2940 mark_smac_params(expansion, tmpl, 0);
2943 while (1) {
2944 ctx = get_ctx(mname, &mname);
2946 if (!smacro_defined(ctx, mname, nparam, &smac, casesense, true)) {
2947 /* Create a new macro */
2948 smtbl = ctx ? &ctx->localmac : &smacros;
2949 smhead = (SMacro **) hash_findi_add(smtbl, mname);
2950 nasm_new(smac);
2951 smac->next = *smhead;
2952 *smhead = smac;
2953 break;
2954 } else if (!smac) {
2955 nasm_warn(WARN_OTHER, "single-line macro `%s' defined both with and"
2956 " without parameters", mname);
2958 * Some instances of the old code considered this a failure,
2959 * some others didn't. What is the right thing to do here?
2961 goto fail;
2962 } else if (!smac->alias || !do_aliases || defining_alias) {
2964 * We're redefining, so we have to take over an
2965 * existing SMacro structure. This means freeing
2966 * what was already in it, but not the structure itself.
2968 clear_smacro(smac);
2969 break;
2970 } else if (smac->in_progress) {
2971 nasm_nonfatal("macro alias loop");
2972 goto fail;
2973 } else {
2974 /* It is an alias macro; follow the alias link */
2975 SMacro *s;
2977 smac->in_progress = true;
2978 s = define_smacro(tok_text(smac->expansion), casesense,
2979 expansion, tmpl);
2980 smac->in_progress = false;
2981 return s;
2985 smac->name = nasm_strdup(mname);
2986 smac->casesense = casesense;
2987 smac->expansion = expansion;
2988 smac->expand = smacro_expand_default;
2989 if (tmpl) {
2990 smac->nparam = tmpl->nparam;
2991 smac->params = tmpl->params;
2992 smac->alias = tmpl->alias;
2993 smac->greedy = tmpl->greedy;
2994 if (tmpl->expand)
2995 smac->expand = tmpl->expand;
2997 if (list_option('s')) {
2998 list_smacro_def((smac->alias ? PP_DEFALIAS : PP_DEFINE)
2999 + !casesense, ctx, smac);
3001 return smac;
3003 fail:
3004 free_tlist(expansion);
3005 if (tmpl)
3006 free_smacro_members(tmpl);
3007 return NULL;
3011 * Undefine an smacro
3013 static void undef_smacro(const char *mname, bool undefalias)
3015 SMacro **smhead, *s, **sp;
3016 struct hash_table *smtbl;
3017 Context *ctx;
3019 ctx = get_ctx(mname, &mname);
3020 smtbl = ctx ? &ctx->localmac : &smacros;
3021 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
3023 if (smhead) {
3025 * We now have a macro name... go hunt for it.
3027 sp = smhead;
3028 while ((s = *sp) != NULL) {
3029 if (!mstrcmp(s->name, mname, s->casesense)) {
3030 if (s->alias && !undefalias) {
3031 if (do_aliases) {
3032 if (s->in_progress) {
3033 nasm_nonfatal("macro alias loop");
3034 } else {
3035 s->in_progress = true;
3036 undef_smacro(tok_text(s->expansion), false);
3037 s->in_progress = false;
3040 } else {
3041 if (list_option('d'))
3042 list_smacro_def(s->alias ? PP_UNDEFALIAS : PP_UNDEF,
3043 ctx, s);
3044 *sp = s->next;
3045 free_smacro(s);
3046 continue;
3049 sp = &s->next;
3055 * Parse a mmacro specification.
3057 static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
3059 tline = tline->next;
3060 tline = skip_white(tline);
3061 tline = expand_id(tline);
3062 if (!tok_type(tline, TOK_ID)) {
3063 nasm_nonfatal("`%s' expects a macro name", directive);
3064 return false;
3067 #if 0
3068 def->prev = NULL;
3069 #endif
3070 def->name = dup_text(tline);
3071 def->plus = false;
3072 def->nolist = false;
3073 def->nparam_min = 0;
3074 def->nparam_max = 0;
3076 tline = expand_smacro(tline->next);
3077 tline = skip_white(tline);
3078 if (!tok_type(tline, TOK_NUMBER))
3079 nasm_nonfatal("`%s' expects a parameter count", directive);
3080 else
3081 def->nparam_min = def->nparam_max = read_param_count(tok_text(tline));
3082 if (tline && tok_is(tline->next, '-')) {
3083 tline = tline->next->next;
3084 if (tok_is(tline, '*')) {
3085 def->nparam_max = INT_MAX;
3086 } else if (!tok_type(tline, TOK_NUMBER)) {
3087 nasm_nonfatal("`%s' expects a parameter count after `-'", directive);
3088 } else {
3089 def->nparam_max = read_param_count(tok_text(tline));
3090 if (def->nparam_min > def->nparam_max) {
3091 nasm_nonfatal("minimum parameter count exceeds maximum");
3092 def->nparam_max = def->nparam_min;
3096 if (tline && tok_is(tline->next, '+')) {
3097 tline = tline->next;
3098 def->plus = true;
3100 if (tline && tok_type(tline->next, TOK_ID) &&
3101 tline->next->len == 7 &&
3102 !nasm_stricmp(tline->next->text.a, ".nolist")) {
3103 tline = tline->next;
3104 def->nolist = !list_option('f') || istk->nolist;
3108 * Handle default parameters.
3110 if (tline && tline->next) {
3111 def->dlist = tline->next;
3112 tline->next = NULL;
3113 count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
3114 } else {
3115 def->dlist = NULL;
3116 def->defaults = NULL;
3118 def->expansion = NULL;
3120 if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
3121 !def->plus) {
3123 *!macro-defaults [on] macros with more default than optional parameters
3124 *! warns when a macro has more default parameters than optional parameters.
3125 *! See \k{mlmacdef} for why might want to disable this warning.
3127 nasm_warn(WARN_MACRO_DEFAULTS,
3128 "too many default macro parameters in macro `%s'", def->name);
3131 return true;
3136 * Decode a size directive
3138 static int parse_size(const char *str) {
3139 static const char *size_names[] =
3140 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
3141 static const int sizes[] =
3142 { 0, 1, 4, 16, 8, 10, 2, 32 };
3143 return str ? sizes[bsii(str, size_names, ARRAY_SIZE(size_names))+1] : 0;
3147 * Process a preprocessor %pragma directive. Currently there are none.
3148 * Gets passed the token list starting with the "preproc" token from
3149 * "%pragma preproc".
3151 static void do_pragma_preproc(Token *tline)
3153 /* Skip to the real stuff */
3154 tline = tline->next;
3155 tline = skip_white(tline);
3156 if (!tline)
3157 return;
3159 (void)tline; /* Nothing else to do at present */
3162 static bool is_macro_id(const Token *t)
3164 return tok_type(t, TOK_ID) || tok_type(t, TOK_LOCAL_MACRO);
3167 static const char *get_id(Token **tp, const char *dname)
3169 const char *id;
3170 Token *t = *tp;
3172 t = t->next; /* Skip directive */
3173 t = skip_white(t);
3174 t = expand_id(t);
3176 if (!is_macro_id(t)) {
3177 nasm_nonfatal("`%s' expects a macro identifier", dname);
3178 return NULL;
3181 id = tok_text(t);
3182 t = skip_white(t);
3183 *tp = t;
3184 return id;
3187 /* Parse a %use package name and find the package. Set *err on syntax error. */
3188 static const struct use_package *
3189 get_use_pkg(Token *t, const char *dname, const char **name)
3191 const char *id;
3193 t = skip_white(t);
3194 t = expand_smacro(t);
3196 *name = NULL;
3198 if (!t) {
3199 nasm_nonfatal("`%s' expects a package name, got end of line", dname);
3200 return NULL;
3201 } else if (t->type != TOK_ID && t->type != TOK_STRING) {
3202 nasm_nonfatal("`%s' expects a package name, got `%s'",
3203 dname, tok_text(t));
3204 return NULL;
3207 *name = id = unquote_token(t);
3209 t = t->next;
3210 t = skip_white(t);
3211 if (t)
3212 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
3214 return nasm_find_use_package(id);
3218 * Mark parameter tokens in an smacro definition. If the type argument
3219 * is 0, create smac param tokens, otherwise use the type specified;
3220 * normally this is used for TOK_XDEF_PARAM, which is used to protect
3221 * parameter tokens during expansion during %xdefine.
3223 * tmpl may not be NULL here.
3225 static void mark_smac_params(Token *tline, const SMacro *tmpl,
3226 enum pp_token_type type)
3228 const struct smac_param *params = tmpl->params;
3229 int nparam = tmpl->nparam;
3230 Token *t;
3231 int i;
3233 list_for_each(t, tline) {
3234 if (t->type != TOK_ID && t->type != TOK_XDEF_PARAM)
3235 continue;
3237 for (i = 0; i < nparam; i++) {
3238 if (tok_text_match(t, &params[i].name))
3239 t->type = type ? type : tok_smac_param(i);
3245 * find and process preprocessor directive in passed line
3246 * Find out if a line contains a preprocessor directive, and deal
3247 * with it if so.
3249 * If a directive _is_ found, it is the responsibility of this routine
3250 * (and not the caller) to free_tlist() the line.
3252 * @param tline a pointer to the current tokeninzed line linked list
3253 * @param output if this directive generated output
3254 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
3257 static int do_directive(Token *tline, Token **output)
3259 enum preproc_token op;
3260 int j;
3261 bool err;
3262 bool nolist;
3263 bool casesense;
3264 int k, m;
3265 int offset;
3266 const char *p;
3267 char *q, *qbuf;
3268 const char *found_path;
3269 const char *mname;
3270 struct ppscan pps;
3271 Include *inc;
3272 Context *ctx;
3273 Cond *cond;
3274 MMacro *mmac, **mmhead;
3275 Token *t = NULL, *tt, *macro_start, *last, *origline;
3276 Line *l;
3277 struct tokenval tokval;
3278 expr *evalresult;
3279 int64_t count;
3280 size_t len;
3281 errflags severity;
3282 const char *dname; /* Name of directive, for messages */
3284 *output = NULL; /* No output generated */
3285 origline = tline;
3287 tline = skip_white(tline);
3288 if (!tline || !tok_type(tline, TOK_PREPROC_ID))
3289 return NO_DIRECTIVE_FOUND;
3291 dname = tok_text(tline);
3292 if (dname[1] == '%')
3293 return NO_DIRECTIVE_FOUND;
3295 op = pp_token_hash(dname);
3297 casesense = true;
3298 if (PP_HAS_CASE(op) & PP_INSENSITIVE(op)) {
3299 casesense = false;
3300 op--;
3304 * If we're in a non-emitting branch of a condition construct,
3305 * or walking to the end of an already terminated %rep block,
3306 * we should ignore all directives except for condition
3307 * directives.
3309 if (((istk->conds && !emitting(istk->conds->state)) ||
3310 (istk->mstk.mstk && !istk->mstk.mstk->in_progress)) &&
3311 !is_condition(op)) {
3312 return NO_DIRECTIVE_FOUND;
3316 * If we're defining a macro or reading a %rep block, we should
3317 * ignore all directives except for %macro/%imacro (which nest),
3318 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
3319 * If we're in a %rep block, another %rep nests, so should be let through.
3321 if (defining && op != PP_MACRO && op != PP_RMACRO &&
3322 op != PP_ENDMACRO && op != PP_ENDM &&
3323 (defining->name || (op != PP_ENDREP && op != PP_REP))) {
3324 return NO_DIRECTIVE_FOUND;
3327 if (defining) {
3328 if (op == PP_MACRO || op == PP_RMACRO) {
3329 nested_mac_count++;
3330 return NO_DIRECTIVE_FOUND;
3331 } else if (nested_mac_count > 0) {
3332 if (op == PP_ENDMACRO) {
3333 nested_mac_count--;
3334 return NO_DIRECTIVE_FOUND;
3337 if (!defining->name) {
3338 if (op == PP_REP) {
3339 nested_rep_count++;
3340 return NO_DIRECTIVE_FOUND;
3341 } else if (nested_rep_count > 0) {
3342 if (op == PP_ENDREP) {
3343 nested_rep_count--;
3344 return NO_DIRECTIVE_FOUND;
3350 switch (op) {
3351 default:
3352 nasm_nonfatal("unknown preprocessor directive `%s'", dname);
3353 return NO_DIRECTIVE_FOUND; /* didn't get it */
3355 case PP_PRAGMA:
3357 * %pragma namespace options...
3359 * The namespace "preproc" is reserved for the preprocessor;
3360 * all other namespaces generate a [pragma] assembly directive.
3362 * Invalid %pragmas are ignored and may have different
3363 * meaning in future versions of NASM.
3365 t = tline;
3366 tline = tline->next;
3367 t->next = NULL;
3368 tline = zap_white(expand_smacro(tline));
3369 if (tok_type(tline, TOK_ID)) {
3370 if (!nasm_stricmp(tok_text(tline), "preproc")) {
3371 /* Preprocessor pragma */
3372 do_pragma_preproc(tline);
3373 free_tlist(tline);
3374 } else {
3375 /* Build the assembler directive */
3377 /* Append bracket to the end of the output */
3378 for (t = tline; t->next; t = t->next)
3380 t->next = make_tok_char(NULL, ']');
3382 /* Prepend "[pragma " */
3383 t = new_White(tline);
3384 t = new_Token(t, TOK_ID, "pragma", 6);
3385 t = make_tok_char(t, '[');
3386 tline = t;
3387 *output = tline;
3390 break;
3392 case PP_STACKSIZE:
3393 /* Directive to tell NASM what the default stack size is. The
3394 * default is for a 16-bit stack, and this can be overriden with
3395 * %stacksize large.
3397 tline = skip_white(tline->next);
3398 if (!tline || tline->type != TOK_ID) {
3399 nasm_nonfatal("`%s' missing size parameter", dname);
3401 if (nasm_stricmp(tok_text(tline), "flat") == 0) {
3402 /* All subsequent ARG directives are for a 32-bit stack */
3403 StackSize = 4;
3404 StackPointer = "ebp";
3405 ArgOffset = 8;
3406 LocalOffset = 0;
3407 } else if (nasm_stricmp(tok_text(tline), "flat64") == 0) {
3408 /* All subsequent ARG directives are for a 64-bit stack */
3409 StackSize = 8;
3410 StackPointer = "rbp";
3411 ArgOffset = 16;
3412 LocalOffset = 0;
3413 } else if (nasm_stricmp(tok_text(tline), "large") == 0) {
3414 /* All subsequent ARG directives are for a 16-bit stack,
3415 * far function call.
3417 StackSize = 2;
3418 StackPointer = "bp";
3419 ArgOffset = 4;
3420 LocalOffset = 0;
3421 } else if (nasm_stricmp(tok_text(tline), "small") == 0) {
3422 /* All subsequent ARG directives are for a 16-bit stack,
3423 * far function call. We don't support near functions.
3425 StackSize = 2;
3426 StackPointer = "bp";
3427 ArgOffset = 6;
3428 LocalOffset = 0;
3429 } else {
3430 nasm_nonfatal("`%s' invalid size type", dname);
3432 break;
3434 case PP_ARG:
3435 /* TASM like ARG directive to define arguments to functions, in
3436 * the following form:
3438 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
3440 offset = ArgOffset;
3441 do {
3442 const char *arg;
3443 char directive[256];
3444 int size = StackSize;
3446 /* Find the argument name */
3447 tline = skip_white(tline->next);
3448 if (!tline || tline->type != TOK_ID) {
3449 nasm_nonfatal("`%s' missing argument parameter", dname);
3450 goto done;
3452 arg = tok_text(tline);
3454 /* Find the argument size type */
3455 tline = tline->next;
3456 if (!tok_is(tline, ':')) {
3457 nasm_nonfatal("syntax error processing `%s' directive", dname);
3458 goto done;
3460 tline = tline->next;
3461 if (!tok_type(tline, TOK_ID)) {
3462 nasm_nonfatal("`%s' missing size type parameter", dname);
3463 goto done;
3466 /* Allow macro expansion of type parameter */
3467 tt = tokenize(tok_text(tline));
3468 tt = expand_smacro(tt);
3469 size = parse_size(tok_text(tt));
3470 if (!size) {
3471 nasm_nonfatal("invalid size type for `%s' missing directive", dname);
3472 free_tlist(tt);
3473 goto done;
3475 free_tlist(tt);
3477 /* Round up to even stack slots */
3478 size = ALIGN(size, StackSize);
3480 /* Now define the macro for the argument */
3481 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
3482 arg, StackPointer, offset);
3483 do_directive(tokenize(directive), output);
3484 offset += size;
3486 /* Move to the next argument in the list */
3487 tline = skip_white(tline->next);
3488 } while (tok_is(tline, ','));
3489 ArgOffset = offset;
3490 break;
3492 case PP_LOCAL:
3493 /* TASM like LOCAL directive to define local variables for a
3494 * function, in the following form:
3496 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
3498 * The '= LocalSize' at the end is ignored by NASM, but is
3499 * required by TASM to define the local parameter size (and used
3500 * by the TASM macro package).
3502 offset = LocalOffset;
3503 do {
3504 const char *local;
3505 char directive[256];
3506 int size = StackSize;
3508 /* Find the argument name */
3509 tline = skip_white(tline->next);
3510 if (!tline || tline->type != TOK_ID) {
3511 nasm_nonfatal("`%s' missing argument parameter", dname);
3512 goto done;
3514 local = tok_text(tline);
3516 /* Find the argument size type */
3517 tline = tline->next;
3518 if (!tok_is(tline, ':')) {
3519 nasm_nonfatal("syntax error processing `%s' directive", dname);
3520 goto done;
3522 tline = tline->next;
3523 if (!tok_type(tline, TOK_ID)) {
3524 nasm_nonfatal("`%s' missing size type parameter", dname);
3525 goto done;
3528 /* Allow macro expansion of type parameter */
3529 tt = tokenize(tok_text(tline));
3530 tt = expand_smacro(tt);
3531 size = parse_size(tok_text(tt));
3532 if (!size) {
3533 nasm_nonfatal("invalid size type for `%s' missing directive", dname);
3534 free_tlist(tt);
3535 goto done;
3537 free_tlist(tt);
3539 /* Round up to even stack slots */
3540 size = ALIGN(size, StackSize);
3542 offset += size; /* Negative offset, increment before */
3544 /* Now define the macro for the argument */
3545 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
3546 local, StackPointer, offset);
3547 do_directive(tokenize(directive), output);
3549 /* Now define the assign to setup the enter_c macro correctly */
3550 snprintf(directive, sizeof(directive),
3551 "%%assign %%$localsize %%$localsize+%d", size);
3552 do_directive(tokenize(directive), output);
3554 /* Move to the next argument in the list */
3555 tline = skip_white(tline->next);
3556 } while (tok_is(tline, ','));
3557 LocalOffset = offset;
3558 break;
3560 case PP_CLEAR:
3561 if (tline->next)
3562 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
3563 free_macros();
3564 init_macros();
3565 break;
3567 case PP_DEPEND:
3568 t = tline->next = expand_smacro(tline->next);
3569 t = skip_white(t);
3570 if (!t || (t->type != TOK_STRING &&
3571 t->type != TOK_INTERNAL_STRING)) {
3572 nasm_nonfatal("`%s' expects a file name", dname);
3573 goto done;
3575 if (t->next)
3576 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
3578 strlist_add(deplist, unquote_token_cstr(t));
3579 goto done;
3581 case PP_INCLUDE:
3582 t = tline->next = expand_smacro(tline->next);
3583 t = skip_white(t);
3585 if (!t || (t->type != TOK_STRING &&
3586 t->type != TOK_INTERNAL_STRING)) {
3587 nasm_nonfatal("`%s' expects a file name", dname);
3588 goto done;
3590 if (t->next)
3591 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
3592 p = unquote_token_cstr(t);
3593 nasm_new(inc);
3594 inc->next = istk;
3595 found_path = NULL;
3596 inc->fp = inc_fopen(p, deplist, &found_path,
3597 (pp_mode == PP_DEPS)
3598 ? INC_OPTIONAL : INC_NEEDED, NF_TEXT);
3599 if (!inc->fp) {
3600 /* -MG given but file not found */
3601 nasm_free(inc);
3602 } else {
3603 inc->fname = src_set_fname(found_path ? found_path : p);
3604 inc->lineno = src_set_linnum(0);
3605 inc->lineinc = 1;
3606 inc->nolist = istk->nolist;
3607 istk = inc;
3608 lfmt->uplevel(LIST_INCLUDE, 0);
3610 break;
3612 case PP_USE:
3614 const struct use_package *pkg;
3615 const char *name;
3617 pkg = get_use_pkg(tline->next, dname, &name);
3618 if (!name)
3619 goto done;
3620 if (!pkg) {
3621 nasm_nonfatal("unknown `%s' package: `%s'", dname, name);
3622 } else if (!use_loaded[pkg->index]) {
3624 * Not already included, go ahead and include it.
3625 * Treat it as an include file for the purpose of
3626 * producing a listing.
3628 use_loaded[pkg->index] = true;
3629 stdmacpos = pkg->macros;
3630 nasm_new(inc);
3631 inc->next = istk;
3632 inc->fname = src_set_fname(NULL);
3633 inc->lineno = src_set_linnum(0);
3634 inc->nolist = !list_option('b') || istk->nolist;
3635 istk = inc;
3636 lfmt->uplevel(LIST_INCLUDE, 0);
3638 break;
3640 case PP_PUSH:
3641 case PP_REPL:
3642 case PP_POP:
3643 tline = tline->next;
3644 tline = skip_white(tline);
3645 tline = expand_id(tline);
3646 if (tline) {
3647 if (!tok_type(tline, TOK_ID)) {
3648 nasm_nonfatal("`%s' expects a context identifier", dname);
3649 goto done;
3651 if (tline->next)
3652 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored",
3653 dname);
3654 p = tok_text(tline);
3655 } else {
3656 p = NULL; /* Anonymous */
3659 if (op == PP_PUSH) {
3660 nasm_new(ctx);
3661 ctx->depth = cstk ? cstk->depth + 1 : 1;
3662 ctx->next = cstk;
3663 ctx->name = p ? nasm_strdup(p) : NULL;
3664 ctx->number = unique++;
3665 cstk = ctx;
3666 } else {
3667 /* %pop or %repl */
3668 if (!cstk) {
3669 nasm_nonfatal("`%s': context stack is empty", dname);
3670 } else if (op == PP_POP) {
3671 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
3672 nasm_nonfatal("`%s' in wrong context: %s, "
3673 "expected %s",
3674 dname, cstk->name ? cstk->name : "anonymous", p);
3675 else
3676 ctx_pop();
3677 } else {
3678 /* op == PP_REPL */
3679 nasm_free((char *)cstk->name);
3680 cstk->name = p ? nasm_strdup(p) : NULL;
3681 p = NULL;
3684 break;
3685 case PP_FATAL:
3686 severity = ERR_FATAL;
3687 goto issue_error;
3688 case PP_ERROR:
3689 severity = ERR_NONFATAL|ERR_PASS2;
3690 goto issue_error;
3691 case PP_WARNING:
3693 *!user [on] %warning directives
3694 *! controls output of \c{%warning} directives (see \k{pperror}).
3696 severity = ERR_WARNING|WARN_USER|ERR_PASS2;
3697 goto issue_error;
3699 issue_error:
3701 /* Only error out if this is the final pass */
3702 tline->next = expand_smacro(tline->next);
3703 tline = tline->next;
3704 tline = skip_white(tline);
3705 t = tline ? tline->next : NULL;
3706 t = skip_white(t);
3707 if (tok_type(tline, TOK_STRING) && !t) {
3708 /* The line contains only a quoted string */
3709 p = unquote_token(tline); /* Ignore NUL character truncation */
3710 nasm_error(severity, "%s", p);
3711 } else {
3712 /* Not a quoted string, or more than a quoted string */
3713 q = detoken(tline, false);
3714 nasm_error(severity, "%s", q);
3715 nasm_free(q);
3717 break;
3720 CASE_PP_IF:
3721 if (istk->conds && !emitting(istk->conds->state))
3722 j = COND_NEVER;
3723 else {
3724 j = if_condition(tline->next, op);
3725 tline->next = NULL; /* it got freed */
3727 cond = nasm_malloc(sizeof(Cond));
3728 cond->next = istk->conds;
3729 cond->state = j;
3730 istk->conds = cond;
3731 if(istk->mstk.mstk)
3732 istk->mstk.mstk->condcnt++;
3733 break;
3735 CASE_PP_ELIF:
3736 if (!istk->conds)
3737 nasm_fatal("`%s': no matching `%%if'", dname);
3738 switch(istk->conds->state) {
3739 case COND_IF_TRUE:
3740 istk->conds->state = COND_DONE;
3741 break;
3743 case COND_DONE:
3744 case COND_NEVER:
3745 break;
3747 case COND_ELSE_TRUE:
3748 case COND_ELSE_FALSE:
3749 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
3750 "`%%elif' after `%%else' ignored");
3751 istk->conds->state = COND_NEVER;
3752 break;
3754 case COND_IF_FALSE:
3756 * IMPORTANT: In the case of %if, we will already have
3757 * called expand_mmac_params(); however, if we're
3758 * processing an %elif we must have been in a
3759 * non-emitting mode, which would have inhibited
3760 * the normal invocation of expand_mmac_params().
3761 * Therefore, we have to do it explicitly here.
3763 j = if_condition(expand_mmac_params(tline->next), op);
3764 tline->next = NULL; /* it got freed */
3765 istk->conds->state = j;
3766 break;
3768 break;
3770 case PP_ELSE:
3771 if (tline->next)
3772 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
3773 "trailing garbage after `%%else' ignored");
3774 if (!istk->conds)
3775 nasm_fatal("`%%else: no matching `%%if'");
3776 switch(istk->conds->state) {
3777 case COND_IF_TRUE:
3778 case COND_DONE:
3779 istk->conds->state = COND_ELSE_FALSE;
3780 break;
3782 case COND_NEVER:
3783 break;
3785 case COND_IF_FALSE:
3786 istk->conds->state = COND_ELSE_TRUE;
3787 break;
3789 case COND_ELSE_TRUE:
3790 case COND_ELSE_FALSE:
3791 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
3792 "`%%else' after `%%else' ignored.");
3793 istk->conds->state = COND_NEVER;
3794 break;
3796 break;
3798 case PP_ENDIF:
3799 if (tline->next)
3800 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
3801 "trailing garbage after `%%endif' ignored");
3802 if (!istk->conds)
3803 nasm_fatal("`%%endif': no matching `%%if'");
3804 cond = istk->conds;
3805 istk->conds = cond->next;
3806 nasm_free(cond);
3807 if(istk->mstk.mstk)
3808 istk->mstk.mstk->condcnt--;
3809 break;
3811 case PP_RMACRO:
3812 case PP_MACRO:
3814 MMacro *def;
3816 nasm_assert(!defining);
3817 nasm_new(def);
3818 def->casesense = casesense;
3819 def->dstk.mmac = defining;
3820 if (op == PP_RMACRO)
3821 def->max_depth = nasm_limit[LIMIT_MACRO_LEVELS];
3822 if (!parse_mmacro_spec(tline, def, dname)) {
3823 nasm_free(def);
3824 goto done;
3827 defining = def;
3828 src_get(&defining->xline, &defining->fname);
3830 mmac = (MMacro *) hash_findix(&mmacros, defining->name);
3831 while (mmac) {
3832 if (!strcmp(mmac->name, defining->name) &&
3833 (mmac->nparam_min <= defining->nparam_max
3834 || defining->plus)
3835 && (defining->nparam_min <= mmac->nparam_max
3836 || mmac->plus)) {
3837 nasm_warn(WARN_OTHER, "redefining multi-line macro `%s'",
3838 defining->name);
3839 break;
3841 mmac = mmac->next;
3843 break;
3846 case PP_ENDM:
3847 case PP_ENDMACRO:
3848 if (!(defining && defining->name)) {
3849 nasm_nonfatal("`%s': not defining a macro", tok_text(tline));
3850 goto done;
3852 mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
3853 defining->next = *mmhead;
3854 *mmhead = defining;
3855 defining = NULL;
3856 break;
3858 case PP_EXITMACRO:
3860 * We must search along istk->expansion until we hit a
3861 * macro-end marker for a macro with a name. Then we
3862 * bypass all lines between exitmacro and endmacro.
3864 list_for_each(l, istk->expansion)
3865 if (l->finishes && l->finishes->name)
3866 break;
3868 if (l) {
3870 * Remove all conditional entries relative to this
3871 * macro invocation. (safe to do in this context)
3873 for ( ; l->finishes->condcnt > 0; l->finishes->condcnt --) {
3874 cond = istk->conds;
3875 istk->conds = cond->next;
3876 nasm_free(cond);
3878 istk->expansion = l;
3879 } else {
3880 nasm_nonfatal("`%%exitmacro' not within `%%macro' block");
3882 break;
3884 case PP_UNIMACRO:
3885 casesense = false;
3886 /* fall through */
3887 case PP_UNMACRO:
3889 MMacro **mmac_p;
3890 MMacro spec;
3892 nasm_zero(spec);
3893 spec.casesense = casesense;
3894 if (!parse_mmacro_spec(tline, &spec, dname)) {
3895 goto done;
3897 mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
3898 while (mmac_p && *mmac_p) {
3899 mmac = *mmac_p;
3900 if (mmac->casesense == spec.casesense &&
3901 !mstrcmp(mmac->name, spec.name, spec.casesense) &&
3902 mmac->nparam_min == spec.nparam_min &&
3903 mmac->nparam_max == spec.nparam_max &&
3904 mmac->plus == spec.plus) {
3905 *mmac_p = mmac->next;
3906 free_mmacro(mmac);
3907 } else {
3908 mmac_p = &mmac->next;
3911 free_tlist(spec.dlist);
3912 break;
3915 case PP_ROTATE:
3916 while (tok_white(tline->next))
3917 tline = tline->next;
3918 if (!tline->next) {
3919 free_tlist(origline);
3920 nasm_nonfatal("`%%rotate' missing rotate count");
3921 return DIRECTIVE_FOUND;
3923 t = expand_smacro(tline->next);
3924 tline->next = NULL;
3925 pps.tptr = tline = t;
3926 pps.ntokens = -1;
3927 tokval.t_type = TOKEN_INVALID;
3928 evalresult =
3929 evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
3930 free_tlist(tline);
3931 if (!evalresult)
3932 return DIRECTIVE_FOUND;
3933 if (tokval.t_type)
3934 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
3935 if (!is_simple(evalresult)) {
3936 nasm_nonfatal("non-constant value given to `%%rotate'");
3937 return DIRECTIVE_FOUND;
3939 mmac = istk->mstk.mmac;
3940 if (!mmac) {
3941 nasm_nonfatal("`%%rotate' invoked outside a macro call");
3942 } else if (mmac->nparam == 0) {
3943 nasm_nonfatal("`%%rotate' invoked within macro without parameters");
3944 } else {
3945 int rotate = mmac->rotate + reloc_value(evalresult);
3947 rotate %= (int)mmac->nparam;
3948 if (rotate < 0)
3949 rotate += mmac->nparam;
3951 mmac->rotate = rotate;
3953 break;
3955 case PP_REP:
3957 MMacro *tmp_defining;
3959 nolist = false;
3960 tline = skip_white(tline->next);
3961 if (tok_type(tline, TOK_ID) && tline->len == 7 &&
3962 !nasm_memicmp(tline->text.a, ".nolist", 7)) {
3963 nolist = !list_option('f') || istk->nolist;
3964 tline = skip_white(tline->next);
3967 if (tline) {
3968 pps.tptr = expand_smacro(tline);
3969 pps.ntokens = -1;
3970 tokval.t_type = TOKEN_INVALID;
3971 /* XXX: really critical?! */
3972 evalresult =
3973 evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
3974 if (!evalresult)
3975 goto done;
3976 if (tokval.t_type)
3977 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
3978 if (!is_simple(evalresult)) {
3979 nasm_nonfatal("non-constant value given to `%%rep'");
3980 goto done;
3982 count = reloc_value(evalresult);
3983 if (count > nasm_limit[LIMIT_REP]) {
3984 nasm_nonfatal("`%%rep' count %"PRId64" exceeds limit (currently %"PRId64")",
3985 count, nasm_limit[LIMIT_REP]);
3986 count = 0;
3987 } else if (count < 0) {
3989 *!negative-rep [on] regative %rep count
3990 *! warns about negative counts given to the \c{%rep}
3991 *! preprocessor directive.
3993 nasm_warn(ERR_PASS2|WARN_NEGATIVE_REP,
3994 "negative `%%rep' count: %"PRId64, count);
3995 count = 0;
3996 } else {
3997 count++;
3999 } else {
4000 nasm_nonfatal("`%%rep' expects a repeat count");
4001 count = 0;
4003 tmp_defining = defining;
4004 nasm_new(defining);
4005 defining->nolist = nolist;
4006 defining->in_progress = count;
4007 defining->mstk = istk->mstk;
4008 defining->dstk.mstk = tmp_defining;
4009 defining->dstk.mmac = tmp_defining ? tmp_defining->dstk.mmac : NULL;
4010 src_get(&defining->xline, &defining->fname);
4011 break;
4014 case PP_ENDREP:
4015 if (!defining || defining->name) {
4016 nasm_nonfatal("`%%endrep': no matching `%%rep'");
4017 goto done;
4021 * Now we have a "macro" defined - although it has no name
4022 * and we won't be entering it in the hash tables - we must
4023 * push a macro-end marker for it on to istk->expansion.
4024 * After that, it will take care of propagating itself (a
4025 * macro-end marker line for a macro which is really a %rep
4026 * block will cause the macro to be re-expanded, complete
4027 * with another macro-end marker to ensure the process
4028 * continues) until the whole expansion is forcibly removed
4029 * from istk->expansion by a %exitrep.
4031 nasm_new(l);
4032 l->next = istk->expansion;
4033 l->finishes = defining;
4034 l->first = NULL;
4035 istk->expansion = l;
4037 istk->mstk.mstk = defining;
4039 lfmt->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
4040 defining = defining->dstk.mstk;
4041 break;
4043 case PP_EXITREP:
4045 * We must search along istk->expansion until we hit a
4046 * macro-end marker for a macro with no name. Then we set
4047 * its `in_progress' flag to 0.
4049 list_for_each(l, istk->expansion)
4050 if (l->finishes && !l->finishes->name)
4051 break;
4053 if (l)
4054 l->finishes->in_progress = 0;
4055 else
4056 nasm_nonfatal("`%%exitrep' not within `%%rep' block");
4057 break;
4059 case PP_DEFINE:
4060 case PP_XDEFINE:
4061 case PP_DEFALIAS:
4063 SMacro tmpl;
4064 Token **lastp;
4065 int nparam;
4067 if (!(mname = get_id(&tline, dname)))
4068 goto done;
4070 nasm_zero(tmpl);
4071 lastp = &tline->next;
4072 nparam = parse_smacro_template(&lastp, &tmpl);
4073 tline = *lastp;
4074 *lastp = NULL;
4076 if (unlikely(op == PP_DEFALIAS)) {
4077 macro_start = tline;
4078 if (!is_macro_id(macro_start)) {
4079 nasm_nonfatal("`%s' expects a macro identifier to alias",
4080 dname);
4081 goto done;
4083 tt = macro_start->next;
4084 macro_start->next = NULL;
4085 tline = tline->next;
4086 tline = skip_white(tline);
4087 if (tline && tline->type) {
4088 nasm_warn(WARN_OTHER,
4089 "trailing garbage after aliasing identifier ignored");
4091 free_tlist(tt);
4092 tmpl.alias = true;
4093 } else {
4094 if (op == PP_XDEFINE) {
4095 /* Protect macro parameter tokens */
4096 if (nparam)
4097 mark_smac_params(tline, &tmpl, TOK_XDEF_PARAM);
4098 tline = expand_smacro(tline);
4100 /* NB: Does this still make sense? */
4101 macro_start = reverse_tokens(tline);
4105 * Good. We now have a macro name, a parameter count, and a
4106 * token list (in reverse order) for an expansion. We ought
4107 * to be OK just to create an SMacro, store it, and let
4108 * free_tlist have the rest of the line (which we have
4109 * carefully re-terminated after chopping off the expansion
4110 * from the end).
4112 define_smacro(mname, casesense, macro_start, &tmpl);
4113 break;
4116 case PP_UNDEF:
4117 case PP_UNDEFALIAS:
4118 if (!(mname = get_id(&tline, dname)))
4119 goto done;
4120 if (tline->next)
4121 nasm_warn(WARN_OTHER, "trailing garbage after macro name ignored");
4123 undef_smacro(mname, op == PP_UNDEFALIAS);
4124 break;
4126 case PP_DEFSTR:
4127 if (!(mname = get_id(&tline, dname)))
4128 goto done;
4130 last = tline;
4131 tline = expand_smacro(tline->next);
4132 last->next = NULL;
4134 tline = zap_white(tline);
4135 q = detoken(tline, false);
4136 macro_start = make_tok_qstr(NULL, q);
4137 nasm_free(q);
4140 * We now have a macro name, an implicit parameter count of
4141 * zero, and a string token to use as an expansion. Create
4142 * and store an SMacro.
4144 define_smacro(mname, casesense, macro_start, NULL);
4145 break;
4147 case PP_DEFTOK:
4148 if (!(mname = get_id(&tline, dname)))
4149 goto done;
4151 last = tline;
4152 tline = expand_smacro(tline->next);
4153 last->next = NULL;
4155 t = skip_white(tline);
4156 /* t should now point to the string */
4157 if (!tok_type(t, TOK_STRING)) {
4158 nasm_nonfatal("`%s' requires string as second parameter", dname);
4159 free_tlist(tline);
4160 goto done;
4164 * Convert the string to a token stream. Note that smacros
4165 * are stored with the token stream reversed, so we have to
4166 * reverse the output of tokenize().
4168 macro_start = reverse_tokens(tokenize(unquote_token_cstr(t)));
4171 * We now have a macro name, an implicit parameter count of
4172 * zero, and a numeric token to use as an expansion. Create
4173 * and store an SMacro.
4175 define_smacro(mname, casesense, macro_start, NULL);
4176 free_tlist(tline);
4177 break;
4179 case PP_PATHSEARCH:
4181 const char *found_path;
4183 if (!(mname = get_id(&tline, dname)))
4184 goto done;
4186 last = tline;
4187 tline = expand_smacro(tline->next);
4188 last->next = NULL;
4190 t = skip_white(tline);
4191 if (!t || (t->type != TOK_STRING &&
4192 t->type != TOK_INTERNAL_STRING)) {
4193 nasm_nonfatal("`%s' expects a file name", dname);
4194 free_tlist(tline);
4195 goto done;
4197 if (t->next)
4198 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
4200 p = unquote_token_cstr(t);
4202 inc_fopen(p, NULL, &found_path, INC_PROBE, NF_BINARY);
4203 if (!found_path)
4204 found_path = p;
4205 macro_start = make_tok_qstr(NULL, found_path);
4208 * We now have a macro name, an implicit parameter count of
4209 * zero, and a string token to use as an expansion. Create
4210 * and store an SMacro.
4212 define_smacro(mname, casesense, macro_start, NULL);
4213 free_tlist(tline);
4214 break;
4217 case PP_STRLEN:
4218 if (!(mname = get_id(&tline, dname)))
4219 goto done;
4221 last = tline;
4222 tline = expand_smacro(tline->next);
4223 last->next = NULL;
4225 t = skip_white(tline);
4226 /* t should now point to the string */
4227 if (!tok_type(t, TOK_STRING)) {
4228 nasm_nonfatal("`%s' requires string as second parameter", dname);
4229 free_tlist(tline);
4230 free_tlist(origline);
4231 return DIRECTIVE_FOUND;
4234 unquote_token(t);
4235 macro_start = make_tok_num(NULL, t->len);
4238 * We now have a macro name, an implicit parameter count of
4239 * zero, and a numeric token to use as an expansion. Create
4240 * and store an SMacro.
4242 define_smacro(mname, casesense, macro_start, NULL);
4243 free_tlist(tline);
4244 free_tlist(origline);
4245 return DIRECTIVE_FOUND;
4247 case PP_STRCAT:
4248 if (!(mname = get_id(&tline, dname)))
4249 goto done;
4251 last = tline;
4252 tline = expand_smacro(tline->next);
4253 last->next = NULL;
4255 len = 0;
4256 list_for_each(t, tline) {
4257 switch (t->type) {
4258 case TOK_WHITESPACE:
4259 break;
4260 case TOK_STRING:
4261 unquote_token(t);
4262 len += t->len;
4263 break;
4264 case TOK_OTHER:
4265 if (tok_is(t, ',')) /* permit comma separators */
4266 break;
4267 /* else fall through */
4268 default:
4269 nasm_nonfatal("non-string passed to `%s': %s", dname,
4270 tok_text(t));
4271 free_tlist(tline);
4272 goto done;
4276 q = qbuf = nasm_malloc(len+1);
4277 list_for_each(t, tline) {
4278 if (t->type == TOK_INTERNAL_STRING)
4279 q = mempcpy(q, tok_text(t), t->len);
4281 *q = '\0';
4284 * We now have a macro name, an implicit parameter count of
4285 * zero, and a numeric token to use as an expansion. Create
4286 * and store an SMacro.
4288 macro_start = make_tok_qstr_len(NULL, qbuf, len);
4289 nasm_free(qbuf);
4290 define_smacro(mname, casesense, macro_start, NULL);
4291 free_tlist(tline);
4292 break;
4294 case PP_SUBSTR:
4296 int64_t start, count;
4297 const char *txt;
4298 size_t len;
4300 if (!(mname = get_id(&tline, dname)))
4301 goto done;
4303 last = tline;
4304 tline = expand_smacro(tline->next);
4305 last->next = NULL;
4307 if (tline) /* skip expanded id */
4308 t = tline->next;
4310 t = skip_white(t);
4312 /* t should now point to the string */
4313 if (!tok_type(t, TOK_STRING)) {
4314 nasm_nonfatal("`%s' requires string as second parameter", dname);
4315 free_tlist(tline);
4316 goto done;
4319 pps.tptr = t->next;
4320 pps.ntokens = -1;
4321 tokval.t_type = TOKEN_INVALID;
4322 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
4323 if (!evalresult) {
4324 free_tlist(tline);
4325 goto done;
4326 } else if (!is_simple(evalresult)) {
4327 nasm_nonfatal("non-constant value given to `%s'", dname);
4328 free_tlist(tline);
4329 goto done;
4331 start = evalresult->value - 1;
4333 pps.tptr = skip_white(pps.tptr);
4334 if (!pps.tptr) {
4335 count = 1; /* Backwards compatibility: one character */
4336 } else {
4337 tokval.t_type = TOKEN_INVALID;
4338 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
4339 if (!evalresult) {
4340 free_tlist(tline);
4341 goto done;
4342 } else if (!is_simple(evalresult)) {
4343 nasm_nonfatal("non-constant value given to `%s'", dname);
4344 free_tlist(tline);
4345 goto done;
4347 count = evalresult->value;
4350 unquote_token(t);
4351 len = t->len;
4353 /* make start and count being in range */
4354 if (start < 0)
4355 start = 0;
4356 if (count < 0)
4357 count = len + count + 1 - start;
4358 if (start + count > (int64_t)len)
4359 count = len - start;
4360 if (!len || count < 0 || start >=(int64_t)len)
4361 start = -1, count = 0; /* empty string */
4363 txt = (start < 0) ? "" : tok_text(t) + start;
4364 len = count;
4365 macro_start = make_tok_qstr_len(NULL, txt, len);
4368 * We now have a macro name, an implicit parameter count of
4369 * zero, and a numeric token to use as an expansion. Create
4370 * and store an SMacro.
4372 define_smacro(mname, casesense, macro_start, NULL);
4373 free_tlist(tline);
4374 break;
4377 case PP_ASSIGN:
4378 if (!(mname = get_id(&tline, dname)))
4379 goto done;
4381 last = tline;
4382 tline = expand_smacro(tline->next);
4383 last->next = NULL;
4385 pps.tptr = tline;
4386 pps.ntokens = -1;
4387 tokval.t_type = TOKEN_INVALID;
4388 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
4389 free_tlist(tline);
4390 if (!evalresult)
4391 goto done;
4393 if (tokval.t_type)
4394 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
4396 if (!is_simple(evalresult)) {
4397 nasm_nonfatal("non-constant value given to `%s'", dname);
4398 free_tlist(origline);
4399 return DIRECTIVE_FOUND;
4402 macro_start = make_tok_num(NULL, reloc_value(evalresult));
4405 * We now have a macro name, an implicit parameter count of
4406 * zero, and a numeric token to use as an expansion. Create
4407 * and store an SMacro.
4409 define_smacro(mname, casesense, macro_start, NULL);
4410 break;
4412 case PP_ALIASES:
4413 tline = tline->next;
4414 tline = expand_smacro(tline);
4415 do_aliases = pp_get_boolean_option(tline, do_aliases);
4416 break;
4418 case PP_LINE:
4420 * Syntax is `%line nnn[+mmm] [filename]'
4422 if (unlikely(pp_noline))
4423 goto done;
4425 tline = tline->next;
4426 tline = skip_white(tline);
4427 if (!tok_type(tline, TOK_NUMBER)) {
4428 nasm_nonfatal("`%s' expects line number", dname);
4429 goto done;
4431 k = readnum(tok_text(tline), &err);
4432 m = 1;
4433 tline = tline->next;
4434 if (tok_is(tline, '+')) {
4435 tline = tline->next;
4436 if (!tok_type(tline, TOK_NUMBER)) {
4437 nasm_nonfatal("`%s' expects line increment", dname);
4438 goto done;
4440 m = readnum(tok_text(tline), &err);
4441 tline = tline->next;
4443 tline = skip_white(tline);
4444 src_set_linnum(k);
4445 istk->lineinc = m;
4446 if (tline) {
4447 char *fname = detoken(tline, false);
4448 src_set_fname(fname);
4449 nasm_free(fname);
4451 break;
4454 done:
4455 free_tlist(origline);
4456 return DIRECTIVE_FOUND;
4460 * Ensure that a macro parameter contains a condition code and
4461 * nothing else. Return the condition code index if so, or -1
4462 * otherwise.
4464 static int find_cc(Token * t)
4466 Token *tt;
4468 if (!t)
4469 return -1; /* Probably a %+ without a space */
4471 t = skip_white(t);
4472 if (!tok_type(t, TOK_ID))
4473 return -1;
4474 tt = t->next;
4475 tt = skip_white(tt);
4476 if (tok_isnt(tt, ','))
4477 return -1;
4479 return bsii(tok_text(t), (const char **)conditions,
4480 ARRAY_SIZE(conditions));
4483 static inline bool pp_concat_match(const Token *t, unsigned int mask)
4485 return t && (PP_CONCAT_MASK(t->type) & mask);
4489 * This routines walks over tokens strem and handles tokens
4490 * pasting, if @handle_explicit passed then explicit pasting
4491 * term is handled, otherwise -- implicit pastings only.
4492 * The @m array can contain a series of token types which are
4493 * executed as separate passes.
4495 static bool paste_tokens(Token **head, const struct tokseq_match *m,
4496 size_t mnum, bool handle_explicit)
4498 Token *tok, *t, *next, **prev_next, **prev_nonspace;
4499 bool pasted = false;
4500 char *buf, *p;
4501 size_t len, i;
4504 * The last token before pasting. We need it
4505 * to be able to connect new handled tokens.
4506 * In other words if there were a tokens stream
4508 * A -> B -> C -> D
4510 * and we've joined tokens B and C, the resulting
4511 * stream should be
4513 * A -> BC -> D
4515 tok = *head;
4516 prev_next = prev_nonspace = head;
4518 if (tok_white(tok) || tok_type(tok, TOK_PASTE))
4519 prev_nonspace = NULL;
4521 while (tok && (next = tok->next)) {
4522 bool did_paste = false;
4524 switch (tok->type) {
4525 case TOK_WHITESPACE:
4526 /* Zap redundant whitespaces */
4527 tok->next = next = zap_white(next);
4528 break;
4530 case TOK_PASTE:
4531 /* Explicit pasting */
4532 if (!handle_explicit)
4533 break;
4535 /* Left pasting token is start of line */
4536 if (!prev_nonspace) {
4537 nasm_nonfatal("No lvalue found on pasting");
4538 tok = delete_Token(tok);
4539 break;
4542 did_paste = true;
4544 prev_next = prev_nonspace;
4545 t = *prev_nonspace;
4547 /* Delete leading whitespace */
4548 next = zap_white(t->next);
4550 /* Delete the %+ token itself */
4551 nasm_assert(next == tok);
4552 next = delete_Token(next);
4554 /* Delete trailing whitespace */
4555 next = zap_white(next);
4558 * No ending token, this might happen in two
4559 * cases
4561 * 1) There indeed no right token at all
4562 * 2) There is a bare "%define ID" statement,
4563 * and @ID does expand to whitespace.
4565 * So technically we need to do a grammar analysis
4566 * in another stage of parsing, but for now lets don't
4567 * change the behaviour people used to. Simply allow
4568 * whitespace after paste token.
4570 if (!next) {
4571 *prev_nonspace = tok = NULL; /* End of line */
4572 break;
4575 p = buf = nasm_malloc(t->len + next->len + 1);
4576 p = mempcpy(p, tok_text(t), t->len);
4577 p = mempcpy(p, tok_text(next), next->len);
4578 *p = '\0';
4579 delete_Token(t);
4580 t = tokenize(buf);
4581 nasm_free(buf);
4583 if (unlikely(!t)) {
4585 * No output at all? Replace with a single whitespace.
4586 * This should never happen.
4588 t = new_White(NULL);
4591 *prev_nonspace = tok = t;
4592 while (t->next)
4593 t = t->next; /* Find the last token produced */
4595 /* Delete the second token and attach to the end of the list */
4596 t->next = delete_Token(next);
4598 /* We want to restart from the head of the pasted token */
4599 next = tok;
4600 break;
4602 default:
4603 /* implicit pasting */
4604 for (i = 0; i < mnum; i++) {
4605 if (pp_concat_match(tok, m[i].mask_head))
4606 break;
4609 if (i >= mnum)
4610 break;
4612 len = tok->len;
4613 while (pp_concat_match(next, m[i].mask_tail)) {
4614 len += next->len;
4615 next = next->next;
4618 /* No match or no text to process */
4619 if (len == tok->len)
4620 break;
4622 p = buf = nasm_malloc(len + 1);
4623 while (tok != next) {
4624 p = mempcpy(p, tok_text(tok), tok->len);
4625 tok = delete_Token(tok);
4627 *p = '\0';
4628 *prev_next = tok = t = tokenize(buf);
4629 nasm_free(buf);
4632 * Connect pasted into original stream,
4633 * ie A -> new-tokens -> B
4635 while (t->next)
4636 t = t->next;
4637 t->next = next;
4638 prev_next = prev_nonspace = &t->next;
4639 did_paste = true;
4640 break;
4643 if (did_paste) {
4644 pasted = true;
4645 } else {
4646 prev_next = &tok->next;
4647 if (next && next->type != TOK_WHITESPACE && next->type != TOK_PASTE)
4648 prev_nonspace = prev_next;
4651 tok = next;
4654 return pasted;
4658 * Computes the proper rotation of mmacro parameters
4660 static int mmac_rotate(const MMacro *mac, unsigned int n)
4662 if (--n < mac->nparam)
4663 n = (n + mac->rotate) % mac->nparam;
4665 return n+1;
4669 * expands to a list of tokens from %{x:y}
4671 static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
4673 Token *t = tline, **tt, *tm, *head;
4674 char *pos;
4675 int fst, lst, j, i;
4677 pos = strchr(tok_text(tline), ':');
4678 nasm_assert(pos);
4680 lst = atoi(pos + 1);
4681 fst = atoi(tok_text(tline) + 1);
4684 * only macros params are accounted so
4685 * if someone passes %0 -- we reject such
4686 * value(s)
4688 if (lst == 0 || fst == 0)
4689 goto err;
4691 /* the values should be sane */
4692 if ((fst > (int)mac->nparam || fst < (-(int)mac->nparam)) ||
4693 (lst > (int)mac->nparam || lst < (-(int)mac->nparam)))
4694 goto err;
4696 fst = fst < 0 ? fst + (int)mac->nparam + 1: fst;
4697 lst = lst < 0 ? lst + (int)mac->nparam + 1: lst;
4699 /* count from zero */
4700 fst--, lst--;
4703 * It will be at least one token. Note we
4704 * need to scan params until separator, otherwise
4705 * only first token will be passed.
4707 j = (fst + mac->rotate) % mac->nparam;
4708 tm = mac->params[j+1];
4709 if (!tm)
4710 goto err;
4711 head = dup_Token(NULL, tm);
4712 tt = &head->next, tm = tm->next;
4713 while (tok_isnt(tm, ',')) {
4714 t = dup_Token(NULL, tm);
4715 *tt = t, tt = &t->next, tm = tm->next;
4718 if (fst < lst) {
4719 for (i = fst + 1; i <= lst; i++) {
4720 t = make_tok_char(NULL, ',');
4721 *tt = t, tt = &t->next;
4722 j = (i + mac->rotate) % mac->nparam;
4723 tm = mac->params[j+1];
4724 while (tok_isnt(tm, ',')) {
4725 t = dup_Token(NULL, tm);
4726 *tt = t, tt = &t->next, tm = tm->next;
4729 } else {
4730 for (i = fst - 1; i >= lst; i--) {
4731 t = make_tok_char(NULL, ',');
4732 *tt = t, tt = &t->next;
4733 j = (i + mac->rotate) % mac->nparam;
4734 tm = mac->params[j+1];
4735 while (!tok_isnt(tm, ',')) {
4736 t = dup_Token(NULL, tm);
4737 *tt = t, tt = &t->next, tm = tm->next;
4742 *last = tt;
4743 return head;
4745 err:
4746 nasm_nonfatal("`%%{%s}': macro parameters out of range",
4747 tok_text(tline) + 1);
4748 return NULL;
4752 * Expand MMacro-local things: parameter references (%0, %n, %+n,
4753 * %-n) and MMacro-local identifiers (%%foo) as well as
4754 * macro indirection (%[...]) and range (%{..:..}).
4756 static Token *expand_mmac_params(Token * tline)
4758 Token **tail, *thead;
4759 bool changed = false;
4760 MMacro *mac = istk->mstk.mmac;
4762 tail = &thead;
4763 thead = NULL;
4765 while (tline) {
4766 bool change;
4767 bool err_not_mac = false;
4768 Token *t = tline;
4769 const char *text = tok_text(t);
4770 int type = t->type;
4772 tline = tline->next;
4773 t->next = NULL;
4775 switch (type) {
4776 case TOK_LOCAL_SYMBOL:
4777 change = true;
4779 if (!mac) {
4780 err_not_mac = true;
4781 break;
4784 type = TOK_ID;
4785 text = nasm_asprintf("..@%"PRIu64".%s", mac->unique, text+2);
4786 break;
4787 case TOK_MMACRO_PARAM:
4789 Token *tt = NULL;
4791 change = true;
4793 if (!mac) {
4794 err_not_mac = true;
4795 break;
4798 if (strchr(text, ':')) {
4800 * seems we have a parameters range here
4802 Token *head, **last;
4803 head = expand_mmac_params_range(mac, t, &last);
4804 if (head) {
4805 *tail = head;
4806 *last = tline;
4807 text = NULL;
4809 break;
4812 switch (text[1]) {
4814 * We have to make a substitution of one of the
4815 * forms %1, %-1, %+1, %%foo, %0, %00.
4817 case '0':
4818 if (!text[2]) {
4819 type = TOK_NUMBER;
4820 text = nasm_asprintf("%d", mac->nparam);
4821 break;
4823 if (text[2] != '0' || text[3])
4824 goto invalid;
4825 /* a possible captured label == mac->params[0] */
4826 /* fall through */
4827 default:
4829 unsigned long n;
4830 char *ep;
4832 n = strtoul(text + 1, &ep, 10);
4833 if (unlikely(*ep))
4834 goto invalid;
4836 if (n <= mac->nparam) {
4837 n = mmac_rotate(mac, n);
4838 dup_tlistn(mac->params[n], mac->paramlen[n], &tail);
4840 text = NULL;
4841 break;
4843 case '-':
4844 case '+':
4846 int cc;
4847 unsigned long n;
4848 char *ep;
4850 n = strtoul(tok_text(t) + 2, &ep, 10);
4851 if (unlikely(*ep))
4852 goto invalid;
4854 if (n && n <= mac->nparam) {
4855 n = mmac_rotate(mac, n);
4856 tt = mac->params[n];
4858 cc = find_cc(tt);
4859 if (cc == -1) {
4860 nasm_nonfatal("macro parameter `%s' is not a condition code",
4861 tok_text(t));
4862 text = NULL;
4863 break;
4866 type = TOK_ID;
4867 if (text[1] == '-') {
4868 int ncc = inverse_ccs[cc];
4869 if (unlikely(ncc == -1)) {
4870 nasm_nonfatal("condition code `%s' is not invertible",
4871 conditions[cc]);
4872 break;
4874 cc = ncc;
4876 text = nasm_strdup(conditions[cc]);
4877 break;
4880 invalid:
4881 nasm_nonfatal("invalid macro parameter: `%s'", text);
4882 text = NULL;
4883 break;
4885 break;
4888 case TOK_PREPROC_Q:
4889 if (mac) {
4890 type = TOK_ID;
4891 text = nasm_strdup(mac->iname);
4892 change = true;
4893 } else {
4894 change = false;
4896 break;
4898 case TOK_PREPROC_QQ:
4899 if (mac) {
4900 type = TOK_ID;
4901 text = nasm_strdup(mac->name);
4902 change = true;
4903 } else {
4904 change = false;
4906 break;
4908 case TOK_INDIRECT:
4910 Token *tt;
4912 tt = tokenize(tok_text(t));
4913 tt = expand_mmac_params(tt);
4914 tt = expand_smacro(tt);
4915 /* Why dup_tlist() here? We should own tt... */
4916 dup_tlist(tt, &tail);
4917 text = NULL;
4918 change = true;
4919 break;
4922 default:
4923 change = false;
4924 break;
4927 if (err_not_mac) {
4928 nasm_nonfatal("`%s': not in a macro call", text);
4929 text = NULL;
4930 change = true;
4933 if (change) {
4934 if (!text) {
4935 delete_Token(t);
4936 } else {
4937 *tail = t;
4938 tail = &t->next;
4939 set_text(t, text, tok_strlen(text));
4940 t->type = type;
4942 changed = true;
4943 } else {
4944 *tail = t;
4945 tail = &t->next;
4949 *tail = NULL;
4951 if (changed) {
4952 const struct tokseq_match t[] = {
4954 PP_CONCAT_MASK(TOK_ID) |
4955 PP_CONCAT_MASK(TOK_FLOAT), /* head */
4956 PP_CONCAT_MASK(TOK_ID) |
4957 PP_CONCAT_MASK(TOK_NUMBER) |
4958 PP_CONCAT_MASK(TOK_FLOAT) |
4959 PP_CONCAT_MASK(TOK_OTHER) /* tail */
4962 PP_CONCAT_MASK(TOK_NUMBER), /* head */
4963 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
4966 paste_tokens(&thead, t, ARRAY_SIZE(t), false);
4969 return thead;
4972 static Token *expand_smacro_noreset(Token * tline);
4975 * Expand *one* single-line macro instance. If the first token is not
4976 * a macro at all, it is simply copied to the output and the pointer
4977 * advanced. tpp should be a pointer to a pointer (usually the next
4978 * pointer of the previous token) to the first token. **tpp is updated
4979 * to point to the first token of the expansion, and *tpp updated to
4980 * point to the next pointer of the last token of the expansion.
4982 * If the expansion is empty, *tpp will be unchanged but **tpp will
4983 * be advanced past the macro call.
4985 * Return the macro expanded, or NULL if no expansion took place.
4987 static SMacro *expand_one_smacro(Token ***tpp)
4989 Token **params = NULL;
4990 const char *mname;
4991 Token *mstart = **tpp;
4992 Token *tline = mstart;
4993 SMacro *head, *m;
4994 int i;
4995 Token *t, *tup, *tafter;
4996 int nparam = 0;
4997 bool cond_comma;
4999 if (!tline)
5000 return false; /* Empty line, nothing to do */
5002 mname = tok_text(mstart);
5004 smacro_deadman.total--;
5005 smacro_deadman.levels--;
5007 if (unlikely(smacro_deadman.total < 0 || smacro_deadman.levels < 0)) {
5008 if (unlikely(!smacro_deadman.triggered)) {
5009 nasm_nonfatal("interminable macro recursion");
5010 smacro_deadman.triggered = true;
5012 goto not_a_macro;
5013 } else if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID) {
5014 head = (SMacro *)hash_findix(&smacros, mname);
5015 } else if (tline->type == TOK_LOCAL_MACRO) {
5016 Context *ctx = get_ctx(mname, &mname);
5017 head = ctx ? (SMacro *)hash_findix(&ctx->localmac, mname) : NULL;
5018 } else {
5019 goto not_a_macro;
5023 * We've hit an identifier of some sort. First check whether the
5024 * identifier is a single-line macro at all, then think about
5025 * checking for parameters if necessary.
5027 list_for_each(m, head) {
5028 if (unlikely(m->alias && !do_aliases))
5029 continue;
5030 if (!mstrcmp(m->name, mname, m->casesense))
5031 break;
5034 if (!m) {
5035 goto not_a_macro;
5038 /* Parse parameters, if applicable */
5040 params = NULL;
5041 nparam = 0;
5043 if (m->nparam == 0) {
5045 * Simple case: the macro is parameterless.
5046 * Nothing to parse; the expansion code will
5047 * drop the macro name token.
5049 } else {
5051 * Complicated case: at least one macro with this name
5052 * exists and takes parameters. We must find the
5053 * parameters in the call, count them, find the SMacro
5054 * that corresponds to that form of the macro call, and
5055 * substitute for the parameters when we expand. What a
5056 * pain.
5058 Token *t;
5059 int paren, brackets;
5061 tline = tline->next;
5062 tline = skip_white(tline);
5063 if (!tok_is(tline, '(')) {
5065 * This macro wasn't called with parameters: ignore
5066 * the call. (Behaviour borrowed from gnu cpp.)
5068 goto not_a_macro;
5071 paren = 1;
5072 nparam = 1;
5073 brackets = 0;
5074 t = tline; /* tline points to leading ( */
5076 while (paren) {
5077 t = t->next;
5079 if (!t) {
5080 nasm_nonfatal("macro call expects terminating `)'");
5081 goto not_a_macro;
5084 if (t->type != TOK_OTHER || t->len != 1)
5085 continue;
5087 switch (t->text.a[0]) {
5088 case ',':
5089 if (!brackets)
5090 nparam++;
5091 break;
5093 case '{':
5094 brackets++;
5095 break;
5097 case '}':
5098 if (brackets > 0)
5099 brackets--;
5100 break;
5102 case '(':
5103 if (!brackets)
5104 paren++;
5105 break;
5107 case ')':
5108 if (!brackets)
5109 paren--;
5110 break;
5112 default:
5113 break; /* Normal token */
5118 * Look for a macro matching in both name and parameter count.
5119 * We already know any matches cannot be anywhere before the
5120 * current position of "m", so there is no reason to
5121 * backtrack.
5123 while (1) {
5124 if (!m) {
5126 *!macro-params-single [on] single-line macro calls with wrong parameter count
5127 *! warns about \i{single-line macros} being invoked
5128 *! with the wrong number of parameters.
5130 nasm_warn(WARN_MACRO_PARAMS_SINGLE|ERR_HOLD,
5131 "single-line macro `%s' exists, "
5132 "but not taking %d parameter%s",
5133 mname, nparam, (nparam == 1) ? "" : "s");
5134 goto not_a_macro;
5137 if (!mstrcmp(m->name, mname, m->casesense)) {
5138 if (nparam == m->nparam)
5139 break; /* It's good */
5140 if (m->greedy && nparam >= m->nparam-1)
5141 break; /* Also good */
5143 m = m->next;
5147 if (m->in_progress)
5148 goto not_a_macro;
5150 /* Expand the macro */
5151 m->in_progress = true;
5153 if (nparam) {
5154 /* Extract parameters */
5155 Token **phead, **pep;
5156 int white = 0;
5157 int brackets = 0;
5158 int paren;
5159 bool bracketed = false;
5160 bool bad_bracket = false;
5161 enum sparmflags flags;
5163 nparam = m->nparam;
5164 paren = 1;
5165 nasm_newn(params, nparam);
5166 i = 0;
5167 flags = m->params[i].flags;
5168 phead = pep = &params[i];
5169 *pep = NULL;
5171 while (paren) {
5172 bool skip;
5173 char ch;
5175 tline = tline->next;
5177 if (!tline)
5178 nasm_nonfatal("macro call expects terminating `)'");
5180 ch = 0;
5181 skip = false;
5184 switch (tline->type) {
5185 case TOK_OTHER:
5186 if (tline->len == 1)
5187 ch = tline->text.a[0];
5188 break;
5190 case TOK_WHITESPACE:
5191 if (!(flags & SPARM_NOSTRIP)) {
5192 if (brackets || *phead)
5193 white++; /* Keep interior whitespace */
5194 skip = true;
5196 break;
5198 default:
5199 break;
5202 switch (ch) {
5203 case ',':
5204 if (!brackets && !(flags & SPARM_GREEDY)) {
5205 i++;
5206 nasm_assert(i < nparam);
5207 phead = pep = &params[i];
5208 *pep = NULL;
5209 bracketed = false;
5210 skip = true;
5211 flags = m->params[i].flags;
5213 break;
5215 case '{':
5216 if (!bracketed) {
5217 bracketed = !*phead && !(flags & SPARM_NOSTRIP);
5218 skip = bracketed;
5220 brackets++;
5221 break;
5223 case '}':
5224 if (brackets > 0) {
5225 if (!--brackets)
5226 skip = bracketed;
5228 break;
5230 case '(':
5231 if (!brackets)
5232 paren++;
5233 break;
5235 case ')':
5236 if (!brackets) {
5237 paren--;
5238 if (!paren) {
5239 skip = true;
5240 i++; /* Found last argument */
5243 break;
5245 default:
5246 break; /* Normal token */
5249 if (!skip) {
5250 Token *t;
5252 bad_bracket |= bracketed && !brackets;
5254 if (white) {
5255 *pep = t = new_White(NULL);
5256 pep = &t->next;
5257 white = 0;
5259 *pep = t = dup_Token(NULL, tline);
5260 pep = &t->next;
5265 * Possible further processing of parameters. Note that the
5266 * ordering matters here.
5268 for (i = 0; i < nparam; i++) {
5269 enum sparmflags flags = m->params[i].flags;
5271 if (flags & SPARM_EVAL) {
5272 /* Evaluate this parameter as a number */
5273 struct ppscan pps;
5274 struct tokenval tokval;
5275 expr *evalresult;
5276 Token *eval_param;
5278 pps.tptr = eval_param = expand_smacro_noreset(params[i]);
5279 pps.ntokens = -1;
5280 tokval.t_type = TOKEN_INVALID;
5281 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
5283 free_tlist(eval_param);
5284 params[i] = NULL;
5286 if (!evalresult) {
5287 /* Nothing meaningful to do */
5288 } else if (tokval.t_type) {
5289 nasm_nonfatal("invalid expression in parameter %d of macro `%s'", i, m->name);
5290 } else if (!is_simple(evalresult)) {
5291 nasm_nonfatal("non-constant expression in parameter %d of macro `%s'", i, m->name);
5292 } else {
5293 params[i] = make_tok_num(NULL, reloc_value(evalresult));
5297 if (flags & SPARM_STR) {
5298 /* Convert expansion to a quoted string */
5299 char *arg;
5300 Token *qs;
5302 qs = expand_smacro_noreset(params[i]);
5303 arg = detoken(qs, false);
5304 free_tlist(qs);
5305 params[i] = make_tok_qstr(NULL, arg);
5306 nasm_free(arg);
5311 /* Note: we own the expansion this returns. */
5312 t = m->expand(m, params, nparam);
5314 tafter = tline->next; /* Skip past the macro call */
5315 tline->next = NULL; /* Truncate list at the macro call end */
5316 tline = tafter;
5318 tup = NULL;
5319 cond_comma = false;
5321 while (t) {
5322 enum pp_token_type type = t->type;
5323 Token *tnext = t->next;
5325 switch (type) {
5326 case TOK_PREPROC_Q:
5327 delete_Token(t);
5328 t = dup_Token(tline, mstart);
5329 break;
5331 case TOK_PREPROC_QQ:
5333 size_t mlen = strlen(m->name);
5334 size_t len;
5335 char *p;
5337 t->type = mstart->type;
5338 if (t->type == TOK_LOCAL_MACRO) {
5339 const char *psp; /* prefix start pointer */
5340 const char *pep; /* prefix end pointer */
5341 size_t plen;
5343 psp = tok_text(mstart);
5344 get_ctx(psp, &pep);
5345 plen = pep - psp;
5347 len = mlen + plen;
5348 p = nasm_malloc(len + 1);
5349 p = mempcpy(p, psp, plen);
5350 } else {
5351 len = mlen;
5352 p = nasm_malloc(len + 1);
5354 p = mempcpy(p, m->name, mlen);
5355 *p = '\0';
5356 set_text_free(t, p, len);
5358 t->next = tline;
5359 break;
5362 case TOK_COND_COMMA:
5363 delete_Token(t);
5364 t = cond_comma ? make_tok_char(tline, ',') : NULL;
5365 break;
5367 case TOK_ID:
5368 case TOK_PREPROC_ID:
5369 case TOK_LOCAL_MACRO:
5372 * Chain this into the target line *before* expanding,
5373 * that way we pick up any arguments to the new macro call,
5374 * if applicable.
5376 Token **tp = &t;
5377 t->next = tline;
5378 expand_one_smacro(&tp);
5379 tline = *tp; /* First token left after any macro call */
5380 break;
5382 default:
5383 if (is_smac_param(t->type)) {
5384 int param = smac_nparam(t->type);
5385 nasm_assert(!tup && param < nparam);
5386 delete_Token(t);
5387 t = NULL;
5388 tup = tnext;
5389 tnext = dup_tlist_reverse(params[param], NULL);
5390 cond_comma = false;
5391 } else {
5392 t->next = tline;
5396 if (t) {
5397 Token *endt = tline;
5399 tline = t;
5400 while (!cond_comma && t && t != endt) {
5401 cond_comma = t->type != TOK_WHITESPACE;
5402 t = t->next;
5406 if (tnext) {
5407 t = tnext;
5408 } else {
5409 t = tup;
5410 tup = NULL;
5414 **tpp = tline;
5415 for (t = tline; t && t != tafter; t = t->next)
5416 *tpp = &t->next;
5418 m->in_progress = false;
5420 /* Don't do this until after expansion or we will clobber mname */
5421 free_tlist(mstart);
5422 goto done;
5425 * No macro expansion needed; roll back to mstart (if necessary)
5426 * and then advance to the next input token. Note that this is
5427 * by far the common case!
5429 not_a_macro:
5430 *tpp = &mstart->next;
5431 m = NULL;
5432 done:
5433 smacro_deadman.levels++;
5434 if (unlikely(params))
5435 free_tlist_array(params, nparam);
5436 return m;
5440 * Expand all single-line macro calls made in the given line.
5441 * Return the expanded version of the line. The original is deemed
5442 * to be destroyed in the process. (In reality we'll just move
5443 * Tokens from input to output a lot of the time, rather than
5444 * actually bothering to destroy and replicate.)
5446 static Token *expand_smacro(Token *tline)
5448 smacro_deadman.total = nasm_limit[LIMIT_MACRO_TOKENS];
5449 smacro_deadman.levels = nasm_limit[LIMIT_MACRO_LEVELS];
5450 smacro_deadman.triggered = false;
5451 return expand_smacro_noreset(tline);
5454 static Token *expand_smacro_noreset(Token *org_tline)
5456 Token *tline;
5457 bool expanded;
5458 errhold errhold; /* Hold warning/errors during expansion */
5460 if (!org_tline)
5461 return NULL; /* Empty input */
5464 * Trick: we should avoid changing the start token pointer since it can
5465 * be contained in "next" field of other token. Because of this
5466 * we allocate a copy of first token and work with it; at the end of
5467 * routine we copy it back
5469 tline = dup_Token(org_tline->next, org_tline);
5472 * Pretend that we always end up doing expansion on the first pass;
5473 * that way %+ get processed. However, if we process %+ before the
5474 * first pass, we end up with things like MACRO %+ TAIL trying to
5475 * look up the macro "MACROTAIL", which we don't want.
5477 expanded = true;
5479 while (true) {
5480 static const struct tokseq_match tmatch[] = {
5482 PP_CONCAT_MASK(TOK_ID) |
5483 PP_CONCAT_MASK(TOK_LOCAL_MACRO) |
5484 PP_CONCAT_MASK(TOK_ENVIRON) |
5485 PP_CONCAT_MASK(TOK_PREPROC_ID), /* head */
5486 PP_CONCAT_MASK(TOK_ID) |
5487 PP_CONCAT_MASK(TOK_LOCAL_MACRO) |
5488 PP_CONCAT_MASK(TOK_ENVIRON) |
5489 PP_CONCAT_MASK(TOK_PREPROC_ID) |
5490 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
5493 Token **tail = &tline;
5494 errhold = nasm_error_hold_push();
5497 * We hold warnings/errors until we are done this this loop. It is
5498 * possible for nuisance warnings to appear that disappear on later
5499 * passes.
5501 errhold = nasm_error_hold_push();
5502 while (*tail) /* main token loop */
5503 expanded |= !!expand_one_smacro(&tail);
5505 if (!expanded)
5506 break; /* Done! */
5509 * Now scan the entire line and look for successive TOK_IDs
5510 * that resulted after expansion (they can't be produced by
5511 * tokenize()). The successive TOK_IDs should be concatenated.
5512 * Also we look for %+ tokens and concatenate the tokens
5513 * before and after them (without white spaces in between).
5515 if (!paste_tokens(&tline, tmatch, ARRAY_SIZE(tmatch), true))
5516 break; /* Done again! */
5518 expanded = false;
5519 nasm_error_hold_pop(errhold, false);
5521 nasm_error_hold_pop(errhold, true);
5523 if (!tline) {
5525 * The expression expanded to empty line;
5526 * we can't return NULL because of the "trick" above.
5527 * Just set the line to a single WHITESPACE token.
5530 tline = new_White(NULL);
5533 steal_Token(org_tline, tline);
5534 org_tline->next = tline->next;
5535 delete_Token(tline);
5537 return org_tline;
5541 * Similar to expand_smacro but used exclusively with macro identifiers
5542 * right before they are fetched in. The reason is that there can be
5543 * identifiers consisting of several subparts. We consider that if there
5544 * are more than one element forming the name, user wants a expansion,
5545 * otherwise it will be left as-is. Example:
5547 * %define %$abc cde
5549 * the identifier %$abc will be left as-is so that the handler for %define
5550 * will suck it and define the corresponding value. Other case:
5552 * %define _%$abc cde
5554 * In this case user wants name to be expanded *before* %define starts
5555 * working, so we'll expand %$abc into something (if it has a value;
5556 * otherwise it will be left as-is) then concatenate all successive
5557 * PP_IDs into one.
5559 static Token *expand_id(Token * tline)
5561 Token *cur, *oldnext = NULL;
5563 if (!tline || !tline->next)
5564 return tline;
5566 cur = tline;
5567 while (cur->next &&
5568 (cur->next->type == TOK_ID || cur->next->type == TOK_PREPROC_ID ||
5569 cur->next->type == TOK_LOCAL_MACRO || cur->next->type == TOK_NUMBER))
5570 cur = cur->next;
5572 /* If identifier consists of just one token, don't expand */
5573 if (cur == tline)
5574 return tline;
5576 if (cur) {
5577 oldnext = cur->next; /* Detach the tail past identifier */
5578 cur->next = NULL; /* so that expand_smacro stops here */
5581 tline = expand_smacro(tline);
5583 if (cur) {
5584 /* expand_smacro possibly changhed tline; re-scan for EOL */
5585 cur = tline;
5586 while (cur && cur->next)
5587 cur = cur->next;
5588 if (cur)
5589 cur->next = oldnext;
5592 return tline;
5596 * Determine whether the given line constitutes a multi-line macro
5597 * call, and return the MMacro structure called if so. Doesn't have
5598 * to check for an initial label - that's taken care of in
5599 * expand_mmacro - but must check numbers of parameters. Guaranteed
5600 * to be called with tline->type == TOK_ID, so the putative macro
5601 * name is easy to find.
5603 static MMacro *is_mmacro(Token * tline, int *nparamp, Token ***params_array)
5605 MMacro *head, *m;
5606 Token **params;
5607 int nparam;
5608 const char *finding = tok_text(tline);
5610 head = (MMacro *) hash_findix(&mmacros, finding);
5613 * Efficiency: first we see if any macro exists with the given
5614 * name which isn't already excluded by macro cycle removal.
5615 * (The cycle removal test here helps optimize the case of wrapping
5616 * instructions, and is cheap to do here.)
5618 * If not, we can return NULL immediately. _Then_ we
5619 * count the parameters, and then we look further along the
5620 * list if necessary to find the proper MMacro.
5622 list_for_each(m, head) {
5623 if (!mstrcmp(m->name, finding, m->casesense) &&
5624 (m->in_progress != 1 || m->max_depth > 0))
5625 break; /* Found something that needs consideration */
5627 if (!m)
5628 return NULL;
5631 * OK, we have a potential macro. Count and demarcate the
5632 * parameters.
5634 count_mmac_params(tline->next, &nparam, &params);
5637 * So we know how many parameters we've got. Find the MMacro
5638 * structure that handles this number.
5640 while (m) {
5641 if (m->nparam_min <= nparam
5642 && (m->plus || nparam <= m->nparam_max)) {
5644 * This one is right. Just check if cycle removal
5645 * prohibits us using it before we actually celebrate...
5647 if (m->in_progress > m->max_depth) {
5648 if (m->max_depth > 0) {
5649 nasm_warn(WARN_OTHER, "reached maximum recursion depth of %i",
5650 m->max_depth);
5652 nasm_free(params);
5653 return NULL;
5656 * It's right, and we can use it. Add its default
5657 * parameters to the end of our list if necessary.
5659 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
5660 int newnparam = m->nparam_min + m->ndefs;
5661 params = nasm_realloc(params, sizeof(*params) * (newnparam+2));
5662 memcpy(&params[nparam+1], &m->defaults[nparam+1-m->nparam_min],
5663 (newnparam - nparam) * sizeof(*params));
5664 nparam = newnparam;
5667 * If we've gone over the maximum parameter count (and
5668 * we're in Plus mode), ignore parameters beyond
5669 * nparam_max.
5671 if (m->plus && nparam > m->nparam_max)
5672 nparam = m->nparam_max;
5675 * If nparam was adjusted above, make sure the list is still
5676 * NULL-terminated.
5678 params[nparam+1] = NULL;
5680 /* Done! */
5681 *params_array = params;
5682 *nparamp = nparam;
5683 return m;
5686 * This one wasn't right: look for the next one with the
5687 * same name.
5689 list_for_each(m, m->next)
5690 if (!mstrcmp(m->name, tok_text(tline), m->casesense))
5691 break;
5695 * After all that, we didn't find one with the right number of
5696 * parameters. Issue a warning, and fail to expand the macro.
5698 *!macro-params-multi [on] multi-line macro calls with wrong parameter count
5699 *! warns about \i{multi-line macros} being invoked
5700 *! with the wrong number of parameters. See \k{mlmacover} for an
5701 *! example of why you might want to disable this warning.
5703 nasm_warn(WARN_MACRO_PARAMS_MULTI,
5704 "multi-line macro `%s' exists, but not taking %d parameter%s",
5705 tok_text(tline), nparam, (nparam == 1) ? "" : "s");
5706 nasm_free(params);
5707 return NULL;
5711 #if 0
5714 * Save MMacro invocation specific fields in
5715 * preparation for a recursive macro expansion
5717 static void push_mmacro(MMacro *m)
5719 MMacroInvocation *i;
5721 i = nasm_malloc(sizeof(MMacroInvocation));
5722 i->prev = m->prev;
5723 i->params = m->params;
5724 i->iline = m->iline;
5725 i->nparam = m->nparam;
5726 i->rotate = m->rotate;
5727 i->paramlen = m->paramlen;
5728 i->unique = m->unique;
5729 i->condcnt = m->condcnt;
5730 m->prev = i;
5735 * Restore MMacro invocation specific fields that were
5736 * saved during a previous recursive macro expansion
5738 static void pop_mmacro(MMacro *m)
5740 MMacroInvocation *i;
5742 if (m->prev) {
5743 i = m->prev;
5744 m->prev = i->prev;
5745 m->params = i->params;
5746 m->iline = i->iline;
5747 m->nparam = i->nparam;
5748 m->rotate = i->rotate;
5749 m->paramlen = i->paramlen;
5750 m->unique = i->unique;
5751 m->condcnt = i->condcnt;
5752 nasm_free(i);
5756 #endif
5759 * List an mmacro call with arguments (-Lm option)
5761 static void list_mmacro_call(const MMacro *m)
5763 const char prefix[] = " ;;; [macro] ";
5764 size_t namelen, size;
5765 char *buf, *p;
5766 unsigned int i;
5767 const Token *t;
5769 namelen = strlen(m->iname);
5770 size = namelen + sizeof(prefix); /* Includes final null (from prefix) */
5772 for (i = 1; i <= m->nparam; i++) {
5773 int j = 0;
5774 size += 3; /* Braces and space/comma */
5775 list_for_each(t, m->params[i]) {
5776 if (j++ >= m->paramlen[i])
5777 break;
5778 size += (t->type == TOK_WHITESPACE) ? 1 : t->len;
5782 buf = p = nasm_malloc(size);
5783 p = mempcpy(p, prefix, sizeof(prefix) - 1);
5784 p = mempcpy(p, m->iname, namelen);
5785 *p++ = ' ';
5787 for (i = 1; i <= m->nparam; i++) {
5788 int j = 0;
5789 *p++ = '{';
5790 list_for_each(t, m->params[i]) {
5791 if (j++ >= m->paramlen[i])
5792 break;
5793 p = mempcpy(p, tok_text(t), t->len);
5795 *p++ = '}';
5796 *p++ = ',';
5799 *--p = '\0'; /* Replace last delimeter with null */
5800 lfmt->line(LIST_MACRO, -1, buf);
5801 nasm_free(buf);
5805 * Expand the multi-line macro call made by the given line, if
5806 * there is one to be expanded. If there is, push the expansion on
5807 * istk->expansion and return 1. Otherwise return 0.
5809 static int expand_mmacro(Token * tline)
5811 Token *startline = tline;
5812 Token *label = NULL;
5813 bool dont_prepend = false;
5814 Token **params, *t, *tt;
5815 MMacro *m;
5816 Line *l, *ll;
5817 int i, *paramlen;
5818 const char *mname;
5819 int nparam = 0;
5821 t = tline;
5822 t = skip_white(t);
5823 /* if (!tok_type(t, TOK_ID)) Lino 02/25/02 */
5824 if (!tok_type(t, TOK_ID) && !tok_type(t, TOK_LOCAL_MACRO))
5825 return 0;
5826 m = is_mmacro(t, &nparam, &params);
5827 if (m) {
5828 mname = tok_text(t);
5829 } else {
5830 Token *last;
5832 * We have an id which isn't a macro call. We'll assume
5833 * it might be a label; we'll also check to see if a
5834 * colon follows it. Then, if there's another id after
5835 * that lot, we'll check it again for macro-hood.
5837 label = last = t;
5838 t = t->next;
5839 if (tok_white(t))
5840 last = t, t = t->next;
5841 if (tok_is(t, ':')) {
5842 dont_prepend = true;
5843 last = t, t = t->next;
5844 if (tok_white(t))
5845 last = t, t = t->next;
5847 if (!tok_type(t, TOK_ID) || !(m = is_mmacro(t, &nparam, &params)))
5848 return 0;
5849 last->next = NULL;
5850 mname = tok_text(t);
5851 tline = t;
5854 if (unlikely(mmacro_deadman.total >= nasm_limit[LIMIT_MMACROS] ||
5855 mmacro_deadman.levels >= nasm_limit[LIMIT_MACRO_LEVELS])) {
5856 if (!mmacro_deadman.triggered) {
5857 nasm_nonfatal("interminable multiline macro recursion");
5858 mmacro_deadman.triggered = true;
5860 return 0;
5863 mmacro_deadman.total++;
5864 mmacro_deadman.levels++;
5867 * Fix up the parameters: this involves stripping leading and
5868 * trailing whitespace, then stripping braces if they are
5869 * present.
5871 nasm_newn(paramlen, nparam+1);
5873 nasm_assert(params[nparam+1] == NULL);
5875 for (i = 1; (t = params[i]); i++) {
5876 bool braced = false;
5877 int brace = 0;
5878 int white = 0;
5879 bool comma = !m->plus || i < nparam;
5881 t = skip_white(t);
5882 if (tok_is(t, '{')) {
5883 t = t->next;
5884 brace = 1;
5885 braced = true;
5886 comma = false;
5889 params[i] = t;
5890 for (; t; t = t->next) {
5891 if (tok_white(t)) {
5892 white++;
5893 continue;
5896 if (t->type == TOK_OTHER && t->len == 1) {
5897 switch (t->text.a[0]) {
5898 case ',':
5899 if (comma && !brace)
5900 goto endparam;
5901 break;
5903 case '{':
5904 brace++;
5905 break;
5907 case '}':
5908 brace--;
5909 if (braced && !brace) {
5910 paramlen[i] += white;
5911 goto endparam;
5913 break;
5915 default:
5916 break;
5920 paramlen[i] += white + 1;
5921 white = 0;
5923 endparam:
5928 * OK, we have a MMacro structure together with a set of
5929 * parameters. We must now go through the expansion and push
5930 * copies of each Line on to istk->expansion. Substitution of
5931 * parameter tokens and macro-local tokens doesn't get done
5932 * until the single-line macro substitution process; this is
5933 * because delaying them allows us to change the semantics
5934 * later through %rotate and give the right semantics for
5935 * nested mmacros.
5937 * First, push an end marker on to istk->expansion, mark this
5938 * macro as in progress, and set up its invocation-specific
5939 * variables.
5941 nasm_new(ll);
5942 ll->next = istk->expansion;
5943 ll->finishes = m;
5944 istk->expansion = ll;
5947 * Save the previous MMacro expansion in the case of
5948 * macro recursion
5950 #if 0
5951 if (m->max_depth && m->in_progress)
5952 push_mmacro(m);
5953 #endif
5955 m->in_progress ++;
5956 m->params = params;
5957 m->iline = tline;
5958 m->iname = nasm_strdup(mname);
5959 m->nparam = nparam;
5960 m->rotate = 0;
5961 m->paramlen = paramlen;
5962 m->unique = unique++;
5963 m->lineno = 0;
5964 m->condcnt = 0;
5966 m->mstk = istk->mstk;
5967 istk->mstk.mstk = istk->mstk.mmac = m;
5969 list_for_each(l, m->expansion) {
5970 nasm_new(ll);
5971 ll->next = istk->expansion;
5972 istk->expansion = ll;
5973 ll->first = dup_tlist(l->first, NULL);
5977 * If we had a label, and this macro definition does not include
5978 * a %00, push it on as the first line of, ot
5979 * the macro expansion.
5981 if (label) {
5983 * We had a label. If this macro contains an %00 parameter,
5984 * save the value as a special parameter (which is what it
5985 * is), otherwise push it as the first line of the macro
5986 * expansion.
5988 if (m->capture_label) {
5989 params[0] = dup_Token(NULL, label);
5990 paramlen[0] = 1;
5991 free_tlist(startline);
5992 } else {
5993 nasm_new(ll);
5994 ll->finishes = NULL;
5995 ll->next = istk->expansion;
5996 istk->expansion = ll;
5997 ll->first = startline;
5998 if (!dont_prepend) {
5999 while (label->next)
6000 label = label->next;
6001 label->next = tt = make_tok_char(NULL, ':');
6006 lfmt->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
6008 if (list_option('m') && !m->nolist)
6009 list_mmacro_call(m);
6011 return 1;
6015 * This function decides if an error message should be suppressed.
6016 * It will never be called with a severity level of ERR_FATAL or
6017 * higher.
6019 static bool pp_suppress_error(errflags severity)
6022 * If we're in a dead branch of IF or something like it, ignore the error.
6023 * However, because %else etc are evaluated in the state context
6024 * of the previous branch, errors might get lost:
6025 * %if 0 ... %else trailing garbage ... %endif
6026 * So %else etc should set the ERR_PP_PRECOND flag.
6028 if (istk && istk->conds &&
6029 ((severity & ERR_PP_PRECOND) ?
6030 istk->conds->state == COND_NEVER :
6031 !emitting(istk->conds->state)))
6032 return true;
6034 return false;
6037 static Token *
6038 stdmac_file(const SMacro *s, Token **params, int nparams)
6040 (void)s;
6041 (void)params;
6042 (void)nparams;
6044 return make_tok_qstr(NULL, src_get_fname());
6047 static Token *
6048 stdmac_line(const SMacro *s, Token **params, int nparams)
6050 (void)s;
6051 (void)params;
6052 (void)nparams;
6054 return make_tok_num(NULL, src_get_linnum());
6057 static Token *
6058 stdmac_bits(const SMacro *s, Token **params, int nparams)
6060 (void)s;
6061 (void)params;
6062 (void)nparams;
6064 return make_tok_num(NULL, globalbits);
6067 static Token *
6068 stdmac_ptr(const SMacro *s, Token **params, int nparams)
6070 (void)s;
6071 (void)params;
6072 (void)nparams;
6074 switch (globalbits) {
6075 case 16:
6076 return new_Token(NULL, TOK_ID, "word", 4);
6077 case 32:
6078 return new_Token(NULL, TOK_ID, "dword", 5);
6079 case 64:
6080 return new_Token(NULL, TOK_ID, "qword", 5);
6081 default:
6082 panic();
6086 /* Add magic standard macros */
6087 struct magic_macros {
6088 const char *name;
6089 int nparam;
6090 ExpandSMacro func;
6092 static const struct magic_macros magic_macros[] =
6094 { "__?FILE?__", 0, stdmac_file },
6095 { "__?LINE?__", 0, stdmac_line },
6096 { "__?BITS?__", 0, stdmac_bits },
6097 { "__?PTR?__", 0, stdmac_ptr },
6098 { NULL, 0, NULL }
6101 static void pp_add_magic_stdmac(void)
6103 const struct magic_macros *m;
6104 SMacro tmpl;
6106 nasm_zero(tmpl);
6108 for (m = magic_macros; m->name; m++) {
6109 tmpl.nparam = m->nparam;
6110 tmpl.expand = m->func;
6111 define_smacro(m->name, true, NULL, &tmpl);
6115 static void
6116 pp_reset(const char *file, enum preproc_mode mode, struct strlist *dep_list)
6118 int apass;
6119 struct Include *inc;
6121 cstk = NULL;
6122 defining = NULL;
6123 nested_mac_count = 0;
6124 nested_rep_count = 0;
6125 init_macros();
6126 unique = 0;
6127 deplist = dep_list;
6128 pp_mode = mode;
6129 do_aliases = true;
6131 if (!use_loaded)
6132 use_loaded = nasm_malloc(use_package_count * sizeof(bool));
6133 memset(use_loaded, 0, use_package_count * sizeof(bool));
6135 /* First set up the top level input file */
6136 nasm_new(istk);
6137 istk->fp = nasm_open_read(file, NF_TEXT);
6138 src_set(0, file);
6139 istk->lineinc = 1;
6140 if (!istk->fp)
6141 nasm_fatalf(ERR_NOFILE, "unable to open input file `%s'", file);
6143 strlist_add(deplist, file);
6146 * Set up the stdmac packages as a virtual include file,
6147 * indicated by a null file pointer.
6149 nasm_new(inc);
6150 inc->next = istk;
6151 inc->fname = src_set_fname(NULL);
6152 inc->nolist = !list_option('b');
6153 istk = inc;
6154 lfmt->uplevel(LIST_INCLUDE, 0);
6156 pp_add_magic_stdmac();
6158 if (tasm_compatible_mode)
6159 pp_add_stdmac(nasm_stdmac_tasm);
6161 pp_add_stdmac(nasm_stdmac_nasm);
6162 pp_add_stdmac(nasm_stdmac_version);
6164 if (extrastdmac)
6165 pp_add_stdmac(extrastdmac);
6167 stdmacpos = stdmacros[0];
6168 stdmacnext = &stdmacros[1];
6170 do_predef = true;
6173 * Define the __?PASS?__ macro. This is defined here unlike all the
6174 * other builtins, because it is special -- it varies between
6175 * passes -- but there is really no particular reason to make it
6176 * magic.
6178 * 0 = dependencies only
6179 * 1 = preparatory passes
6180 * 2 = final pass
6181 * 3 = preproces only
6183 switch (mode) {
6184 case PP_NORMAL:
6185 apass = pass_final() ? 2 : 1;
6186 break;
6187 case PP_DEPS:
6188 apass = 0;
6189 break;
6190 case PP_PREPROC:
6191 apass = 3;
6192 break;
6193 default:
6194 panic();
6197 define_smacro("__?PASS?__", true, make_tok_num(NULL, apass), NULL);
6200 static void pp_init(void)
6205 * Get a line of tokens. If we popped the macro expansion/include stack,
6206 * we return a pointer to the dummy token tok_pop; at that point if
6207 * istk is NULL then we have reached end of input;
6209 static Token tok_pop; /* Dummy token placeholder */
6211 static Token *pp_tokline(void)
6213 while (true) {
6214 Line *l = istk->expansion;
6215 Token *tline = NULL;
6216 Token *dtline;
6219 * Fetch a tokenized line, either from the macro-expansion
6220 * buffer or from the input file.
6222 tline = NULL;
6223 while (l && l->finishes) {
6224 MMacro *fm = l->finishes;
6226 if (!fm->name && fm->in_progress > 1) {
6228 * This is a macro-end marker for a macro with no
6229 * name, which means it's not really a macro at all
6230 * but a %rep block, and the `in_progress' field is
6231 * more than 1, meaning that we still need to
6232 * repeat. (1 means the natural last repetition; 0
6233 * means termination by %exitrep.) We have
6234 * therefore expanded up to the %endrep, and must
6235 * push the whole block on to the expansion buffer
6236 * again. We don't bother to remove the macro-end
6237 * marker: we'd only have to generate another one
6238 * if we did.
6240 fm->in_progress--;
6241 list_for_each(l, fm->expansion) {
6242 Token *t, *tt, **tail;
6243 Line *ll;
6245 istk->mstk.mstk->lineno = 0;
6246 nasm_new(ll);
6247 ll->next = istk->expansion;
6248 tail = &ll->first;
6250 list_for_each(t, l->first) {
6251 if (t->len) {
6252 tt = *tail = dup_Token(NULL, t);
6253 tail = &tt->next;
6256 istk->expansion = ll;
6258 break;
6259 } else {
6260 MMacro *m = istk->mstk.mstk;
6263 * Check whether a `%rep' was started and not ended
6264 * within this macro expansion. This can happen and
6265 * should be detected. It's a fatal error because
6266 * I'm too confused to work out how to recover
6267 * sensibly from it.
6269 if (defining) {
6270 if (defining->name)
6271 nasm_panic("defining with name in expansion");
6272 else if (m->name)
6273 nasm_fatal("`%%rep' without `%%endrep' within"
6274 " expansion of macro `%s'", m->name);
6278 * FIXME: investigate the relationship at this point between
6279 * istk->mstk.mstk and fm
6281 istk->mstk = m->mstk;
6282 if (m->name) {
6284 * This was a real macro call, not a %rep, and
6285 * therefore the parameter information needs to
6286 * be freed and the iteration count/nesting
6287 * depth adjusted.
6290 if (!--mmacro_deadman.levels) {
6292 * If all mmacro processing done,
6293 * clear all counters and the deadman
6294 * message trigger.
6296 nasm_zero(mmacro_deadman); /* Clear all counters */
6299 #if 0
6300 if (m->prev) {
6301 pop_mmacro(m);
6302 fm->in_progress --;
6303 } else
6304 #endif
6306 nasm_free(m->params);
6307 free_tlist(m->iline);
6308 nasm_free(m->paramlen);
6309 fm->in_progress = 0;
6314 * FIXME It is incorrect to always free_mmacro here.
6315 * It leads to usage-after-free.
6317 * https://bugzilla.nasm.us/show_bug.cgi?id=3392414
6319 #if 0
6320 else
6321 free_mmacro(m);
6322 #endif
6324 istk->expansion = l->next;
6325 nasm_free(l);
6326 lfmt->downlevel(LIST_MACRO);
6327 return &tok_pop;
6330 do { /* until we get a line we can use */
6331 char *line;
6333 if (istk->expansion) { /* from a macro expansion */
6334 Line *l = istk->expansion;
6335 int32_t lineno;
6337 if (istk->mstk.mstk) {
6338 istk->mstk.mstk->lineno++;
6339 if (istk->mstk.mstk->fname)
6340 lineno = istk->mstk.mstk->lineno +
6341 istk->mstk.mstk->xline;
6342 else
6343 lineno = 0; /* Defined at init time or builtin */
6344 } else {
6345 lineno = src_get_linnum();
6348 tline = l->first;
6349 istk->expansion = l->next;
6350 nasm_free(l);
6352 line = detoken(tline, false);
6353 if (!istk->nolist)
6354 lfmt->line(LIST_MACRO, lineno, line);
6355 nasm_free(line);
6356 } else if ((line = read_line())) {
6357 line = prepreproc(line);
6358 tline = tokenize(line);
6359 nasm_free(line);
6360 } else {
6362 * The current file has ended; work down the istk
6364 Include *i = istk;
6365 if (i->fp)
6366 fclose(i->fp);
6367 if (i->conds) {
6368 /* nasm_error can't be conditionally suppressed */
6369 nasm_fatal("expected `%%endif' before end of file");
6371 /* only set line and file name if there's a next node */
6372 if (i->next)
6373 src_set(i->lineno, i->fname);
6374 istk = i->next;
6375 lfmt->downlevel(LIST_INCLUDE);
6376 nasm_free(i);
6377 return &tok_pop;
6379 } while (0);
6382 * We must expand MMacro parameters and MMacro-local labels
6383 * _before_ we plunge into directive processing, to cope
6384 * with things like `%define something %1' such as STRUC
6385 * uses. Unless we're _defining_ a MMacro, in which case
6386 * those tokens should be left alone to go into the
6387 * definition; and unless we're in a non-emitting
6388 * condition, in which case we don't want to meddle with
6389 * anything.
6391 if (!defining && !(istk->conds && !emitting(istk->conds->state))
6392 && !(istk->mstk.mstk && !istk->mstk.mstk->in_progress)) {
6393 tline = expand_mmac_params(tline);
6397 * Check the line to see if it's a preprocessor directive.
6399 if (do_directive(tline, &dtline) == DIRECTIVE_FOUND) {
6400 if (dtline)
6401 return dtline;
6402 } else if (defining) {
6404 * We're defining a multi-line macro. We emit nothing
6405 * at all, and just
6406 * shove the tokenized line on to the macro definition.
6408 MMacro *mmac = defining->dstk.mmac;
6410 Line *l = nasm_malloc(sizeof(Line));
6411 l->next = defining->expansion;
6412 l->first = tline;
6413 l->finishes = NULL;
6414 defining->expansion = l;
6417 * Remember if this mmacro expansion contains %00:
6418 * if it does, we will have to handle leading labels
6419 * specially.
6421 if (mmac) {
6422 const Token *t;
6423 list_for_each(t, tline) {
6424 if (!memcmp(t->text.a, "%00", 4))
6425 mmac->capture_label = true;
6428 } else if (istk->conds && !emitting(istk->conds->state)) {
6430 * We're in a non-emitting branch of a condition block.
6431 * Emit nothing at all, not even a blank line: when we
6432 * emerge from the condition we'll give a line-number
6433 * directive so we keep our place correctly.
6435 free_tlist(tline);
6436 } else if (istk->mstk.mstk && !istk->mstk.mstk->in_progress) {
6438 * We're in a %rep block which has been terminated, so
6439 * we're walking through to the %endrep without
6440 * emitting anything. Emit nothing at all, not even a
6441 * blank line: when we emerge from the %rep block we'll
6442 * give a line-number directive so we keep our place
6443 * correctly.
6445 free_tlist(tline);
6446 } else {
6447 tline = expand_smacro(tline);
6448 if (!expand_mmacro(tline))
6449 return tline;
6454 static char *pp_getline(void)
6456 char *line = NULL;
6457 Token *tline;
6459 while (true) {
6460 tline = pp_tokline();
6461 if (tline == &tok_pop) {
6463 * We popped the macro/include stack. If istk is empty,
6464 * we are at end of input, otherwise just loop back.
6466 if (!istk)
6467 break;
6468 } else {
6470 * De-tokenize the line and emit it.
6472 line = detoken(tline, true);
6473 free_tlist(tline);
6474 break;
6478 if (list_option('e') && istk && !istk->nolist && line && line[0]) {
6479 char *buf = nasm_strcat(" ;;; ", line);
6480 lfmt->line(LIST_MACRO, -1, buf);
6481 nasm_free(buf);
6484 return line;
6487 static void pp_cleanup_pass(void)
6489 if (defining) {
6490 if (defining->name) {
6491 nasm_nonfatal("end of file while still defining macro `%s'",
6492 defining->name);
6493 } else {
6494 nasm_nonfatal("end of file while still in %%rep");
6497 free_mmacro(defining);
6498 defining = NULL;
6501 while (cstk)
6502 ctx_pop();
6503 free_macros();
6504 while (istk) {
6505 Include *i = istk;
6506 istk = istk->next;
6507 fclose(i->fp);
6508 nasm_free(i);
6510 while (cstk)
6511 ctx_pop();
6512 src_set_fname(NULL);
6515 static void pp_cleanup_session(void)
6517 nasm_free(use_loaded);
6518 free_llist(predef);
6519 predef = NULL;
6520 delete_Blocks();
6521 ipath_list = NULL;
6524 static void pp_include_path(struct strlist *list)
6526 ipath_list = list;
6529 static void pp_pre_include(char *fname)
6531 Token *inc, *space, *name;
6532 Line *l;
6534 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
6535 space = new_White(name);
6536 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
6538 l = nasm_malloc(sizeof(Line));
6539 l->next = predef;
6540 l->first = inc;
6541 l->finishes = NULL;
6542 predef = l;
6545 static void pp_pre_define(char *definition)
6547 Token *def, *space;
6548 Line *l;
6549 char *equals;
6551 equals = strchr(definition, '=');
6552 space = new_White(NULL);
6553 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
6554 if (equals)
6555 *equals = ' ';
6556 space->next = tokenize(definition);
6557 if (equals)
6558 *equals = '=';
6560 /* We can't predefine a TOK_LOCAL_MACRO for obvious reasons... */
6561 if (space->next->type != TOK_PREPROC_ID &&
6562 space->next->type != TOK_ID)
6563 nasm_warn(WARN_OTHER, "pre-defining non ID `%s\'\n", definition);
6565 l = nasm_malloc(sizeof(Line));
6566 l->next = predef;
6567 l->first = def;
6568 l->finishes = NULL;
6569 predef = l;
6572 static void pp_pre_undefine(char *definition)
6574 Token *def, *space;
6575 Line *l;
6577 space = new_White(NULL);
6578 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
6579 space->next = tokenize(definition);
6581 l = nasm_malloc(sizeof(Line));
6582 l->next = predef;
6583 l->first = def;
6584 l->finishes = NULL;
6585 predef = l;
6588 /* Insert an early preprocessor command that doesn't need special handling */
6589 static void pp_pre_command(const char *what, char *string)
6591 char *cmd;
6592 Token *def, *space;
6593 Line *l;
6595 def = tokenize(string);
6596 if (what) {
6597 space = new_White(def);
6598 cmd = nasm_strcat(what[0] == '%' ? "" : "%", what);
6599 def = new_Token(space, TOK_PREPROC_ID, cmd, nasm_last_string_len());
6600 nasm_free(cmd);
6603 l = nasm_malloc(sizeof(Line));
6604 l->next = predef;
6605 l->first = def;
6606 l->finishes = NULL;
6607 predef = l;
6610 static void pp_add_stdmac(macros_t *macros)
6612 macros_t **mp;
6614 /* Find the end of the list and avoid duplicates */
6615 for (mp = stdmacros; *mp; mp++) {
6616 if (*mp == macros)
6617 return; /* Nothing to do */
6620 nasm_assert(mp < &stdmacros[ARRAY_SIZE(stdmacros)-1]);
6622 *mp = macros;
6625 static void pp_extra_stdmac(macros_t *macros)
6627 extrastdmac = macros;
6630 /* Create a numeric token */
6631 static Token *make_tok_num(Token *next, int64_t val)
6633 char numbuf[32];
6634 int len = snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
6635 return new_Token(next, TOK_NUMBER, numbuf, len);
6638 /* Create a quoted string token */
6639 static Token *make_tok_qstr_len(Token *next, const char *str, size_t len)
6641 char *p = nasm_quote(str, &len);
6642 return new_Token_free(next, TOK_STRING, p, len);
6644 static Token *make_tok_qstr(Token *next, const char *str)
6646 return make_tok_qstr_len(next, str, strlen(str));
6649 /* Create a single-character operator token */
6650 static Token *make_tok_char(Token *next, char op)
6652 Token *t = new_Token(next, TOK_OTHER, NULL, 1);
6653 t->text.a[0] = op;
6654 return t;
6657 static void pp_list_one_macro(MMacro *m, errflags severity)
6659 if (!m)
6660 return;
6662 /* We need to print the mstk.mmac list in reverse order */
6663 pp_list_one_macro(m->mstk.mmac, severity);
6665 if (m->name && !m->nolist) {
6666 src_set(m->xline + m->lineno, m->fname);
6667 nasm_error(severity, "... from macro `%s' defined", m->name);
6671 static void pp_error_list_macros(errflags severity)
6673 struct src_location saved;
6675 severity |= ERR_PP_LISTMACRO | ERR_NO_SEVERITY | ERR_HERE;
6676 saved = src_where();
6678 if (istk)
6679 pp_list_one_macro(istk->mstk.mmac, severity);
6681 src_update(saved);
6684 const struct preproc_ops nasmpp = {
6685 pp_init,
6686 pp_reset,
6687 pp_getline,
6688 pp_cleanup_pass,
6689 pp_cleanup_session,
6690 pp_extra_stdmac,
6691 pp_pre_define,
6692 pp_pre_undefine,
6693 pp_pre_include,
6694 pp_pre_command,
6695 pp_include_path,
6696 pp_error_list_macros,
6697 pp_suppress_error