travis: weirdpaste.i now has better line directives
[nasm.git] / asm / preproc.c
blob81c7204274dc4031920d759fecbb55e0c39f0ec3
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"
80 * Preprocessor execution options that can be controlled by %pragma or
81 * other directives. This structure is initialized to zero on each
82 * pass; this *must* reflect the default initial state.
84 static struct pp_opts {
85 bool noaliases;
86 bool sane_empty_expansion;
87 } ppopt;
89 typedef struct SMacro SMacro;
90 typedef struct MMacro MMacro;
91 typedef struct MMacroInvocation MMacroInvocation;
92 typedef struct Context Context;
93 typedef struct Token Token;
94 typedef struct Line Line;
95 typedef struct Include Include;
96 typedef struct Cond Cond;
99 * This is the internal form which we break input lines up into.
100 * Typically stored in linked lists.
102 * Note that `type' serves a double meaning: TOK_SMAC_START_PARAMS is
103 * not necessarily used as-is, but is also used to encode the number
104 * and expansion type of substituted parameter. So in the definition
106 * %define a(x,=y) ( (x) & ~(y) )
108 * the token representing `x' will have its type changed to
109 * tok_smac_param(0) but the one representing `y' will be
110 * tok_smac_param(1); see the accessor functions below.
112 * TOK_INTERNAL_STRING is a string which has been unquoted, but should
113 * be treated as if it was a quoted string. The code is free to change
114 * one into the other at will. TOK_NAKED_STRING is a text token which
115 * should be treated as a string, but which MUST NOT be turned into a
116 * quoted string. TOK_INTERNAL_STRINGs can contain any character,
117 * including NUL, but TOK_NAKED_STRING must be a valid C string.
119 enum pp_token_type {
120 TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT,
121 TOK_CORRUPT, /* Token text modified in an unsafe manner, now bogus */
122 TOK_BLOCK, /* Storage block pointer, not a real token */
123 TOK_ID,
124 TOK_PREPROC_ID, TOK_MMACRO_PARAM, TOK_LOCAL_SYMBOL,
125 TOK_LOCAL_MACRO, TOK_ENVIRON, TOK_STRING,
126 TOK_NUMBER, TOK_FLOAT, TOK_OTHER,
127 TOK_INTERNAL_STRING, TOK_NAKED_STRING,
128 TOK_PREPROC_Q, TOK_PREPROC_QQ,
129 TOK_PASTE, /* %+ */
130 TOK_COND_COMMA, /* %, */
131 TOK_INDIRECT, /* %[...] */
132 TOK_XDEF_PARAM, /* Used during %xdefine processing */
133 TOK_SMAC_START_PARAMS, /* MUST BE LAST IN THE LIST!!! */
134 TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
137 static inline enum pp_token_type tok_smac_param(int param)
139 return TOK_SMAC_START_PARAMS + param;
141 static int smac_nparam(enum pp_token_type toktype)
143 return toktype - TOK_SMAC_START_PARAMS;
145 static bool is_smac_param(enum pp_token_type toktype)
147 return toktype >= TOK_SMAC_START_PARAMS;
150 #define PP_CONCAT_MASK(x) (1U << (x))
152 struct tokseq_match {
153 int mask_head;
154 int mask_tail;
158 * This is tuned so struct Token should be 64 bytes on 64-bit
159 * systems and 32 bytes on 32-bit systems. It enables them
160 * to be nicely cache aligned, and the text to still be kept
161 * inline for nearly all tokens.
163 * We prohibit tokens of length > MAX_TEXT even though
164 * length here is an unsigned int; this avoids problems
165 * if the length is passed through an interface with type "int",
166 * and is absurdly large anyway.
168 * For the text mode, in pointer mode the pointer is stored at the end
169 * of the union and the pad field is cleared. This allows short tokens
170 * to be unconditionally tested for by only looking at the first text
171 * bytes and not examining the type or len fields.
173 #define INLINE_TEXT (7*sizeof(char *)-sizeof(enum pp_token_type)-sizeof(unsigned int)-1)
174 #define MAX_TEXT (INT_MAX-2)
176 struct Token {
177 Token *next;
178 enum pp_token_type type;
179 unsigned int len;
180 union {
181 char a[INLINE_TEXT+1];
182 struct {
183 char pad[INLINE_TEXT+1 - sizeof(char *)];
184 char *ptr;
185 } p;
186 } text;
190 * Note on the storage of both SMacro and MMacros: the hash table
191 * indexes them case-insensitively, and we then have to go through a
192 * linked list of potential case aliases (and, for MMacros, parameter
193 * ranges); this is to preserve the matching semantics of the earlier
194 * code. If the number of case aliases for a specific macro is a
195 * performance issue, you may want to reconsider your coding style.
199 * Function call tp obtain the expansion of an smacro
201 typedef Token *(*ExpandSMacro)(const SMacro *s, Token **params, int nparams);
204 * Store the definition of a single-line macro.
206 enum sparmflags {
207 SPARM_PLAIN = 0,
208 SPARM_EVAL = 1, /* Evaluate as a numeric expression (=) */
209 SPARM_STR = 2, /* Convert to quoted string ($) */
210 SPARM_NOSTRIP = 4, /* Don't strip braces (!) */
211 SPARM_GREEDY = 8 /* Greedy final parameter (+) */
214 struct smac_param {
215 Token name;
216 enum sparmflags flags;
219 struct SMacro {
220 SMacro *next; /* MUST BE FIRST - see free_smacro() */
221 char *name;
222 Token *expansion;
223 ExpandSMacro expand;
224 intorptr expandpvt;
225 struct smac_param *params;
226 int nparam;
227 bool greedy;
228 bool casesense;
229 bool in_progress;
230 bool alias; /* This is an alias macro */
234 * "No listing" flags. Inside a loop (%rep..%endrep) we may have
235 * macro listing suppressed with .nolist, but we still need to
236 * update line numbers for error messages and debug information...
237 * unless we are nested inside an actual .nolist macro.
239 enum nolist_flags {
240 NL_LIST = 1, /* Suppress list output */
241 NL_LINE = 2 /* Don't update line information */
245 * Store the definition of a multi-line macro. This is also used to
246 * store the interiors of `%rep...%endrep' blocks, which are
247 * effectively self-re-invoking multi-line macros which simply
248 * don't have a name or bother to appear in the hash tables. %rep
249 * blocks are signified by having a NULL `name' field.
251 * In a MMacro describing a `%rep' block, the `in_progress' field
252 * isn't merely boolean, but gives the number of repeats left to
253 * run.
255 * The `next' field is used for storing MMacros in hash tables; the
256 * `next_active' field is for stacking them on istk entries.
258 * When a MMacro is being expanded, `params', `iline', `nparam',
259 * `paramlen', `rotate' and `unique' are local to the invocation.
263 * Expansion stack. Note that .mmac can point back to the macro itself,
264 * whereas .mstk cannot.
266 struct mstk {
267 MMacro *mstk; /* Any expansion, real macro or not */
268 MMacro *mmac; /* Highest level actual mmacro */
271 struct MMacro {
272 MMacro *next;
273 #if 0
274 MMacroInvocation *prev; /* previous invocation */
275 #endif
276 char *name;
277 int nparam_min, nparam_max;
278 enum nolist_flags nolist; /* is this macro listing-inhibited? */
279 bool casesense;
280 bool plus; /* is the last parameter greedy? */
281 bool capture_label; /* macro definition has %00; capture label */
282 int32_t in_progress; /* is this macro currently being expanded? */
283 int32_t max_depth; /* maximum number of recursive expansions allowed */
284 Token *dlist; /* All defaults as one list */
285 Token **defaults; /* Parameter default pointers */
286 int ndefs; /* number of default parameters */
287 Line *expansion;
289 struct mstk mstk; /* Macro expansion stack */
290 struct mstk dstk; /* Macro definitions stack */
291 Token **params; /* actual parameters */
292 Token *iline; /* invocation line */
293 struct src_location where; /* location of definition */
294 unsigned int nparam, rotate;
295 char *iname; /* name invoked as */
296 int *paramlen;
297 uint64_t unique;
298 uint64_t condcnt; /* number of if blocks... */
302 /* Store the definition of a multi-line macro, as defined in a
303 * previous recursive macro expansion.
305 #if 0
307 struct MMacroInvocation {
308 MMacroInvocation *prev; /* previous invocation */
309 Token **params; /* actual parameters */
310 Token *iline; /* invocation line */
311 unsigned int nparam, rotate;
312 int *paramlen;
313 uint64_t unique;
314 uint64_t condcnt;
317 #endif
320 * The context stack is composed of a linked list of these.
322 struct Context {
323 Context *next;
324 const char *name;
325 struct hash_table localmac;
326 uint64_t number;
327 unsigned int depth;
331 static inline const char *tok_text(const struct Token *t)
333 return (t->len <= INLINE_TEXT) ? t->text.a : t->text.p.ptr;
337 * Returns a mutable pointer to the text buffer. The text can be changed,
338 * but the length MUST NOT CHANGE, in either direction; nor is it permitted
339 * to pad with null characters to create an artificially shorter string.
341 static inline char *tok_text_buf(struct Token *t)
343 return (t->len <= INLINE_TEXT) ? t->text.a : t->text.p.ptr;
346 static inline unsigned int tok_check_len(size_t len)
348 if (unlikely(len > MAX_TEXT))
349 nasm_fatal("impossibly large token");
351 return len;
354 static inline bool tok_text_match(const struct Token *a, const struct Token *b)
356 return a->len == b->len && !memcmp(tok_text(a), tok_text(b), a->len);
359 static inline unused_func bool
360 tok_match(const struct Token *a, const struct Token *b)
362 return a->type == b->type && tok_text_match(a, b);
365 /* strlen() variant useful for set_text() and its variants */
366 static size_t tok_strlen(const char *str)
368 return strnlen(str, MAX_TEXT+1);
372 * Set the text field to a copy of the given string; the length if
373 * not given should be obtained with tok_strlen().
375 static Token *set_text(struct Token *t, const char *text, size_t len)
377 char *textp;
379 if (t->len > INLINE_TEXT)
380 nasm_free(t->text.p.ptr);
382 nasm_zero(t->text);
384 t->len = len = tok_check_len(len);
385 textp = (len > INLINE_TEXT)
386 ? (t->text.p.ptr = nasm_malloc(len+1)) : t->text.a;
387 memcpy(textp, text, len);
388 textp[len] = '\0';
389 return t;
393 * Set the text field to the existing pre-allocated string, either
394 * taking over or freeing the allocation in the process.
396 static Token *set_text_free(struct Token *t, char *text, unsigned int len)
398 char *textp;
400 if (t->len > INLINE_TEXT)
401 nasm_free(t->text.p.ptr);
403 nasm_zero(t->text);
405 t->len = len = tok_check_len(len);
406 if (len > INLINE_TEXT) {
407 textp = t->text.p.ptr = text;
408 } else {
409 textp = memcpy(t->text.a, text, len);
410 nasm_free(text);
412 textp[len] = '\0';
414 return t;
418 * Allocate a new buffer containing a copy of the text field
419 * of the token.
421 static char *dup_text(const struct Token *t)
423 size_t size = t->len + 1;
424 char *p = nasm_malloc(size);
426 return memcpy(p, tok_text(t), size);
430 * Multi-line macro definitions are stored as a linked list of
431 * these, which is essentially a container to allow several linked
432 * lists of Tokens.
434 * Note that in this module, linked lists are treated as stacks
435 * wherever possible. For this reason, Lines are _pushed_ on to the
436 * `expansion' field in MMacro structures, so that the linked list,
437 * if walked, would give the macro lines in reverse order; this
438 * means that we can walk the list when expanding a macro, and thus
439 * push the lines on to the `expansion' field in _istk_ in reverse
440 * order (so that when popped back off they are in the right
441 * order). It may seem cockeyed, and it relies on my design having
442 * an even number of steps in, but it works...
444 * Some of these structures, rather than being actual lines, are
445 * markers delimiting the end of the expansion of a given macro.
446 * This is for use in the cycle-tracking and %rep-handling code.
447 * Such structures have `finishes' non-NULL, and `first' NULL. All
448 * others have `finishes' NULL, but `first' may still be NULL if
449 * the line is blank.
451 struct Line {
452 Line *next;
453 MMacro *finishes;
454 Token *first;
455 struct src_location where; /* Where defined */
459 * To handle an arbitrary level of file inclusion, we maintain a
460 * stack (ie linked list) of these things.
462 * Note: when we issue a message for a continuation line, we want to
463 * issue it for the actual *start* of the continuation line. This means
464 * we need to remember how many lines to skip over for the next one.
466 struct Include {
467 Include *next;
468 FILE *fp;
469 Cond *conds;
470 Line *expansion;
471 uint64_t nolist; /* Listing inhibit counter */
472 uint64_t noline; /* Line number update inhibit counter */
473 struct mstk mstk;
474 struct src_location where; /* Filename and current line number */
475 int32_t lineinc; /* Increment given by %line */
476 int32_t lineskip; /* Accounting for passed continuation lines */
480 * File real name hash, so we don't have to re-search the include
481 * path for every pass (and potentially more than that if a file
482 * is used more than once.)
484 struct hash_table FileHash;
487 * Counters to trap on insane macro recursion or processing.
488 * Note: for smacros these count *down*, for mmacros they count *up*.
490 struct deadman {
491 int64_t total; /* Total number of macros/tokens */
492 int64_t levels; /* Descent depth across all macros */
493 bool triggered; /* Already triggered, no need for error msg */
496 static struct deadman smacro_deadman, mmacro_deadman;
499 * Conditional assembly: we maintain a separate stack of these for
500 * each level of file inclusion. (The only reason we keep the
501 * stacks separate is to ensure that a stray `%endif' in a file
502 * included from within the true branch of a `%if' won't terminate
503 * it and cause confusion: instead, rightly, it'll cause an error.)
505 enum cond_state {
507 * These states are for use just after %if or %elif: IF_TRUE
508 * means the condition has evaluated to truth so we are
509 * currently emitting, whereas IF_FALSE means we are not
510 * currently emitting but will start doing so if a %else comes
511 * up. In these states, all directives are admissible: %elif,
512 * %else and %endif. (And of course %if.)
514 COND_IF_TRUE, COND_IF_FALSE,
516 * These states come up after a %else: ELSE_TRUE means we're
517 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
518 * any %elif or %else will cause an error.
520 COND_ELSE_TRUE, COND_ELSE_FALSE,
522 * These states mean that we're not emitting now, and also that
523 * nothing until %endif will be emitted at all. COND_DONE is
524 * used when we've had our moment of emission
525 * and have now started seeing %elifs. COND_NEVER is used when
526 * the condition construct in question is contained within a
527 * non-emitting branch of a larger condition construct,
528 * or if there is an error.
530 COND_DONE, COND_NEVER
532 struct Cond {
533 Cond *next;
534 enum cond_state state;
536 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
539 * These defines are used as the possible return values for do_directive
541 #define NO_DIRECTIVE_FOUND 0
542 #define DIRECTIVE_FOUND 1
545 * Condition codes. Note that we use c_ prefix not C_ because C_ is
546 * used in nasm.h for the "real" condition codes. At _this_ level,
547 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
548 * ones, so we need a different enum...
550 static const char * const conditions[] = {
551 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
552 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
553 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
555 enum pp_conds {
556 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
557 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
558 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
559 c_none = -1
561 static const enum pp_conds inverse_ccs[] = {
562 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
563 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,
564 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
568 * Directive names.
570 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
571 static int is_condition(enum preproc_token arg)
573 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
576 /* For TASM compatibility we need to be able to recognise TASM compatible
577 * conditional compilation directives. Using the NASM pre-processor does
578 * not work, so we look for them specifically from the following list and
579 * then jam in the equivalent NASM directive into the input stream.
582 enum {
583 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
584 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
587 static const char * const tasm_directives[] = {
588 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
589 "ifndef", "include", "local"
592 static int StackSize = 4;
593 static const char *StackPointer = "ebp";
594 static int ArgOffset = 8;
595 static int LocalOffset = 0;
597 static Context *cstk;
598 static Include *istk;
599 static const struct strlist *ipath_list;
601 static struct strlist *deplist;
603 static uint64_t unique; /* unique identifier numbers */
605 static Line *predef = NULL;
606 static bool do_predef;
607 static enum preproc_mode pp_mode;
610 * The current set of multi-line macros we have defined.
612 static struct hash_table mmacros;
615 * The current set of single-line macros we have defined.
617 static struct hash_table smacros;
620 * The multi-line macro we are currently defining, or the %rep
621 * block we are currently reading, if any.
623 static MMacro *defining;
625 static uint64_t nested_mac_count;
626 static uint64_t nested_rep_count;
629 * The number of macro parameters to allocate space for at a time.
631 #define PARAM_DELTA 16
634 * The standard macro set: defined in macros.c in a set of arrays.
635 * This gives our position in any macro set, while we are processing it.
636 * The stdmacset is an array of such macro sets.
638 static macros_t *stdmacpos;
639 static macros_t **stdmacnext;
640 static macros_t *stdmacros[8];
641 static macros_t *extrastdmac;
644 * Map of which %use packages have been loaded
646 static bool *use_loaded;
649 * Forward declarations.
651 static void pp_add_stdmac(macros_t *macros);
652 static Token *expand_mmac_params(Token * tline);
653 static Token *expand_smacro(Token * tline);
654 static Token *expand_id(Token * tline);
655 static Context *get_ctx(const char *name, const char **namep);
656 static Token *make_tok_num(Token *next, int64_t val);
657 static Token *make_tok_qstr(Token *next, const char *str);
658 static Token *make_tok_qstr_len(Token *next, const char *str, size_t len);
659 static Token *make_tok_char(Token *next, char op);
660 static Token *new_Token(Token * next, enum pp_token_type type,
661 const char *text, size_t txtlen);
662 static Token *new_Token_free(Token * next, enum pp_token_type type,
663 char *text, size_t txtlen);
664 static Token *dup_Token(Token *next, const Token *src);
665 static Token *new_White(Token *next);
666 static Token *delete_Token(Token *t);
667 static Token *steal_Token(Token *dst, Token *src);
668 static const struct use_package *
669 get_use_pkg(Token *t, const char *dname, const char **name);
670 static void mark_smac_params(Token *tline, const SMacro *tmpl,
671 enum pp_token_type type);
673 /* Safe test for token type, false on x == NULL */
674 static inline bool tok_type(const Token *x, enum pp_token_type t)
676 return x && x->type == t;
679 /* Whitespace token? */
680 static inline bool tok_white(const Token *x)
682 return tok_type(x, TOK_WHITESPACE);
685 /* Skip past any whitespace */
686 static inline Token *skip_white(Token *x)
688 while (tok_white(x))
689 x = x->next;
691 return x;
694 /* Delete any whitespace */
695 static Token *zap_white(Token *x)
697 while (tok_white(x))
698 x = delete_Token(x);
700 return x;
704 * Single special character tests. The use of & rather than && is intentional; it
705 * tells the compiler that it is safe to access text.a[1] unconditionally; hopefully
706 * a smart compiler should turn it into a 16-bit memory reference.
708 static inline bool tok_is(const Token *x, char c)
710 return x && ((x->text.a[0] == c) & !x->text.a[1]);
713 /* True if any other kind of token that "c", but not NULL */
714 static inline bool tok_isnt(const Token *x, char c)
716 return x && !((x->text.a[0] == c) & !x->text.a[1]);
720 * Unquote a token if it is a string, and set its type to
721 * TOK_INTERNAL_STRING.
723 static const char *unquote_token(Token *t)
725 if (t->type != TOK_STRING)
726 return tok_text(t);
728 t->type = TOK_INTERNAL_STRING;
730 if (t->len > INLINE_TEXT) {
731 char *p = t->text.p.ptr;
733 t->len = nasm_unquote(p, NULL);
735 if (t->len <= INLINE_TEXT) {
736 nasm_zero(t->text.a);
737 memcpy(t->text.a, p, t->len);
738 nasm_free(p);
739 return t->text.a;
740 } else {
741 return p;
743 } else {
744 t->len = nasm_unquote(t->text.a, NULL);
745 return t->text.a;
750 * Same as unquote_token(), but error out if the resulting string
751 * contains unacceptable control characters.
753 static const char *unquote_token_cstr(Token *t)
755 if (t->type != TOK_STRING)
756 return tok_text(t);
758 t->type = TOK_INTERNAL_STRING;
760 if (t->len > INLINE_TEXT) {
761 char *p = t->text.p.ptr;
763 t->len = nasm_unquote_cstr(p, NULL);
765 if (t->len <= INLINE_TEXT) {
766 nasm_zero(t->text.a);
767 memcpy(t->text.a, p, t->len);
768 nasm_free(p);
769 return t->text.a;
770 } else {
771 return p;
773 } else {
774 t->len = nasm_unquote_cstr(t->text.a, NULL);
775 return t->text.a;
780 * Convert a TOK_INTERNAL_STRING token to a quoted
781 * TOK_STRING tokens.
783 static Token *quote_any_token(Token *t);
784 static inline unused_func
785 Token *quote_token(Token *t)
787 if (likely(!tok_is(t, TOK_INTERNAL_STRING)))
788 return t;
790 return quote_any_token(t);
794 * Convert *any* kind of token to a quoted
795 * TOK_STRING token.
797 static Token *quote_any_token(Token *t)
799 size_t len;
800 char *p;
802 p = nasm_quote(tok_text(t), &len);
803 t->type = TOK_STRING;
804 return set_text_free(t, p, len);
808 * In-place reverse a list of tokens.
810 static Token *reverse_tokens(Token *t)
812 Token *prev = NULL;
813 Token *next;
815 while (t) {
816 next = t->next;
817 t->next = prev;
818 prev = t;
819 t = next;
822 return prev;
826 * getenv() variant operating on an input token
828 static const char *pp_getenv(const Token *t, bool warn)
830 const char *txt = tok_text(t);
831 const char *v;
832 char *buf = NULL;
833 bool is_string = false;
835 if (!t)
836 return NULL;
838 switch (t->type) {
839 case TOK_ENVIRON:
840 txt += 2; /* Skip leading %! */
841 is_string = nasm_isquote(*txt);
842 break;
844 case TOK_STRING:
845 is_string = true;
846 break;
848 case TOK_INTERNAL_STRING:
849 case TOK_NAKED_STRING:
850 case TOK_ID:
851 is_string = false;
852 break;
854 default:
855 return NULL;
858 if (is_string) {
859 buf = nasm_strdup(txt);
860 nasm_unquote_cstr(buf, NULL);
861 txt = buf;
864 v = getenv(txt);
865 if (warn && !v) {
867 *!environment [on] nonexistent environment variable
868 *! warns if a nonexistent environment variable
869 *! is accessed using the \c{%!} preprocessor
870 *! construct (see \k{getenv}.) Such environment
871 *! variables are treated as empty (with this
872 *! warning issued) starting in NASM 2.15;
873 *! earlier versions of NASM would treat this as
874 *! an error.
876 nasm_warn(WARN_ENVIRONMENT, "nonexistent environment variable `%s'", txt);
877 v = "";
880 if (buf)
881 nasm_free(buf);
883 return v;
887 * Handle TASM specific directives, which do not contain a % in
888 * front of them. We do it here because I could not find any other
889 * place to do it for the moment, and it is a hack (ideally it would
890 * be nice to be able to use the NASM pre-processor to do it).
892 static char *check_tasm_directive(char *line)
894 int32_t i, j, k, m, len;
895 char *p, *q, *oldline, oldchar;
897 p = nasm_skip_spaces(line);
899 /* Binary search for the directive name */
900 i = -1;
901 j = ARRAY_SIZE(tasm_directives);
902 q = nasm_skip_word(p);
903 len = q - p;
904 if (len) {
905 oldchar = p[len];
906 p[len] = 0;
907 while (j - i > 1) {
908 k = (j + i) / 2;
909 m = nasm_stricmp(p, tasm_directives[k]);
910 if (m == 0) {
911 /* We have found a directive, so jam a % in front of it
912 * so that NASM will then recognise it as one if it's own.
914 p[len] = oldchar;
915 len = strlen(p);
916 oldline = line;
917 line = nasm_malloc(len + 2);
918 line[0] = '%';
919 if (k == TM_IFDIFI) {
921 * NASM does not recognise IFDIFI, so we convert
922 * it to %if 0. This is not used in NASM
923 * compatible code, but does need to parse for the
924 * TASM macro package.
926 strcpy(line + 1, "if 0");
927 } else {
928 memcpy(line + 1, p, len + 1);
930 nasm_free(oldline);
931 return line;
932 } else if (m < 0) {
933 j = k;
934 } else
935 i = k;
937 p[len] = oldchar;
939 return line;
943 * The pre-preprocessing stage... This function translates line
944 * number indications as they emerge from GNU cpp (`# lineno "file"
945 * flags') into NASM preprocessor line number indications (`%line
946 * lineno file').
948 static char *prepreproc(char *line)
950 int lineno, fnlen;
951 char *fname, *oldline;
953 if (line[0] == '#' && line[1] == ' ') {
954 oldline = line;
955 fname = oldline + 2;
956 lineno = atoi(fname);
957 fname += strspn(fname, "0123456789 ");
958 if (*fname == '"')
959 fname++;
960 fnlen = strcspn(fname, "\"");
961 line = nasm_malloc(20 + fnlen);
962 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
963 nasm_free(oldline);
965 if (tasm_compatible_mode)
966 return check_tasm_directive(line);
967 return line;
971 * Free a linked list of tokens.
973 static void free_tlist(Token * list)
975 while (list)
976 list = delete_Token(list);
980 * Free a linked list of lines.
982 static void free_llist(Line * list)
984 Line *l, *tmp;
985 list_for_each_safe(l, tmp, list) {
986 free_tlist(l->first);
987 nasm_free(l);
992 * Free an array of linked lists of tokens
994 static void free_tlist_array(Token **array, size_t nlists)
996 Token **listp = array;
998 while (nlists--)
999 free_tlist(*listp++);
1001 nasm_free(array);
1005 * Duplicate a linked list of tokens.
1007 static Token *dup_tlist(const Token *list, Token ***tailp)
1009 Token *newlist = NULL;
1010 Token **tailpp = &newlist;
1011 const Token *t;
1013 list_for_each(t, list) {
1014 Token *nt;
1015 *tailpp = nt = dup_Token(NULL, t);
1016 tailpp = &nt->next;
1019 if (tailp) {
1020 **tailp = newlist;
1021 *tailp = tailpp;
1024 return newlist;
1028 * Duplicate a linked list of tokens with a maximum count
1030 static Token *dup_tlistn(const Token *list, size_t cnt, Token ***tailp)
1032 Token *newlist = NULL;
1033 Token **tailpp = &newlist;
1034 const Token *t;
1036 list_for_each(t, list) {
1037 Token *nt;
1038 if (!cnt--)
1039 break;
1040 *tailpp = nt = dup_Token(NULL, t);
1041 tailpp = &nt->next;
1044 if (tailp) {
1045 **tailp = newlist;
1046 if (newlist)
1047 *tailp = tailpp;
1050 return newlist;
1054 * Duplicate a linked list of tokens in reverse order
1056 static Token *dup_tlist_reverse(const Token *list, Token *tail)
1058 const Token *t;
1060 list_for_each(t, list)
1061 tail = dup_Token(tail, t);
1063 return tail;
1067 * Free an MMacro
1069 static void free_mmacro(MMacro * m)
1071 nasm_free(m->name);
1072 free_tlist(m->dlist);
1073 nasm_free(m->defaults);
1074 free_llist(m->expansion);
1075 nasm_free(m);
1079 * Clear or free an SMacro
1081 static void free_smacro_members(SMacro *s)
1083 if (s->params) {
1084 int i;
1085 for (i = 0; i < s->nparam; i++) {
1086 if (s->params[i].name.len > INLINE_TEXT)
1087 nasm_free(s->params[i].name.text.p.ptr);
1089 nasm_free(s->params);
1091 nasm_free(s->name);
1092 free_tlist(s->expansion);
1095 static void clear_smacro(SMacro *s)
1097 free_smacro_members(s);
1098 /* Wipe everything except the next pointer */
1099 memset(&s->next + 1, 0, sizeof *s - sizeof s->next);
1103 * Free an SMacro
1105 static void free_smacro(SMacro *s)
1107 free_smacro_members(s);
1108 nasm_free(s);
1112 * Free all currently defined macros, and free the hash tables if empty
1114 enum clear_what {
1115 CLEAR_NONE = 0,
1116 CLEAR_DEFINE = 1, /* Clear smacros */
1117 CLEAR_DEFALIAS = 2, /* Clear smacro aliases */
1118 CLEAR_ALLDEFINE = CLEAR_DEFINE|CLEAR_DEFALIAS,
1119 CLEAR_MMACRO = 4,
1120 CLEAR_ALL = CLEAR_ALLDEFINE|CLEAR_MMACRO
1123 static void clear_smacro_table(struct hash_table *smt, enum clear_what what)
1125 struct hash_iterator it;
1126 const struct hash_node *np;
1127 bool empty = true;
1130 * Walk the hash table and clear out anything we don't want
1132 hash_for_each(smt, it, np) {
1133 SMacro *tmp;
1134 SMacro *s = np->data;
1135 SMacro **head = (SMacro **)&np->data;
1137 list_for_each_safe(s, tmp, s) {
1138 if (what & ((enum clear_what)s->alias + 1)) {
1139 *head = s->next;
1140 free_smacro(s);
1141 } else {
1142 empty = false;
1148 * Free the hash table and keys if and only if it is now empty.
1149 * Note: we cannot free keys even for an empty list above, as that
1150 * mucks up the hash algorithm.
1152 if (empty)
1153 hash_free_all(smt, true);
1156 static void free_smacro_table(struct hash_table *smt)
1158 clear_smacro_table(smt, CLEAR_ALLDEFINE);
1161 static void free_mmacro_table(struct hash_table *mmt)
1163 struct hash_iterator it;
1164 const struct hash_node *np;
1166 hash_for_each(mmt, it, np) {
1167 MMacro *tmp;
1168 MMacro *m = np->data;
1169 nasm_free((void *)np->key);
1170 list_for_each_safe(m, tmp, m)
1171 free_mmacro(m);
1173 hash_free(mmt);
1176 static void free_macros(void)
1178 free_smacro_table(&smacros);
1179 free_mmacro_table(&mmacros);
1183 * Initialize the hash tables
1185 static void init_macros(void)
1190 * Pop the context stack.
1192 static void ctx_pop(void)
1194 Context *c = cstk;
1196 cstk = cstk->next;
1197 free_smacro_table(&c->localmac);
1198 nasm_free((char *)c->name);
1199 nasm_free(c);
1203 * Search for a key in the hash index; adding it if necessary
1204 * (in which case we initialize the data pointer to NULL.)
1206 static void **
1207 hash_findi_add(struct hash_table *hash, const char *str)
1209 struct hash_insert hi;
1210 void **r;
1211 char *strx;
1212 size_t l = strlen(str) + 1;
1214 r = hash_findib(hash, str, l, &hi);
1215 if (r)
1216 return r;
1218 strx = nasm_malloc(l); /* Use a more efficient allocator here? */
1219 memcpy(strx, str, l);
1220 return hash_add(&hi, strx, NULL);
1224 * Like hash_findi, but returns the data element rather than a pointer
1225 * to it. Used only when not adding a new element, hence no third
1226 * argument.
1228 static void *
1229 hash_findix(struct hash_table *hash, const char *str)
1231 void **p;
1233 p = hash_findi(hash, str, NULL);
1234 return p ? *p : NULL;
1238 * read line from standart macros set,
1239 * if there no more left -- return NULL
1241 static char *line_from_stdmac(void)
1243 unsigned char c;
1244 const unsigned char *p = stdmacpos;
1245 char *line, *q;
1246 size_t len = 0;
1248 if (!stdmacpos)
1249 return NULL;
1252 * 32-126 is ASCII, 127 is end of line, 128-31 are directives
1253 * (allowed to wrap around) corresponding to PP_* tokens 0-159.
1255 while ((c = *p++) != 127) {
1256 uint8_t ndir = c - 128;
1257 if (ndir < 256-96)
1258 len += pp_directives_len[ndir] + 1;
1259 else
1260 len++;
1263 line = nasm_malloc(len + 1);
1264 q = line;
1266 while ((c = *stdmacpos++) != 127) {
1267 uint8_t ndir = c - 128;
1268 if (ndir < 256-96) {
1269 memcpy(q, pp_directives[ndir], pp_directives_len[ndir]);
1270 q += pp_directives_len[ndir];
1271 *q++ = ' ';
1272 } else {
1273 *q++ = c;
1276 stdmacpos = p;
1277 *q = '\0';
1279 if (*stdmacpos == 127) {
1280 /* This was the last of this particular macro set */
1281 stdmacpos = NULL;
1282 if (*stdmacnext) {
1283 stdmacpos = *stdmacnext++;
1284 } else if (do_predef) {
1285 Line *pd, *l;
1288 * Nasty hack: here we push the contents of
1289 * `predef' on to the top-level expansion stack,
1290 * since this is the most convenient way to
1291 * implement the pre-include and pre-define
1292 * features.
1294 list_for_each(pd, predef) {
1295 nasm_new(l);
1296 l->next = istk->expansion;
1297 l->first = dup_tlist(pd->first, NULL);
1298 l->finishes = NULL;
1300 istk->expansion = l;
1302 do_predef = false;
1306 return line;
1310 * Read a line from a file. Return NULL on end of file.
1312 static char *line_from_file(FILE *f)
1314 int c;
1315 unsigned int size, next;
1316 const unsigned int delta = 512;
1317 const unsigned int pad = 8;
1318 bool cont = false;
1319 char *buffer, *p;
1321 istk->where.lineno += istk->lineskip + istk->lineinc;
1322 src_set_linnum(istk->where.lineno);
1323 istk->lineskip = 0;
1325 size = delta;
1326 p = buffer = nasm_malloc(size);
1328 do {
1329 c = fgetc(f);
1331 switch (c) {
1332 case EOF:
1333 if (p == buffer) {
1334 nasm_free(buffer);
1335 return NULL;
1337 c = 0;
1338 break;
1340 case '\r':
1341 next = fgetc(f);
1342 if (next != '\n')
1343 ungetc(next, f);
1344 if (cont) {
1345 cont = false;
1346 continue;
1348 c = 0;
1349 break;
1351 case '\n':
1352 if (cont) {
1353 cont = false;
1354 continue;
1356 c = 0;
1357 break;
1359 case 032: /* ^Z = legacy MS-DOS end of file mark */
1360 c = 0;
1361 break;
1363 case '\\':
1364 next = fgetc(f);
1365 ungetc(next, f);
1366 if (next == '\r' || next == '\n') {
1367 cont = true;
1368 istk->lineskip += istk->lineinc;
1369 continue;
1371 break;
1374 if (p >= (buffer + size - pad)) {
1375 buffer = nasm_realloc(buffer, size + delta);
1376 p = buffer + size - pad;
1377 size += delta;
1380 *p++ = c;
1381 } while (c);
1383 return buffer;
1387 * Common read routine regardless of source
1389 static char *read_line(void)
1391 char *line;
1392 FILE *f = istk->fp;
1394 if (f)
1395 line = line_from_file(f);
1396 else
1397 line = line_from_stdmac();
1399 if (!line)
1400 return NULL;
1402 if (!istk->nolist)
1403 lfmt->line(LIST_READ, istk->where.lineno, line);
1405 return line;
1409 * Tokenize a line of text. This is a very simple process since we
1410 * don't need to parse the value out of e.g. numeric tokens: we
1411 * simply split one string into many.
1413 static Token *tokenize(const char *line)
1415 enum pp_token_type type;
1416 Token *list = NULL;
1417 Token *t, **tail = &list;
1419 while (*line) {
1420 const char *p = line;
1421 const char *ep = NULL; /* End of token, for trimming the end */
1422 size_t toklen;
1423 char firstchar = *p; /* Can be used to override the first char */
1425 if (*p == '%') {
1427 * Preprocessor construct; find the end of the token.
1428 * Classification is handled later, because %{...} can be
1429 * used to create any preprocessor token.
1431 p++;
1432 if (*p == '+' && !nasm_isdigit(p[1])) {
1433 /* Paste token */
1434 p++;
1435 } else if (nasm_isdigit(*p) ||
1436 ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
1437 do {
1438 p++;
1440 while (nasm_isdigit(*p));
1441 } else if (*p == '{' || *p == '[') {
1442 /* %{...} or %[...] */
1443 char firstchar = *p;
1444 char endchar = *p + 2; /* } or ] */
1445 int lvl = 1;
1446 line += (*p++ == '{'); /* Skip { but not [ (yet) */
1447 while (lvl) {
1448 if (*p == firstchar) {
1449 lvl++;
1450 } else if (*p == endchar) {
1451 lvl--;
1452 } else if (nasm_isquote(*p)) {
1453 p = nasm_skip_string(p);
1457 * *p can have been advanced to a null character by
1458 * nasm_skip_string()
1460 if (!*p) {
1461 nasm_warn(WARN_OTHER, "unterminated %%%c construct",
1462 firstchar);
1463 break;
1465 p++;
1467 ep = lvl ? p : p-1; /* Terminal character not part of token */
1468 } else if (*p == '?') {
1469 /* %? or %?? */
1470 p++;
1471 if (*p == '?')
1472 p++;
1473 } else if (*p == '!') {
1474 /* Environment variable reference */
1475 p++;
1476 if (nasm_isidchar(*p)) {
1477 do {
1478 p++;
1480 while (nasm_isidchar(*p));
1481 } else if (nasm_isquote(*p)) {
1482 p = nasm_skip_string(p);
1483 if (*p)
1484 p++;
1485 else
1486 nasm_nonfatalf(ERR_PASS1, "unterminated %%! string");
1487 } else {
1488 /* %! without anything else... */
1490 } else if (*p == ',') {
1491 /* Conditional comma */
1492 p++;
1493 } else if (nasm_isidchar(*p) ||
1494 ((*p == '%' || *p == '$') && nasm_isidchar(p[1]))) {
1495 /* Identifier or some sort */
1496 do {
1497 p++;
1499 while (nasm_isidchar(*p));
1500 } else if (*p == '%') {
1501 /* %% operator */
1502 p++;
1505 if (!ep)
1506 ep = p;
1507 toklen = ep - line;
1509 /* Classify here, to handle %{...} correctly */
1510 if (toklen < 2) {
1511 type = TOK_OTHER; /* % operator */
1512 } else {
1513 char c0 = line[1];
1515 switch (c0) {
1516 case '+':
1517 type = (toklen == 2) ? TOK_PASTE : TOK_MMACRO_PARAM;
1518 break;
1520 case '-':
1521 type = TOK_MMACRO_PARAM;
1522 break;
1524 case '?':
1525 if (toklen == 2)
1526 type = TOK_PREPROC_Q;
1527 else if (toklen == 3 && line[2] == '?')
1528 type = TOK_PREPROC_QQ;
1529 else
1530 type = TOK_PREPROC_ID;
1531 break;
1533 case '!':
1534 type = (toklen == 2) ? TOK_OTHER : TOK_ENVIRON;
1535 break;
1537 case '%':
1538 type = (toklen == 2) ? TOK_OTHER : TOK_LOCAL_SYMBOL;
1539 break;
1541 case '$':
1542 type = (toklen == 2) ? TOK_OTHER : TOK_LOCAL_MACRO;
1543 break;
1545 case '[':
1546 line += 2; /* Skip %[ */
1547 firstchar = *line; /* Don't clobber */
1548 toklen -= 2;
1549 type = TOK_INDIRECT;
1550 break;
1552 case ',':
1553 type = (toklen == 2) ? TOK_COND_COMMA : TOK_PREPROC_ID;
1554 break;
1556 case '\'':
1557 case '\"':
1558 case '`':
1559 /* %{'string'} */
1560 type = TOK_PREPROC_ID;
1561 break;
1563 case ':':
1564 type = TOK_MMACRO_PARAM; /* %{:..} */
1565 break;
1567 default:
1568 if (nasm_isdigit(c0))
1569 type = TOK_MMACRO_PARAM;
1570 else if (nasm_isidchar(c0) || toklen > 2)
1571 type = TOK_PREPROC_ID;
1572 else
1573 type = TOK_OTHER;
1574 break;
1577 } else if (nasm_isidstart(*p) || (*p == '$' && nasm_isidstart(p[1]))) {
1579 * An identifier. This includes the ? operator, which is
1580 * treated as a keyword, not as a special character
1581 * operator
1583 type = TOK_ID;
1584 while (nasm_isidchar(*++p))
1586 } else if (nasm_isquote(*p)) {
1588 * A string token.
1590 type = TOK_STRING;
1591 p = nasm_skip_string(p);
1593 if (*p) {
1594 p++;
1595 } else {
1596 nasm_warn(WARN_OTHER, "unterminated string");
1597 /* Handling unterminated strings by UNV */
1598 /* type = -1; */
1600 } else if (p[0] == '$' && p[1] == '$') {
1601 type = TOK_OTHER; /* TOKEN_BASE */
1602 p += 2;
1603 } else if (nasm_isnumstart(*p)) {
1604 bool is_hex = false;
1605 bool is_float = false;
1606 bool has_e = false;
1607 char c;
1610 * A numeric token.
1613 if (*p == '$') {
1614 p++;
1615 is_hex = true;
1618 for (;;) {
1619 c = *p++;
1621 if (!is_hex && (c == 'e' || c == 'E')) {
1622 has_e = true;
1623 if (*p == '+' || *p == '-') {
1625 * e can only be followed by +/- if it is either a
1626 * prefixed hex number or a floating-point number
1628 p++;
1629 is_float = true;
1631 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
1632 is_hex = true;
1633 } else if (c == 'P' || c == 'p') {
1634 is_float = true;
1635 if (*p == '+' || *p == '-')
1636 p++;
1637 } else if (nasm_isnumchar(c))
1638 ; /* just advance */
1639 else if (c == '.') {
1641 * we need to deal with consequences of the legacy
1642 * parser, like "1.nolist" being two tokens
1643 * (TOK_NUMBER, TOK_ID) here; at least give it
1644 * a shot for now. In the future, we probably need
1645 * a flex-based scanner with proper pattern matching
1646 * to do it as well as it can be done. Nothing in
1647 * the world is going to help the person who wants
1648 * 0x123.p16 interpreted as two tokens, though.
1650 const char *r = p;
1651 while (*r == '_')
1652 r++;
1654 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
1655 (!is_hex && (*r == 'e' || *r == 'E')) ||
1656 (*r == 'p' || *r == 'P')) {
1657 p = r;
1658 is_float = true;
1659 } else
1660 break; /* Terminate the token */
1661 } else
1662 break;
1664 p--; /* Point to first character beyond number */
1666 if (p == line+1 && *line == '$') {
1667 type = TOK_OTHER; /* TOKEN_HERE */
1668 } else {
1669 if (has_e && !is_hex) {
1670 /* 1e13 is floating-point, but 1e13h is not */
1671 is_float = true;
1674 type = is_float ? TOK_FLOAT : TOK_NUMBER;
1676 } else if (nasm_isspace(*p)) {
1677 type = TOK_WHITESPACE;
1678 p = nasm_skip_spaces(p);
1680 * Whitespace just before end-of-line is discarded by
1681 * pretending it's a comment; whitespace just before a
1682 * comment gets lumped into the comment.
1684 if (!*p || *p == ';') {
1685 type = TOK_COMMENT;
1686 while (*p)
1687 p++;
1689 } else if (*p == ';') {
1690 type = TOK_COMMENT;
1691 while (*p)
1692 p++;
1693 } else {
1695 * Anything else is an operator of some kind. We check
1696 * for all the double-character operators (>>, <<, //,
1697 * %%, <=, >=, ==, !=, <>, &&, ||, ^^) and the triple-
1698 * character operators (<<<, >>>, <=>) but anything
1699 * else is a single-character operator.
1701 type = TOK_OTHER;
1702 switch (*p++) {
1703 case '>':
1704 if (*p == '>') {
1705 p++;
1706 if (*p == '>')
1707 p++;
1708 } else if (*p == '=') {
1709 p++;
1711 break;
1713 case '<':
1714 if (*p == '<') {
1715 p++;
1716 if (*p == '<')
1717 p++;
1718 } else if (*p == '=') {
1719 p++;
1720 if (*p == '>')
1721 p++;
1722 } else if (*p == '>') {
1723 p++;
1725 break;
1727 case '!':
1728 if (*p == '=')
1729 p++;
1730 break;
1732 case '/':
1733 case '=':
1734 case '&':
1735 case '|':
1736 case '^':
1737 /* These operators can be doubled but nothing else */
1738 if (*p == p[-1])
1739 p++;
1740 break;
1742 default:
1743 break;
1747 if (type == TOK_WHITESPACE) {
1748 *tail = t = new_White(NULL);
1749 tail = &t->next;
1750 } else if (type != TOK_COMMENT) {
1751 if (!ep)
1752 ep = p;
1753 *tail = t = new_Token(NULL, type, line, ep - line);
1754 *tok_text_buf(t) = firstchar; /* E.g. %{foo} -> {foo -> %foo */
1755 tail = &t->next;
1757 line = p;
1759 return list;
1763 * Tokens are allocated in blocks to improve speed. Set the blocksize
1764 * to 0 to use regular nasm_malloc(); this is useful for debugging.
1766 * alloc_Token() returns a zero-initialized token structure.
1768 #define TOKEN_BLOCKSIZE 4096
1770 #if TOKEN_BLOCKSIZE
1772 static Token *freeTokens = NULL;
1773 static Token *tokenblocks = NULL;
1775 static Token *alloc_Token(void)
1777 Token *t = freeTokens;
1779 if (unlikely(!t)) {
1780 Token *block;
1781 size_t i;
1783 nasm_newn(block, TOKEN_BLOCKSIZE);
1786 * The first entry in each array are a linked list of
1787 * block allocations and is not used for data.
1789 block[0].next = tokenblocks;
1790 block[0].type = TOK_BLOCK;
1791 tokenblocks = block;
1794 * Add the rest to the free list
1796 for (i = 2; i < TOKEN_BLOCKSIZE - 1; i++)
1797 block[i].next = &block[i+1];
1799 freeTokens = &block[2];
1802 * Return the topmost usable token
1804 return &block[1];
1807 freeTokens = t->next;
1808 t->next = NULL;
1809 return t;
1812 static Token *delete_Token(Token *t)
1814 Token *next = t->next;
1816 nasm_zero(*t);
1817 t->next = freeTokens;
1818 freeTokens = t;
1820 return next;
1823 static void delete_Blocks(void)
1825 Token *block, *blocktmp;
1827 list_for_each_safe(block, blocktmp, tokenblocks)
1828 nasm_free(block);
1830 freeTokens = tokenblocks = NULL;
1833 #else
1835 static inline Token *alloc_Token(void)
1837 Token *t;
1838 nasm_new(*t);
1839 return t;
1842 static Token *delete_Token(Token *t)
1844 Token *next = t->next;
1845 nasm_free(t);
1846 return next;
1849 static inline void delete_Blocks(void)
1851 /* Nothing to do */
1854 #endif
1857 * this function creates a new Token and passes a pointer to it
1858 * back to the caller. It sets the type, text, and next pointer elements.
1860 static Token *new_Token(Token * next, enum pp_token_type type,
1861 const char *text, size_t txtlen)
1863 Token *t = alloc_Token();
1864 char *textp;
1866 t->next = next;
1867 t->type = type;
1868 if (type == TOK_WHITESPACE) {
1869 t->len = 1;
1870 t->text.a[0] = ' ';
1871 } else {
1872 if (text && text[0] && !txtlen)
1873 txtlen = tok_strlen(text);
1875 t->len = tok_check_len(txtlen);
1877 if (text) {
1878 textp = (txtlen > INLINE_TEXT)
1879 ? (t->text.p.ptr = nasm_malloc(txtlen+1)) : t->text.a;
1880 memcpy(textp, text, txtlen);
1881 textp[txtlen] = '\0'; /* In case we needed malloc() */
1882 } else {
1884 * Allocate a buffer but do not fill it. The caller
1885 * can fill in text, but must not change the length.
1886 * The filled in text must be exactly txtlen once
1887 * the buffer is filled and before the token is added
1888 * to any line lists.
1890 if (txtlen > INLINE_TEXT)
1891 t->text.p.ptr = nasm_zalloc(txtlen+1);
1894 return t;
1898 * Same as new_Token(), but text belongs to the new token and is
1899 * either taken over or freed. This function MUST be called
1900 * with valid txt and txtlen, unlike new_Token().
1902 static Token *new_Token_free(Token * next, enum pp_token_type type,
1903 char *text, size_t txtlen)
1905 Token *t = alloc_Token();
1907 t->next = next;
1908 t->type = type;
1909 t->len = tok_check_len(txtlen);
1911 if (txtlen <= INLINE_TEXT) {
1912 memcpy(t->text.a, text, txtlen);
1913 free(text);
1914 } else {
1915 t->text.p.ptr = text;
1918 return t;
1921 static Token *dup_Token(Token *next, const Token *src)
1923 Token *t = alloc_Token();
1925 memcpy(t, src, sizeof *src);
1926 t->next = next;
1928 if (t->len > INLINE_TEXT) {
1929 t->text.p.ptr = nasm_malloc(t->len + 1);
1930 memcpy(t->text.p.ptr, src->text.p.ptr, t->len+1);
1933 return t;
1936 static Token *new_White(Token *next)
1938 Token *t = alloc_Token();
1940 t->next = next;
1941 t->type = TOK_WHITESPACE;
1942 t->len = 1;
1943 t->text.a[0] = ' ';
1945 return t;
1949 * This *transfers* the content from one token to another, leaving the
1950 * next pointer of the latter intact. Unlike dup_Token(), the old
1951 * token is destroyed, except for its next pointer, and the text
1952 * pointer allocation, if any, is simply transferred.
1954 static Token *steal_Token(Token *dst, Token *src)
1956 /* Overwrite everything except the next pointers */
1957 memcpy((char *)dst + sizeof(Token *), (char *)src + sizeof(Token *),
1958 sizeof(Token) - sizeof(Token *));
1960 /* Clear the donor token */
1961 memset((char *)src + sizeof(Token *), 0, sizeof(Token) - sizeof(Token *));
1963 return dst;
1967 * Convert a line of tokens back into text. This modifies the list
1968 * by expanding environment variables.
1970 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1971 * are also transformed into ..@ctxnum.xxx
1973 static char *detoken(Token * tlist, bool expand_locals)
1975 Token *t;
1976 char *line, *p;
1977 int len = 0;
1979 list_for_each(t, tlist) {
1980 switch (t->type) {
1981 case TOK_ENVIRON:
1983 const char *v = pp_getenv(t, true);
1984 set_text(t, v, tok_strlen(v));
1985 t->type = TOK_NAKED_STRING;
1986 break;
1989 case TOK_LOCAL_MACRO:
1990 case TOK_LOCAL_SYMBOL:
1991 if (expand_locals) {
1992 const char *q;
1993 char *p;
1994 Context *ctx = get_ctx(tok_text(t), &q);
1995 if (ctx) {
1996 p = nasm_asprintf("..@%"PRIu64".%s", ctx->number, q);
1997 set_text_free(t, p, nasm_last_string_len());
1998 t->type = TOK_ID;
2001 break;
2003 default:
2004 break; /* No modifications */
2007 if (debug_level(2)) {
2008 unsigned int t_len = t->len;
2009 unsigned int s_len = tok_strlen(tok_text(t));
2010 if (t_len != s_len) {
2011 nasm_panic("assertion failed: token \"%s\" type %u len %u has t->len %u\n",
2012 tok_text(t), t->type, s_len, t_len);
2013 t->len = s_len;
2017 len += t->len;
2020 p = line = nasm_malloc(len + 1);
2022 list_for_each(t, tlist)
2023 p = mempcpy(p, tok_text(t), t->len);
2024 *p = '\0';
2026 return line;
2030 * A scanner, suitable for use by the expression evaluator, which
2031 * operates on a line of Tokens. Expects a pointer to a pointer to
2032 * the first token in the line to be passed in as its private_data
2033 * field.
2035 * FIX: This really needs to be unified with stdscan.
2037 struct ppscan {
2038 Token *tptr;
2039 int ntokens;
2042 static int ppscan(void *private_data, struct tokenval *tokval)
2044 struct ppscan *pps = private_data;
2045 Token *tline;
2046 const char *txt;
2048 do {
2049 if (pps->ntokens && (tline = pps->tptr)) {
2050 pps->ntokens--;
2051 pps->tptr = tline->next;
2052 } else {
2053 pps->tptr = NULL;
2054 pps->ntokens = 0;
2055 return tokval->t_type = TOKEN_EOS;
2057 } while (tline->type == TOK_WHITESPACE || tline->type == TOK_COMMENT);
2059 txt = tok_text(tline);
2060 tokval->t_charptr = (char *)txt; /* Fix this */
2062 if (txt[0] == '$') {
2063 if (!txt[1]) {
2064 return tokval->t_type = TOKEN_HERE;
2065 } else if (txt[1] == '$' && !txt[2]) {
2066 return tokval->t_type = TOKEN_BASE;
2067 } else if (tline->type == TOK_ID) {
2068 tokval->t_charptr++;
2069 return tokval->t_type = TOKEN_ID;
2073 switch (tline->type) {
2074 default:
2075 if (tline->len == 1)
2076 return tokval->t_type = txt[0];
2077 /* fall through */
2078 case TOK_ID:
2079 return nasm_token_hash(txt, tokval);
2081 case TOK_NUMBER:
2083 bool rn_error;
2084 tokval->t_integer = readnum(txt, &rn_error);
2085 if (rn_error)
2086 return tokval->t_type = TOKEN_ERRNUM;
2087 else
2088 return tokval->t_type = TOKEN_NUM;
2091 case TOK_FLOAT:
2092 return tokval->t_type = TOKEN_FLOAT;
2094 case TOK_STRING:
2095 tokval->t_charptr = (char *)unquote_token(tline);
2096 tokval->t_inttwo = tline->len;
2097 return tokval->t_type = TOKEN_STR;
2102 * 1. An expression (true if nonzero 0)
2103 * 2. The keywords true, on, yes for true
2104 * 3. The keywords false, off, no for false
2105 * 4. An empty line, for true
2107 * On error, return defval (usually the previous value)
2109 static bool pp_get_boolean_option(Token *tline, bool defval)
2111 static const char * const noyes[] = {
2112 "no", "yes",
2113 "false", "true",
2114 "off", "on"
2116 struct ppscan pps;
2117 struct tokenval tokval;
2118 expr *evalresult;
2120 tline = skip_white(tline);
2121 if (!tline)
2122 return true;
2124 if (tline->type == TOK_ID) {
2125 size_t i;
2126 const char *txt = tok_text(tline);
2128 for (i = 0; i < ARRAY_SIZE(noyes); i++)
2129 if (!nasm_stricmp(txt, noyes[i]))
2130 return i & 1;
2133 pps.tptr = NULL;
2134 pps.tptr = tline;
2135 pps.ntokens = -1;
2136 tokval.t_type = TOKEN_INVALID;
2137 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
2139 if (!evalresult)
2140 return true;
2142 if (tokval.t_type)
2143 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
2144 if (!is_really_simple(evalresult)) {
2145 nasm_nonfatal("boolean flag expression must be a constant");
2146 return defval;
2149 return reloc_value(evalresult) != 0;
2153 * Compare a string to the name of an existing macro; this is a
2154 * simple wrapper which calls either strcmp or nasm_stricmp
2155 * depending on the value of the `casesense' parameter.
2157 static int mstrcmp(const char *p, const char *q, bool casesense)
2159 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
2163 * Compare a string to the name of an existing macro; this is a
2164 * simple wrapper which calls either strcmp or nasm_stricmp
2165 * depending on the value of the `casesense' parameter.
2167 static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
2169 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
2173 * Return the Context structure associated with a %$ token. Return
2174 * NULL, having _already_ reported an error condition, if the
2175 * context stack isn't deep enough for the supplied number of $
2176 * signs.
2178 * If "namep" is non-NULL, set it to the pointer to the macro name
2179 * tail, i.e. the part beyond %$...
2181 static Context *get_ctx(const char *name, const char **namep)
2183 Context *ctx;
2184 int i;
2186 if (namep)
2187 *namep = name;
2189 if (!name || name[0] != '%' || name[1] != '$')
2190 return NULL;
2192 if (!cstk) {
2193 nasm_nonfatal("`%s': context stack is empty", name);
2194 return NULL;
2197 name += 2;
2198 ctx = cstk;
2199 i = 0;
2200 while (ctx && *name == '$') {
2201 name++;
2202 i++;
2203 ctx = ctx->next;
2205 if (!ctx) {
2206 nasm_nonfatal("`%s': context stack is only"
2207 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
2208 return NULL;
2211 if (namep)
2212 *namep = name;
2214 return ctx;
2218 * Open an include file. This routine must always return a valid
2219 * file pointer if it returns - it's responsible for throwing an
2220 * ERR_FATAL and bombing out completely if not. It should also try
2221 * the include path one by one until it finds the file or reaches
2222 * the end of the path.
2224 * Note: for INC_PROBE the function returns NULL at all times;
2225 * instead look for the
2227 enum incopen_mode {
2228 INC_NEEDED, /* File must exist */
2229 INC_OPTIONAL, /* Missing is OK */
2230 INC_PROBE /* Only an existence probe */
2233 /* This is conducts a full pathname search */
2234 static FILE *inc_fopen_search(const char *file, char **slpath,
2235 enum incopen_mode omode, enum file_flags fmode)
2237 const struct strlist_entry *ip = strlist_head(ipath_list);
2238 FILE *fp;
2239 const char *prefix = "";
2240 char *sp;
2241 bool found;
2243 while (1) {
2244 sp = nasm_catfile(prefix, file);
2245 if (omode == INC_PROBE) {
2246 fp = NULL;
2247 found = nasm_file_exists(sp);
2248 } else {
2249 fp = nasm_open_read(sp, fmode);
2250 found = (fp != NULL);
2252 if (found) {
2253 *slpath = sp;
2254 return fp;
2257 nasm_free(sp);
2259 if (!ip) {
2260 *slpath = NULL;
2261 return NULL;
2264 prefix = ip->str;
2265 ip = ip->next;
2270 * Open a file, or test for the presence of one (depending on omode),
2271 * considering the include path.
2273 static FILE *inc_fopen(const char *file,
2274 struct strlist *dhead,
2275 const char **found_path,
2276 enum incopen_mode omode,
2277 enum file_flags fmode)
2279 struct hash_insert hi;
2280 void **hp;
2281 char *path;
2282 FILE *fp = NULL;
2284 hp = hash_find(&FileHash, file, &hi);
2285 if (hp) {
2286 path = *hp;
2287 if (path || omode != INC_NEEDED) {
2288 strlist_add(dhead, path ? path : file);
2290 } else {
2291 /* Need to do the actual path search */
2292 fp = inc_fopen_search(file, &path, omode, fmode);
2294 /* Positive or negative result */
2295 hash_add(&hi, nasm_strdup(file), path);
2298 * Add file to dependency path.
2300 if (path || omode != INC_NEEDED)
2301 strlist_add(dhead, file);
2304 if (path && !fp && omode != INC_PROBE)
2305 fp = nasm_open_read(path, fmode);
2307 if (omode == INC_NEEDED && !fp) {
2308 if (!path)
2309 errno = ENOENT;
2311 nasm_nonfatal("unable to open include file `%s': %s",
2312 file, strerror(errno));
2315 if (found_path)
2316 *found_path = path;
2318 return fp;
2322 * Opens an include or input file. Public version, for use by modules
2323 * that get a file:lineno pair and need to look at the file again
2324 * (e.g. the CodeView debug backend). Returns NULL on failure.
2326 FILE *pp_input_fopen(const char *filename, enum file_flags mode)
2328 return inc_fopen(filename, NULL, NULL, INC_OPTIONAL, mode);
2332 * Determine if we should warn on defining a single-line macro of
2333 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
2334 * return true if _any_ single-line macro of that name is defined.
2335 * Otherwise, will return true if a single-line macro with either
2336 * `nparam' or no parameters is defined.
2338 * If a macro with precisely the right number of parameters is
2339 * defined, or nparam is -1, the address of the definition structure
2340 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
2341 * is NULL, no action will be taken regarding its contents, and no
2342 * error will occur.
2344 * Note that this is also called with nparam zero to resolve
2345 * `ifdef'.
2347 static bool
2348 smacro_defined(Context *ctx, const char *name, int nparam, SMacro **defn,
2349 bool nocase, bool find_alias)
2351 struct hash_table *smtbl;
2352 SMacro *m;
2354 smtbl = ctx ? &ctx->localmac : &smacros;
2356 restart:
2357 m = (SMacro *) hash_findix(smtbl, name);
2359 while (m) {
2360 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
2361 (nparam <= 0 || m->nparam == 0 || nparam == m->nparam ||
2362 (m->greedy && nparam >= m->nparam-1))) {
2363 if (m->alias && !find_alias) {
2364 if (!ppopt.noaliases) {
2365 name = tok_text(m->expansion);
2366 goto restart;
2367 } else {
2368 continue;
2371 if (defn) {
2372 *defn = (nparam == m->nparam || nparam == -1) ? m : NULL;
2374 return true;
2376 m = m->next;
2379 return false;
2382 /* param should be a natural number [0; INT_MAX] */
2383 static int read_param_count(const char *str)
2385 int result;
2386 bool err;
2388 result = readnum(str, &err);
2389 if (result < 0 || result > INT_MAX) {
2390 result = 0;
2391 nasm_nonfatal("parameter count `%s' is out of bounds [%d; %d]",
2392 str, 0, INT_MAX);
2393 } else if (err)
2394 nasm_nonfatal("unable to parse parameter count `%s'", str);
2395 return result;
2399 * Count and mark off the parameters in a multi-line macro call.
2400 * This is called both from within the multi-line macro expansion
2401 * code, and also to mark off the default parameters when provided
2402 * in a %macro definition line.
2404 * Note that we need space in the params array for parameter 0 being
2405 * a possible captured label as well as the final NULL.
2407 * Returns a pointer to the pointer to a terminal comma if present;
2408 * used to drop an empty terminal argument for legacy reasons.
2410 static Token **count_mmac_params(Token *tline, int *nparamp, Token ***paramsp)
2412 int paramsize;
2413 int nparam = 0;
2414 Token *t;
2415 Token **comma = NULL, **maybe_comma = NULL;
2416 Token **params;
2418 paramsize = PARAM_DELTA;
2419 nasm_newn(params, paramsize);
2421 t = skip_white(tline);
2422 if (t) {
2423 while (true) {
2424 /* Need two slots for captured label and NULL */
2425 if (unlikely(nparam+2 >= paramsize)) {
2426 paramsize += PARAM_DELTA;
2427 params = nasm_realloc(params, sizeof(*params) * paramsize);
2429 params[++nparam] = t;
2430 if (tok_is(t, '{')) {
2431 int brace = 1;
2433 comma = NULL; /* Non-empty parameter */
2435 while (brace && (t = t->next)) {
2436 brace += tok_is(t, '{');
2437 brace -= tok_is(t, '}');
2440 if (t) {
2442 * Now we've found the closing brace, look further
2443 * for the comma.
2445 t = skip_white(t->next);
2446 if (tok_isnt(t, ','))
2447 nasm_nonfatal("braces do not enclose all of macro parameter");
2448 } else {
2449 nasm_nonfatal("expecting closing brace in macro parameter");
2453 /* Advance to the next comma */
2454 maybe_comma = &t->next;
2455 while (tok_isnt(t, ',')) {
2456 if (!tok_white(t))
2457 comma = NULL; /* Non-empty parameter */
2458 maybe_comma = &t->next;
2459 t = t->next;
2462 if (!t)
2463 break; /* End of string, no comma */
2465 comma = maybe_comma; /* Point to comma pointer */
2466 t = skip_white(t->next); /* Eat the comma and whitespace */
2470 params[nparam+1] = NULL;
2471 *paramsp = params;
2472 *nparamp = nparam;
2474 return comma;
2478 * Determine whether one of the various `if' conditions is true or
2479 * not.
2481 * We must free the tline we get passed.
2483 static enum cond_state if_condition(Token * tline, enum preproc_token ct)
2485 bool j;
2486 Token *t, *tt, *origline;
2487 struct ppscan pps;
2488 struct tokenval tokval;
2489 expr *evalresult;
2490 enum pp_token_type needtype;
2491 const char *dname = pp_directives[ct];
2492 bool casesense = true;
2493 enum preproc_token cond = PP_COND(ct);
2495 origline = tline;
2497 switch (cond) {
2498 case PP_IFCTX:
2499 j = false; /* have we matched yet? */
2500 while (true) {
2501 tline = skip_white(tline);
2502 if (!tline)
2503 break;
2504 if (tline->type != TOK_ID) {
2505 nasm_nonfatal("`%s' expects context identifiers",
2506 dname);
2507 goto fail;
2509 if (cstk && cstk->name && !nasm_stricmp(tok_text(tline), cstk->name))
2510 j = true;
2511 tline = tline->next;
2513 break;
2515 case PP_IFDEF:
2516 case PP_IFDEFALIAS:
2518 bool alias = cond == PP_IFDEFALIAS;
2519 SMacro *smac;
2520 Context *ctx;
2521 const char *mname;
2523 j = false; /* have we matched yet? */
2524 while (tline) {
2525 tline = skip_white(tline);
2526 if (!tline || (tline->type != TOK_ID &&
2527 tline->type != TOK_LOCAL_MACRO)) {
2528 nasm_nonfatal("`%s' expects macro identifiers",
2529 dname);
2530 goto fail;
2533 mname = tok_text(tline);
2534 ctx = get_ctx(mname, &mname);
2535 if (smacro_defined(ctx, mname, -1, &smac, true, alias) && smac
2536 && smac->alias == alias) {
2537 j = true;
2538 break;
2540 tline = tline->next;
2542 break;
2545 case PP_IFENV:
2546 tline = expand_smacro(tline);
2547 j = false; /* have we matched yet? */
2548 while (tline) {
2549 tline = skip_white(tline);
2550 if (!tline || (tline->type != TOK_ID &&
2551 tline->type != TOK_STRING &&
2552 tline->type != TOK_INTERNAL_STRING &&
2553 tline->type != TOK_ENVIRON)) {
2554 nasm_nonfatal("`%s' expects environment variable names",
2555 dname);
2556 goto fail;
2559 j |= !!pp_getenv(tline, false);
2560 tline = tline->next;
2562 break;
2564 case PP_IFIDNI:
2565 casesense = false;
2566 /* fall through */
2567 case PP_IFIDN:
2568 tline = expand_smacro(tline);
2569 t = tt = tline;
2570 while (tok_isnt(tt, ','))
2571 tt = tt->next;
2572 if (!tt) {
2573 nasm_nonfatal("`%s' expects two comma-separated arguments",
2574 dname);
2575 goto fail;
2577 tt = tt->next;
2578 j = true; /* assume equality unless proved not */
2579 while (tok_isnt(t, ',') && tt) {
2580 unsigned int l1, l2;
2581 const char *t1, *t2;
2583 if (tok_is(tt, ',')) {
2584 nasm_nonfatal("`%s': more than one comma on line",
2585 dname);
2586 goto fail;
2588 if (t->type == TOK_WHITESPACE) {
2589 t = t->next;
2590 continue;
2592 if (tt->type == TOK_WHITESPACE) {
2593 tt = tt->next;
2594 continue;
2596 if (tt->type != t->type) {
2597 j = false; /* found mismatching tokens */
2598 break;
2601 t1 = unquote_token(t);
2602 t2 = unquote_token(tt);
2603 l1 = t->len;
2604 l2 = tt->len;
2606 if (l1 != l2 || mmemcmp(t1, t2, l1, casesense)) {
2607 j = false;
2608 break;
2611 t = t->next;
2612 tt = tt->next;
2614 if (!tok_is(t, ',') || tt)
2615 j = false; /* trailing gunk on one end or other */
2616 break;
2618 case PP_IFMACRO:
2620 bool found = false;
2621 MMacro searching, *mmac;
2623 tline = skip_white(tline);
2624 tline = expand_id(tline);
2625 if (!tok_type(tline, TOK_ID)) {
2626 nasm_nonfatal("`%s' expects a macro name", dname);
2627 goto fail;
2629 nasm_zero(searching);
2630 searching.name = dup_text(tline);
2631 searching.casesense = true;
2632 searching.nparam_min = 0;
2633 searching.nparam_max = INT_MAX;
2634 tline = expand_smacro(tline->next);
2635 tline = skip_white(tline);
2636 if (!tline) {
2637 } else if (!tok_type(tline, TOK_NUMBER)) {
2638 nasm_nonfatal("`%s' expects a parameter count or nothing",
2639 dname);
2640 } else {
2641 searching.nparam_min = searching.nparam_max =
2642 read_param_count(tok_text(tline));
2644 if (tline && tok_is(tline->next, '-')) {
2645 tline = tline->next->next;
2646 if (tok_is(tline, '*'))
2647 searching.nparam_max = INT_MAX;
2648 else if (!tok_type(tline, TOK_NUMBER))
2649 nasm_nonfatal("`%s' expects a parameter count after `-'",
2650 dname);
2651 else {
2652 searching.nparam_max = read_param_count(tok_text(tline));
2653 if (searching.nparam_min > searching.nparam_max) {
2654 nasm_nonfatal("minimum parameter count exceeds maximum");
2655 searching.nparam_max = searching.nparam_min;
2659 if (tline && tok_is(tline->next, '+')) {
2660 tline = tline->next;
2661 searching.plus = true;
2663 mmac = (MMacro *) hash_findix(&mmacros, searching.name);
2664 while (mmac) {
2665 if (!strcmp(mmac->name, searching.name) &&
2666 (mmac->nparam_min <= searching.nparam_max
2667 || searching.plus)
2668 && (searching.nparam_min <= mmac->nparam_max
2669 || mmac->plus)) {
2670 found = true;
2671 break;
2673 mmac = mmac->next;
2675 if (tline && tline->next)
2676 nasm_warn(WARN_OTHER, "trailing garbage after %%ifmacro ignored");
2677 nasm_free(searching.name);
2678 j = found;
2679 break;
2682 case PP_IFID:
2683 needtype = TOK_ID;
2684 goto iftype;
2685 case PP_IFNUM:
2686 needtype = TOK_NUMBER;
2687 goto iftype;
2688 case PP_IFSTR:
2689 needtype = TOK_STRING;
2690 goto iftype;
2692 iftype:
2693 t = tline = expand_smacro(tline);
2695 while (tok_white(t) ||
2696 (needtype == TOK_NUMBER && (tok_is(t, '-') | tok_is(t, '+'))))
2697 t = t->next;
2699 j = tok_type(t, needtype);
2700 break;
2702 case PP_IFTOKEN:
2703 tline = expand_smacro(tline);
2704 t = skip_white(tline);
2706 j = false;
2707 if (t) {
2708 t = skip_white(t->next); /* Skip the actual token + whitespace */
2709 j = !t;
2711 break;
2713 case PP_IFEMPTY:
2714 tline = expand_smacro(tline);
2715 t = skip_white(tline);
2716 j = !t; /* Should be empty */
2717 break;
2719 case PP_IF:
2720 pps.tptr = tline = expand_smacro(tline);
2721 pps.ntokens = -1;
2722 tokval.t_type = TOKEN_INVALID;
2723 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
2724 if (!evalresult)
2725 return -1;
2726 if (tokval.t_type)
2727 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
2728 if (!is_simple(evalresult)) {
2729 nasm_nonfatal("non-constant value given to `%s'",
2730 dname);
2731 goto fail;
2733 j = reloc_value(evalresult) != 0;
2734 break;
2736 case PP_IFUSING:
2737 case PP_IFUSABLE:
2739 const struct use_package *pkg;
2740 const char *name;
2742 pkg = get_use_pkg(tline, dname, &name);
2743 if (!name)
2744 goto fail;
2746 j = pkg && ((cond == PP_IFUSABLE) | use_loaded[pkg->index]);
2747 break;
2750 default:
2751 nasm_nonfatal("unknown preprocessor directive `%s'", dname);
2752 goto fail;
2755 free_tlist(origline);
2756 return (j ^ PP_COND_NEGATIVE(ct)) ? COND_IF_TRUE : COND_IF_FALSE;
2758 fail:
2759 free_tlist(origline);
2760 return COND_NEVER;
2764 * Default smacro expansion routine: just returns a copy of the
2765 * expansion list.
2767 static Token *
2768 smacro_expand_default(const SMacro *s, Token **params, int nparams)
2770 (void)params;
2771 (void)nparams;
2773 return dup_tlist(s->expansion, NULL);
2777 * Emit a macro defintion or undef to the listing file, if
2778 * desired. This is similar to detoken(), but it handles the reverse
2779 * expansion list, does not expand %! or local variable tokens, and
2780 * does some special handling for macro parameters.
2782 static void
2783 list_smacro_def(enum preproc_token op, const Context *ctx, const SMacro *m)
2785 Token *t;
2786 size_t namelen, size;
2787 char *def, *p;
2788 char *context_prefix = NULL;
2789 size_t context_len;
2791 namelen = strlen(m->name);
2792 size = namelen + 2; /* Include room for space after name + NUL */
2794 if (ctx) {
2795 int context_depth = cstk->depth - ctx->depth + 1;
2796 context_prefix =
2797 nasm_asprintf("[%s::%"PRIu64"] %%%-*s",
2798 ctx->name ? ctx->name : "",
2799 ctx->number, context_depth, "");
2801 context_len = nasm_last_string_len();
2802 memset(context_prefix + context_len - context_depth,
2803 '$', context_depth);
2804 size += context_len;
2807 list_for_each(t, m->expansion)
2808 size += t->len;
2810 if (m->nparam) {
2812 * Space for ( and either , or ) around each
2813 * parameter, plus up to 4 flags.
2815 int i;
2817 size += 1 + 4 * m->nparam;
2818 for (i = 0; i < m->nparam; i++)
2819 size += m->params[i].name.len;
2822 def = nasm_malloc(size);
2823 p = def+size;
2824 *--p = '\0';
2826 list_for_each(t, m->expansion) {
2827 p -= t->len;
2828 memcpy(p, tok_text(t), t->len);
2831 *--p = ' ';
2833 if (m->nparam) {
2834 int i;
2836 *--p = ')';
2837 for (i = m->nparam-1; i >= 0; i--) {
2838 enum sparmflags flags = m->params[i].flags;
2839 if (flags & SPARM_GREEDY)
2840 *--p = '+';
2841 p -= m->params[i].name.len;
2842 memcpy(p, tok_text(&m->params[i].name), m->params[i].name.len);
2844 if (flags & SPARM_NOSTRIP)
2845 *--p = '!';
2846 if (flags & SPARM_STR)
2847 *--p = '&';
2848 if (flags & SPARM_EVAL)
2849 *--p = '=';
2850 *--p = ',';
2852 *p = '('; /* First parameter starts with ( not , */
2855 p -= namelen;
2856 memcpy(p, m->name, namelen);
2858 if (context_prefix) {
2859 p -= context_len;
2860 memcpy(p, context_prefix, context_len);
2861 nasm_free(context_prefix);
2864 nasm_listmsg("%s %s", pp_directives[op], p);
2865 nasm_free(def);
2869 * Parse smacro arguments, return argument count. If the tmpl argument
2870 * is set, set the nparam, greedy and params field in the template.
2871 * *tpp is updated to point to the pointer to the first token after the
2872 * prototype.
2874 * The text values from any argument tokens are "stolen" and the
2875 * corresponding text fields set to NULL.
2877 static int parse_smacro_template(Token ***tpp, SMacro *tmpl)
2879 int nparam = 0;
2880 enum sparmflags flags;
2881 struct smac_param *params = NULL;
2882 bool err, done;
2883 bool greedy = false;
2884 Token **tn = *tpp;
2885 Token *t = *tn;
2886 Token *name;
2889 * DO NOT skip whitespace here, or we won't be able to distinguish:
2891 * %define foo (a,b) ; no arguments, (a,b) is the expansion
2892 * %define bar(a,b) ; two arguments, empty expansion
2894 * This ambiguity was inherited from C.
2897 if (!tok_is(t, '('))
2898 goto finish;
2900 if (tmpl) {
2901 Token *tx = t;
2902 Token **txpp = &tx;
2903 int sparam;
2905 /* Count parameters first */
2906 sparam = parse_smacro_template(&txpp, NULL);
2907 if (!sparam)
2908 goto finish; /* No parameters, we're done */
2909 nasm_newn(params, sparam);
2912 /* Skip leading paren */
2913 tn = &t->next;
2914 t = *tn;
2916 name = NULL;
2917 flags = 0;
2918 err = done = false;
2920 while (!done) {
2921 if (!t || !t->type) {
2922 if (name || flags)
2923 nasm_nonfatal("`)' expected to terminate macro template");
2924 else
2925 nasm_nonfatal("parameter identifier expected");
2926 break;
2929 switch (t->type) {
2930 case TOK_ID:
2931 if (name)
2932 goto bad;
2933 name = t;
2934 break;
2936 case TOK_OTHER:
2937 if (t->len != 1)
2938 goto bad;
2939 switch (t->text.a[0]) {
2940 case '=':
2941 flags |= SPARM_EVAL;
2942 break;
2943 case '&':
2944 flags |= SPARM_STR;
2945 break;
2946 case '!':
2947 flags |= SPARM_NOSTRIP;
2948 break;
2949 case '+':
2950 flags |= SPARM_GREEDY;
2951 greedy = true;
2952 break;
2953 case ',':
2954 if (greedy)
2955 nasm_nonfatal("greedy parameter must be last");
2956 /* fall through */
2957 case ')':
2958 if (params) {
2959 if (name)
2960 steal_Token(&params[nparam].name, name);
2961 params[nparam].flags = flags;
2963 nparam++;
2964 name = NULL;
2965 flags = 0;
2966 done = t->text.a[0] == ')';
2967 break;
2968 default:
2969 goto bad;
2971 break;
2973 case TOK_WHITESPACE:
2974 break;
2976 default:
2977 bad:
2978 if (!err) {
2979 nasm_nonfatal("garbage `%s' in macro parameter list", tok_text(t));
2980 err = true;
2982 break;
2985 tn = &t->next;
2986 t = *tn;
2989 finish:
2990 while (t && t->type == TOK_WHITESPACE) {
2991 tn = &t->next;
2992 t = t->next;
2994 *tpp = tn;
2995 if (tmpl) {
2996 tmpl->nparam = nparam;
2997 tmpl->greedy = greedy;
2998 tmpl->params = params;
3000 return nparam;
3004 * Common code for defining an smacro. The tmpl argument, if not NULL,
3005 * contains any macro parameters that aren't explicit arguments;
3006 * those are the more uncommon macro variants.
3008 static SMacro *define_smacro(const char *mname, bool casesense,
3009 Token *expansion, SMacro *tmpl)
3011 SMacro *smac, **smhead;
3012 struct hash_table *smtbl;
3013 Context *ctx;
3014 bool defining_alias = false;
3015 unsigned int nparam = 0;
3017 if (tmpl) {
3018 defining_alias = tmpl->alias;
3019 nparam = tmpl->nparam;
3020 if (nparam && !defining_alias)
3021 mark_smac_params(expansion, tmpl, 0);
3024 while (1) {
3025 ctx = get_ctx(mname, &mname);
3027 if (!smacro_defined(ctx, mname, nparam, &smac, casesense, true)) {
3028 /* Create a new macro */
3029 smtbl = ctx ? &ctx->localmac : &smacros;
3030 smhead = (SMacro **) hash_findi_add(smtbl, mname);
3031 nasm_new(smac);
3032 smac->next = *smhead;
3033 *smhead = smac;
3034 break;
3035 } else if (!smac) {
3036 nasm_warn(WARN_OTHER, "single-line macro `%s' defined both with and"
3037 " without parameters", mname);
3039 * Some instances of the old code considered this a failure,
3040 * some others didn't. What is the right thing to do here?
3042 goto fail;
3043 } else if (!smac->alias || ppopt.noaliases || defining_alias) {
3045 * We're redefining, so we have to take over an
3046 * existing SMacro structure. This means freeing
3047 * what was already in it, but not the structure itself.
3049 clear_smacro(smac);
3050 break;
3051 } else if (smac->in_progress) {
3052 nasm_nonfatal("macro alias loop");
3053 goto fail;
3054 } else {
3055 /* It is an alias macro; follow the alias link */
3056 SMacro *s;
3058 smac->in_progress = true;
3059 s = define_smacro(tok_text(smac->expansion), casesense,
3060 expansion, tmpl);
3061 smac->in_progress = false;
3062 return s;
3066 smac->name = nasm_strdup(mname);
3067 smac->casesense = casesense;
3068 smac->expansion = expansion;
3069 smac->expand = smacro_expand_default;
3070 if (tmpl) {
3071 smac->nparam = tmpl->nparam;
3072 smac->params = tmpl->params;
3073 smac->alias = tmpl->alias;
3074 smac->greedy = tmpl->greedy;
3075 if (tmpl->expand)
3076 smac->expand = tmpl->expand;
3078 if (list_option('s')) {
3079 list_smacro_def((smac->alias ? PP_DEFALIAS : PP_DEFINE)
3080 + !casesense, ctx, smac);
3082 return smac;
3084 fail:
3085 free_tlist(expansion);
3086 if (tmpl)
3087 free_smacro_members(tmpl);
3088 return NULL;
3092 * Undefine an smacro
3094 static void undef_smacro(const char *mname, bool undefalias)
3096 SMacro **smhead, *s, **sp;
3097 struct hash_table *smtbl;
3098 Context *ctx;
3100 ctx = get_ctx(mname, &mname);
3101 smtbl = ctx ? &ctx->localmac : &smacros;
3102 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
3104 if (smhead) {
3106 * We now have a macro name... go hunt for it.
3108 sp = smhead;
3109 while ((s = *sp) != NULL) {
3110 if (!mstrcmp(s->name, mname, s->casesense)) {
3111 if (s->alias && !undefalias) {
3112 if (!ppopt.noaliases) {
3113 if (s->in_progress) {
3114 nasm_nonfatal("macro alias loop");
3115 } else {
3116 s->in_progress = true;
3117 undef_smacro(tok_text(s->expansion), false);
3118 s->in_progress = false;
3121 } else {
3122 if (list_option('d'))
3123 list_smacro_def(s->alias ? PP_UNDEFALIAS : PP_UNDEF,
3124 ctx, s);
3125 *sp = s->next;
3126 free_smacro(s);
3127 continue;
3130 sp = &s->next;
3136 * Parse a mmacro specification.
3138 static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
3140 tline = tline->next;
3141 tline = skip_white(tline);
3142 tline = expand_id(tline);
3143 if (!tok_type(tline, TOK_ID)) {
3144 nasm_nonfatal("`%s' expects a macro name", directive);
3145 return false;
3148 #if 0
3149 def->prev = NULL;
3150 #endif
3151 def->name = dup_text(tline);
3152 def->plus = false;
3153 def->nolist = 0;
3154 def->nparam_min = 0;
3155 def->nparam_max = 0;
3157 tline = expand_smacro(tline->next);
3158 tline = skip_white(tline);
3159 if (!tok_type(tline, TOK_NUMBER))
3160 nasm_nonfatal("`%s' expects a parameter count", directive);
3161 else
3162 def->nparam_min = def->nparam_max = read_param_count(tok_text(tline));
3163 if (tline && tok_is(tline->next, '-')) {
3164 tline = tline->next->next;
3165 if (tok_is(tline, '*')) {
3166 def->nparam_max = INT_MAX;
3167 } else if (!tok_type(tline, TOK_NUMBER)) {
3168 nasm_nonfatal("`%s' expects a parameter count after `-'", directive);
3169 } else {
3170 def->nparam_max = read_param_count(tok_text(tline));
3171 if (def->nparam_min > def->nparam_max) {
3172 nasm_nonfatal("minimum parameter count exceeds maximum");
3173 def->nparam_max = def->nparam_min;
3177 if (tline && tok_is(tline->next, '+')) {
3178 tline = tline->next;
3179 def->plus = true;
3181 if (tline && tok_type(tline->next, TOK_ID) &&
3182 tline->next->len == 7 &&
3183 !nasm_stricmp(tline->next->text.a, ".nolist")) {
3184 tline = tline->next;
3185 if (!list_option('f'))
3186 def->nolist |= NL_LIST|NL_LINE;
3190 * Handle default parameters.
3192 def->ndefs = 0;
3193 if (tline && tline->next) {
3194 Token **comma;
3195 def->dlist = tline->next;
3196 tline->next = NULL;
3197 comma = count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
3198 if (!ppopt.sane_empty_expansion && comma) {
3199 *comma = NULL;
3200 def->ndefs--;
3201 nasm_warn(WARN_MACRO_PARAMS_LEGACY,
3202 "dropping trailing empty default parameter in defintion of multi-line macro `%s'",
3203 def->name);
3205 } else {
3206 def->dlist = NULL;
3207 def->defaults = NULL;
3209 def->expansion = NULL;
3211 if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
3212 !def->plus) {
3214 *!macro-defaults [on] macros with more default than optional parameters
3215 *! warns when a macro has more default parameters than optional parameters.
3216 *! See \k{mlmacdef} for why might want to disable this warning.
3218 nasm_warn(WARN_MACRO_DEFAULTS,
3219 "too many default macro parameters in macro `%s'", def->name);
3222 return true;
3227 * Decode a size directive
3229 static int parse_size(const char *str) {
3230 static const char *size_names[] =
3231 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
3232 static const int sizes[] =
3233 { 0, 1, 4, 16, 8, 10, 2, 32 };
3234 return str ? sizes[bsii(str, size_names, ARRAY_SIZE(size_names))+1] : 0;
3238 * Process a preprocessor %pragma directive. Currently there are none.
3239 * Gets passed the token list starting with the "preproc" token from
3240 * "%pragma preproc".
3242 static void do_pragma_preproc(Token *tline)
3244 const char *txt;
3246 /* Skip to the real stuff */
3247 tline = tline->next;
3248 tline = skip_white(tline);
3250 if (!tok_type(tline, TOK_ID))
3251 return;
3253 txt = tok_text(tline);
3254 if (!nasm_stricmp(txt, "sane_empty_expansion")) {
3255 tline = skip_white(tline->next);
3256 ppopt.sane_empty_expansion =
3257 pp_get_boolean_option(tline, ppopt.sane_empty_expansion);
3258 } else {
3259 /* Unknown pragma, ignore for now */
3263 static bool is_macro_id(const Token *t)
3265 return tok_type(t, TOK_ID) || tok_type(t, TOK_LOCAL_MACRO);
3268 static const char *get_id(Token **tp, const char *dname)
3270 const char *id;
3271 Token *t = *tp;
3273 t = t->next; /* Skip directive */
3274 t = skip_white(t);
3275 t = expand_id(t);
3277 if (!is_macro_id(t)) {
3278 nasm_nonfatal("`%s' expects a macro identifier", dname);
3279 return NULL;
3282 id = tok_text(t);
3283 t = skip_white(t);
3284 *tp = t;
3285 return id;
3288 /* Parse a %use package name and find the package. Set *err on syntax error. */
3289 static const struct use_package *
3290 get_use_pkg(Token *t, const char *dname, const char **name)
3292 const char *id;
3294 t = skip_white(t);
3295 t = expand_smacro(t);
3297 *name = NULL;
3299 if (!t) {
3300 nasm_nonfatal("`%s' expects a package name, got end of line", dname);
3301 return NULL;
3302 } else if (t->type != TOK_ID && t->type != TOK_STRING) {
3303 nasm_nonfatal("`%s' expects a package name, got `%s'",
3304 dname, tok_text(t));
3305 return NULL;
3308 *name = id = unquote_token(t);
3310 t = t->next;
3311 t = skip_white(t);
3312 if (t)
3313 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
3315 return nasm_find_use_package(id);
3319 * Mark parameter tokens in an smacro definition. If the type argument
3320 * is 0, create smac param tokens, otherwise use the type specified;
3321 * normally this is used for TOK_XDEF_PARAM, which is used to protect
3322 * parameter tokens during expansion during %xdefine.
3324 * tmpl may not be NULL here.
3326 static void mark_smac_params(Token *tline, const SMacro *tmpl,
3327 enum pp_token_type type)
3329 const struct smac_param *params = tmpl->params;
3330 int nparam = tmpl->nparam;
3331 Token *t;
3332 int i;
3334 list_for_each(t, tline) {
3335 if (t->type != TOK_ID && t->type != TOK_XDEF_PARAM)
3336 continue;
3338 for (i = 0; i < nparam; i++) {
3339 if (tok_text_match(t, &params[i].name))
3340 t->type = type ? type : tok_smac_param(i);
3346 * %clear selected macro sets either globally or in contexts
3348 static void do_clear(enum clear_what what, bool context)
3350 if (context) {
3351 if (what & CLEAR_ALLDEFINE) {
3352 Context *ctx;
3353 list_for_each(ctx, cstk)
3354 clear_smacro_table(&ctx->localmac, what);
3356 /* Nothing else can be context-local */
3357 } else {
3358 if (what & CLEAR_ALLDEFINE)
3359 clear_smacro_table(&smacros, what);
3360 if (what & CLEAR_MMACRO)
3361 free_mmacro_table(&mmacros);
3366 * find and process preprocessor directive in passed line
3367 * Find out if a line contains a preprocessor directive, and deal
3368 * with it if so.
3370 * If a directive _is_ found, it is the responsibility of this routine
3371 * (and not the caller) to free_tlist() the line.
3373 * @param tline a pointer to the current tokeninzed line linked list
3374 * @param output if this directive generated output
3375 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
3378 static int do_directive(Token *tline, Token **output)
3380 enum preproc_token op;
3381 int j;
3382 bool err;
3383 enum nolist_flags nolist;
3384 bool casesense;
3385 int k, m;
3386 int offset;
3387 const char *p;
3388 char *q, *qbuf;
3389 const char *found_path;
3390 const char *mname;
3391 struct ppscan pps;
3392 Include *inc;
3393 Context *ctx;
3394 Cond *cond;
3395 MMacro *mmac, **mmhead;
3396 Token *t = NULL, *tt, *macro_start, *last, *origline;
3397 Line *l;
3398 struct tokenval tokval;
3399 expr *evalresult;
3400 int64_t count;
3401 size_t len;
3402 errflags severity;
3403 const char *dname; /* Name of directive, for messages */
3405 *output = NULL; /* No output generated */
3406 origline = tline;
3408 tline = skip_white(tline);
3409 if (!tline || !tok_type(tline, TOK_PREPROC_ID))
3410 return NO_DIRECTIVE_FOUND;
3412 dname = tok_text(tline);
3413 if (dname[1] == '%')
3414 return NO_DIRECTIVE_FOUND;
3416 op = pp_token_hash(dname);
3418 casesense = true;
3419 if (PP_HAS_CASE(op) & PP_INSENSITIVE(op)) {
3420 casesense = false;
3421 op--;
3425 * %line directives are always processed immediately and
3426 * unconditionally, as they are intended to reflect position
3427 * in externally preprocessed sources.
3429 if (op == PP_LINE) {
3431 * Syntax is `%line nnn[+mmm] [filename]'
3433 if (pp_noline || istk->mstk.mstk)
3434 goto done;
3436 tline = tline->next;
3437 tline = skip_white(tline);
3438 if (!tok_type(tline, TOK_NUMBER)) {
3439 nasm_nonfatal("`%s' expects line number", dname);
3440 goto done;
3442 k = readnum(tok_text(tline), &err);
3443 m = 1;
3444 tline = tline->next;
3445 if (tok_is(tline, '+') || tok_is(tline, '-')) {
3446 bool minus = tok_is(tline, '-');
3447 tline = tline->next;
3448 if (!tok_type(tline, TOK_NUMBER)) {
3449 nasm_nonfatal("`%s' expects line increment", dname);
3450 goto done;
3452 m = readnum(tok_text(tline), &err);
3453 if (minus)
3454 m = -m;
3455 tline = tline->next;
3457 tline = skip_white(tline);
3458 if (tline) {
3459 if (tline->type == TOK_STRING) {
3460 src_set_fname(unquote_token(tline));
3461 } else {
3462 char *fname = detoken(tline, false);
3463 src_set_fname(fname);
3464 nasm_free(fname);
3467 src_set_linnum(k);
3469 istk->where = src_where();
3470 istk->lineinc = m;
3471 goto done;
3475 * If we're in a non-emitting branch of a condition construct,
3476 * or walking to the end of an already terminated %rep block,
3477 * we should ignore all directives except for condition
3478 * directives.
3480 if (((istk->conds && !emitting(istk->conds->state)) ||
3481 (istk->mstk.mstk && !istk->mstk.mstk->in_progress)) &&
3482 !is_condition(op)) {
3483 return NO_DIRECTIVE_FOUND;
3487 * If we're defining a macro or reading a %rep block, we should
3488 * ignore all directives except for %macro/%imacro (which nest),
3489 * %endm/%endmacro, %line and (only if we're in a %rep block) %endrep.
3490 * If we're in a %rep block, another %rep nests, so should be let through.
3492 if (defining && op != PP_MACRO && op != PP_RMACRO &&
3493 op != PP_ENDMACRO && op != PP_ENDM &&
3494 (defining->name || (op != PP_ENDREP && op != PP_REP))) {
3495 return NO_DIRECTIVE_FOUND;
3498 if (defining) {
3499 if (op == PP_MACRO || op == PP_RMACRO) {
3500 nested_mac_count++;
3501 return NO_DIRECTIVE_FOUND;
3502 } else if (nested_mac_count > 0) {
3503 if (op == PP_ENDMACRO) {
3504 nested_mac_count--;
3505 return NO_DIRECTIVE_FOUND;
3508 if (!defining->name) {
3509 if (op == PP_REP) {
3510 nested_rep_count++;
3511 return NO_DIRECTIVE_FOUND;
3512 } else if (nested_rep_count > 0) {
3513 if (op == PP_ENDREP) {
3514 nested_rep_count--;
3515 return NO_DIRECTIVE_FOUND;
3521 switch (op) {
3522 default:
3523 nasm_nonfatal("unknown preprocessor directive `%s'", dname);
3524 return NO_DIRECTIVE_FOUND; /* didn't get it */
3526 case PP_PRAGMA:
3528 * %pragma namespace options...
3530 * The namespace "preproc" is reserved for the preprocessor;
3531 * all other namespaces generate a [pragma] assembly directive.
3533 * Invalid %pragmas are ignored and may have different
3534 * meaning in future versions of NASM.
3536 t = tline;
3537 tline = tline->next;
3538 t->next = NULL;
3539 tline = zap_white(expand_smacro(tline));
3540 if (tok_type(tline, TOK_ID)) {
3541 if (!nasm_stricmp(tok_text(tline), "preproc")) {
3542 /* Preprocessor pragma */
3543 do_pragma_preproc(tline);
3544 free_tlist(tline);
3545 } else {
3546 /* Build the assembler directive */
3548 /* Append bracket to the end of the output */
3549 for (t = tline; t->next; t = t->next)
3551 t->next = make_tok_char(NULL, ']');
3553 /* Prepend "[pragma " */
3554 t = new_White(tline);
3555 t = new_Token(t, TOK_ID, "pragma", 6);
3556 t = make_tok_char(t, '[');
3557 tline = t;
3558 *output = tline;
3561 break;
3563 case PP_STACKSIZE:
3564 /* Directive to tell NASM what the default stack size is. The
3565 * default is for a 16-bit stack, and this can be overriden with
3566 * %stacksize large.
3568 tline = skip_white(tline->next);
3569 if (!tline || tline->type != TOK_ID) {
3570 nasm_nonfatal("`%s' missing size parameter", dname);
3572 if (nasm_stricmp(tok_text(tline), "flat") == 0) {
3573 /* All subsequent ARG directives are for a 32-bit stack */
3574 StackSize = 4;
3575 StackPointer = "ebp";
3576 ArgOffset = 8;
3577 LocalOffset = 0;
3578 } else if (nasm_stricmp(tok_text(tline), "flat64") == 0) {
3579 /* All subsequent ARG directives are for a 64-bit stack */
3580 StackSize = 8;
3581 StackPointer = "rbp";
3582 ArgOffset = 16;
3583 LocalOffset = 0;
3584 } else if (nasm_stricmp(tok_text(tline), "large") == 0) {
3585 /* All subsequent ARG directives are for a 16-bit stack,
3586 * far function call.
3588 StackSize = 2;
3589 StackPointer = "bp";
3590 ArgOffset = 4;
3591 LocalOffset = 0;
3592 } else if (nasm_stricmp(tok_text(tline), "small") == 0) {
3593 /* All subsequent ARG directives are for a 16-bit stack,
3594 * far function call. We don't support near functions.
3596 StackSize = 2;
3597 StackPointer = "bp";
3598 ArgOffset = 6;
3599 LocalOffset = 0;
3600 } else {
3601 nasm_nonfatal("`%s' invalid size type", dname);
3603 break;
3605 case PP_ARG:
3606 /* TASM like ARG directive to define arguments to functions, in
3607 * the following form:
3609 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
3611 offset = ArgOffset;
3612 do {
3613 const char *arg;
3614 char directive[256];
3615 int size = StackSize;
3617 /* Find the argument name */
3618 tline = skip_white(tline->next);
3619 if (!tline || tline->type != TOK_ID) {
3620 nasm_nonfatal("`%s' missing argument parameter", dname);
3621 goto done;
3623 arg = tok_text(tline);
3625 /* Find the argument size type */
3626 tline = tline->next;
3627 if (!tok_is(tline, ':')) {
3628 nasm_nonfatal("syntax error processing `%s' directive", dname);
3629 goto done;
3631 tline = tline->next;
3632 if (!tok_type(tline, TOK_ID)) {
3633 nasm_nonfatal("`%s' missing size type parameter", dname);
3634 goto done;
3637 /* Allow macro expansion of type parameter */
3638 tt = tokenize(tok_text(tline));
3639 tt = expand_smacro(tt);
3640 size = parse_size(tok_text(tt));
3641 if (!size) {
3642 nasm_nonfatal("invalid size type for `%s' missing directive", dname);
3643 free_tlist(tt);
3644 goto done;
3646 free_tlist(tt);
3648 /* Round up to even stack slots */
3649 size = ALIGN(size, StackSize);
3651 /* Now define the macro for the argument */
3652 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
3653 arg, StackPointer, offset);
3654 do_directive(tokenize(directive), output);
3655 offset += size;
3657 /* Move to the next argument in the list */
3658 tline = skip_white(tline->next);
3659 } while (tok_is(tline, ','));
3660 ArgOffset = offset;
3661 break;
3663 case PP_LOCAL:
3664 /* TASM like LOCAL directive to define local variables for a
3665 * function, in the following form:
3667 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
3669 * The '= LocalSize' at the end is ignored by NASM, but is
3670 * required by TASM to define the local parameter size (and used
3671 * by the TASM macro package).
3673 offset = LocalOffset;
3674 do {
3675 const char *local;
3676 char directive[256];
3677 int size = StackSize;
3679 /* Find the argument name */
3680 tline = skip_white(tline->next);
3681 if (!tline || tline->type != TOK_ID) {
3682 nasm_nonfatal("`%s' missing argument parameter", dname);
3683 goto done;
3685 local = tok_text(tline);
3687 /* Find the argument size type */
3688 tline = tline->next;
3689 if (!tok_is(tline, ':')) {
3690 nasm_nonfatal("syntax error processing `%s' directive", dname);
3691 goto done;
3693 tline = tline->next;
3694 if (!tok_type(tline, TOK_ID)) {
3695 nasm_nonfatal("`%s' missing size type parameter", dname);
3696 goto done;
3699 /* Allow macro expansion of type parameter */
3700 tt = tokenize(tok_text(tline));
3701 tt = expand_smacro(tt);
3702 size = parse_size(tok_text(tt));
3703 if (!size) {
3704 nasm_nonfatal("invalid size type for `%s' missing directive", dname);
3705 free_tlist(tt);
3706 goto done;
3708 free_tlist(tt);
3710 /* Round up to even stack slots */
3711 size = ALIGN(size, StackSize);
3713 offset += size; /* Negative offset, increment before */
3715 /* Now define the macro for the argument */
3716 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
3717 local, StackPointer, offset);
3718 do_directive(tokenize(directive), output);
3720 /* Now define the assign to setup the enter_c macro correctly */
3721 snprintf(directive, sizeof(directive),
3722 "%%assign %%$localsize %%$localsize+%d", size);
3723 do_directive(tokenize(directive), output);
3725 /* Move to the next argument in the list */
3726 tline = skip_white(tline->next);
3727 } while (tok_is(tline, ','));
3728 LocalOffset = offset;
3729 break;
3731 case PP_CLEAR:
3733 bool context = false;
3735 t = tline->next = expand_smacro(tline->next);
3736 t = skip_white(t);
3737 if (!t) {
3738 /* Emulate legacy behavior */
3739 do_clear(CLEAR_DEFINE|CLEAR_MMACRO, false);
3740 } else {
3741 while ((t = skip_white(t)) && t->type == TOK_ID) {
3742 const char *txt = tok_text(t);
3743 if (!nasm_stricmp(txt, "all")) {
3744 do_clear(CLEAR_ALL, context);
3745 } else if (!nasm_stricmp(txt, "define") ||
3746 !nasm_stricmp(txt, "def") ||
3747 !nasm_stricmp(txt, "smacro")) {
3748 do_clear(CLEAR_DEFINE, context);
3749 } else if (!nasm_stricmp(txt, "defalias") ||
3750 !nasm_stricmp(txt, "alias") ||
3751 !nasm_stricmp(txt, "salias")) {
3752 do_clear(CLEAR_DEFALIAS, context);
3753 } else if (!nasm_stricmp(txt, "alldef") ||
3754 !nasm_stricmp(txt, "alldefine")) {
3755 do_clear(CLEAR_ALLDEFINE, context);
3756 } else if (!nasm_stricmp(txt, "macro") ||
3757 !nasm_stricmp(txt, "mmacro")) {
3758 do_clear(CLEAR_MMACRO, context);
3759 } else if (!nasm_stricmp(txt, "context") ||
3760 !nasm_stricmp(txt, "ctx")) {
3761 context = true;
3762 } else if (!nasm_stricmp(txt, "global")) {
3763 context = false;
3764 } else if (!nasm_stricmp(txt, "nothing") ||
3765 !nasm_stricmp(txt, "none") ||
3766 !nasm_stricmp(txt, "ignore") ||
3767 !nasm_stricmp(txt, "-") ||
3768 !nasm_stricmp(txt, "--")) {
3769 /* Do nothing */
3770 } else {
3771 nasm_nonfatal("invalid option to %s: %s", dname, txt);
3772 t = NULL;
3777 t = skip_white(t);
3778 if (t)
3779 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
3780 break;
3783 case PP_DEPEND:
3784 t = tline->next = expand_smacro(tline->next);
3785 t = skip_white(t);
3786 if (!t || (t->type != TOK_STRING &&
3787 t->type != TOK_INTERNAL_STRING)) {
3788 nasm_nonfatal("`%s' expects a file name", dname);
3789 goto done;
3791 if (t->next)
3792 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
3794 strlist_add(deplist, unquote_token_cstr(t));
3795 goto done;
3797 case PP_INCLUDE:
3798 t = tline->next = expand_smacro(tline->next);
3799 t = skip_white(t);
3801 if (!t || (t->type != TOK_STRING &&
3802 t->type != TOK_INTERNAL_STRING)) {
3803 nasm_nonfatal("`%s' expects a file name", dname);
3804 goto done;
3806 if (t->next)
3807 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
3808 p = unquote_token_cstr(t);
3809 nasm_new(inc);
3810 inc->next = istk;
3811 found_path = NULL;
3812 inc->fp = inc_fopen(p, deplist, &found_path,
3813 (pp_mode == PP_DEPS)
3814 ? INC_OPTIONAL : INC_NEEDED, NF_TEXT);
3815 if (!inc->fp) {
3816 /* -MG given but file not found */
3817 nasm_free(inc);
3818 } else {
3819 inc->where = src_where();
3820 inc->lineinc = 1;
3821 inc->nolist = istk->nolist;
3822 inc->noline = istk->noline;
3823 if (!inc->noline)
3824 src_set(0, found_path ? found_path : p);
3825 istk = inc;
3826 lfmt->uplevel(LIST_INCLUDE, 0);
3828 break;
3830 case PP_USE:
3832 const struct use_package *pkg;
3833 const char *name;
3835 pkg = get_use_pkg(tline->next, dname, &name);
3836 if (!name)
3837 goto done;
3838 if (!pkg) {
3839 nasm_nonfatal("unknown `%s' package: `%s'", dname, name);
3840 } else if (!use_loaded[pkg->index]) {
3842 * Not already included, go ahead and include it.
3843 * Treat it as an include file for the purpose of
3844 * producing a listing.
3846 use_loaded[pkg->index] = true;
3847 stdmacpos = pkg->macros;
3848 nasm_new(inc);
3849 inc->next = istk;
3850 inc->nolist = istk->nolist + !list_option('b');
3851 inc->noline = istk->noline;
3852 if (!inc->noline)
3853 src_set(0, NULL);
3854 istk = inc;
3855 lfmt->uplevel(LIST_INCLUDE, 0);
3857 break;
3859 case PP_PUSH:
3860 case PP_REPL:
3861 case PP_POP:
3862 tline = tline->next;
3863 tline = skip_white(tline);
3864 tline = expand_id(tline);
3865 if (tline) {
3866 if (!tok_type(tline, TOK_ID)) {
3867 nasm_nonfatal("`%s' expects a context identifier", dname);
3868 goto done;
3870 if (tline->next)
3871 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored",
3872 dname);
3873 p = tok_text(tline);
3874 } else {
3875 p = NULL; /* Anonymous */
3878 if (op == PP_PUSH) {
3879 nasm_new(ctx);
3880 ctx->depth = cstk ? cstk->depth + 1 : 1;
3881 ctx->next = cstk;
3882 ctx->name = p ? nasm_strdup(p) : NULL;
3883 ctx->number = unique++;
3884 cstk = ctx;
3885 } else {
3886 /* %pop or %repl */
3887 if (!cstk) {
3888 nasm_nonfatal("`%s': context stack is empty", dname);
3889 } else if (op == PP_POP) {
3890 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
3891 nasm_nonfatal("`%s' in wrong context: %s, "
3892 "expected %s",
3893 dname, cstk->name ? cstk->name : "anonymous", p);
3894 else
3895 ctx_pop();
3896 } else {
3897 /* op == PP_REPL */
3898 nasm_free((char *)cstk->name);
3899 cstk->name = p ? nasm_strdup(p) : NULL;
3900 p = NULL;
3903 break;
3904 case PP_FATAL:
3905 severity = ERR_FATAL;
3906 goto issue_error;
3907 case PP_ERROR:
3908 severity = ERR_NONFATAL|ERR_PASS2;
3909 goto issue_error;
3910 case PP_WARNING:
3912 *!user [on] %warning directives
3913 *! controls output of \c{%warning} directives (see \k{pperror}).
3915 severity = ERR_WARNING|WARN_USER|ERR_PASS2;
3916 goto issue_error;
3918 issue_error:
3920 /* Only error out if this is the final pass */
3921 tline->next = expand_smacro(tline->next);
3922 tline = tline->next;
3923 tline = skip_white(tline);
3924 t = tline ? tline->next : NULL;
3925 t = skip_white(t);
3926 if (tok_type(tline, TOK_STRING) && !t) {
3927 /* The line contains only a quoted string */
3928 p = unquote_token(tline); /* Ignore NUL character truncation */
3929 nasm_error(severity, "%s", p);
3930 } else {
3931 /* Not a quoted string, or more than a quoted string */
3932 q = detoken(tline, false);
3933 nasm_error(severity, "%s", q);
3934 nasm_free(q);
3936 break;
3939 CASE_PP_IF:
3940 if (istk->conds && !emitting(istk->conds->state))
3941 j = COND_NEVER;
3942 else {
3943 j = if_condition(tline->next, op);
3944 tline->next = NULL; /* it got freed */
3946 cond = nasm_malloc(sizeof(Cond));
3947 cond->next = istk->conds;
3948 cond->state = j;
3949 istk->conds = cond;
3950 if(istk->mstk.mstk)
3951 istk->mstk.mstk->condcnt++;
3952 break;
3954 CASE_PP_ELIF:
3955 if (!istk->conds)
3956 nasm_fatal("`%s': no matching `%%if'", dname);
3957 switch(istk->conds->state) {
3958 case COND_IF_TRUE:
3959 istk->conds->state = COND_DONE;
3960 break;
3962 case COND_DONE:
3963 case COND_NEVER:
3964 break;
3966 case COND_ELSE_TRUE:
3967 case COND_ELSE_FALSE:
3968 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
3969 "`%%elif' after `%%else' ignored");
3970 istk->conds->state = COND_NEVER;
3971 break;
3973 case COND_IF_FALSE:
3975 * IMPORTANT: In the case of %if, we will already have
3976 * called expand_mmac_params(); however, if we're
3977 * processing an %elif we must have been in a
3978 * non-emitting mode, which would have inhibited
3979 * the normal invocation of expand_mmac_params().
3980 * Therefore, we have to do it explicitly here.
3982 j = if_condition(expand_mmac_params(tline->next), op);
3983 tline->next = NULL; /* it got freed */
3984 istk->conds->state = j;
3985 break;
3987 break;
3989 case PP_ELSE:
3990 if (tline->next)
3991 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
3992 "trailing garbage after `%%else' ignored");
3993 if (!istk->conds)
3994 nasm_fatal("`%%else: no matching `%%if'");
3995 switch(istk->conds->state) {
3996 case COND_IF_TRUE:
3997 case COND_DONE:
3998 istk->conds->state = COND_ELSE_FALSE;
3999 break;
4001 case COND_NEVER:
4002 break;
4004 case COND_IF_FALSE:
4005 istk->conds->state = COND_ELSE_TRUE;
4006 break;
4008 case COND_ELSE_TRUE:
4009 case COND_ELSE_FALSE:
4010 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
4011 "`%%else' after `%%else' ignored.");
4012 istk->conds->state = COND_NEVER;
4013 break;
4015 break;
4017 case PP_ENDIF:
4018 if (tline->next)
4019 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
4020 "trailing garbage after `%%endif' ignored");
4021 if (!istk->conds)
4022 nasm_fatal("`%%endif': no matching `%%if'");
4023 cond = istk->conds;
4024 istk->conds = cond->next;
4025 nasm_free(cond);
4026 if(istk->mstk.mstk)
4027 istk->mstk.mstk->condcnt--;
4028 break;
4030 case PP_RMACRO:
4031 case PP_MACRO:
4033 MMacro *def;
4035 nasm_assert(!defining);
4036 nasm_new(def);
4037 def->casesense = casesense;
4038 def->dstk.mmac = defining;
4039 if (op == PP_RMACRO)
4040 def->max_depth = nasm_limit[LIMIT_MACRO_LEVELS];
4041 if (!parse_mmacro_spec(tline, def, dname)) {
4042 nasm_free(def);
4043 goto done;
4046 defining = def;
4047 defining->where = istk->where;
4049 mmac = (MMacro *) hash_findix(&mmacros, defining->name);
4050 while (mmac) {
4051 if (!strcmp(mmac->name, defining->name) &&
4052 (mmac->nparam_min <= defining->nparam_max
4053 || defining->plus)
4054 && (defining->nparam_min <= mmac->nparam_max
4055 || mmac->plus)) {
4056 nasm_warn(WARN_OTHER, "redefining multi-line macro `%s'",
4057 defining->name);
4058 break;
4060 mmac = mmac->next;
4062 break;
4065 case PP_ENDM:
4066 case PP_ENDMACRO:
4067 if (!(defining && defining->name)) {
4068 nasm_nonfatal("`%s': not defining a macro", tok_text(tline));
4069 goto done;
4071 mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
4072 defining->next = *mmhead;
4073 *mmhead = defining;
4074 defining = NULL;
4075 break;
4077 case PP_EXITMACRO:
4079 * We must search along istk->expansion until we hit a
4080 * macro-end marker for a macro with a name. Then we
4081 * bypass all lines between exitmacro and endmacro.
4083 list_for_each(l, istk->expansion)
4084 if (l->finishes && l->finishes->name)
4085 break;
4087 if (l) {
4089 * Remove all conditional entries relative to this
4090 * macro invocation. (safe to do in this context)
4092 for ( ; l->finishes->condcnt > 0; l->finishes->condcnt --) {
4093 cond = istk->conds;
4094 istk->conds = cond->next;
4095 nasm_free(cond);
4097 istk->expansion = l;
4098 } else {
4099 nasm_nonfatal("`%%exitmacro' not within `%%macro' block");
4101 break;
4103 case PP_UNIMACRO:
4104 casesense = false;
4105 /* fall through */
4106 case PP_UNMACRO:
4108 MMacro **mmac_p;
4109 MMacro spec;
4111 nasm_zero(spec);
4112 spec.casesense = casesense;
4113 if (!parse_mmacro_spec(tline, &spec, dname)) {
4114 goto done;
4116 mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
4117 while (mmac_p && *mmac_p) {
4118 mmac = *mmac_p;
4119 if (mmac->casesense == spec.casesense &&
4120 !mstrcmp(mmac->name, spec.name, spec.casesense) &&
4121 mmac->nparam_min == spec.nparam_min &&
4122 mmac->nparam_max == spec.nparam_max &&
4123 mmac->plus == spec.plus) {
4124 *mmac_p = mmac->next;
4125 free_mmacro(mmac);
4126 } else {
4127 mmac_p = &mmac->next;
4130 free_tlist(spec.dlist);
4131 break;
4134 case PP_ROTATE:
4135 while (tok_white(tline->next))
4136 tline = tline->next;
4137 if (!tline->next) {
4138 free_tlist(origline);
4139 nasm_nonfatal("`%%rotate' missing rotate count");
4140 return DIRECTIVE_FOUND;
4142 t = expand_smacro(tline->next);
4143 tline->next = NULL;
4144 pps.tptr = tline = t;
4145 pps.ntokens = -1;
4146 tokval.t_type = TOKEN_INVALID;
4147 evalresult =
4148 evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
4149 free_tlist(tline);
4150 if (!evalresult)
4151 return DIRECTIVE_FOUND;
4152 if (tokval.t_type)
4153 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
4154 if (!is_simple(evalresult)) {
4155 nasm_nonfatal("non-constant value given to `%%rotate'");
4156 return DIRECTIVE_FOUND;
4158 mmac = istk->mstk.mmac;
4159 if (!mmac) {
4160 nasm_nonfatal("`%%rotate' invoked outside a macro call");
4161 } else if (mmac->nparam == 0) {
4162 nasm_nonfatal("`%%rotate' invoked within macro without parameters");
4163 } else {
4164 int rotate = mmac->rotate + reloc_value(evalresult);
4166 rotate %= (int)mmac->nparam;
4167 if (rotate < 0)
4168 rotate += mmac->nparam;
4170 mmac->rotate = rotate;
4172 break;
4174 case PP_REP:
4176 MMacro *tmp_defining;
4178 nolist = 0;
4179 tline = skip_white(tline->next);
4180 if (tok_type(tline, TOK_ID) && tline->len == 7 &&
4181 !nasm_memicmp(tline->text.a, ".nolist", 7)) {
4182 if (!list_option('f'))
4183 nolist |= NL_LIST; /* ... but update line numbers */
4184 tline = skip_white(tline->next);
4187 if (tline) {
4188 pps.tptr = expand_smacro(tline);
4189 pps.ntokens = -1;
4190 tokval.t_type = TOKEN_INVALID;
4191 /* XXX: really critical?! */
4192 evalresult =
4193 evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
4194 if (!evalresult)
4195 goto done;
4196 if (tokval.t_type)
4197 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
4198 if (!is_simple(evalresult)) {
4199 nasm_nonfatal("non-constant value given to `%%rep'");
4200 goto done;
4202 count = reloc_value(evalresult);
4203 if (count > nasm_limit[LIMIT_REP]) {
4204 nasm_nonfatal("`%%rep' count %"PRId64" exceeds limit (currently %"PRId64")",
4205 count, nasm_limit[LIMIT_REP]);
4206 count = 0;
4207 } else if (count < 0) {
4209 *!negative-rep [on] regative %rep count
4210 *! warns about negative counts given to the \c{%rep}
4211 *! preprocessor directive.
4213 nasm_warn(ERR_PASS2|WARN_NEGATIVE_REP,
4214 "negative `%%rep' count: %"PRId64, count);
4215 count = 0;
4216 } else {
4217 count++;
4219 } else {
4220 nasm_nonfatal("`%%rep' expects a repeat count");
4221 count = 0;
4223 tmp_defining = defining;
4224 nasm_new(defining);
4225 defining->nolist = nolist;
4226 defining->in_progress = count;
4227 defining->mstk = istk->mstk;
4228 defining->dstk.mstk = tmp_defining;
4229 defining->dstk.mmac = tmp_defining ? tmp_defining->dstk.mmac : NULL;
4230 defining->where = istk->where;
4231 break;
4234 case PP_ENDREP:
4235 if (!defining || defining->name) {
4236 nasm_nonfatal("`%%endrep': no matching `%%rep'");
4237 goto done;
4241 * Now we have a "macro" defined - although it has no name
4242 * and we won't be entering it in the hash tables - we must
4243 * push a macro-end marker for it on to istk->expansion.
4244 * After that, it will take care of propagating itself (a
4245 * macro-end marker line for a macro which is really a %rep
4246 * block will cause the macro to be re-expanded, complete
4247 * with another macro-end marker to ensure the process
4248 * continues) until the whole expansion is forcibly removed
4249 * from istk->expansion by a %exitrep.
4251 nasm_new(l);
4252 l->next = istk->expansion;
4253 l->finishes = defining;
4254 l->first = NULL;
4255 l->where = src_where();
4256 istk->expansion = l;
4258 istk->mstk.mstk = defining;
4260 /* A loop does not change istk->noline */
4261 istk->nolist += !!(defining->nolist & NL_LIST);
4262 if (!istk->nolist)
4263 lfmt->uplevel(LIST_MACRO, 0);
4265 defining = defining->dstk.mstk;
4266 break;
4268 case PP_EXITREP:
4270 * We must search along istk->expansion until we hit a
4271 * macro-end marker for a macro with no name. Then we set
4272 * its `in_progress' flag to 0.
4274 list_for_each(l, istk->expansion)
4275 if (l->finishes && !l->finishes->name)
4276 break;
4278 if (l)
4279 l->finishes->in_progress = 0;
4280 else
4281 nasm_nonfatal("`%%exitrep' not within `%%rep' block");
4282 break;
4284 case PP_DEFINE:
4285 case PP_XDEFINE:
4286 case PP_DEFALIAS:
4288 SMacro tmpl;
4289 Token **lastp;
4290 int nparam;
4292 if (!(mname = get_id(&tline, dname)))
4293 goto done;
4295 nasm_zero(tmpl);
4296 lastp = &tline->next;
4297 nparam = parse_smacro_template(&lastp, &tmpl);
4298 tline = *lastp;
4299 *lastp = NULL;
4301 if (unlikely(op == PP_DEFALIAS)) {
4302 macro_start = tline;
4303 if (!is_macro_id(macro_start)) {
4304 nasm_nonfatal("`%s' expects a macro identifier to alias",
4305 dname);
4306 goto done;
4308 tt = macro_start->next;
4309 macro_start->next = NULL;
4310 tline = tline->next;
4311 tline = skip_white(tline);
4312 if (tline && tline->type) {
4313 nasm_warn(WARN_OTHER,
4314 "trailing garbage after aliasing identifier ignored");
4316 free_tlist(tt);
4317 tmpl.alias = true;
4318 } else {
4319 if (op == PP_XDEFINE) {
4320 /* Protect macro parameter tokens */
4321 if (nparam)
4322 mark_smac_params(tline, &tmpl, TOK_XDEF_PARAM);
4323 tline = expand_smacro(tline);
4325 /* NB: Does this still make sense? */
4326 macro_start = reverse_tokens(tline);
4330 * Good. We now have a macro name, a parameter count, and a
4331 * token list (in reverse order) for an expansion. We ought
4332 * to be OK just to create an SMacro, store it, and let
4333 * free_tlist have the rest of the line (which we have
4334 * carefully re-terminated after chopping off the expansion
4335 * from the end).
4337 define_smacro(mname, casesense, macro_start, &tmpl);
4338 break;
4341 case PP_UNDEF:
4342 case PP_UNDEFALIAS:
4343 if (!(mname = get_id(&tline, dname)))
4344 goto done;
4345 if (tline->next)
4346 nasm_warn(WARN_OTHER, "trailing garbage after macro name ignored");
4348 undef_smacro(mname, op == PP_UNDEFALIAS);
4349 break;
4351 case PP_DEFSTR:
4352 if (!(mname = get_id(&tline, dname)))
4353 goto done;
4355 last = tline;
4356 tline = expand_smacro(tline->next);
4357 last->next = NULL;
4359 tline = zap_white(tline);
4360 q = detoken(tline, false);
4361 macro_start = make_tok_qstr(NULL, q);
4362 nasm_free(q);
4365 * We now have a macro name, an implicit parameter count of
4366 * zero, and a string token to use as an expansion. Create
4367 * and store an SMacro.
4369 define_smacro(mname, casesense, macro_start, NULL);
4370 break;
4372 case PP_DEFTOK:
4373 if (!(mname = get_id(&tline, dname)))
4374 goto done;
4376 last = tline;
4377 tline = expand_smacro(tline->next);
4378 last->next = NULL;
4380 t = skip_white(tline);
4381 /* t should now point to the string */
4382 if (!tok_type(t, TOK_STRING)) {
4383 nasm_nonfatal("`%s' requires string as second parameter", dname);
4384 free_tlist(tline);
4385 goto done;
4389 * Convert the string to a token stream. Note that smacros
4390 * are stored with the token stream reversed, so we have to
4391 * reverse the output of tokenize().
4393 macro_start = reverse_tokens(tokenize(unquote_token_cstr(t)));
4396 * We now have a macro name, an implicit parameter count of
4397 * zero, and a numeric token to use as an expansion. Create
4398 * and store an SMacro.
4400 define_smacro(mname, casesense, macro_start, NULL);
4401 free_tlist(tline);
4402 break;
4404 case PP_PATHSEARCH:
4406 const char *found_path;
4408 if (!(mname = get_id(&tline, dname)))
4409 goto done;
4411 last = tline;
4412 tline = expand_smacro(tline->next);
4413 last->next = NULL;
4415 t = skip_white(tline);
4416 if (!t || (t->type != TOK_STRING &&
4417 t->type != TOK_INTERNAL_STRING)) {
4418 nasm_nonfatal("`%s' expects a file name", dname);
4419 free_tlist(tline);
4420 goto done;
4422 if (t->next)
4423 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
4425 p = unquote_token_cstr(t);
4427 inc_fopen(p, NULL, &found_path, INC_PROBE, NF_BINARY);
4428 if (!found_path)
4429 found_path = p;
4430 macro_start = make_tok_qstr(NULL, found_path);
4433 * We now have a macro name, an implicit parameter count of
4434 * zero, and a string token to use as an expansion. Create
4435 * and store an SMacro.
4437 define_smacro(mname, casesense, macro_start, NULL);
4438 free_tlist(tline);
4439 break;
4442 case PP_STRLEN:
4443 if (!(mname = get_id(&tline, dname)))
4444 goto done;
4446 last = tline;
4447 tline = expand_smacro(tline->next);
4448 last->next = NULL;
4450 t = skip_white(tline);
4451 /* t should now point to the string */
4452 if (!tok_type(t, TOK_STRING)) {
4453 nasm_nonfatal("`%s' requires string as second parameter", dname);
4454 free_tlist(tline);
4455 free_tlist(origline);
4456 return DIRECTIVE_FOUND;
4459 unquote_token(t);
4460 macro_start = make_tok_num(NULL, t->len);
4463 * We now have a macro name, an implicit parameter count of
4464 * zero, and a numeric token to use as an expansion. Create
4465 * and store an SMacro.
4467 define_smacro(mname, casesense, macro_start, NULL);
4468 free_tlist(tline);
4469 free_tlist(origline);
4470 return DIRECTIVE_FOUND;
4472 case PP_STRCAT:
4473 if (!(mname = get_id(&tline, dname)))
4474 goto done;
4476 last = tline;
4477 tline = expand_smacro(tline->next);
4478 last->next = NULL;
4480 len = 0;
4481 list_for_each(t, tline) {
4482 switch (t->type) {
4483 case TOK_WHITESPACE:
4484 break;
4485 case TOK_STRING:
4486 unquote_token(t);
4487 len += t->len;
4488 break;
4489 case TOK_OTHER:
4490 if (tok_is(t, ',')) /* permit comma separators */
4491 break;
4492 /* else fall through */
4493 default:
4494 nasm_nonfatal("non-string passed to `%s': %s", dname,
4495 tok_text(t));
4496 free_tlist(tline);
4497 goto done;
4501 q = qbuf = nasm_malloc(len+1);
4502 list_for_each(t, tline) {
4503 if (t->type == TOK_INTERNAL_STRING)
4504 q = mempcpy(q, tok_text(t), t->len);
4506 *q = '\0';
4509 * We now have a macro name, an implicit parameter count of
4510 * zero, and a numeric token to use as an expansion. Create
4511 * and store an SMacro.
4513 macro_start = make_tok_qstr_len(NULL, qbuf, len);
4514 nasm_free(qbuf);
4515 define_smacro(mname, casesense, macro_start, NULL);
4516 free_tlist(tline);
4517 break;
4519 case PP_SUBSTR:
4521 int64_t start, count;
4522 const char *txt;
4523 size_t len;
4525 if (!(mname = get_id(&tline, dname)))
4526 goto done;
4528 last = tline;
4529 tline = expand_smacro(tline->next);
4530 last->next = NULL;
4532 if (tline) /* skip expanded id */
4533 t = tline->next;
4535 t = skip_white(t);
4537 /* t should now point to the string */
4538 if (!tok_type(t, TOK_STRING)) {
4539 nasm_nonfatal("`%s' requires string as second parameter", dname);
4540 free_tlist(tline);
4541 goto done;
4544 pps.tptr = t->next;
4545 pps.ntokens = -1;
4546 tokval.t_type = TOKEN_INVALID;
4547 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
4548 if (!evalresult) {
4549 free_tlist(tline);
4550 goto done;
4551 } else if (!is_simple(evalresult)) {
4552 nasm_nonfatal("non-constant value given to `%s'", dname);
4553 free_tlist(tline);
4554 goto done;
4556 start = evalresult->value - 1;
4558 pps.tptr = skip_white(pps.tptr);
4559 if (!pps.tptr) {
4560 count = 1; /* Backwards compatibility: one character */
4561 } else {
4562 tokval.t_type = TOKEN_INVALID;
4563 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
4564 if (!evalresult) {
4565 free_tlist(tline);
4566 goto done;
4567 } else if (!is_simple(evalresult)) {
4568 nasm_nonfatal("non-constant value given to `%s'", dname);
4569 free_tlist(tline);
4570 goto done;
4572 count = evalresult->value;
4575 unquote_token(t);
4576 len = t->len;
4578 /* make start and count being in range */
4579 if (start < 0)
4580 start = 0;
4581 if (count < 0)
4582 count = len + count + 1 - start;
4583 if (start + count > (int64_t)len)
4584 count = len - start;
4585 if (!len || count < 0 || start >=(int64_t)len)
4586 start = -1, count = 0; /* empty string */
4588 txt = (start < 0) ? "" : tok_text(t) + start;
4589 len = count;
4590 macro_start = make_tok_qstr_len(NULL, txt, len);
4593 * We now have a macro name, an implicit parameter count of
4594 * zero, and a numeric token to use as an expansion. Create
4595 * and store an SMacro.
4597 define_smacro(mname, casesense, macro_start, NULL);
4598 free_tlist(tline);
4599 break;
4602 case PP_ASSIGN:
4603 if (!(mname = get_id(&tline, dname)))
4604 goto done;
4606 last = tline;
4607 tline = expand_smacro(tline->next);
4608 last->next = NULL;
4610 pps.tptr = tline;
4611 pps.ntokens = -1;
4612 tokval.t_type = TOKEN_INVALID;
4613 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
4614 free_tlist(tline);
4615 if (!evalresult)
4616 goto done;
4618 if (tokval.t_type)
4619 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
4621 if (!is_simple(evalresult)) {
4622 nasm_nonfatal("non-constant value given to `%s'", dname);
4623 free_tlist(origline);
4624 return DIRECTIVE_FOUND;
4627 macro_start = make_tok_num(NULL, reloc_value(evalresult));
4630 * We now have a macro name, an implicit parameter count of
4631 * zero, and a numeric token to use as an expansion. Create
4632 * and store an SMacro.
4634 define_smacro(mname, casesense, macro_start, NULL);
4635 break;
4637 case PP_ALIASES:
4638 tline = tline->next;
4639 tline = expand_smacro(tline);
4640 ppopt.noaliases = !pp_get_boolean_option(tline, !ppopt.noaliases);
4641 break;
4643 case PP_LINE:
4644 nasm_panic("`%s' directive not preprocessed early", dname);
4645 break;
4648 done:
4649 free_tlist(origline);
4650 return DIRECTIVE_FOUND;
4654 * Ensure that a macro parameter contains a condition code and
4655 * nothing else. Return the condition code index if so, or -1
4656 * otherwise.
4658 static int find_cc(Token * t)
4660 Token *tt;
4662 if (!t)
4663 return -1; /* Probably a %+ without a space */
4665 t = skip_white(t);
4666 if (!tok_type(t, TOK_ID))
4667 return -1;
4668 tt = t->next;
4669 tt = skip_white(tt);
4670 if (tok_isnt(tt, ','))
4671 return -1;
4673 return bsii(tok_text(t), (const char **)conditions,
4674 ARRAY_SIZE(conditions));
4677 static inline bool pp_concat_match(const Token *t, unsigned int mask)
4679 return t && (PP_CONCAT_MASK(t->type) & mask);
4683 * This routines walks over tokens strem and handles tokens
4684 * pasting, if @handle_explicit passed then explicit pasting
4685 * term is handled, otherwise -- implicit pastings only.
4686 * The @m array can contain a series of token types which are
4687 * executed as separate passes.
4689 static bool paste_tokens(Token **head, const struct tokseq_match *m,
4690 size_t mnum, bool handle_explicit)
4692 Token *tok, *t, *next, **prev_next, **prev_nonspace;
4693 bool pasted = false;
4694 char *buf, *p;
4695 size_t len, i;
4698 * The last token before pasting. We need it
4699 * to be able to connect new handled tokens.
4700 * In other words if there were a tokens stream
4702 * A -> B -> C -> D
4704 * and we've joined tokens B and C, the resulting
4705 * stream should be
4707 * A -> BC -> D
4709 tok = *head;
4710 prev_next = prev_nonspace = head;
4712 if (tok_white(tok) || tok_type(tok, TOK_PASTE))
4713 prev_nonspace = NULL;
4715 while (tok && (next = tok->next)) {
4716 bool did_paste = false;
4718 switch (tok->type) {
4719 case TOK_WHITESPACE:
4720 /* Zap redundant whitespaces */
4721 tok->next = next = zap_white(next);
4722 break;
4724 case TOK_PASTE:
4725 /* Explicit pasting */
4726 if (!handle_explicit)
4727 break;
4729 /* Left pasting token is start of line, just drop %+ */
4730 if (!prev_nonspace) {
4731 tok = delete_Token(tok);
4732 break;
4735 did_paste = true;
4737 prev_next = prev_nonspace;
4738 t = *prev_nonspace;
4740 /* Delete leading whitespace */
4741 next = zap_white(t->next);
4744 * Delete the %+ token itself, followed by any whitespace.
4745 * In a sequence of %+ ... %+ ... %+ pasting sequences where
4746 * some expansions in the middle have ended up empty,
4747 * we can end up having multiple %+ tokens in a row;
4748 * just drop whem in that case.
4750 while (next) {
4751 if (next->type == TOK_PASTE || next->type == TOK_WHITESPACE)
4752 next = delete_Token(next);
4753 else
4754 break;
4758 * Nothing after? Just leave the existing token.
4760 if (!next) {
4761 t->next = tok = NULL; /* End of line */
4762 break;
4765 p = buf = nasm_malloc(t->len + next->len + 1);
4766 p = mempcpy(p, tok_text(t), t->len);
4767 p = mempcpy(p, tok_text(next), next->len);
4768 *p = '\0';
4769 delete_Token(t);
4770 t = tokenize(buf);
4771 nasm_free(buf);
4773 if (unlikely(!t)) {
4775 * No output at all? Replace with a single whitespace.
4776 * This should never happen.
4778 t = new_White(NULL);
4781 *prev_nonspace = tok = t;
4782 while (t->next)
4783 t = t->next; /* Find the last token produced */
4785 /* Delete the second token and attach to the end of the list */
4786 t->next = delete_Token(next);
4788 /* We want to restart from the head of the pasted token */
4789 next = tok;
4790 break;
4792 default:
4793 /* implicit pasting */
4794 for (i = 0; i < mnum; i++) {
4795 if (pp_concat_match(tok, m[i].mask_head))
4796 break;
4799 if (i >= mnum)
4800 break;
4802 len = tok->len;
4803 while (pp_concat_match(next, m[i].mask_tail)) {
4804 len += next->len;
4805 next = next->next;
4808 /* No match or no text to process */
4809 if (len == tok->len)
4810 break;
4812 p = buf = nasm_malloc(len + 1);
4813 while (tok != next) {
4814 p = mempcpy(p, tok_text(tok), tok->len);
4815 tok = delete_Token(tok);
4817 *p = '\0';
4818 *prev_next = tok = t = tokenize(buf);
4819 nasm_free(buf);
4822 * Connect pasted into original stream,
4823 * ie A -> new-tokens -> B
4825 while (t->next)
4826 t = t->next;
4827 t->next = next;
4828 prev_next = prev_nonspace = &t->next;
4829 did_paste = true;
4830 break;
4833 if (did_paste) {
4834 pasted = true;
4835 } else {
4836 prev_next = &tok->next;
4837 if (next && next->type != TOK_WHITESPACE && next->type != TOK_PASTE)
4838 prev_nonspace = prev_next;
4841 tok = next;
4844 return pasted;
4848 * Computes the proper rotation of mmacro parameters
4850 static int mmac_rotate(const MMacro *mac, unsigned int n)
4852 if (--n < mac->nparam)
4853 n = (n + mac->rotate) % mac->nparam;
4855 return n+1;
4859 * expands to a list of tokens from %{x:y}
4861 static void expand_mmac_params_range(MMacro *mac, Token *tline, Token ***tail)
4863 Token *t;
4864 const char *arg = tok_text(tline) + 1;
4865 int fst, lst, incr, n;
4866 int parsed;
4868 parsed = sscanf(arg, "%d:%d", &fst, &lst);
4869 nasm_assert(parsed == 2);
4872 * only macros params are accounted so
4873 * if someone passes %0 -- we reject such
4874 * value(s)
4876 if (lst == 0 || fst == 0)
4877 goto err;
4879 /* the values should be sane */
4880 if ((fst > (int)mac->nparam || fst < (-(int)mac->nparam)) ||
4881 (lst > (int)mac->nparam || lst < (-(int)mac->nparam)))
4882 goto err;
4884 fst = fst < 0 ? fst + (int)mac->nparam + 1: fst;
4885 lst = lst < 0 ? lst + (int)mac->nparam + 1: lst;
4888 * It will be at least one parameter, as we can loop
4889 * in either direction.
4891 incr = (fst < lst) ? 1 : -1;
4893 while (true) {
4894 n = mmac_rotate(mac, fst);
4895 dup_tlistn(mac->params[n], mac->paramlen[n], tail);
4896 if (fst == lst)
4897 break;
4898 t = make_tok_char(NULL, ',');
4899 **tail = t;
4900 *tail = &t->next;
4901 fst += incr;
4904 return;
4906 err:
4907 nasm_nonfatal("`%%{%s}': macro parameters out of range", arg);
4908 return;
4912 * Expand MMacro-local things: parameter references (%0, %n, %+n,
4913 * %-n) and MMacro-local identifiers (%%foo) as well as
4914 * macro indirection (%[...]) and range (%{..:..}).
4916 static Token *expand_mmac_params(Token * tline)
4918 Token **tail, *thead;
4919 bool changed = false;
4920 MMacro *mac = istk->mstk.mmac;
4922 tail = &thead;
4923 thead = NULL;
4925 while (tline) {
4926 bool change;
4927 bool err_not_mac = false;
4928 Token *t = tline;
4929 const char *text = tok_text(t);
4930 int type = t->type;
4932 tline = tline->next;
4933 t->next = NULL;
4935 switch (type) {
4936 case TOK_LOCAL_SYMBOL:
4937 change = true;
4939 if (!mac) {
4940 err_not_mac = true;
4941 break;
4944 type = TOK_ID;
4945 text = nasm_asprintf("..@%"PRIu64".%s", mac->unique, text+2);
4946 break;
4947 case TOK_MMACRO_PARAM:
4949 Token *tt = NULL;
4951 change = true;
4953 if (!mac) {
4954 err_not_mac = true;
4955 break;
4958 if (strchr(text, ':')) {
4959 /* It is a range */
4960 expand_mmac_params_range(mac, t, &tail);
4961 text = NULL;
4962 break;
4965 switch (text[1]) {
4967 * We have to make a substitution of one of the
4968 * forms %1, %-1, %+1, %%foo, %0, %00.
4970 case '0':
4971 if (!text[2]) {
4972 type = TOK_NUMBER;
4973 text = nasm_asprintf("%d", mac->nparam);
4974 break;
4976 if (text[2] != '0' || text[3])
4977 goto invalid;
4978 /* a possible captured label == mac->params[0] */
4979 /* fall through */
4980 default:
4982 unsigned long n;
4983 char *ep;
4985 n = strtoul(text + 1, &ep, 10);
4986 if (unlikely(*ep))
4987 goto invalid;
4989 if (n <= mac->nparam) {
4990 n = mmac_rotate(mac, n);
4991 dup_tlistn(mac->params[n], mac->paramlen[n], &tail);
4993 text = NULL;
4994 break;
4996 case '-':
4997 case '+':
4999 int cc;
5000 unsigned long n;
5001 char *ep;
5003 n = strtoul(tok_text(t) + 2, &ep, 10);
5004 if (unlikely(*ep))
5005 goto invalid;
5007 if (n && n <= mac->nparam) {
5008 n = mmac_rotate(mac, n);
5009 tt = mac->params[n];
5011 cc = find_cc(tt);
5012 if (cc == -1) {
5013 nasm_nonfatal("macro parameter `%s' is not a condition code",
5014 tok_text(t));
5015 text = NULL;
5016 break;
5019 type = TOK_ID;
5020 if (text[1] == '-') {
5021 int ncc = inverse_ccs[cc];
5022 if (unlikely(ncc == -1)) {
5023 nasm_nonfatal("condition code `%s' is not invertible",
5024 conditions[cc]);
5025 break;
5027 cc = ncc;
5029 text = nasm_strdup(conditions[cc]);
5030 break;
5033 invalid:
5034 nasm_nonfatal("invalid macro parameter: `%s'", text);
5035 text = NULL;
5036 break;
5038 break;
5041 case TOK_PREPROC_Q:
5042 if (mac) {
5043 type = TOK_ID;
5044 text = nasm_strdup(mac->iname);
5045 change = true;
5046 } else {
5047 change = false;
5049 break;
5051 case TOK_PREPROC_QQ:
5052 if (mac) {
5053 type = TOK_ID;
5054 text = nasm_strdup(mac->name);
5055 change = true;
5056 } else {
5057 change = false;
5059 break;
5061 case TOK_INDIRECT:
5063 Token *tt;
5065 tt = tokenize(tok_text(t));
5066 tt = expand_mmac_params(tt);
5067 tt = expand_smacro(tt);
5068 /* Why dup_tlist() here? We should own tt... */
5069 dup_tlist(tt, &tail);
5070 text = NULL;
5071 change = true;
5072 break;
5075 default:
5076 change = false;
5077 break;
5080 if (err_not_mac) {
5081 nasm_nonfatal("`%s': not in a macro call", text);
5082 text = NULL;
5083 change = true;
5086 if (change) {
5087 if (!text) {
5088 delete_Token(t);
5089 } else {
5090 *tail = t;
5091 tail = &t->next;
5092 set_text(t, text, tok_strlen(text));
5093 t->type = type;
5095 changed = true;
5096 } else {
5097 *tail = t;
5098 tail = &t->next;
5102 *tail = NULL;
5104 if (changed) {
5105 const struct tokseq_match t[] = {
5107 PP_CONCAT_MASK(TOK_ID) |
5108 PP_CONCAT_MASK(TOK_FLOAT), /* head */
5109 PP_CONCAT_MASK(TOK_ID) |
5110 PP_CONCAT_MASK(TOK_NUMBER) |
5111 PP_CONCAT_MASK(TOK_FLOAT) |
5112 PP_CONCAT_MASK(TOK_OTHER) /* tail */
5115 PP_CONCAT_MASK(TOK_NUMBER), /* head */
5116 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
5119 paste_tokens(&thead, t, ARRAY_SIZE(t), false);
5122 return thead;
5125 static Token *expand_smacro_noreset(Token * tline);
5128 * Expand *one* single-line macro instance. If the first token is not
5129 * a macro at all, it is simply copied to the output and the pointer
5130 * advanced. tpp should be a pointer to a pointer (usually the next
5131 * pointer of the previous token) to the first token. **tpp is updated
5132 * to point to the first token of the expansion, and *tpp updated to
5133 * point to the next pointer of the last token of the expansion.
5135 * If the expansion is empty, *tpp will be unchanged but **tpp will
5136 * be advanced past the macro call.
5138 * Return the macro expanded, or NULL if no expansion took place.
5140 static SMacro *expand_one_smacro(Token ***tpp)
5142 Token **params = NULL;
5143 const char *mname;
5144 Token *mstart = **tpp;
5145 Token *tline = mstart;
5146 SMacro *head, *m;
5147 int i;
5148 Token *t, *tup, *tafter;
5149 int nparam = 0;
5150 bool cond_comma;
5152 if (!tline)
5153 return false; /* Empty line, nothing to do */
5155 mname = tok_text(mstart);
5157 smacro_deadman.total--;
5158 smacro_deadman.levels--;
5160 if (unlikely(smacro_deadman.total < 0 || smacro_deadman.levels < 0)) {
5161 if (unlikely(!smacro_deadman.triggered)) {
5162 nasm_nonfatal("interminable macro recursion");
5163 smacro_deadman.triggered = true;
5165 goto not_a_macro;
5166 } else if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID) {
5167 head = (SMacro *)hash_findix(&smacros, mname);
5168 } else if (tline->type == TOK_LOCAL_MACRO) {
5169 Context *ctx = get_ctx(mname, &mname);
5170 head = ctx ? (SMacro *)hash_findix(&ctx->localmac, mname) : NULL;
5171 } else {
5172 goto not_a_macro;
5176 * We've hit an identifier of some sort. First check whether the
5177 * identifier is a single-line macro at all, then think about
5178 * checking for parameters if necessary.
5180 list_for_each(m, head) {
5181 if (unlikely(m->alias && ppopt.noaliases))
5182 continue;
5183 if (!mstrcmp(m->name, mname, m->casesense))
5184 break;
5187 if (!m) {
5188 goto not_a_macro;
5191 /* Parse parameters, if applicable */
5193 params = NULL;
5194 nparam = 0;
5196 if (m->nparam == 0) {
5198 * Simple case: the macro is parameterless.
5199 * Nothing to parse; the expansion code will
5200 * drop the macro name token.
5202 } else {
5204 * Complicated case: at least one macro with this name
5205 * exists and takes parameters. We must find the
5206 * parameters in the call, count them, find the SMacro
5207 * that corresponds to that form of the macro call, and
5208 * substitute for the parameters when we expand. What a
5209 * pain.
5211 Token *t;
5212 int paren, brackets;
5214 tline = tline->next;
5215 tline = skip_white(tline);
5216 if (!tok_is(tline, '(')) {
5218 * This macro wasn't called with parameters: ignore
5219 * the call. (Behaviour borrowed from gnu cpp.)
5221 goto not_a_macro;
5224 paren = 1;
5225 nparam = 1;
5226 brackets = 0;
5227 t = tline; /* tline points to leading ( */
5229 while (paren) {
5230 t = t->next;
5232 if (!t) {
5233 nasm_nonfatal("macro call expects terminating `)'");
5234 goto not_a_macro;
5237 if (t->type != TOK_OTHER || t->len != 1)
5238 continue;
5240 switch (t->text.a[0]) {
5241 case ',':
5242 if (!brackets && paren == 1)
5243 nparam++;
5244 break;
5246 case '{':
5247 brackets++;
5248 break;
5250 case '}':
5251 if (brackets > 0)
5252 brackets--;
5253 break;
5255 case '(':
5256 if (!brackets)
5257 paren++;
5258 break;
5260 case ')':
5261 if (!brackets)
5262 paren--;
5263 break;
5265 default:
5266 break; /* Normal token */
5271 * Look for a macro matching in both name and parameter count.
5272 * We already know any matches cannot be anywhere before the
5273 * current position of "m", so there is no reason to
5274 * backtrack.
5276 while (1) {
5277 if (!m) {
5279 *!macro-params-single [on] single-line macro calls with wrong parameter count
5280 *! warns about \i{single-line macros} being invoked
5281 *! with the wrong number of parameters.
5283 nasm_warn(WARN_MACRO_PARAMS_SINGLE|ERR_HOLD,
5284 "single-line macro `%s' exists, "
5285 "but not taking %d parameter%s",
5286 mname, nparam, (nparam == 1) ? "" : "s");
5287 goto not_a_macro;
5290 if (!mstrcmp(m->name, mname, m->casesense)) {
5291 if (nparam == m->nparam)
5292 break; /* It's good */
5293 if (m->greedy && nparam >= m->nparam-1)
5294 break; /* Also good */
5296 m = m->next;
5300 if (m->in_progress)
5301 goto not_a_macro;
5303 /* Expand the macro */
5304 m->in_progress = true;
5306 if (nparam) {
5307 /* Extract parameters */
5308 Token **phead, **pep;
5309 int white = 0;
5310 int brackets = 0;
5311 int paren;
5312 bool bracketed = false;
5313 bool bad_bracket = false;
5314 enum sparmflags flags;
5316 nparam = m->nparam;
5317 paren = 1;
5318 nasm_newn(params, nparam);
5319 i = 0;
5320 flags = m->params[i].flags;
5321 phead = pep = &params[i];
5322 *pep = NULL;
5324 while (paren) {
5325 bool skip;
5326 char ch;
5328 tline = tline->next;
5330 if (!tline)
5331 nasm_nonfatal("macro call expects terminating `)'");
5333 ch = 0;
5334 skip = false;
5337 switch (tline->type) {
5338 case TOK_OTHER:
5339 if (tline->len == 1)
5340 ch = tline->text.a[0];
5341 break;
5343 case TOK_WHITESPACE:
5344 if (!(flags & SPARM_NOSTRIP)) {
5345 if (brackets || *phead)
5346 white++; /* Keep interior whitespace */
5347 skip = true;
5349 break;
5351 default:
5352 break;
5355 switch (ch) {
5356 case ',':
5357 if (!brackets && paren == 1 && !(flags & SPARM_GREEDY)) {
5358 i++;
5359 nasm_assert(i < nparam);
5360 phead = pep = &params[i];
5361 *pep = NULL;
5362 bracketed = false;
5363 skip = true;
5364 flags = m->params[i].flags;
5366 break;
5368 case '{':
5369 if (!bracketed) {
5370 bracketed = !*phead && !(flags & SPARM_NOSTRIP);
5371 skip = bracketed;
5373 brackets++;
5374 break;
5376 case '}':
5377 if (brackets > 0) {
5378 if (!--brackets)
5379 skip = bracketed;
5381 break;
5383 case '(':
5384 if (!brackets)
5385 paren++;
5386 break;
5388 case ')':
5389 if (!brackets) {
5390 paren--;
5391 if (!paren) {
5392 skip = true;
5393 i++; /* Found last argument */
5396 break;
5398 default:
5399 break; /* Normal token */
5402 if (!skip) {
5403 Token *t;
5405 bad_bracket |= bracketed && !brackets;
5407 if (white) {
5408 *pep = t = new_White(NULL);
5409 pep = &t->next;
5410 white = 0;
5412 *pep = t = dup_Token(NULL, tline);
5413 pep = &t->next;
5418 * Possible further processing of parameters. Note that the
5419 * ordering matters here.
5421 for (i = 0; i < nparam; i++) {
5422 enum sparmflags flags = m->params[i].flags;
5424 if (flags & SPARM_EVAL) {
5425 /* Evaluate this parameter as a number */
5426 struct ppscan pps;
5427 struct tokenval tokval;
5428 expr *evalresult;
5429 Token *eval_param;
5431 pps.tptr = eval_param = expand_smacro_noreset(params[i]);
5432 pps.ntokens = -1;
5433 tokval.t_type = TOKEN_INVALID;
5434 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
5436 free_tlist(eval_param);
5437 params[i] = NULL;
5439 if (!evalresult) {
5440 /* Nothing meaningful to do */
5441 } else if (tokval.t_type) {
5442 nasm_nonfatal("invalid expression in parameter %d of macro `%s'", i, m->name);
5443 } else if (!is_simple(evalresult)) {
5444 nasm_nonfatal("non-constant expression in parameter %d of macro `%s'", i, m->name);
5445 } else {
5446 params[i] = make_tok_num(NULL, reloc_value(evalresult));
5450 if (flags & SPARM_STR) {
5451 /* Convert expansion to a quoted string */
5452 char *arg;
5453 Token *qs;
5455 qs = expand_smacro_noreset(params[i]);
5456 arg = detoken(qs, false);
5457 free_tlist(qs);
5458 params[i] = make_tok_qstr(NULL, arg);
5459 nasm_free(arg);
5464 /* Note: we own the expansion this returns. */
5465 t = m->expand(m, params, nparam);
5467 tafter = tline->next; /* Skip past the macro call */
5468 tline->next = NULL; /* Truncate list at the macro call end */
5469 tline = tafter;
5471 tup = NULL;
5472 cond_comma = false;
5474 while (t) {
5475 enum pp_token_type type = t->type;
5476 Token *tnext = t->next;
5478 switch (type) {
5479 case TOK_PREPROC_Q:
5480 delete_Token(t);
5481 t = dup_Token(tline, mstart);
5482 break;
5484 case TOK_PREPROC_QQ:
5486 size_t mlen = strlen(m->name);
5487 size_t len;
5488 char *p;
5490 t->type = mstart->type;
5491 if (t->type == TOK_LOCAL_MACRO) {
5492 const char *psp; /* prefix start pointer */
5493 const char *pep; /* prefix end pointer */
5494 size_t plen;
5496 psp = tok_text(mstart);
5497 get_ctx(psp, &pep);
5498 plen = pep - psp;
5500 len = mlen + plen;
5501 p = nasm_malloc(len + 1);
5502 p = mempcpy(p, psp, plen);
5503 } else {
5504 len = mlen;
5505 p = nasm_malloc(len + 1);
5507 p = mempcpy(p, m->name, mlen);
5508 *p = '\0';
5509 set_text_free(t, p, len);
5511 t->next = tline;
5512 break;
5515 case TOK_COND_COMMA:
5516 delete_Token(t);
5517 t = cond_comma ? make_tok_char(tline, ',') : NULL;
5518 break;
5520 case TOK_ID:
5521 case TOK_PREPROC_ID:
5522 case TOK_LOCAL_MACRO:
5525 * Chain this into the target line *before* expanding,
5526 * that way we pick up any arguments to the new macro call,
5527 * if applicable.
5529 Token **tp = &t;
5530 t->next = tline;
5531 expand_one_smacro(&tp);
5532 tline = *tp; /* First token left after any macro call */
5533 break;
5535 default:
5536 if (is_smac_param(t->type)) {
5537 int param = smac_nparam(t->type);
5538 nasm_assert(!tup && param < nparam);
5539 delete_Token(t);
5540 t = NULL;
5541 tup = tnext;
5542 tnext = dup_tlist_reverse(params[param], NULL);
5543 cond_comma = false;
5544 } else {
5545 t->next = tline;
5549 if (t) {
5550 Token *endt = tline;
5552 tline = t;
5553 while (!cond_comma && t && t != endt) {
5554 cond_comma = t->type != TOK_WHITESPACE;
5555 t = t->next;
5559 if (tnext) {
5560 t = tnext;
5561 } else {
5562 t = tup;
5563 tup = NULL;
5567 **tpp = tline;
5568 for (t = tline; t && t != tafter; t = t->next)
5569 *tpp = &t->next;
5571 m->in_progress = false;
5573 /* Don't do this until after expansion or we will clobber mname */
5574 free_tlist(mstart);
5575 goto done;
5578 * No macro expansion needed; roll back to mstart (if necessary)
5579 * and then advance to the next input token. Note that this is
5580 * by far the common case!
5582 not_a_macro:
5583 *tpp = &mstart->next;
5584 m = NULL;
5585 done:
5586 smacro_deadman.levels++;
5587 if (unlikely(params))
5588 free_tlist_array(params, nparam);
5589 return m;
5593 * Expand all single-line macro calls made in the given line.
5594 * Return the expanded version of the line. The original is deemed
5595 * to be destroyed in the process. (In reality we'll just move
5596 * Tokens from input to output a lot of the time, rather than
5597 * actually bothering to destroy and replicate.)
5599 static Token *expand_smacro(Token *tline)
5601 smacro_deadman.total = nasm_limit[LIMIT_MACRO_TOKENS];
5602 smacro_deadman.levels = nasm_limit[LIMIT_MACRO_LEVELS];
5603 smacro_deadman.triggered = false;
5604 return expand_smacro_noreset(tline);
5607 static Token *expand_smacro_noreset(Token *org_tline)
5609 Token *tline;
5610 bool expanded;
5611 errhold errhold; /* Hold warning/errors during expansion */
5613 if (!org_tline)
5614 return NULL; /* Empty input */
5617 * Trick: we should avoid changing the start token pointer since it can
5618 * be contained in "next" field of other token. Because of this
5619 * we allocate a copy of first token and work with it; at the end of
5620 * routine we copy it back
5622 tline = dup_Token(org_tline->next, org_tline);
5625 * Pretend that we always end up doing expansion on the first pass;
5626 * that way %+ get processed. However, if we process %+ before the
5627 * first pass, we end up with things like MACRO %+ TAIL trying to
5628 * look up the macro "MACROTAIL", which we don't want.
5630 expanded = true;
5632 while (true) {
5633 static const struct tokseq_match tmatch[] = {
5635 PP_CONCAT_MASK(TOK_ID) |
5636 PP_CONCAT_MASK(TOK_LOCAL_MACRO) |
5637 PP_CONCAT_MASK(TOK_ENVIRON) |
5638 PP_CONCAT_MASK(TOK_PREPROC_ID), /* head */
5639 PP_CONCAT_MASK(TOK_ID) |
5640 PP_CONCAT_MASK(TOK_LOCAL_MACRO) |
5641 PP_CONCAT_MASK(TOK_ENVIRON) |
5642 PP_CONCAT_MASK(TOK_PREPROC_ID) |
5643 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
5646 Token **tail = &tline;
5649 * We hold warnings/errors until we are done this this loop. It is
5650 * possible for nuisance warnings to appear that disappear on later
5651 * passes.
5653 errhold = nasm_error_hold_push();
5655 while (*tail) /* main token loop */
5656 expanded |= !!expand_one_smacro(&tail);
5658 if (!expanded)
5659 break; /* Done! */
5662 * Now scan the entire line and look for successive TOK_IDs
5663 * that resulted after expansion (they can't be produced by
5664 * tokenize()). The successive TOK_IDs should be concatenated.
5665 * Also we look for %+ tokens and concatenate the tokens
5666 * before and after them (without white spaces in between).
5668 if (!paste_tokens(&tline, tmatch, ARRAY_SIZE(tmatch), true))
5669 break; /* Done again! */
5671 nasm_error_hold_pop(errhold, false);
5672 expanded = false;
5674 nasm_error_hold_pop(errhold, true);
5676 if (!tline) {
5678 * The expression expanded to empty line;
5679 * we can't return NULL because of the "trick" above.
5680 * Just set the line to a single WHITESPACE token.
5683 tline = new_White(NULL);
5686 steal_Token(org_tline, tline);
5687 org_tline->next = tline->next;
5688 delete_Token(tline);
5690 return org_tline;
5694 * Similar to expand_smacro but used exclusively with macro identifiers
5695 * right before they are fetched in. The reason is that there can be
5696 * identifiers consisting of several subparts. We consider that if there
5697 * are more than one element forming the name, user wants a expansion,
5698 * otherwise it will be left as-is. Example:
5700 * %define %$abc cde
5702 * the identifier %$abc will be left as-is so that the handler for %define
5703 * will suck it and define the corresponding value. Other case:
5705 * %define _%$abc cde
5707 * In this case user wants name to be expanded *before* %define starts
5708 * working, so we'll expand %$abc into something (if it has a value;
5709 * otherwise it will be left as-is) then concatenate all successive
5710 * PP_IDs into one.
5712 static Token *expand_id(Token * tline)
5714 Token *cur, *oldnext = NULL;
5716 if (!tline || !tline->next)
5717 return tline;
5719 cur = tline;
5720 while (cur->next &&
5721 (cur->next->type == TOK_ID || cur->next->type == TOK_PREPROC_ID ||
5722 cur->next->type == TOK_LOCAL_MACRO || cur->next->type == TOK_NUMBER))
5723 cur = cur->next;
5725 /* If identifier consists of just one token, don't expand */
5726 if (cur == tline)
5727 return tline;
5729 if (cur) {
5730 oldnext = cur->next; /* Detach the tail past identifier */
5731 cur->next = NULL; /* so that expand_smacro stops here */
5734 tline = expand_smacro(tline);
5736 if (cur) {
5737 /* expand_smacro possibly changhed tline; re-scan for EOL */
5738 cur = tline;
5739 while (cur && cur->next)
5740 cur = cur->next;
5741 if (cur)
5742 cur->next = oldnext;
5745 return tline;
5749 * This is called from find_mmacro_in_list() after finding a suitable macro.
5751 static MMacro *use_mmacro(MMacro *m, int *nparamp, Token ***paramsp)
5753 int nparam = *nparamp;
5754 Token **params = *paramsp;
5757 * This one is right. Just check if cycle removal
5758 * prohibits us using it before we actually celebrate...
5760 if (m->in_progress > m->max_depth) {
5761 if (m->max_depth > 0) {
5762 nasm_warn(WARN_OTHER, "reached maximum recursion depth of %i",
5763 m->max_depth);
5765 nasm_free(params);
5766 *nparamp = 0;
5767 *paramsp = NULL;
5768 return NULL;
5772 * It's right, and we can use it. Add its default
5773 * parameters to the end of our list if necessary.
5775 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
5776 int newnparam = m->nparam_min + m->ndefs;
5777 params = nasm_realloc(params, sizeof(*params) * (newnparam+2));
5778 memcpy(&params[nparam+1], &m->defaults[nparam+1-m->nparam_min],
5779 (newnparam - nparam) * sizeof(*params));
5780 nparam = newnparam;
5783 * If we've gone over the maximum parameter count (and
5784 * we're in Plus mode), ignore parameters beyond
5785 * nparam_max.
5787 if (m->plus && nparam > m->nparam_max)
5788 nparam = m->nparam_max;
5791 * If nparam was adjusted above, make sure the list is still
5792 * NULL-terminated.
5794 params[nparam+1] = NULL;
5796 /* Done! */
5797 *paramsp = params;
5798 *nparamp = nparam;
5799 return m;
5803 * Search a macro list and try to find a match. If matching, call
5804 * use_mmacro() to set up the macro call. m points to the list of
5805 * search, which is_mmacro() sets to the first *possible* match.
5807 static MMacro *
5808 find_mmacro_in_list(MMacro *m, const char *finding,
5809 int *nparamp, Token ***paramsp)
5811 int nparam = *nparamp;
5813 while (m) {
5814 if (m->nparam_min <= nparam
5815 && (m->plus || nparam <= m->nparam_max)) {
5817 * This one matches, use it.
5819 return use_mmacro(m, nparamp, paramsp);
5823 * Otherwise search for the next one with a name match.
5825 list_for_each(m, m->next) {
5826 if (!mstrcmp(m->name, finding, m->casesense))
5827 break;
5831 return NULL;
5835 * Determine whether the given line constitutes a multi-line macro
5836 * call, and return the MMacro structure called if so. Doesn't have
5837 * to check for an initial label - that's taken care of in
5838 * expand_mmacro - but must check numbers of parameters. Guaranteed
5839 * to be called with tline->type == TOK_ID, so the putative macro
5840 * name is easy to find.
5842 static MMacro *is_mmacro(Token * tline, int *nparamp, Token ***paramsp)
5844 MMacro *head, *m, *found;
5845 Token **params, **comma;
5846 int raw_nparam, nparam;
5847 const char *finding = tok_text(tline);
5848 bool empty_args = !tline->next;
5850 *nparamp = 0;
5851 *paramsp = NULL;
5853 head = (MMacro *) hash_findix(&mmacros, finding);
5856 * Efficiency: first we see if any macro exists with the given
5857 * name which isn't already excluded by macro cycle removal.
5858 * (The cycle removal test here helps optimize the case of wrapping
5859 * instructions, and is cheap to do here.)
5861 * If not, we can return NULL immediately. _Then_ we
5862 * count the parameters, and then we look further along the
5863 * list if necessary to find the proper MMacro.
5865 list_for_each(m, head) {
5866 if (!mstrcmp(m->name, finding, m->casesense) &&
5867 (m->in_progress != 1 || m->max_depth > 0))
5868 break; /* Found something that needs consideration */
5870 if (!m)
5871 return NULL;
5874 * OK, we have a potential macro. Count and demarcate the
5875 * parameters.
5877 comma = count_mmac_params(tline->next, nparamp, paramsp);
5878 raw_nparam = *nparamp;
5881 * Search for an exact match. This cannot come *before* the m
5882 * found in the list search before, so we can start there.
5884 * If found is NULL and *paramsp has been cleared, then we
5885 * encountered an error for which we have already issued a
5886 * diagnostic, so we should not proceed.
5888 found = find_mmacro_in_list(m, finding, nparamp, paramsp);
5889 if (!*paramsp)
5890 return NULL;
5892 nparam = *nparamp;
5893 params = *paramsp;
5896 * Special weirdness: in NASM < 2.15, an expansion of
5897 * *only* whitespace, as can happen during macro expansion under
5898 * certain circumstances, is counted as zero arguments for the
5899 * purpose of %0, but one argument for the purpose of macro
5900 * matching! In particular, this affects:
5902 * foobar %1
5904 * ... with %1 being empty; this would call the one-argument
5905 * version of "foobar" with an empty argument, equivalent to
5907 * foobar {%1}
5909 * ... except that %0 would be set to 0 inside foobar, even if
5910 * foobar is declared with "%macro foobar 1" or equivalent!
5912 * The proper way to do that is to define "%macro foobar 0-1".
5914 * To be compatible without doing something too stupid, try to
5915 * match a zero-argument macro first, but if that fails, try
5916 * for a one-argument macro with the above behavior.
5918 * Furthermore, NASM < 2.15 will match stripping a tailing empty
5919 * argument, but in that case %0 *does* reflect that this argument
5920 * have been stripped; this is handled in count_mmac_params().
5922 * To disable these insane legacy behaviors, use:
5924 * %pragma preproc sane_empty_expansion yes
5926 *!macro-params-legacy [on] improperly calling multi-line macro for legacy support
5927 *! warns about \i{multi-line macros} being invoked
5928 *! with the wrong number of parameters, but for bug-compatibility
5929 *! with NASM versions older than 2.15, NASM tried to fix up the
5930 *! parameters to match the legacy behavior and call the macro anyway.
5931 *! This can happen in certain cases where there are empty arguments
5932 *! without braces, sometimes as a result of macro expansion.
5934 *! The legacy behavior is quite strange and highly context-dependent,
5935 *! and can be disabled with:
5937 *! \c %pragma preproc sane_empty_expansion true
5939 *! It is highly recommended to use this option in new code.
5941 if (!ppopt.sane_empty_expansion) {
5942 if (!found) {
5943 if (raw_nparam == 0 && !empty_args) {
5945 * A single all-whitespace parameter as the only thing?
5946 * Look for a one-argument macro, but don't adjust
5947 * *nparamp.
5949 int bogus_nparam = 1;
5950 params[2] = NULL;
5951 found = find_mmacro_in_list(m, finding, &bogus_nparam, paramsp);
5952 } else if (raw_nparam > 1 && comma) {
5953 Token *comma_tail = *comma;
5956 * Drop the terminal argument and try again.
5957 * If we fail, we need to restore the comma to
5958 * preserve tlist.
5960 *comma = NULL;
5961 *nparamp = raw_nparam - 1;
5962 found = find_mmacro_in_list(m, finding, nparamp, paramsp);
5963 if (found)
5964 free_tlist(comma_tail);
5965 else
5966 *comma = comma_tail;
5969 if (!*paramsp)
5970 return NULL;
5971 } else if (comma) {
5972 free_tlist(*comma);
5973 *comma = NULL;
5974 if (raw_nparam > found->nparam_min &&
5975 raw_nparam <= found->nparam_min + found->ndefs) {
5976 /* Replace empty argument with default parameter */
5977 params[raw_nparam] =
5978 found->defaults[raw_nparam - found->nparam_min];
5979 } else if (raw_nparam > found->nparam_max && found->plus) {
5980 /* Just drop the comma, don't adjust argument count */
5981 } else {
5982 /* Drop argument. This may cause nparam < nparam_min. */
5983 params[raw_nparam] = NULL;
5984 *nparamp = nparam = raw_nparam - 1;
5988 if (found) {
5989 if (raw_nparam < found->nparam_min ||
5990 (raw_nparam > found->nparam_max && !found->plus)) {
5991 nasm_warn(WARN_MACRO_PARAMS_LEGACY,
5992 "improperly calling multi-line macro `%s' with %d parameters",
5993 found->name, raw_nparam);
5994 } else if (comma) {
5995 nasm_warn(WARN_MACRO_PARAMS_LEGACY,
5996 "dropping trailing empty parameter in call to multi-line macro `%s'", found->name);
6002 * After all that, we didn't find one with the right number of
6003 * parameters. Issue a warning, and fail to expand the macro.
6005 *!macro-params-multi [on] multi-line macro calls with wrong parameter count
6006 *! warns about \i{multi-line macros} being invoked
6007 *! with the wrong number of parameters. See \k{mlmacover} for an
6008 *! example of why you might want to disable this warning.
6010 if (found)
6011 return found;
6013 nasm_warn(WARN_MACRO_PARAMS_MULTI,
6014 "multi-line macro `%s' exists, but not taking %d parameter%s",
6015 finding, nparam, (nparam == 1) ? "" : "s");
6016 nasm_free(*paramsp);
6017 return NULL;
6021 #if 0
6024 * Save MMacro invocation specific fields in
6025 * preparation for a recursive macro expansion
6027 static void push_mmacro(MMacro *m)
6029 MMacroInvocation *i;
6031 i = nasm_malloc(sizeof(MMacroInvocation));
6032 i->prev = m->prev;
6033 i->params = m->params;
6034 i->iline = m->iline;
6035 i->nparam = m->nparam;
6036 i->rotate = m->rotate;
6037 i->paramlen = m->paramlen;
6038 i->unique = m->unique;
6039 i->condcnt = m->condcnt;
6040 m->prev = i;
6045 * Restore MMacro invocation specific fields that were
6046 * saved during a previous recursive macro expansion
6048 static void pop_mmacro(MMacro *m)
6050 MMacroInvocation *i;
6052 if (m->prev) {
6053 i = m->prev;
6054 m->prev = i->prev;
6055 m->params = i->params;
6056 m->iline = i->iline;
6057 m->nparam = i->nparam;
6058 m->rotate = i->rotate;
6059 m->paramlen = i->paramlen;
6060 m->unique = i->unique;
6061 m->condcnt = i->condcnt;
6062 nasm_free(i);
6066 #endif
6069 * List an mmacro call with arguments (-Lm option)
6071 static void list_mmacro_call(const MMacro *m)
6073 const char prefix[] = " ;;; [macro] ";
6074 size_t namelen, size;
6075 char *buf, *p;
6076 unsigned int i;
6077 const Token *t;
6079 namelen = strlen(m->iname);
6080 size = namelen + sizeof(prefix); /* Includes final null (from prefix) */
6082 for (i = 1; i <= m->nparam; i++) {
6083 int j = 0;
6084 size += 3; /* Braces and space/comma */
6085 list_for_each(t, m->params[i]) {
6086 if (j++ >= m->paramlen[i])
6087 break;
6088 size += (t->type == TOK_WHITESPACE) ? 1 : t->len;
6092 buf = p = nasm_malloc(size);
6093 p = mempcpy(p, prefix, sizeof(prefix) - 1);
6094 p = mempcpy(p, m->iname, namelen);
6095 *p++ = ' ';
6097 for (i = 1; i <= m->nparam; i++) {
6098 int j = 0;
6099 *p++ = '{';
6100 list_for_each(t, m->params[i]) {
6101 if (j++ >= m->paramlen[i])
6102 break;
6103 p = mempcpy(p, tok_text(t), t->len);
6105 *p++ = '}';
6106 *p++ = ',';
6109 *--p = '\0'; /* Replace last delimeter with null */
6110 lfmt->line(LIST_MACRO, -1, buf);
6111 nasm_free(buf);
6115 * Expand the multi-line macro call made by the given line, if
6116 * there is one to be expanded. If there is, push the expansion on
6117 * istk->expansion and return 1. Otherwise return 0.
6119 static int expand_mmacro(Token * tline)
6121 Token *startline = tline;
6122 Token *label = NULL;
6123 bool dont_prepend = false;
6124 Token **params, *t, *tt;
6125 MMacro *m;
6126 Line *l, *ll;
6127 int i, *paramlen;
6128 const char *mname;
6129 int nparam = 0;
6131 t = tline;
6132 t = skip_white(t);
6133 /* if (!tok_type(t, TOK_ID)) Lino 02/25/02 */
6134 if (!tok_type(t, TOK_ID) && !tok_type(t, TOK_LOCAL_MACRO))
6135 return 0;
6136 m = is_mmacro(t, &nparam, &params);
6137 if (m) {
6138 mname = tok_text(t);
6139 } else {
6140 Token *last;
6142 * We have an id which isn't a macro call. We'll assume
6143 * it might be a label; we'll also check to see if a
6144 * colon follows it. Then, if there's another id after
6145 * that lot, we'll check it again for macro-hood.
6147 label = last = t;
6148 t = t->next;
6149 if (tok_white(t))
6150 last = t, t = t->next;
6151 if (tok_is(t, ':')) {
6152 dont_prepend = true;
6153 last = t, t = t->next;
6154 if (tok_white(t))
6155 last = t, t = t->next;
6157 if (!tok_type(t, TOK_ID) || !(m = is_mmacro(t, &nparam, &params)))
6158 return 0;
6159 last->next = NULL;
6160 mname = tok_text(t);
6161 tline = t;
6164 if (unlikely(mmacro_deadman.total >= nasm_limit[LIMIT_MMACROS] ||
6165 mmacro_deadman.levels >= nasm_limit[LIMIT_MACRO_LEVELS])) {
6166 if (!mmacro_deadman.triggered) {
6167 nasm_nonfatal("interminable multiline macro recursion");
6168 mmacro_deadman.triggered = true;
6170 return 0;
6173 mmacro_deadman.total++;
6174 mmacro_deadman.levels++;
6177 * Fix up the parameters: this involves stripping leading and
6178 * trailing whitespace and stripping braces if they are present.
6180 nasm_newn(paramlen, nparam+1);
6182 for (i = 1; (t = params[i]); i++) {
6183 bool braced = false;
6184 int brace = 0;
6185 int white = 0;
6186 bool comma = !m->plus || i < nparam;
6188 t = skip_white(t);
6189 if (tok_is(t, '{')) {
6190 t = t->next;
6191 brace = 1;
6192 braced = true;
6193 comma = false;
6196 params[i] = t;
6197 for (; t; t = t->next) {
6198 if (tok_white(t)) {
6199 white++;
6200 continue;
6203 if (t->type == TOK_OTHER && t->len == 1) {
6204 switch (t->text.a[0]) {
6205 case ',':
6206 if (comma && !brace)
6207 goto endparam;
6208 break;
6210 case '{':
6211 brace++;
6212 break;
6214 case '}':
6215 brace--;
6216 if (braced && !brace) {
6217 paramlen[i] += white;
6218 goto endparam;
6220 break;
6222 default:
6223 break;
6227 paramlen[i] += white + 1;
6228 white = 0;
6230 endparam:
6235 * OK, we have a MMacro structure together with a set of
6236 * parameters. We must now go through the expansion and push
6237 * copies of each Line on to istk->expansion. Substitution of
6238 * parameter tokens and macro-local tokens doesn't get done
6239 * until the single-line macro substitution process; this is
6240 * because delaying them allows us to change the semantics
6241 * later through %rotate and give the right semantics for
6242 * nested mmacros.
6244 * First, push an end marker on to istk->expansion, mark this
6245 * macro as in progress, and set up its invocation-specific
6246 * variables.
6248 nasm_new(ll);
6249 ll->next = istk->expansion;
6250 ll->finishes = m;
6251 ll->where = istk->where;
6252 istk->expansion = ll;
6255 * Save the previous MMacro expansion in the case of
6256 * macro recursion
6258 #if 0
6259 if (m->max_depth && m->in_progress)
6260 push_mmacro(m);
6261 #endif
6263 m->in_progress ++;
6264 m->params = params;
6265 m->iline = tline;
6266 m->iname = nasm_strdup(mname);
6267 m->nparam = nparam;
6268 m->rotate = 0;
6269 m->paramlen = paramlen;
6270 m->unique = unique++;
6271 m->condcnt = 0;
6273 m->mstk = istk->mstk;
6274 istk->mstk.mstk = istk->mstk.mmac = m;
6276 list_for_each(l, m->expansion) {
6277 nasm_new(ll);
6278 ll->next = istk->expansion;
6279 istk->expansion = ll;
6280 ll->first = dup_tlist(l->first, NULL);
6281 ll->where = l->where;
6285 * If we had a label, and this macro definition does not include
6286 * a %00, push it on as the first line of, ot
6287 * the macro expansion.
6289 if (label) {
6291 * We had a label. If this macro contains an %00 parameter,
6292 * save the value as a special parameter (which is what it
6293 * is), otherwise push it as the first line of the macro
6294 * expansion.
6296 if (m->capture_label) {
6297 params[0] = dup_Token(NULL, label);
6298 paramlen[0] = 1;
6299 free_tlist(startline);
6300 } else {
6301 nasm_new(ll);
6302 ll->finishes = NULL;
6303 ll->next = istk->expansion;
6304 istk->expansion = ll;
6305 ll->first = startline;
6306 ll->where = istk->where;
6307 if (!dont_prepend) {
6308 while (label->next)
6309 label = label->next;
6310 label->next = tt = make_tok_char(NULL, ':');
6315 istk->nolist += !!(m->nolist & NL_LIST);
6316 istk->noline += !!(m->nolist & NL_LINE);
6318 if (!istk->nolist) {
6319 lfmt->uplevel(LIST_MACRO, 0);
6321 if (list_option('m'))
6322 list_mmacro_call(m);
6325 if (!istk->noline)
6326 src_macro_push(m, istk->where);
6328 return 1;
6332 * This function decides if an error message should be suppressed.
6333 * It will never be called with a severity level of ERR_FATAL or
6334 * higher.
6336 static bool pp_suppress_error(errflags severity)
6339 * If we're in a dead branch of IF or something like it, ignore the error.
6340 * However, because %else etc are evaluated in the state context
6341 * of the previous branch, errors might get lost:
6342 * %if 0 ... %else trailing garbage ... %endif
6343 * So %else etc should set the ERR_PP_PRECOND flag.
6345 if (istk && istk->conds &&
6346 ((severity & ERR_PP_PRECOND) ?
6347 istk->conds->state == COND_NEVER :
6348 !emitting(istk->conds->state)))
6349 return true;
6351 return false;
6354 static Token *
6355 stdmac_file(const SMacro *s, Token **params, int nparams)
6357 (void)s;
6358 (void)params;
6359 (void)nparams;
6361 return make_tok_qstr(NULL, src_get_fname());
6364 static Token *
6365 stdmac_line(const SMacro *s, Token **params, int nparams)
6367 (void)s;
6368 (void)params;
6369 (void)nparams;
6371 return make_tok_num(NULL, src_get_linnum());
6374 static Token *
6375 stdmac_bits(const SMacro *s, Token **params, int nparams)
6377 (void)s;
6378 (void)params;
6379 (void)nparams;
6381 return make_tok_num(NULL, globalbits);
6384 static Token *
6385 stdmac_ptr(const SMacro *s, Token **params, int nparams)
6387 (void)s;
6388 (void)params;
6389 (void)nparams;
6391 switch (globalbits) {
6392 case 16:
6393 return new_Token(NULL, TOK_ID, "word", 4);
6394 case 32:
6395 return new_Token(NULL, TOK_ID, "dword", 5);
6396 case 64:
6397 return new_Token(NULL, TOK_ID, "qword", 5);
6398 default:
6399 panic();
6403 /* Add magic standard macros */
6404 struct magic_macros {
6405 const char *name;
6406 int nparam;
6407 ExpandSMacro func;
6409 static const struct magic_macros magic_macros[] =
6411 { "__?FILE?__", 0, stdmac_file },
6412 { "__?LINE?__", 0, stdmac_line },
6413 { "__?BITS?__", 0, stdmac_bits },
6414 { "__?PTR?__", 0, stdmac_ptr },
6415 { NULL, 0, NULL }
6418 static void pp_add_magic_stdmac(void)
6420 const struct magic_macros *m;
6421 SMacro tmpl;
6423 nasm_zero(tmpl);
6425 for (m = magic_macros; m->name; m++) {
6426 tmpl.nparam = m->nparam;
6427 tmpl.expand = m->func;
6428 define_smacro(m->name, true, NULL, &tmpl);
6432 static void
6433 pp_reset(const char *file, enum preproc_mode mode, struct strlist *dep_list)
6435 int apass;
6436 struct Include *inc;
6438 cstk = NULL;
6439 defining = NULL;
6440 nested_mac_count = 0;
6441 nested_rep_count = 0;
6442 init_macros();
6443 unique = 0;
6444 deplist = dep_list;
6445 pp_mode = mode;
6447 /* Reset options to default */
6448 nasm_zero(ppopt);
6450 if (!use_loaded)
6451 use_loaded = nasm_malloc(use_package_count * sizeof(bool));
6452 memset(use_loaded, 0, use_package_count * sizeof(bool));
6454 /* First set up the top level input file */
6455 nasm_new(istk);
6456 istk->fp = nasm_open_read(file, NF_TEXT);
6457 if (!istk->fp) {
6458 nasm_fatalf(ERR_NOFILE, "unable to open input file `%s'%s%s",
6459 file, errno ? " " : "", errno ? strerror(errno) : "");
6461 src_set(0, file);
6462 istk->where = src_where();
6463 istk->lineinc = 1;
6465 strlist_add(deplist, file);
6468 * Set up the stdmac packages as a virtual include file,
6469 * indicated by a null file pointer.
6471 nasm_new(inc);
6472 inc->next = istk;
6473 src_set(0, NULL);
6474 inc->where = src_where();
6475 inc->nolist = !list_option('b');
6476 istk = inc;
6477 lfmt->uplevel(LIST_INCLUDE, 0);
6479 pp_add_magic_stdmac();
6481 if (tasm_compatible_mode)
6482 pp_add_stdmac(nasm_stdmac_tasm);
6484 pp_add_stdmac(nasm_stdmac_nasm);
6485 pp_add_stdmac(nasm_stdmac_version);
6487 if (extrastdmac)
6488 pp_add_stdmac(extrastdmac);
6490 stdmacpos = stdmacros[0];
6491 stdmacnext = &stdmacros[1];
6493 do_predef = true;
6496 * Define the __?PASS?__ macro. This is defined here unlike all the
6497 * other builtins, because it is special -- it varies between
6498 * passes -- but there is really no particular reason to make it
6499 * magic.
6501 * 0 = dependencies only
6502 * 1 = preparatory passes
6503 * 2 = final pass
6504 * 3 = preproces only
6506 switch (mode) {
6507 case PP_NORMAL:
6508 apass = pass_final() ? 2 : 1;
6509 break;
6510 case PP_DEPS:
6511 apass = 0;
6512 break;
6513 case PP_PREPROC:
6514 apass = 3;
6515 break;
6516 default:
6517 panic();
6520 define_smacro("__?PASS?__", true, make_tok_num(NULL, apass), NULL);
6523 static void pp_init(void)
6528 * Get a line of tokens. If we popped the macro expansion/include stack,
6529 * we return a pointer to the dummy token tok_pop; at that point if
6530 * istk is NULL then we have reached end of input;
6532 static Token tok_pop; /* Dummy token placeholder */
6534 static Token *pp_tokline(void)
6536 while (true) {
6537 Line *l = istk->expansion;
6538 Token *tline = NULL;
6539 Token *dtline;
6542 * Fetch a tokenized line, either from the macro-expansion
6543 * buffer or from the input file.
6545 tline = NULL;
6546 while (l && l->finishes) {
6547 MMacro *fm = l->finishes;
6549 nasm_assert(fm == istk->mstk.mstk);
6551 if (!fm->name && fm->in_progress > 1) {
6553 * This is a macro-end marker for a macro with no
6554 * name, which means it's not really a macro at all
6555 * but a %rep block, and the `in_progress' field is
6556 * more than 1, meaning that we still need to
6557 * repeat. (1 means the natural last repetition; 0
6558 * means termination by %exitrep.) We have
6559 * therefore expanded up to the %endrep, and must
6560 * push the whole block on to the expansion buffer
6561 * again. We don't bother to remove the macro-end
6562 * marker: we'd only have to generate another one
6563 * if we did.
6565 fm->in_progress--;
6566 list_for_each(l, fm->expansion) {
6567 Line *ll;
6569 nasm_new(ll);
6570 ll->next = istk->expansion;
6571 ll->first = dup_tlist(l->first, NULL);
6572 ll->where = l->where;
6573 istk->expansion = ll;
6575 break;
6576 } else {
6577 MMacro *m = istk->mstk.mstk;
6580 * Check whether a `%rep' was started and not ended
6581 * within this macro expansion. This can happen and
6582 * should be detected. It's a fatal error because
6583 * I'm too confused to work out how to recover
6584 * sensibly from it.
6586 if (defining) {
6587 if (defining->name)
6588 nasm_panic("defining with name in expansion");
6589 else if (m->name)
6590 nasm_fatal("`%%rep' without `%%endrep' within"
6591 " expansion of macro `%s'", m->name);
6595 * FIXME: investigate the relationship at this point between
6596 * istk->mstk.mstk and fm
6598 istk->mstk = m->mstk;
6599 if (m->name) {
6601 * This was a real macro call, not a %rep, and
6602 * therefore the parameter information needs to
6603 * be freed and the iteration count/nesting
6604 * depth adjusted.
6607 if (!--mmacro_deadman.levels) {
6609 * If all mmacro processing done,
6610 * clear all counters and the deadman
6611 * message trigger.
6613 nasm_zero(mmacro_deadman); /* Clear all counters */
6616 #if 0
6617 if (m->prev) {
6618 pop_mmacro(m);
6619 fm->in_progress --;
6620 } else
6621 #endif
6623 nasm_free(m->params);
6624 free_tlist(m->iline);
6625 nasm_free(m->paramlen);
6626 fm->in_progress = 0;
6630 if (fm->nolist & NL_LIST) {
6631 istk->nolist--;
6632 } else if (!istk->nolist) {
6633 lfmt->downlevel(LIST_MACRO);
6636 if (fm->nolist & NL_LINE) {
6637 istk->noline--;
6638 } else if (!istk->noline) {
6639 if (fm == src_macro_current())
6640 src_macro_pop();
6641 src_update(l->where);
6644 istk->where = l->where;
6647 * FIXME It is incorrect to always free_mmacro here.
6648 * It leads to usage-after-free.
6650 * https://bugzilla.nasm.us/show_bug.cgi?id=3392414
6652 #if 0
6653 else
6654 free_mmacro(m);
6655 #endif
6657 istk->expansion = l->next;
6658 nasm_free(l);
6660 return &tok_pop;
6663 do { /* until we get a line we can use */
6664 char *line;
6666 if (istk->expansion) { /* from a macro expansion */
6667 Line *l = istk->expansion;
6669 istk->expansion = l->next;
6670 istk->where = l->where;
6671 tline = l->first;
6672 nasm_free(l);
6674 if (!istk->noline)
6675 src_update(istk->where);
6677 if (!istk->nolist) {
6678 line = detoken(tline, false);
6679 lfmt->line(LIST_MACRO, istk->where.lineno, line);
6680 nasm_free(line);
6682 } else if ((line = read_line())) {
6683 line = prepreproc(line);
6684 tline = tokenize(line);
6685 nasm_free(line);
6686 } else {
6688 * The current file has ended; work down the istk
6690 Include *i = istk;
6691 Include *is;
6693 if (i->fp)
6694 fclose(i->fp);
6695 if (i->conds) {
6696 /* nasm_fatal can't be conditionally suppressed */
6697 nasm_fatal("expected `%%endif' before end of file");
6700 list_for_each(is, i->next) {
6701 if (is->fp) {
6702 lfmt->downlevel(LIST_INCLUDE);
6703 src_update(is->where);
6704 break;
6707 istk = i->next;
6708 nasm_free(i);
6709 return &tok_pop;
6711 } while (0);
6714 * We must expand MMacro parameters and MMacro-local labels
6715 * _before_ we plunge into directive processing, to cope
6716 * with things like `%define something %1' such as STRUC
6717 * uses. Unless we're _defining_ a MMacro, in which case
6718 * those tokens should be left alone to go into the
6719 * definition; and unless we're in a non-emitting
6720 * condition, in which case we don't want to meddle with
6721 * anything.
6723 if (!defining &&
6724 !(istk->conds && !emitting(istk->conds->state)) &&
6725 !(istk->mstk.mmac && !istk->mstk.mmac->in_progress)) {
6726 tline = expand_mmac_params(tline);
6730 * Check the line to see if it's a preprocessor directive.
6732 if (do_directive(tline, &dtline) == DIRECTIVE_FOUND) {
6733 if (dtline)
6734 return dtline;
6735 } else if (defining) {
6737 * We're defining a multi-line macro. We emit nothing
6738 * at all, and just
6739 * shove the tokenized line on to the macro definition.
6741 MMacro *mmac = defining->dstk.mmac;
6742 Line *l;
6744 nasm_new(l);
6745 l->next = defining->expansion;
6746 l->first = tline;
6747 l->finishes = NULL;
6748 l->where = istk->where;
6749 defining->expansion = l;
6752 * Remember if this mmacro expansion contains %00:
6753 * if it does, we will have to handle leading labels
6754 * specially.
6756 if (mmac) {
6757 const Token *t;
6758 list_for_each(t, tline) {
6759 if (!memcmp(t->text.a, "%00", 4))
6760 mmac->capture_label = true;
6763 } else if (istk->conds && !emitting(istk->conds->state)) {
6765 * We're in a non-emitting branch of a condition block.
6766 * Emit nothing at all, not even a blank line: when we
6767 * emerge from the condition we'll give a line-number
6768 * directive so we keep our place correctly.
6770 free_tlist(tline);
6771 } else if (istk->mstk.mstk && !istk->mstk.mstk->in_progress) {
6773 * We're in a %rep block which has been terminated, so
6774 * we're walking through to the %endrep without
6775 * emitting anything. Emit nothing at all, not even a
6776 * blank line: when we emerge from the %rep block we'll
6777 * give a line-number directive so we keep our place
6778 * correctly.
6780 free_tlist(tline);
6781 } else {
6782 tline = expand_smacro(tline);
6783 if (!expand_mmacro(tline))
6784 return tline;
6789 static char *pp_getline(void)
6791 char *line = NULL;
6792 Token *tline;
6794 while (true) {
6795 tline = pp_tokline();
6796 if (tline == &tok_pop) {
6798 * We popped the macro/include stack. If istk is empty,
6799 * we are at end of input, otherwise just loop back.
6801 if (!istk)
6802 break;
6803 } else {
6805 * De-tokenize the line and emit it.
6807 line = detoken(tline, true);
6808 free_tlist(tline);
6809 break;
6813 if (list_option('e') && istk && !istk->nolist && line && line[0]) {
6814 char *buf = nasm_strcat(" ;;; ", line);
6815 lfmt->line(LIST_MACRO, -1, buf);
6816 nasm_free(buf);
6819 return line;
6822 static void pp_cleanup_pass(void)
6824 if (defining) {
6825 if (defining->name) {
6826 nasm_nonfatal("end of file while still defining macro `%s'",
6827 defining->name);
6828 } else {
6829 nasm_nonfatal("end of file while still in %%rep");
6832 free_mmacro(defining);
6833 defining = NULL;
6836 while (cstk)
6837 ctx_pop();
6838 free_macros();
6839 while (istk) {
6840 Include *i = istk;
6841 istk = istk->next;
6842 fclose(i->fp);
6843 nasm_free(i);
6845 while (cstk)
6846 ctx_pop();
6847 src_set_fname(NULL);
6850 static void pp_cleanup_session(void)
6852 nasm_free(use_loaded);
6853 free_llist(predef);
6854 predef = NULL;
6855 delete_Blocks();
6856 ipath_list = NULL;
6859 static void pp_include_path(struct strlist *list)
6861 ipath_list = list;
6864 static void pp_pre_include(char *fname)
6866 Token *inc, *space, *name;
6867 Line *l;
6869 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
6870 space = new_White(name);
6871 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
6873 l = nasm_malloc(sizeof(Line));
6874 l->next = predef;
6875 l->first = inc;
6876 l->finishes = NULL;
6877 predef = l;
6880 static void pp_pre_define(char *definition)
6882 Token *def, *space;
6883 Line *l;
6884 char *equals;
6886 equals = strchr(definition, '=');
6887 space = new_White(NULL);
6888 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
6889 if (equals)
6890 *equals = ' ';
6891 space->next = tokenize(definition);
6892 if (equals)
6893 *equals = '=';
6895 /* We can't predefine a TOK_LOCAL_MACRO for obvious reasons... */
6896 if (space->next->type != TOK_PREPROC_ID &&
6897 space->next->type != TOK_ID)
6898 nasm_warn(WARN_OTHER, "pre-defining non ID `%s\'\n", definition);
6900 l = nasm_malloc(sizeof(Line));
6901 l->next = predef;
6902 l->first = def;
6903 l->finishes = NULL;
6904 predef = l;
6907 static void pp_pre_undefine(char *definition)
6909 Token *def, *space;
6910 Line *l;
6912 space = new_White(NULL);
6913 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
6914 space->next = tokenize(definition);
6916 l = nasm_malloc(sizeof(Line));
6917 l->next = predef;
6918 l->first = def;
6919 l->finishes = NULL;
6920 predef = l;
6923 /* Insert an early preprocessor command that doesn't need special handling */
6924 static void pp_pre_command(const char *what, char *string)
6926 char *cmd;
6927 Token *def, *space;
6928 Line *l;
6930 def = tokenize(string);
6931 if (what) {
6932 space = new_White(def);
6933 cmd = nasm_strcat(what[0] == '%' ? "" : "%", what);
6934 def = new_Token(space, TOK_PREPROC_ID, cmd, nasm_last_string_len());
6935 nasm_free(cmd);
6938 l = nasm_malloc(sizeof(Line));
6939 l->next = predef;
6940 l->first = def;
6941 l->finishes = NULL;
6942 predef = l;
6945 static void pp_add_stdmac(macros_t *macros)
6947 macros_t **mp;
6949 /* Find the end of the list and avoid duplicates */
6950 for (mp = stdmacros; *mp; mp++) {
6951 if (*mp == macros)
6952 return; /* Nothing to do */
6955 nasm_assert(mp < &stdmacros[ARRAY_SIZE(stdmacros)-1]);
6957 *mp = macros;
6960 static void pp_extra_stdmac(macros_t *macros)
6962 extrastdmac = macros;
6965 /* Create a numeric token */
6966 static Token *make_tok_num(Token *next, int64_t val)
6968 char numbuf[32];
6969 int len = snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
6970 return new_Token(next, TOK_NUMBER, numbuf, len);
6973 /* Create a quoted string token */
6974 static Token *make_tok_qstr_len(Token *next, const char *str, size_t len)
6976 char *p = nasm_quote(str, &len);
6977 return new_Token_free(next, TOK_STRING, p, len);
6979 static Token *make_tok_qstr(Token *next, const char *str)
6981 return make_tok_qstr_len(next, str, strlen(str));
6984 /* Create a single-character operator token */
6985 static Token *make_tok_char(Token *next, char op)
6987 Token *t = new_Token(next, TOK_OTHER, NULL, 1);
6988 t->text.a[0] = op;
6989 return t;
6993 * Descent the macro hierarchy and display the expansion after
6994 * encountering an error message.
6996 static void pp_error_list_macros(errflags severity)
6998 const MMacro *m;
7000 severity |= ERR_PP_LISTMACRO | ERR_NO_SEVERITY | ERR_HERE;
7002 while ((m = src_error_down())) {
7003 nasm_error(severity, "... from macro `%s' defined", m->name);
7006 src_error_reset();
7009 const struct preproc_ops nasmpp = {
7010 pp_init,
7011 pp_reset,
7012 pp_getline,
7013 pp_cleanup_pass,
7014 pp_cleanup_session,
7015 pp_extra_stdmac,
7016 pp_pre_define,
7017 pp_pre_undefine,
7018 pp_pre_include,
7019 pp_pre_command,
7020 pp_include_path,
7021 pp_error_list_macros,
7022 pp_suppress_error