preproc: fix the detection of the >= operator
[nasm.git] / asm / preproc.c
blob14a73885ac2304118047ced75b3a2571ee59c033
1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2019 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
35 * preproc.c macro preprocessor for the Netwide Assembler
38 /* Typical flow of text through preproc
40 * pp_getline gets tokenized lines, either
42 * from a macro expansion
44 * or
45 * {
46 * read_line gets raw text from stdmacpos, or predef, or current input file
47 * tokenize converts to tokens
48 * }
50 * expand_mmac_params is used to expand %1 etc., unless a macro is being
51 * defined or a false conditional is being processed
52 * (%0, %1, %+1, %-1, %%foo
54 * do_directive checks for directives
56 * expand_smacro is used to expand single line macros
58 * expand_mmacro is used to expand multi-line macros
60 * detoken is used to convert the line back to text
63 #include "compiler.h"
65 #include "nctype.h"
67 #include "nasm.h"
68 #include "nasmlib.h"
69 #include "error.h"
70 #include "preproc.h"
71 #include "hashtbl.h"
72 #include "quote.h"
73 #include "stdscan.h"
74 #include "eval.h"
75 #include "tokens.h"
76 #include "tables.h"
77 #include "listing.h"
79 typedef struct SMacro SMacro;
80 typedef struct MMacro MMacro;
81 typedef struct MMacroInvocation MMacroInvocation;
82 typedef struct Context Context;
83 typedef struct Token Token;
84 typedef struct Line Line;
85 typedef struct Include Include;
86 typedef struct Cond Cond;
89 * This is the internal form which we break input lines up into.
90 * Typically stored in linked lists.
92 * Note that `type' serves a double meaning: TOK_SMAC_START_PARAMS is
93 * not necessarily used as-is, but is also used to encode the number
94 * and expansion type of substituted parameter. So in the definition
96 * %define a(x,=y) ( (x) & ~(y) )
98 * the token representing `x' will have its type changed to
99 * tok_smac_param(0) but the one representing `y' will be
100 * tok_smac_param(1); see the accessor functions below.
102 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
103 * which doesn't need quotes around it. Used in the pre-include
104 * mechanism as an alternative to trying to find a sensible type of
105 * quote to use on the filename we were passed.
107 enum pp_token_type {
108 TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT,
109 TOK_CORRUPT, /* Token text modified in an unsafe manner, now bogus */
110 TOK_BLOCK, /* Storage block pointer, not a real token */
111 TOK_ID,
112 TOK_PREPROC_ID, TOK_MMACRO_PARAM, TOK_LOCAL_SYMBOL,
113 TOK_LOCAL_MACRO, TOK_ENVIRON, TOK_STRING,
114 TOK_NUMBER, TOK_FLOAT, TOK_OTHER,
115 TOK_INTERNAL_STRING,
116 TOK_PREPROC_Q, TOK_PREPROC_QQ,
117 TOK_PASTE, /* %+ */
118 TOK_COND_COMMA, /* %, */
119 TOK_INDIRECT, /* %[...] */
120 TOK_SMAC_START_PARAMS, /* MUST BE LAST IN THE LIST!!! */
121 TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
124 static inline enum pp_token_type tok_smac_param(int param)
126 return TOK_SMAC_START_PARAMS + param;
128 static int smac_nparam(enum pp_token_type toktype)
130 return toktype - TOK_SMAC_START_PARAMS;
132 static bool is_smac_param(enum pp_token_type toktype)
134 return toktype >= TOK_SMAC_START_PARAMS;
137 #define PP_CONCAT_MASK(x) (1U << (x))
139 struct tokseq_match {
140 int mask_head;
141 int mask_tail;
145 * This is tuned so struct Token should be 64 bytes on 64-bit
146 * systems and 32 bytes on 32-bit systems. It enables them
147 * to be nicely cache aligned, and the text to still be kept
148 * inline for nearly all tokens.
150 * We prohibit tokens of length > MAX_TEXT even though
151 * length here is an unsigned int; this avoids problems
152 * if the length is passed through an interface with type "int",
153 * and is absurdly large anyway.
155 * For the text mode, in pointer mode the pointer is stored at the end
156 * of the union and the pad field is cleared. This allows short tokens
157 * to be unconditionally tested for by only looking at the first text
158 * bytes and not examining the type or len fields.
160 #define INLINE_TEXT (7*sizeof(char *)-sizeof(enum pp_token_type)-sizeof(unsigned int)-1)
161 #define MAX_TEXT (INT_MAX-2)
163 struct Token {
164 Token *next;
165 enum pp_token_type type;
166 unsigned int len;
167 union {
168 char a[INLINE_TEXT+1];
169 struct {
170 char pad[INLINE_TEXT+1 - sizeof(char *)];
171 char *ptr;
172 } p;
173 } text;
177 * Note on the storage of both SMacro and MMacros: the hash table
178 * indexes them case-insensitively, and we then have to go through a
179 * linked list of potential case aliases (and, for MMacros, parameter
180 * ranges); this is to preserve the matching semantics of the earlier
181 * code. If the number of case aliases for a specific macro is a
182 * performance issue, you may want to reconsider your coding style.
186 * Function call tp obtain the expansion of an smacro
188 typedef Token *(*ExpandSMacro)(const SMacro *s, Token **params, int nparams);
191 * Store the definition of a single-line macro.
193 enum sparmflags {
194 SPARM_PLAIN = 0,
195 SPARM_EVAL = 1, /* Evaluate as a numeric expression (=) */
196 SPARM_STR = 2, /* Convert to quoted string ($) */
197 SPARM_NOSTRIP = 4, /* Don't strip braces (!) */
198 SPARM_GREEDY = 8 /* Greedy final parameter (+) */
201 struct smac_param {
202 Token name;
203 enum sparmflags flags;
206 struct SMacro {
207 SMacro *next; /* MUST BE FIRST - see free_smacro() */
208 char *name;
209 Token *expansion;
210 ExpandSMacro expand;
211 intorptr expandpvt;
212 struct smac_param *params;
213 int nparam;
214 bool greedy;
215 bool casesense;
216 bool in_progress;
217 bool alias; /* This is an alias macro */
221 * Store the definition of a multi-line macro. This is also used to
222 * store the interiors of `%rep...%endrep' blocks, which are
223 * effectively self-re-invoking multi-line macros which simply
224 * don't have a name or bother to appear in the hash tables. %rep
225 * blocks are signified by having a NULL `name' field.
227 * In a MMacro describing a `%rep' block, the `in_progress' field
228 * isn't merely boolean, but gives the number of repeats left to
229 * run.
231 * The `next' field is used for storing MMacros in hash tables; the
232 * `next_active' field is for stacking them on istk entries.
234 * When a MMacro is being expanded, `params', `iline', `nparam',
235 * `paramlen', `rotate' and `unique' are local to the invocation.
239 * Expansion stack. Note that .mmac can point back to the macro itself,
240 * whereas .mstk cannot.
242 struct mstk {
243 MMacro *mstk; /* Any expansion, real macro or not */
244 MMacro *mmac; /* Highest level actual mmacro */
247 struct MMacro {
248 MMacro *next;
249 #if 0
250 MMacroInvocation *prev; /* previous invocation */
251 #endif
252 char *name;
253 int nparam_min, nparam_max;
254 bool casesense;
255 bool plus; /* is the last parameter greedy? */
256 bool nolist; /* is this macro listing-inhibited? */
257 bool capture_label; /* macro definition has %00; capture label */
258 int32_t in_progress; /* is this macro currently being expanded? */
259 int32_t max_depth; /* maximum number of recursive expansions allowed */
260 Token *dlist; /* All defaults as one list */
261 Token **defaults; /* Parameter default pointers */
262 int ndefs; /* number of default parameters */
263 Line *expansion;
265 struct mstk mstk; /* Macro expansion stack */
266 struct mstk dstk; /* Macro definitions stack */
267 Token **params; /* actual parameters */
268 Token *iline; /* invocation line */
269 unsigned int nparam, rotate;
270 char *iname; /* name invoked as */
271 int *paramlen;
272 uint64_t unique;
273 int lineno; /* Current line number on expansion */
274 uint64_t condcnt; /* number of if blocks... */
276 const char *fname; /* File where defined */
277 int32_t xline; /* First line in macro */
281 /* Store the definition of a multi-line macro, as defined in a
282 * previous recursive macro expansion.
284 #if 0
286 struct MMacroInvocation {
287 MMacroInvocation *prev; /* previous invocation */
288 Token **params; /* actual parameters */
289 Token *iline; /* invocation line */
290 unsigned int nparam, rotate;
291 int *paramlen;
292 uint64_t unique;
293 uint64_t condcnt;
296 #endif
299 * The context stack is composed of a linked list of these.
301 struct Context {
302 Context *next;
303 const char *name;
304 struct hash_table localmac;
305 uint64_t number;
306 unsigned int depth;
310 static inline const char *tok_text(const struct Token *t)
312 return (t->len <= INLINE_TEXT) ? t->text.a : t->text.p.ptr;
316 * Returns a mutable pointer to the text buffer. The text can be changed,
317 * but the length MUST NOT CHANGE, in either direction; nor is it permitted
318 * to pad with null characters to create an artificially shorter string.
320 static inline char *tok_text_buf(struct Token *t)
322 return (t->len <= INLINE_TEXT) ? t->text.a : t->text.p.ptr;
325 static inline unsigned int tok_check_len(size_t len)
327 if (unlikely(len > MAX_TEXT))
328 nasm_fatal("impossibly large token");
330 return len;
333 /* strlen() variant useful for set_text() and its variants */
334 static size_t tok_strlen(const char *str)
336 return strnlen(str, MAX_TEXT+1);
340 * Set the text field to a copy of the given string; the length if
341 * not given should be obtained with tok_strlen().
343 static Token *set_text(struct Token *t, const char *text, size_t len)
345 char *textp;
347 if (t->len > INLINE_TEXT)
348 nasm_free(t->text.p.ptr);
350 nasm_zero(t->text.a);
352 t->len = tok_check_len(len);
353 textp = (len > INLINE_TEXT)
354 ? (t->text.p.ptr = nasm_malloc(len+1)) : t->text.a;
355 memcpy(textp, text, len+1);
356 return t;
360 * Set the text field to the existing pre-allocated string, either
361 * taking over or freeing the allocation in the process.
363 static Token *set_text_free(struct Token *t, char *text, unsigned int len)
365 if (t->len > INLINE_TEXT)
366 nasm_free(t->text.p.ptr);
368 nasm_zero(t->text.a);
370 t->len = tok_check_len(len);
371 if (len > INLINE_TEXT) {
372 t->text.p.ptr = text;
373 } else {
374 memcpy(t->text.a, text, len+1);
375 nasm_free(text);
378 return t;
382 * Allocate a new buffer containing a copy of the text field
383 * of the token.
385 static char *dup_text(const struct Token *t)
387 size_t size = t->len + 1;
388 char *p = nasm_malloc(size);
390 return memcpy(p, tok_text(t), size);
394 * Multi-line macro definitions are stored as a linked list of
395 * these, which is essentially a container to allow several linked
396 * lists of Tokens.
398 * Note that in this module, linked lists are treated as stacks
399 * wherever possible. For this reason, Lines are _pushed_ on to the
400 * `expansion' field in MMacro structures, so that the linked list,
401 * if walked, would give the macro lines in reverse order; this
402 * means that we can walk the list when expanding a macro, and thus
403 * push the lines on to the `expansion' field in _istk_ in reverse
404 * order (so that when popped back off they are in the right
405 * order). It may seem cockeyed, and it relies on my design having
406 * an even number of steps in, but it works...
408 * Some of these structures, rather than being actual lines, are
409 * markers delimiting the end of the expansion of a given macro.
410 * This is for use in the cycle-tracking and %rep-handling code.
411 * Such structures have `finishes' non-NULL, and `first' NULL. All
412 * others have `finishes' NULL, but `first' may still be NULL if
413 * the line is blank.
415 struct Line {
416 Line *next;
417 MMacro *finishes;
418 Token *first;
422 * To handle an arbitrary level of file inclusion, we maintain a
423 * stack (ie linked list) of these things.
425 struct Include {
426 Include *next;
427 FILE *fp;
428 Cond *conds;
429 Line *expansion;
430 const char *fname;
431 struct mstk mstk;
432 int lineno, lineinc;
433 bool nolist;
437 * File real name hash, so we don't have to re-search the include
438 * path for every pass (and potentially more than that if a file
439 * is used more than once.)
441 struct hash_table FileHash;
444 * Counters to trap on insane macro recursion or processing.
445 * Note: for smacros these count *down*, for mmacros they count *up*.
447 struct deadman {
448 int64_t total; /* Total number of macros/tokens */
449 int64_t levels; /* Descent depth across all macros */
450 bool triggered; /* Already triggered, no need for error msg */
453 static struct deadman smacro_deadman, mmacro_deadman;
456 * Conditional assembly: we maintain a separate stack of these for
457 * each level of file inclusion. (The only reason we keep the
458 * stacks separate is to ensure that a stray `%endif' in a file
459 * included from within the true branch of a `%if' won't terminate
460 * it and cause confusion: instead, rightly, it'll cause an error.)
462 enum cond_state {
464 * These states are for use just after %if or %elif: IF_TRUE
465 * means the condition has evaluated to truth so we are
466 * currently emitting, whereas IF_FALSE means we are not
467 * currently emitting but will start doing so if a %else comes
468 * up. In these states, all directives are admissible: %elif,
469 * %else and %endif. (And of course %if.)
471 COND_IF_TRUE, COND_IF_FALSE,
473 * These states come up after a %else: ELSE_TRUE means we're
474 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
475 * any %elif or %else will cause an error.
477 COND_ELSE_TRUE, COND_ELSE_FALSE,
479 * These states mean that we're not emitting now, and also that
480 * nothing until %endif will be emitted at all. COND_DONE is
481 * used when we've had our moment of emission
482 * and have now started seeing %elifs. COND_NEVER is used when
483 * the condition construct in question is contained within a
484 * non-emitting branch of a larger condition construct,
485 * or if there is an error.
487 COND_DONE, COND_NEVER
489 struct Cond {
490 Cond *next;
491 enum cond_state state;
493 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
496 * These defines are used as the possible return values for do_directive
498 #define NO_DIRECTIVE_FOUND 0
499 #define DIRECTIVE_FOUND 1
502 * Condition codes. Note that we use c_ prefix not C_ because C_ is
503 * used in nasm.h for the "real" condition codes. At _this_ level,
504 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
505 * ones, so we need a different enum...
507 static const char * const conditions[] = {
508 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
509 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
510 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
512 enum pp_conds {
513 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
514 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
515 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
516 c_none = -1
518 static const enum pp_conds inverse_ccs[] = {
519 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
520 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,
521 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
525 * Directive names.
527 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
528 static int is_condition(enum preproc_token arg)
530 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
533 /* For TASM compatibility we need to be able to recognise TASM compatible
534 * conditional compilation directives. Using the NASM pre-processor does
535 * not work, so we look for them specifically from the following list and
536 * then jam in the equivalent NASM directive into the input stream.
539 enum {
540 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
541 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
544 static const char * const tasm_directives[] = {
545 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
546 "ifndef", "include", "local"
549 static int StackSize = 4;
550 static const char *StackPointer = "ebp";
551 static int ArgOffset = 8;
552 static int LocalOffset = 0;
554 static Context *cstk;
555 static Include *istk;
556 static const struct strlist *ipath_list;
557 static bool do_aliases;
559 static struct strlist *deplist;
561 static uint64_t unique; /* unique identifier numbers */
563 static Line *predef = NULL;
564 static bool do_predef;
565 static enum preproc_mode pp_mode;
568 * The current set of multi-line macros we have defined.
570 static struct hash_table mmacros;
573 * The current set of single-line macros we have defined.
575 static struct hash_table smacros;
578 * The multi-line macro we are currently defining, or the %rep
579 * block we are currently reading, if any.
581 static MMacro *defining;
583 static uint64_t nested_mac_count;
584 static uint64_t nested_rep_count;
587 * The number of macro parameters to allocate space for at a time.
589 #define PARAM_DELTA 16
592 * The standard macro set: defined in macros.c in a set of arrays.
593 * This gives our position in any macro set, while we are processing it.
594 * The stdmacset is an array of such macro sets.
596 static macros_t *stdmacpos;
597 static macros_t **stdmacnext;
598 static macros_t *stdmacros[8];
599 static macros_t *extrastdmac;
602 * Map of which %use packages have been loaded
604 static bool *use_loaded;
607 * Forward declarations.
609 static void pp_add_stdmac(macros_t *macros);
610 static Token *expand_mmac_params(Token * tline);
611 static Token *expand_smacro(Token * tline);
612 static Token *expand_id(Token * tline);
613 static Context *get_ctx(const char *name, const char **namep);
614 static Token *make_tok_num(Token *next, int64_t val);
615 static Token *make_tok_qstr(Token *next, const char *str);
616 static Token *make_tok_char(Token *next, char op);
617 static Token *new_Token(Token * next, enum pp_token_type type,
618 const char *text, size_t txtlen);
619 static Token *new_Token_free(Token * next, enum pp_token_type type,
620 char *text, size_t txtlen);
621 static Token *dup_Token(Token *next, const Token *src);
622 static Token *new_White(Token *next);
623 static Token *delete_Token(Token *t);
624 static Token *steal_Token(Token *dst, Token *src);
625 static const struct use_package *
626 get_use_pkg(Token *t, const char *dname, const char **name);
628 /* Safe test for token type, false on x == NULL */
629 static inline bool tok_type(const Token *x, enum pp_token_type t)
631 return x && x->type == t;
634 /* Whitespace token? */
635 static inline bool tok_white(const Token *x)
637 return tok_type(x, TOK_WHITESPACE);
640 /* Skip past any whitespace */
641 static inline Token *skip_white(Token *x)
643 while (tok_white(x))
644 x = x->next;
646 return x;
649 /* Delete any whitespace */
650 static Token *zap_white(Token *x)
652 while (tok_white(x))
653 x = delete_Token(x);
655 return x;
659 * Single special character tests. The use of & rather than && is intentional; it
660 * tells the compiler that it is safe to access text.a[1] unconditionally; hopefully
661 * a smart compiler should turn it into a 16-bit memory reference.
663 static inline bool tok_is(const Token *x, char c)
665 return x && ((x->text.a[0] == c) & !x->text.a[1]);
668 /* True if any other kind of token that "c", but not NULL */
669 static inline bool tok_isnt(const Token *x, char c)
671 return x && !((x->text.a[0] == c) & !x->text.a[1]);
675 * Unquote a token if it is a string, and set its type to
676 * TOK_INTERNAL_STRING.
678 static const char *unquote_token(Token *t)
680 if (t->type != TOK_STRING)
681 return tok_text(t);
683 t->type = TOK_INTERNAL_STRING;
685 if (t->len > INLINE_TEXT) {
686 char *p = t->text.p.ptr;
688 t->len = nasm_unquote(p, NULL);
690 if (t->len <= INLINE_TEXT) {
691 nasm_zero(t->text.a);
692 memcpy(t->text.a, p, t->len);
693 nasm_free(p);
694 return t->text.a;
695 } else {
696 return p;
698 } else {
699 t->len = nasm_unquote(t->text.a, NULL);
700 return t->text.a;
704 static const char *unquote_token_cstr(Token *t)
706 if (t->type != TOK_STRING)
707 return tok_text(t);
709 t->type = TOK_INTERNAL_STRING;
711 if (t->len > INLINE_TEXT) {
712 char *p = t->text.p.ptr;
714 t->len = nasm_unquote_cstr(p, NULL);
716 if (t->len <= INLINE_TEXT) {
717 nasm_zero(t->text.a);
718 memcpy(t->text.a, p, t->len);
719 nasm_free(p);
720 return t->text.a;
721 } else {
722 return p;
724 } else {
725 t->len = nasm_unquote_cstr(t->text.a, NULL);
726 return t->text.a;
730 static Token *quote_internal_string_token(Token *t)
732 size_t len;
733 char *p;
735 p = nasm_quote(tok_text(t), &len);
736 t->type = TOK_STRING;
737 return set_text_free(t, p, len);
740 static inline Token *quote_token(Token *t)
742 if (likely(!tok_is(t, TOK_INTERNAL_STRING)))
743 return t;
745 return quote_internal_string_token(t);
749 * In-place reverse a list of tokens.
751 static Token *reverse_tokens(Token *t)
753 Token *prev = NULL;
754 Token *next;
756 while (t) {
757 next = t->next;
758 t->next = prev;
759 prev = t;
760 t = next;
763 return prev;
767 * getenv() variant operating on an input token
769 static const char *pp_getenv(const Token *t, bool warn)
771 const char *txt = tok_text(t);
772 const char *v;
773 char *buf = NULL;
774 bool is_string = false;
776 if (!t)
777 return NULL;
779 switch (t->type) {
780 case TOK_ENVIRON:
781 txt += 2; /* Skip leading %! */
782 is_string = nasm_isquote(*txt);
783 break;
785 case TOK_STRING:
786 is_string = true;
787 break;
789 case TOK_INTERNAL_STRING:
790 case TOK_ID:
791 is_string = false;
792 break;
794 default:
795 return NULL;
798 if (is_string) {
799 buf = nasm_strdup(txt);
800 nasm_unquote_cstr(buf, NULL);
801 txt = buf;
804 v = getenv(txt);
805 if (warn && !v) {
807 *!environment [on] nonexistent environment variable
808 *! warns if a nonexistent environment variable
809 *! is accessed using the \c{%!} preprocessor
810 *! construct (see \k{getenv}.) Such environment
811 *! variables are treated as empty (with this
812 *! warning issued) starting in NASM 2.15;
813 *! earlier versions of NASM would treat this as
814 *! an error.
816 nasm_warn(WARN_ENVIRONMENT, "nonexistent environment variable `%s'", txt);
817 v = "";
820 if (buf)
821 nasm_free(buf);
823 return v;
827 * Handle TASM specific directives, which do not contain a % in
828 * front of them. We do it here because I could not find any other
829 * place to do it for the moment, and it is a hack (ideally it would
830 * be nice to be able to use the NASM pre-processor to do it).
832 static char *check_tasm_directive(char *line)
834 int32_t i, j, k, m, len;
835 char *p, *q, *oldline, oldchar;
837 p = nasm_skip_spaces(line);
839 /* Binary search for the directive name */
840 i = -1;
841 j = ARRAY_SIZE(tasm_directives);
842 q = nasm_skip_word(p);
843 len = q - p;
844 if (len) {
845 oldchar = p[len];
846 p[len] = 0;
847 while (j - i > 1) {
848 k = (j + i) / 2;
849 m = nasm_stricmp(p, tasm_directives[k]);
850 if (m == 0) {
851 /* We have found a directive, so jam a % in front of it
852 * so that NASM will then recognise it as one if it's own.
854 p[len] = oldchar;
855 len = strlen(p);
856 oldline = line;
857 line = nasm_malloc(len + 2);
858 line[0] = '%';
859 if (k == TM_IFDIFI) {
861 * NASM does not recognise IFDIFI, so we convert
862 * it to %if 0. This is not used in NASM
863 * compatible code, but does need to parse for the
864 * TASM macro package.
866 strcpy(line + 1, "if 0");
867 } else {
868 memcpy(line + 1, p, len + 1);
870 nasm_free(oldline);
871 return line;
872 } else if (m < 0) {
873 j = k;
874 } else
875 i = k;
877 p[len] = oldchar;
879 return line;
883 * The pre-preprocessing stage... This function translates line
884 * number indications as they emerge from GNU cpp (`# lineno "file"
885 * flags') into NASM preprocessor line number indications (`%line
886 * lineno file').
888 static char *prepreproc(char *line)
890 int lineno, fnlen;
891 char *fname, *oldline;
893 if (line[0] == '#' && line[1] == ' ') {
894 oldline = line;
895 fname = oldline + 2;
896 lineno = atoi(fname);
897 fname += strspn(fname, "0123456789 ");
898 if (*fname == '"')
899 fname++;
900 fnlen = strcspn(fname, "\"");
901 line = nasm_malloc(20 + fnlen);
902 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
903 nasm_free(oldline);
905 if (tasm_compatible_mode)
906 return check_tasm_directive(line);
907 return line;
911 * Free a linked list of tokens.
913 static void free_tlist(Token * list)
915 while (list)
916 list = delete_Token(list);
920 * Free a linked list of lines.
922 static void free_llist(Line * list)
924 Line *l, *tmp;
925 list_for_each_safe(l, tmp, list) {
926 free_tlist(l->first);
927 nasm_free(l);
932 * Free an array of linked lists of tokens
934 static void free_tlist_array(Token **array, size_t nlists)
936 Token **listp = array;
938 while (nlists--)
939 free_tlist(*listp++);
941 nasm_free(array);
945 * Duplicate a linked list of tokens.
947 static Token *dup_tlist(const Token *list, Token ***tailp)
949 Token *newlist = NULL;
950 Token **tailpp = &newlist;
951 const Token *t;
953 list_for_each(t, list) {
954 Token *nt;
955 *tailpp = nt = dup_Token(NULL, t);
956 tailpp = &nt->next;
959 if (tailp) {
960 **tailp = newlist;
961 *tailp = tailpp;
964 return newlist;
968 * Duplicate a linked list of tokens with a maximum count
970 static Token *dup_tlistn(const Token *list, size_t cnt, Token ***tailp)
972 Token *newlist = NULL;
973 Token **tailpp = &newlist;
974 const Token *t;
976 list_for_each(t, list) {
977 Token *nt;
978 if (!cnt--)
979 break;
980 *tailpp = nt = dup_Token(NULL, t);
981 tailpp = &nt->next;
984 if (tailp) {
985 **tailp = newlist;
986 if (newlist)
987 *tailp = tailpp;
990 return newlist;
994 * Duplicate a linked list of tokens in reverse order
996 static Token *dup_tlist_reverse(const Token *list, Token *tail)
998 const Token *t;
1000 list_for_each(t, list)
1001 tail = dup_Token(tail, t);
1003 return tail;
1007 * Free an MMacro
1009 static void free_mmacro(MMacro * m)
1011 nasm_free(m->name);
1012 free_tlist(m->dlist);
1013 nasm_free(m->defaults);
1014 free_llist(m->expansion);
1015 nasm_free(m);
1019 * Clear or free an SMacro
1021 static void free_smacro_members(SMacro *s)
1023 if (s->params) {
1024 int i;
1025 for (i = 0; i < s->nparam; i++) {
1026 if (s->params[i].name.len > INLINE_TEXT)
1027 nasm_free(s->params[i].name.text.p.ptr);
1029 nasm_free(s->params);
1031 nasm_free(s->name);
1032 free_tlist(s->expansion);
1035 static void clear_smacro(SMacro *s)
1037 free_smacro_members(s);
1038 /* Wipe everything except the next pointer */
1039 memset(&s->next + 1, 0, sizeof *s - sizeof s->next);
1043 * Free an SMacro
1045 static void free_smacro(SMacro *s)
1047 free_smacro_members(s);
1048 nasm_free(s);
1052 * Free all currently defined macros, and free the hash tables
1054 static void free_smacro_table(struct hash_table *smt)
1056 struct hash_iterator it;
1057 const struct hash_node *np;
1059 hash_for_each(smt, it, np) {
1060 SMacro *tmp;
1061 SMacro *s = np->data;
1062 nasm_free((void *)np->key);
1063 list_for_each_safe(s, tmp, s)
1064 free_smacro(s);
1066 hash_free(smt);
1069 static void free_mmacro_table(struct hash_table *mmt)
1071 struct hash_iterator it;
1072 const struct hash_node *np;
1074 hash_for_each(mmt, it, np) {
1075 MMacro *tmp;
1076 MMacro *m = np->data;
1077 nasm_free((void *)np->key);
1078 list_for_each_safe(m, tmp, m)
1079 free_mmacro(m);
1081 hash_free(mmt);
1084 static void free_macros(void)
1086 free_smacro_table(&smacros);
1087 free_mmacro_table(&mmacros);
1091 * Initialize the hash tables
1093 static void init_macros(void)
1098 * Pop the context stack.
1100 static void ctx_pop(void)
1102 Context *c = cstk;
1104 cstk = cstk->next;
1105 free_smacro_table(&c->localmac);
1106 nasm_free((char *)c->name);
1107 nasm_free(c);
1111 * Search for a key in the hash index; adding it if necessary
1112 * (in which case we initialize the data pointer to NULL.)
1114 static void **
1115 hash_findi_add(struct hash_table *hash, const char *str)
1117 struct hash_insert hi;
1118 void **r;
1119 char *strx;
1120 size_t l = strlen(str) + 1;
1122 r = hash_findib(hash, str, l, &hi);
1123 if (r)
1124 return r;
1126 strx = nasm_malloc(l); /* Use a more efficient allocator here? */
1127 memcpy(strx, str, l);
1128 return hash_add(&hi, strx, NULL);
1132 * Like hash_findi, but returns the data element rather than a pointer
1133 * to it. Used only when not adding a new element, hence no third
1134 * argument.
1136 static void *
1137 hash_findix(struct hash_table *hash, const char *str)
1139 void **p;
1141 p = hash_findi(hash, str, NULL);
1142 return p ? *p : NULL;
1146 * read line from standart macros set,
1147 * if there no more left -- return NULL
1149 static char *line_from_stdmac(void)
1151 unsigned char c;
1152 const unsigned char *p = stdmacpos;
1153 char *line, *q;
1154 size_t len = 0;
1156 if (!stdmacpos)
1157 return NULL;
1160 * 32-126 is ASCII, 127 is end of line, 128-31 are directives
1161 * (allowed to wrap around) corresponding to PP_* tokens 0-159.
1163 while ((c = *p++) != 127) {
1164 uint8_t ndir = c - 128;
1165 if (ndir < 256-96)
1166 len += pp_directives_len[ndir] + 1;
1167 else
1168 len++;
1171 line = nasm_malloc(len + 1);
1172 q = line;
1174 while ((c = *stdmacpos++) != 127) {
1175 uint8_t ndir = c - 128;
1176 if (ndir < 256-96) {
1177 memcpy(q, pp_directives[ndir], pp_directives_len[ndir]);
1178 q += pp_directives_len[ndir];
1179 *q++ = ' ';
1180 } else {
1181 *q++ = c;
1184 stdmacpos = p;
1185 *q = '\0';
1187 if (*stdmacpos == 127) {
1188 /* This was the last of this particular macro set */
1189 stdmacpos = NULL;
1190 if (*stdmacnext) {
1191 stdmacpos = *stdmacnext++;
1192 } else if (do_predef) {
1193 Line *pd, *l;
1196 * Nasty hack: here we push the contents of
1197 * `predef' on to the top-level expansion stack,
1198 * since this is the most convenient way to
1199 * implement the pre-include and pre-define
1200 * features.
1202 list_for_each(pd, predef) {
1203 nasm_new(l);
1204 l->next = istk->expansion;
1205 l->first = dup_tlist(pd->first, NULL);
1206 l->finishes = NULL;
1208 istk->expansion = l;
1210 do_predef = false;
1214 return line;
1218 * Read a line from a file. Return NULL on end of file.
1220 static char *line_from_file(FILE *f)
1222 int c;
1223 unsigned int size, next;
1224 const unsigned int delta = 512;
1225 const unsigned int pad = 8;
1226 unsigned int nr_cont = 0;
1227 bool cont = false;
1228 char *buffer, *p;
1229 int32_t lineno;
1231 size = delta;
1232 p = buffer = nasm_malloc(size);
1234 do {
1235 c = fgetc(f);
1237 switch (c) {
1238 case EOF:
1239 if (p == buffer) {
1240 nasm_free(buffer);
1241 return NULL;
1243 c = 0;
1244 break;
1246 case '\r':
1247 next = fgetc(f);
1248 if (next != '\n')
1249 ungetc(next, f);
1250 if (cont) {
1251 cont = false;
1252 continue;
1254 c = 0;
1255 break;
1257 case '\n':
1258 if (cont) {
1259 cont = false;
1260 continue;
1262 c = 0;
1263 break;
1265 case 032: /* ^Z = legacy MS-DOS end of file mark */
1266 c = 0;
1267 break;
1269 case '\\':
1270 next = fgetc(f);
1271 ungetc(next, f);
1272 if (next == '\r' || next == '\n') {
1273 cont = true;
1274 nr_cont++;
1275 continue;
1277 break;
1280 if (p >= (buffer + size - pad)) {
1281 buffer = nasm_realloc(buffer, size + delta);
1282 p = buffer + size - pad;
1283 size += delta;
1286 *p++ = c;
1287 } while (c);
1289 lineno = src_get_linnum() + istk->lineinc +
1290 (nr_cont * istk->lineinc);
1291 src_set_linnum(lineno);
1293 return buffer;
1297 * Common read routine regardless of source
1299 static char *read_line(void)
1301 char *line;
1302 FILE *f = istk->fp;
1304 if (f)
1305 line = line_from_file(f);
1306 else
1307 line = line_from_stdmac();
1309 if (!line)
1310 return NULL;
1312 if (!istk->nolist)
1313 lfmt->line(LIST_READ, src_get_linnum(), line);
1315 return line;
1319 * Tokenize a line of text. This is a very simple process since we
1320 * don't need to parse the value out of e.g. numeric tokens: we
1321 * simply split one string into many.
1323 static Token *tokenize(const char *line)
1325 enum pp_token_type type;
1326 Token *list = NULL;
1327 Token *t, **tail = &list;
1329 while (*line) {
1330 const char *p = line;
1331 const char *ep = NULL; /* End of token, for trimming the end */
1332 size_t toklen;
1333 char firstchar = *p; /* Can be used to override the first char */
1335 if (*p == '%') {
1337 * Preprocessor construct; find the end of the token.
1338 * Classification is handled later, because %{...} can be
1339 * used to create any preprocessor token.
1341 p++;
1342 if (*p == '+' && !nasm_isdigit(p[1])) {
1343 /* Paste token */
1344 p++;
1345 } else if (nasm_isdigit(*p) ||
1346 ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
1347 do {
1348 p++;
1350 while (nasm_isdigit(*p));
1351 } else if (*p == '{' || *p == '[') {
1352 /* %{...} or %[...] */
1353 char firstchar = *p;
1354 char endchar = *p + 2; /* } or ] */
1355 int lvl = 1;
1356 line += (*p++ == '{'); /* Skip { but not [ (yet) */
1357 while (lvl) {
1358 if (*p == firstchar) {
1359 lvl++;
1360 } else if (*p == endchar) {
1361 lvl--;
1362 } else if (nasm_isquote(*p)) {
1363 p = nasm_skip_string(p);
1367 * *p can have been advanced to a null character by
1368 * nasm_skip_string()
1370 if (!*p) {
1371 nasm_warn(WARN_OTHER, "unterminated %%%c construct",
1372 firstchar);
1373 break;
1375 p++;
1377 ep = lvl ? p : p-1; /* Terminal character not part of token */
1378 } else if (*p == '?') {
1379 /* %? or %?? */
1380 p++;
1381 if (*p == '?')
1382 p++;
1383 } else if (*p == '!') {
1384 /* Environment variable reference */
1385 p++;
1386 if (nasm_isidchar(*p)) {
1387 do {
1388 p++;
1390 while (nasm_isidchar(*p));
1391 } else if (nasm_isquote(*p)) {
1392 p = nasm_skip_string(p);
1393 if (*p)
1394 p++;
1395 else
1396 nasm_nonfatalf(ERR_PASS1, "unterminated %%! string");
1397 } else {
1398 /* %! without anything else... */
1400 } else if (*p == ',') {
1401 /* Conditional comma */
1402 p++;
1403 } else if (nasm_isidchar(*p) ||
1404 ((*p == '%' || *p == '$') && nasm_isidchar(p[1]))) {
1405 /* Identifier or some sort */
1406 do {
1407 p++;
1409 while (nasm_isidchar(*p));
1410 } else if (*p == '%') {
1411 /* %% operator */
1412 p++;
1415 if (!ep)
1416 ep = p;
1417 toklen = ep - line;
1419 /* Classify here, to handle %{...} correctly */
1420 if (toklen < 2) {
1421 type = TOK_OTHER; /* % operator */
1422 } else {
1423 char c0 = line[1];
1425 switch (c0) {
1426 case '+':
1427 type = (toklen == 2) ? TOK_PASTE : TOK_MMACRO_PARAM;
1428 break;
1430 case '-':
1431 type = TOK_MMACRO_PARAM;
1432 break;
1434 case '?':
1435 if (toklen == 2)
1436 type = TOK_PREPROC_Q;
1437 else if (toklen == 3 && line[2] == '?')
1438 type = TOK_PREPROC_QQ;
1439 else
1440 type = TOK_PREPROC_ID;
1441 break;
1443 case '!':
1444 type = (toklen == 2) ? TOK_OTHER : TOK_ENVIRON;
1445 break;
1447 case '%':
1448 type = (toklen == 2) ? TOK_OTHER : TOK_LOCAL_SYMBOL;
1449 break;
1451 case '$':
1452 type = (toklen == 2) ? TOK_OTHER : TOK_LOCAL_MACRO;
1453 break;
1455 case '[':
1456 line += 2; /* Skip %[ */
1457 firstchar = *line; /* Don't clobber */
1458 toklen -= 2;
1459 type = TOK_INDIRECT;
1460 break;
1462 case ',':
1463 type = (toklen == 2) ? TOK_COND_COMMA : TOK_PREPROC_ID;
1464 break;
1466 case '\'':
1467 case '\"':
1468 case '`':
1469 /* %{'string'} */
1470 type = TOK_PREPROC_ID;
1471 break;
1473 case ':':
1474 type = TOK_MMACRO_PARAM; /* %{:..} */
1475 break;
1477 default:
1478 if (nasm_isdigit(c0))
1479 type = TOK_MMACRO_PARAM;
1480 else if (nasm_isidchar(c0) || toklen > 2)
1481 type = TOK_PREPROC_ID;
1482 else
1483 type = TOK_OTHER;
1484 break;
1487 } else if (nasm_isidstart(*p) || (*p == '$' && nasm_isidstart(p[1]))) {
1489 * An identifier. This includes the ? operator, which is
1490 * treated as a keyword, not as a special character
1491 * operator
1493 type = TOK_ID;
1494 while (nasm_isidchar(*++p))
1496 } else if (nasm_isquote(*p)) {
1498 * A string token.
1500 type = TOK_STRING;
1501 p = nasm_skip_string(p);
1503 if (*p) {
1504 p++;
1505 } else {
1506 nasm_warn(WARN_OTHER, "unterminated string");
1507 /* Handling unterminated strings by UNV */
1508 /* type = -1; */
1510 } else if (p[0] == '$' && p[1] == '$') {
1511 type = TOK_OTHER; /* TOKEN_BASE */
1512 p += 2;
1513 } else if (nasm_isnumstart(*p)) {
1514 bool is_hex = false;
1515 bool is_float = false;
1516 bool has_e = false;
1517 char c;
1520 * A numeric token.
1523 if (*p == '$') {
1524 p++;
1525 is_hex = true;
1528 for (;;) {
1529 c = *p++;
1531 if (!is_hex && (c == 'e' || c == 'E')) {
1532 has_e = true;
1533 if (*p == '+' || *p == '-') {
1535 * e can only be followed by +/- if it is either a
1536 * prefixed hex number or a floating-point number
1538 p++;
1539 is_float = true;
1541 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
1542 is_hex = true;
1543 } else if (c == 'P' || c == 'p') {
1544 is_float = true;
1545 if (*p == '+' || *p == '-')
1546 p++;
1547 } else if (nasm_isnumchar(c))
1548 ; /* just advance */
1549 else if (c == '.') {
1551 * we need to deal with consequences of the legacy
1552 * parser, like "1.nolist" being two tokens
1553 * (TOK_NUMBER, TOK_ID) here; at least give it
1554 * a shot for now. In the future, we probably need
1555 * a flex-based scanner with proper pattern matching
1556 * to do it as well as it can be done. Nothing in
1557 * the world is going to help the person who wants
1558 * 0x123.p16 interpreted as two tokens, though.
1560 const char *r = p;
1561 while (*r == '_')
1562 r++;
1564 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
1565 (!is_hex && (*r == 'e' || *r == 'E')) ||
1566 (*r == 'p' || *r == 'P')) {
1567 p = r;
1568 is_float = true;
1569 } else
1570 break; /* Terminate the token */
1571 } else
1572 break;
1574 p--; /* Point to first character beyond number */
1576 if (p == line+1 && *line == '$') {
1577 type = TOK_OTHER; /* TOKEN_HERE */
1578 } else {
1579 if (has_e && !is_hex) {
1580 /* 1e13 is floating-point, but 1e13h is not */
1581 is_float = true;
1584 type = is_float ? TOK_FLOAT : TOK_NUMBER;
1586 } else if (nasm_isspace(*p)) {
1587 type = TOK_WHITESPACE;
1588 p = nasm_skip_spaces(p);
1590 * Whitespace just before end-of-line is discarded by
1591 * pretending it's a comment; whitespace just before a
1592 * comment gets lumped into the comment.
1594 if (!*p || *p == ';') {
1595 type = TOK_COMMENT;
1596 while (*p)
1597 p++;
1599 } else if (*p == ';') {
1600 type = TOK_COMMENT;
1601 while (*p)
1602 p++;
1603 } else {
1605 * Anything else is an operator of some kind. We check
1606 * for all the double-character operators (>>, <<, //,
1607 * %%, <=, >=, ==, !=, <>, &&, ||, ^^) and the triple-
1608 * character operators (<<<, >>>, <=>) but anything
1609 * else is a single-character operator.
1611 type = TOK_OTHER;
1612 switch (*p++) {
1613 case '>':
1614 if (*p == '>') {
1615 p++;
1616 if (*p == '>')
1617 p++;
1618 } else if (*p == '=') {
1619 p++;
1621 break;
1623 case '<':
1624 if (*p == '<') {
1625 p++;
1626 if (*p == '<')
1627 p++;
1628 } else if (*p == '=') {
1629 p++;
1630 if (*p == '>')
1631 p++;
1632 } else if (*p == '>') {
1633 p++;
1635 break;
1637 case '!':
1638 if (*p == '=')
1639 p++;
1640 break;
1642 case '/':
1643 case '=':
1644 case '&':
1645 case '|':
1646 case '^':
1647 /* These operators can be doubled but nothing else */
1648 if (*p == p[-1])
1649 p++;
1650 break;
1652 default:
1653 break;
1657 if (type == TOK_WHITESPACE) {
1658 *tail = t = new_White(NULL);
1659 tail = &t->next;
1660 } else if (type != TOK_COMMENT) {
1661 if (!ep)
1662 ep = p;
1663 *tail = t = new_Token(NULL, type, line, ep - line);
1664 *tok_text_buf(t) = firstchar; /* E.g. %{foo} -> {foo -> %foo */
1665 tail = &t->next;
1667 line = p;
1669 return list;
1673 * Tokens are allocated in blocks to improve speed. Set the blocksize
1674 * to 0 to use regular nasm_malloc(); this is useful for debugging.
1676 * alloc_Token() returns a zero-initialized token structure.
1678 #define TOKEN_BLOCKSIZE 4096
1680 #if TOKEN_BLOCKSIZE
1682 static Token *freeTokens = NULL;
1683 static Token *tokenblocks = NULL;
1685 static Token *alloc_Token(void)
1687 Token *t = freeTokens;
1689 if (unlikely(!t)) {
1690 Token *block;
1691 size_t i;
1693 nasm_newn(block, TOKEN_BLOCKSIZE);
1696 * The first entry in each array are a linked list of
1697 * block allocations and is not used for data.
1699 block[0].next = tokenblocks;
1700 block[0].type = TOK_BLOCK;
1701 tokenblocks = block;
1704 * Add the rest to the free list
1706 for (i = 2; i < TOKEN_BLOCKSIZE - 1; i++)
1707 block[i].next = &block[i+1];
1709 freeTokens = &block[2];
1712 * Return the topmost usable token
1714 return &block[1];
1717 freeTokens = t->next;
1718 t->next = NULL;
1719 return t;
1722 static Token *delete_Token(Token *t)
1724 Token *next = t->next;
1726 nasm_zero(*t);
1727 t->next = freeTokens;
1728 freeTokens = t;
1730 return next;
1733 static void delete_Blocks(void)
1735 Token *block, *blocktmp;
1737 list_for_each_safe(block, blocktmp, tokenblocks)
1738 nasm_free(block);
1740 freeTokens = tokenblocks = NULL;
1743 #else
1745 static inline Token *alloc_Token(void)
1747 Token *t;
1748 nasm_new(*t);
1749 return t;
1752 static Token *delete_Token(Token *t)
1754 Token *next = t->next;
1755 nasm_free(t);
1756 return next;
1759 static inline void delete_Blocks(void)
1761 /* Nothing to do */
1764 #endif
1767 * this function creates a new Token and passes a pointer to it
1768 * back to the caller. It sets the type, text, and next pointer elements.
1770 static Token *new_Token(Token * next, enum pp_token_type type,
1771 const char *text, size_t txtlen)
1773 Token *t = alloc_Token();
1774 char *textp;
1776 t->next = next;
1777 t->type = type;
1778 if (type == TOK_WHITESPACE) {
1779 t->len = 1;
1780 t->text.a[0] = ' ';
1781 } else {
1782 if (text && text[0] && !txtlen)
1783 txtlen = tok_strlen(text);
1785 t->len = tok_check_len(txtlen);
1787 if (text) {
1788 textp = (txtlen > INLINE_TEXT)
1789 ? (t->text.p.ptr = nasm_malloc(txtlen+1)) : t->text.a;
1790 memcpy(textp, text, txtlen);
1791 textp[txtlen] = '\0'; /* In case we needed malloc() */
1792 } else {
1794 * Allocate a buffer but do not fill it. The caller
1795 * can fill in text, but must not change the length.
1796 * The filled in text must be exactly txtlen once
1797 * the buffer is filled and before the token is added
1798 * to any line lists.
1800 if (txtlen > INLINE_TEXT)
1801 t->text.p.ptr = nasm_zalloc(txtlen+1);
1804 return t;
1808 * Same as new_Token(), but text belongs to the new token and is
1809 * either taken over or freed. This function MUST be called
1810 * with valid txt and txtlen, unlike new_Token().
1812 static Token *new_Token_free(Token * next, enum pp_token_type type,
1813 char *text, size_t txtlen)
1815 Token *t = alloc_Token();
1817 t->next = next;
1818 t->type = type;
1819 t->len = tok_check_len(txtlen);
1821 if (txtlen <= INLINE_TEXT) {
1822 memcpy(t->text.a, text, txtlen);
1823 free(text);
1824 } else {
1825 t->text.p.ptr = text;
1828 return t;
1831 static Token *dup_Token(Token *next, const Token *src)
1833 Token *t = alloc_Token();
1835 memcpy(t, src, sizeof *src);
1836 t->next = next;
1838 if (t->len > INLINE_TEXT) {
1839 t->text.p.ptr = nasm_malloc(t->len + 1);
1840 memcpy(t->text.p.ptr, src->text.p.ptr, t->len+1);
1843 return t;
1846 static Token *new_White(Token *next)
1848 Token *t = alloc_Token();
1850 t->next = next;
1851 t->type = TOK_WHITESPACE;
1852 t->len = 1;
1853 t->text.a[0] = ' ';
1855 return t;
1859 * This *transfers* the content from one token to another, leaving the
1860 * next pointer of the latter intact. Unlike dup_Token(), the old
1861 * token is destroyed, except for its next pointer, and the text
1862 * pointer allocation, if any, is simply transferred.
1864 static Token *steal_Token(Token *dst, Token *src)
1866 /* Overwrite everything except the next pointers */
1867 memcpy((char *)dst + sizeof(Token *), (char *)src + sizeof(Token *),
1868 sizeof(Token) - sizeof(Token *));
1870 /* Clear the donor token */
1871 memset((char *)src + sizeof(Token *), 0, sizeof(Token) - sizeof(Token *));
1873 return dst;
1877 * Convert a line of tokens back into text. This modifies the list
1878 * by expanding environment variables.
1880 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1881 * are also transformed into ..@ctxnum.xxx
1883 static char *detoken(Token * tlist, bool expand_locals)
1885 Token *t;
1886 char *line, *p;
1887 int len = 0;
1889 list_for_each(t, tlist) {
1890 switch (t->type) {
1891 case TOK_ENVIRON:
1893 const char *v = pp_getenv(t, true);
1894 set_text(t, v, tok_strlen(v));
1895 t->type = TOK_INTERNAL_STRING;
1896 break;
1899 case TOK_LOCAL_MACRO:
1900 case TOK_LOCAL_SYMBOL:
1901 if (expand_locals) {
1902 const char *q;
1903 char *p;
1904 Context *ctx = get_ctx(tok_text(t), &q);
1905 if (ctx) {
1906 p = nasm_asprintf("..@%"PRIu64".%s", ctx->number, q);
1907 set_text_free(t, p, nasm_last_string_len());
1908 t->type = TOK_ID;
1911 break;
1913 default:
1914 break; /* No modifications */
1917 if (debug_level(2)) {
1918 unsigned int t_len = t->len;
1919 unsigned int s_len = tok_strlen(tok_text(t));
1920 if (t_len != s_len) {
1921 nasm_panic("assertion failed: token \"%s\" type %u len %u has t->len %u\n",
1922 tok_text(t), t->type, s_len, t_len);
1923 t->len = s_len;
1927 len += t->len;
1930 p = line = nasm_malloc(len + 1);
1932 list_for_each(t, tlist)
1933 p = mempcpy(p, tok_text(t), t->len);
1934 *p = '\0';
1936 return line;
1940 * A scanner, suitable for use by the expression evaluator, which
1941 * operates on a line of Tokens. Expects a pointer to a pointer to
1942 * the first token in the line to be passed in as its private_data
1943 * field.
1945 * FIX: This really needs to be unified with stdscan.
1947 struct ppscan {
1948 Token *tptr;
1949 int ntokens;
1952 static int ppscan(void *private_data, struct tokenval *tokval)
1954 struct ppscan *pps = private_data;
1955 Token *tline;
1956 const char *txt;
1958 do {
1959 if (pps->ntokens && (tline = pps->tptr)) {
1960 pps->ntokens--;
1961 pps->tptr = tline->next;
1962 } else {
1963 pps->tptr = NULL;
1964 pps->ntokens = 0;
1965 return tokval->t_type = TOKEN_EOS;
1967 } while (tline->type == TOK_WHITESPACE || tline->type == TOK_COMMENT);
1969 txt = tok_text(tline);
1970 tokval->t_charptr = (char *)txt; /* Fix this */
1972 if (txt[0] == '$') {
1973 if (!txt[1]) {
1974 return tokval->t_type = TOKEN_HERE;
1975 } else if (txt[1] == '$' && !txt[2]) {
1976 return tokval->t_type = TOKEN_BASE;
1977 } else if (tline->type == TOK_ID) {
1978 tokval->t_charptr++;
1979 return tokval->t_type = TOKEN_ID;
1983 switch (tline->type) {
1984 default:
1985 if (tline->len == 1)
1986 return tokval->t_type = txt[0];
1987 /* fall through */
1988 case TOK_ID:
1989 return nasm_token_hash(txt, tokval);
1991 case TOK_NUMBER:
1993 bool rn_error;
1994 tokval->t_integer = readnum(txt, &rn_error);
1995 if (rn_error)
1996 return tokval->t_type = TOKEN_ERRNUM;
1997 else
1998 return tokval->t_type = TOKEN_NUM;
2001 case TOK_FLOAT:
2002 return tokval->t_type = TOKEN_FLOAT;
2004 case TOK_STRING:
2005 tokval->t_charptr = (char *)unquote_token(tline);
2006 tokval->t_inttwo = tline->len;
2007 return tokval->t_type = TOKEN_STR;
2012 * 1. An expression (true if nonzero 0)
2013 * 2. The keywords true, on, yes for true
2014 * 3. The keywords false, off, no for false
2015 * 4. An empty line, for true
2017 * On error, return defval (usually the previous value)
2019 static bool pp_get_boolean_option(Token *tline, bool defval)
2021 static const char * const noyes[] = {
2022 "no", "yes",
2023 "false", "true",
2024 "off", "on"
2026 struct ppscan pps;
2027 struct tokenval tokval;
2028 expr *evalresult;
2030 tline = skip_white(tline);
2031 if (!tline)
2032 return true;
2034 if (tline->type == TOK_ID) {
2035 size_t i;
2036 const char *txt = tok_text(tline);
2038 for (i = 0; i < ARRAY_SIZE(noyes); i++)
2039 if (!nasm_stricmp(txt, noyes[i]))
2040 return i & 1;
2043 pps.tptr = NULL;
2044 pps.tptr = tline;
2045 pps.ntokens = -1;
2046 tokval.t_type = TOKEN_INVALID;
2047 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
2049 if (!evalresult)
2050 return true;
2052 if (tokval.t_type)
2053 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
2054 if (!is_really_simple(evalresult)) {
2055 nasm_nonfatal("boolean flag expression must be a constant");
2056 return defval;
2059 return reloc_value(evalresult) != 0;
2063 * Compare a string to the name of an existing macro; this is a
2064 * simple wrapper which calls either strcmp or nasm_stricmp
2065 * depending on the value of the `casesense' parameter.
2067 static int mstrcmp(const char *p, const char *q, bool casesense)
2069 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
2073 * Compare a string to the name of an existing macro; this is a
2074 * simple wrapper which calls either strcmp or nasm_stricmp
2075 * depending on the value of the `casesense' parameter.
2077 static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
2079 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
2083 * Return the Context structure associated with a %$ token. Return
2084 * NULL, having _already_ reported an error condition, if the
2085 * context stack isn't deep enough for the supplied number of $
2086 * signs.
2088 * If "namep" is non-NULL, set it to the pointer to the macro name
2089 * tail, i.e. the part beyond %$...
2091 static Context *get_ctx(const char *name, const char **namep)
2093 Context *ctx;
2094 int i;
2096 if (namep)
2097 *namep = name;
2099 if (!name || name[0] != '%' || name[1] != '$')
2100 return NULL;
2102 if (!cstk) {
2103 nasm_nonfatal("`%s': context stack is empty", name);
2104 return NULL;
2107 name += 2;
2108 ctx = cstk;
2109 i = 0;
2110 while (ctx && *name == '$') {
2111 name++;
2112 i++;
2113 ctx = ctx->next;
2115 if (!ctx) {
2116 nasm_nonfatal("`%s': context stack is only"
2117 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
2118 return NULL;
2121 if (namep)
2122 *namep = name;
2124 return ctx;
2128 * Open an include file. This routine must always return a valid
2129 * file pointer if it returns - it's responsible for throwing an
2130 * ERR_FATAL and bombing out completely if not. It should also try
2131 * the include path one by one until it finds the file or reaches
2132 * the end of the path.
2134 * Note: for INC_PROBE the function returns NULL at all times;
2135 * instead look for the
2137 enum incopen_mode {
2138 INC_NEEDED, /* File must exist */
2139 INC_OPTIONAL, /* Missing is OK */
2140 INC_PROBE /* Only an existence probe */
2143 /* This is conducts a full pathname search */
2144 static FILE *inc_fopen_search(const char *file, char **slpath,
2145 enum incopen_mode omode, enum file_flags fmode)
2147 const struct strlist_entry *ip = strlist_head(ipath_list);
2148 FILE *fp;
2149 const char *prefix = "";
2150 char *sp;
2151 bool found;
2153 while (1) {
2154 sp = nasm_catfile(prefix, file);
2155 if (omode == INC_PROBE) {
2156 fp = NULL;
2157 found = nasm_file_exists(sp);
2158 } else {
2159 fp = nasm_open_read(sp, fmode);
2160 found = (fp != NULL);
2162 if (found) {
2163 *slpath = sp;
2164 return fp;
2167 nasm_free(sp);
2169 if (!ip) {
2170 *slpath = NULL;
2171 return NULL;
2174 prefix = ip->str;
2175 ip = ip->next;
2180 * Open a file, or test for the presence of one (depending on omode),
2181 * considering the include path.
2183 static FILE *inc_fopen(const char *file,
2184 struct strlist *dhead,
2185 const char **found_path,
2186 enum incopen_mode omode,
2187 enum file_flags fmode)
2189 struct hash_insert hi;
2190 void **hp;
2191 char *path;
2192 FILE *fp = NULL;
2194 hp = hash_find(&FileHash, file, &hi);
2195 if (hp) {
2196 path = *hp;
2197 if (path || omode != INC_NEEDED) {
2198 strlist_add(dhead, path ? path : file);
2200 } else {
2201 /* Need to do the actual path search */
2202 fp = inc_fopen_search(file, &path, omode, fmode);
2204 /* Positive or negative result */
2205 hash_add(&hi, nasm_strdup(file), path);
2208 * Add file to dependency path.
2210 if (path || omode != INC_NEEDED)
2211 strlist_add(dhead, file);
2214 if (!path) {
2215 if (omode == INC_NEEDED)
2216 nasm_fatal("unable to open include file `%s'", file);
2217 } else {
2218 if (!fp && omode != INC_PROBE)
2219 fp = nasm_open_read(path, fmode);
2222 if (found_path)
2223 *found_path = path;
2225 return fp;
2229 * Opens an include or input file. Public version, for use by modules
2230 * that get a file:lineno pair and need to look at the file again
2231 * (e.g. the CodeView debug backend). Returns NULL on failure.
2233 FILE *pp_input_fopen(const char *filename, enum file_flags mode)
2235 return inc_fopen(filename, NULL, NULL, INC_OPTIONAL, mode);
2239 * Determine if we should warn on defining a single-line macro of
2240 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
2241 * return true if _any_ single-line macro of that name is defined.
2242 * Otherwise, will return true if a single-line macro with either
2243 * `nparam' or no parameters is defined.
2245 * If a macro with precisely the right number of parameters is
2246 * defined, or nparam is -1, the address of the definition structure
2247 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
2248 * is NULL, no action will be taken regarding its contents, and no
2249 * error will occur.
2251 * Note that this is also called with nparam zero to resolve
2252 * `ifdef'.
2254 * If you already know which context macro belongs to, you can pass
2255 * the context pointer as first parameter; if you won't but name begins
2256 * with %$ the context will be automatically computed. If all_contexts
2257 * is true, macro will be searched in outer contexts as well.
2259 static bool
2260 smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
2261 bool nocase, bool find_alias)
2263 struct hash_table *smtbl;
2264 SMacro *m;
2266 if (ctx) {
2267 smtbl = &ctx->localmac;
2268 } else if (name[0] == '%' && name[1] == '$') {
2269 if (cstk)
2270 ctx = get_ctx(name, &name);
2271 if (!ctx)
2272 return false; /* got to return _something_ */
2273 smtbl = &ctx->localmac;
2274 } else {
2275 smtbl = &smacros;
2278 restart:
2279 m = (SMacro *) hash_findix(smtbl, name);
2281 while (m) {
2282 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
2283 (nparam <= 0 || m->nparam == 0 || nparam == m->nparam ||
2284 (m->greedy && nparam >= m->nparam-1))) {
2285 if (m->alias && !find_alias) {
2286 if (do_aliases) {
2287 name = tok_text(m->expansion);
2288 goto restart;
2289 } else {
2290 continue;
2293 if (defn) {
2294 *defn = (nparam == m->nparam || nparam == -1) ? m : NULL;
2296 return true;
2298 m = m->next;
2301 return false;
2304 /* param should be a natural number [0; INT_MAX] */
2305 static int read_param_count(const char *str)
2307 int result;
2308 bool err;
2310 result = readnum(str, &err);
2311 if (result < 0 || result > INT_MAX) {
2312 result = 0;
2313 nasm_nonfatal("parameter count `%s' is out of bounds [%d; %d]",
2314 str, 0, INT_MAX);
2315 } else if (err)
2316 nasm_nonfatal("unable to parse parameter count `%s'", str);
2317 return result;
2321 * Count and mark off the parameters in a multi-line macro call.
2322 * This is called both from within the multi-line macro expansion
2323 * code, and also to mark off the default parameters when provided
2324 * in a %macro definition line.
2326 * Note that we need space in the params array for parameter 0 being
2327 * a possible captured label as well as the final NULL.
2329 static void count_mmac_params(Token * t, int *nparamp, Token ***paramsp)
2331 int paramsize;
2332 int nparam = 0;
2333 Token **params;
2335 paramsize = PARAM_DELTA;
2336 params = nasm_malloc(paramsize * sizeof(*params));
2337 params[0] = NULL;
2339 while ((t = skip_white(t))) {
2340 /* 2 slots for captured label and NULL */
2341 if (nparam+2 >= paramsize) {
2342 paramsize += PARAM_DELTA;
2343 params = nasm_realloc(params, sizeof(*params) * paramsize);
2345 params[++nparam] = t;
2346 if (tok_is(t, '{')) {
2347 int brace = 1;
2348 while (brace && (t = t->next)) {
2349 brace += tok_is(t, '{');
2350 brace -= tok_is(t, '}');
2353 if (t) {
2355 * Now we've found the closing brace, look further
2356 * for the comma.
2358 t = skip_white(t->next);
2359 if (tok_isnt(t, ','))
2360 nasm_nonfatal("braces do not enclose all of macro parameter");
2361 } else {
2362 nasm_nonfatal("expecting closing brace in macro parameter");
2366 while (tok_isnt(t, ','))
2367 t = t->next;
2369 if (t) /* got a comma */
2370 t = t->next; /* eat the comma */
2373 params[nparam+1] = NULL;
2374 *paramsp = params;
2375 *nparamp = nparam;
2379 * Determine whether one of the various `if' conditions is true or
2380 * not.
2382 * We must free the tline we get passed.
2384 static enum cond_state if_condition(Token * tline, enum preproc_token ct)
2386 bool j;
2387 Token *t, *tt, *origline;
2388 struct ppscan pps;
2389 struct tokenval tokval;
2390 expr *evalresult;
2391 enum pp_token_type needtype;
2392 const char *dname = pp_directives[ct];
2393 bool casesense = true;
2394 enum preproc_token cond = PP_COND(ct);
2396 origline = tline;
2398 switch (cond) {
2399 case PP_IFCTX:
2400 j = false; /* have we matched yet? */
2401 while (true) {
2402 tline = skip_white(tline);
2403 if (!tline)
2404 break;
2405 if (tline->type != TOK_ID) {
2406 nasm_nonfatal("`%s' expects context identifiers",
2407 dname);
2408 goto fail;
2410 if (cstk && cstk->name && !nasm_stricmp(tok_text(tline), cstk->name))
2411 j = true;
2412 tline = tline->next;
2414 break;
2416 case PP_IFDEF:
2417 j = false; /* have we matched yet? */
2418 while (tline) {
2419 tline = skip_white(tline);
2420 if (!tline || (tline->type != TOK_ID &&
2421 tline->type != TOK_LOCAL_MACRO)) {
2422 nasm_nonfatal("`%s' expects macro identifiers",
2423 dname);
2424 goto fail;
2426 if (smacro_defined(NULL, tok_text(tline), 0, NULL, true, false))
2427 j = true;
2428 tline = tline->next;
2430 break;
2432 case PP_IFENV:
2433 tline = expand_smacro(tline);
2434 j = false; /* have we matched yet? */
2435 while (tline) {
2436 tline = skip_white(tline);
2437 if (!tline || (tline->type != TOK_ID &&
2438 tline->type != TOK_STRING &&
2439 tline->type != TOK_INTERNAL_STRING &&
2440 tline->type != TOK_ENVIRON)) {
2441 nasm_nonfatal("`%s' expects environment variable names",
2442 dname);
2443 goto fail;
2446 j |= !!pp_getenv(tline, false);
2447 tline = tline->next;
2449 break;
2451 case PP_IFIDNI:
2452 casesense = false;
2453 /* fall through */
2454 case PP_IFIDN:
2455 tline = expand_smacro(tline);
2456 t = tt = tline;
2457 while (tok_isnt(tt, ','))
2458 tt = tt->next;
2459 if (!tt) {
2460 nasm_nonfatal("`%s' expects two comma-separated arguments",
2461 dname);
2462 goto fail;
2464 tt = tt->next;
2465 j = true; /* assume equality unless proved not */
2466 while (tok_isnt(t, ',') && tt) {
2467 unsigned int l1, l2;
2468 const char *t1, *t2;
2470 if (tok_is(tt, ',')) {
2471 nasm_nonfatal("`%s': more than one comma on line",
2472 dname);
2473 goto fail;
2475 if (t->type == TOK_WHITESPACE) {
2476 t = t->next;
2477 continue;
2479 if (tt->type == TOK_WHITESPACE) {
2480 tt = tt->next;
2481 continue;
2483 if (tt->type != t->type) {
2484 j = false; /* found mismatching tokens */
2485 break;
2488 t1 = unquote_token(t);
2489 t2 = unquote_token(tt);
2490 l1 = t->len;
2491 l2 = tt->len;
2493 if (l1 != l2 || mmemcmp(t1, t2, l1, casesense)) {
2494 j = false;
2495 break;
2498 t = t->next;
2499 tt = tt->next;
2501 if (!tok_is(t, ',') || tt)
2502 j = false; /* trailing gunk on one end or other */
2503 break;
2505 case PP_IFMACRO:
2507 bool found = false;
2508 MMacro searching, *mmac;
2510 tline = skip_white(tline);
2511 tline = expand_id(tline);
2512 if (!tok_type(tline, TOK_ID)) {
2513 nasm_nonfatal("`%s' expects a macro name", dname);
2514 goto fail;
2516 nasm_zero(searching);
2517 searching.name = dup_text(tline);
2518 searching.casesense = true;
2519 searching.nparam_min = 0;
2520 searching.nparam_max = INT_MAX;
2521 tline = expand_smacro(tline->next);
2522 tline = skip_white(tline);
2523 if (!tline) {
2524 } else if (!tok_type(tline, TOK_NUMBER)) {
2525 nasm_nonfatal("`%s' expects a parameter count or nothing",
2526 dname);
2527 } else {
2528 searching.nparam_min = searching.nparam_max =
2529 read_param_count(tok_text(tline));
2531 if (tline && tok_is(tline->next, '-')) {
2532 tline = tline->next->next;
2533 if (tok_is(tline, '*'))
2534 searching.nparam_max = INT_MAX;
2535 else if (!tok_type(tline, TOK_NUMBER))
2536 nasm_nonfatal("`%s' expects a parameter count after `-'",
2537 dname);
2538 else {
2539 searching.nparam_max = read_param_count(tok_text(tline));
2540 if (searching.nparam_min > searching.nparam_max) {
2541 nasm_nonfatal("minimum parameter count exceeds maximum");
2542 searching.nparam_max = searching.nparam_min;
2546 if (tline && tok_is(tline->next, '+')) {
2547 tline = tline->next;
2548 searching.plus = true;
2550 mmac = (MMacro *) hash_findix(&mmacros, searching.name);
2551 while (mmac) {
2552 if (!strcmp(mmac->name, searching.name) &&
2553 (mmac->nparam_min <= searching.nparam_max
2554 || searching.plus)
2555 && (searching.nparam_min <= mmac->nparam_max
2556 || mmac->plus)) {
2557 found = true;
2558 break;
2560 mmac = mmac->next;
2562 if (tline && tline->next)
2563 nasm_warn(WARN_OTHER, "trailing garbage after %%ifmacro ignored");
2564 nasm_free(searching.name);
2565 j = found;
2566 break;
2569 case PP_IFID:
2570 needtype = TOK_ID;
2571 goto iftype;
2572 case PP_IFNUM:
2573 needtype = TOK_NUMBER;
2574 goto iftype;
2575 case PP_IFSTR:
2576 needtype = TOK_STRING;
2577 goto iftype;
2579 iftype:
2580 t = tline = expand_smacro(tline);
2582 while (tok_white(t) ||
2583 (needtype == TOK_NUMBER && (tok_is(t, '-') | tok_is(t, '+'))))
2584 t = t->next;
2586 j = tok_type(t, needtype);
2587 break;
2589 case PP_IFTOKEN:
2590 tline = expand_smacro(tline);
2591 t = skip_white(tline);
2593 j = false;
2594 if (t) {
2595 t = skip_white(t->next); /* Skip the actual token + whitespace */
2596 j = !t;
2598 break;
2600 case PP_IFEMPTY:
2601 tline = expand_smacro(tline);
2602 t = skip_white(tline);
2603 j = !t; /* Should be empty */
2604 break;
2606 case PP_IF:
2607 pps.tptr = tline = expand_smacro(tline);
2608 pps.ntokens = -1;
2609 tokval.t_type = TOKEN_INVALID;
2610 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
2611 if (!evalresult)
2612 return -1;
2613 if (tokval.t_type)
2614 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
2615 if (!is_simple(evalresult)) {
2616 nasm_nonfatal("non-constant value given to `%s'",
2617 dname);
2618 goto fail;
2620 j = reloc_value(evalresult) != 0;
2621 break;
2623 case PP_IFUSING:
2624 case PP_IFUSABLE:
2626 const struct use_package *pkg;
2627 const char *name;
2629 pkg = get_use_pkg(tline, dname, &name);
2630 if (!name)
2631 goto fail;
2633 j = pkg && ((cond == PP_IFUSABLE) | use_loaded[pkg->index]);
2634 break;
2637 default:
2638 nasm_nonfatal("unknown preprocessor directive `%s'", dname);
2639 goto fail;
2642 free_tlist(origline);
2643 return (j ^ PP_COND_NEGATIVE(ct)) ? COND_IF_TRUE : COND_IF_FALSE;
2645 fail:
2646 free_tlist(origline);
2647 return COND_NEVER;
2651 * Default smacro expansion routine: just returns a copy of the
2652 * expansion list.
2654 static Token *
2655 smacro_expand_default(const SMacro *s, Token **params, int nparams)
2657 (void)params;
2658 (void)nparams;
2660 return dup_tlist(s->expansion, NULL);
2664 * Emit a macro defintion or undef to the listing file, if
2665 * desired. This is similar to detoken(), but it handles the reverse
2666 * expansion list, does not expand %! or local variable tokens, and
2667 * does some special handling for macro parameters.
2669 static void
2670 list_smacro_def(enum preproc_token op, const Context *ctx, const SMacro *m)
2672 Token *t;
2673 size_t namelen, size;
2674 char *def, *p;
2675 char *context_prefix = NULL;
2676 size_t context_len;
2678 namelen = strlen(m->name);
2679 size = namelen + 2; /* Include room for space after name + NUL */
2681 if (ctx) {
2682 int context_depth = cstk->depth - ctx->depth + 1;
2683 context_prefix =
2684 nasm_asprintf("[%s::%"PRIu64"] %%%-*s",
2685 ctx->name ? ctx->name : "",
2686 ctx->number, context_depth, "");
2688 context_len = nasm_last_string_len();
2689 memset(context_prefix + context_len - context_depth,
2690 '$', context_depth);
2691 size += context_len;
2694 list_for_each(t, m->expansion)
2695 size += t->len;
2697 if (m->nparam) {
2699 * Space for ( and either , or ) around each
2700 * parameter, plus up to 4 flags.
2702 int i;
2704 size += 1 + 4 * m->nparam;
2705 for (i = 0; i < m->nparam; i++)
2706 size += m->params[i].name.len;
2709 def = nasm_malloc(size);
2710 p = def+size;
2711 *--p = '\0';
2713 list_for_each(t, m->expansion) {
2714 p -= t->len;
2715 memcpy(p, tok_text(t), t->len);
2718 *--p = ' ';
2720 if (m->nparam) {
2721 int i;
2723 *--p = ')';
2724 for (i = m->nparam-1; i >= 0; i--) {
2725 enum sparmflags flags = m->params[i].flags;
2726 if (flags & SPARM_GREEDY)
2727 *--p = '+';
2728 p -= m->params[i].name.len;
2729 memcpy(p, tok_text(&m->params[i].name), m->params[i].name.len);
2731 if (flags & SPARM_NOSTRIP)
2732 *--p = '!';
2733 if (flags & SPARM_STR)
2734 *--p = '&';
2735 if (flags & SPARM_EVAL)
2736 *--p = '=';
2737 *--p = ',';
2739 *p = '('; /* First parameter starts with ( not , */
2742 p -= namelen;
2743 memcpy(p, m->name, namelen);
2745 if (context_prefix) {
2746 p -= context_len;
2747 memcpy(p, context_prefix, context_len);
2748 nasm_free(context_prefix);
2751 nasm_listmsg("%s %s", pp_directives[op], p);
2752 nasm_free(def);
2756 * Parse smacro arguments, return argument count. If the tmpl argument
2757 * is set, set the nparam, greedy and params field in the template.
2758 * *tpp is updated to point to the pointer to the first token after the
2759 * prototype.
2761 * The text values from any argument tokens are "stolen" and the
2762 * corresponding text fields set to NULL.
2764 static int parse_smacro_template(Token ***tpp, SMacro *tmpl)
2766 int nparam = 0;
2767 enum sparmflags flags;
2768 struct smac_param *params = NULL;
2769 bool err, done;
2770 bool greedy = false;
2771 Token **tn = *tpp;
2772 Token *t = *tn;
2773 Token *name;
2776 * DO NOT skip whitespace here, or we won't be able to distinguish:
2778 * %define foo (a,b) ; no arguments, (a,b) is the expansion
2779 * %define bar(a,b) ; two arguments, empty expansion
2781 * This ambiguity was inherited from C.
2784 if (!tok_is(t, '('))
2785 goto finish;
2787 if (tmpl) {
2788 Token *tx = t;
2789 Token **txpp = &tx;
2790 int sparam;
2792 /* Count parameters first */
2793 sparam = parse_smacro_template(&txpp, NULL);
2794 if (!sparam)
2795 goto finish; /* No parameters, we're done */
2796 nasm_newn(params, sparam);
2799 /* Skip leading paren */
2800 tn = &t->next;
2801 t = *tn;
2803 name = NULL;
2804 flags = 0;
2805 err = done = false;
2807 while (!done) {
2808 if (!t || !t->type) {
2809 if (name || flags)
2810 nasm_nonfatal("`)' expected to terminate macro template");
2811 else
2812 nasm_nonfatal("parameter identifier expected");
2813 break;
2816 switch (t->type) {
2817 case TOK_ID:
2818 if (name)
2819 goto bad;
2820 name = t;
2821 break;
2823 case TOK_OTHER:
2824 if (t->len != 1)
2825 goto bad;
2826 switch (t->text.a[0]) {
2827 case '=':
2828 flags |= SPARM_EVAL;
2829 break;
2830 case '&':
2831 flags |= SPARM_STR;
2832 break;
2833 case '!':
2834 flags |= SPARM_NOSTRIP;
2835 break;
2836 case '+':
2837 flags |= SPARM_GREEDY;
2838 greedy = true;
2839 break;
2840 case ',':
2841 if (greedy)
2842 nasm_nonfatal("greedy parameter must be last");
2843 /* fall through */
2844 case ')':
2845 if (params) {
2846 if (name)
2847 steal_Token(&params[nparam].name, name);
2848 params[nparam].flags = flags;
2850 nparam++;
2851 name = NULL;
2852 flags = 0;
2853 done = t->text.a[0] == ')';
2854 break;
2855 default:
2856 goto bad;
2858 break;
2860 case TOK_WHITESPACE:
2861 break;
2863 default:
2864 bad:
2865 if (!err) {
2866 nasm_nonfatal("garbage `%s' in macro parameter list", tok_text(t));
2867 err = true;
2869 break;
2872 tn = &t->next;
2873 t = *tn;
2876 finish:
2877 while (t && t->type == TOK_WHITESPACE) {
2878 tn = &t->next;
2879 t = t->next;
2881 *tpp = tn;
2882 if (tmpl) {
2883 tmpl->nparam = nparam;
2884 tmpl->greedy = greedy;
2885 tmpl->params = params;
2887 return nparam;
2891 * Common code for defining an smacro. The tmpl argument, if not NULL,
2892 * contains any macro parameters that aren't explicit arguments;
2893 * those are the more uncommon macro variants.
2895 static SMacro *define_smacro(const char *mname, bool casesense,
2896 Token *expansion, SMacro *tmpl)
2898 SMacro *smac, **smhead;
2899 struct hash_table *smtbl;
2900 Context *ctx;
2901 bool defining_alias = false;
2902 unsigned int nparam = 0;
2904 if (tmpl) {
2905 defining_alias = tmpl->alias;
2906 nparam = tmpl->nparam;
2909 while (1) {
2910 ctx = get_ctx(mname, &mname);
2912 if (!smacro_defined(ctx, mname, nparam, &smac, casesense, true)) {
2913 /* Create a new macro */
2914 smtbl = ctx ? &ctx->localmac : &smacros;
2915 smhead = (SMacro **) hash_findi_add(smtbl, mname);
2916 nasm_new(smac);
2917 smac->next = *smhead;
2918 *smhead = smac;
2919 break;
2920 } else if (!smac) {
2921 nasm_warn(WARN_OTHER, "single-line macro `%s' defined both with and"
2922 " without parameters", mname);
2924 * Some instances of the old code considered this a failure,
2925 * some others didn't. What is the right thing to do here?
2927 goto fail;
2928 } else if (!smac->alias || !do_aliases || defining_alias) {
2930 * We're redefining, so we have to take over an
2931 * existing SMacro structure. This means freeing
2932 * what was already in it, but not the structure itself.
2934 clear_smacro(smac);
2935 break;
2936 } else if (smac->in_progress) {
2937 nasm_nonfatal("macro alias loop");
2938 goto fail;
2939 } else {
2940 /* It is an alias macro; follow the alias link */
2941 SMacro *s;
2943 smac->in_progress = true;
2944 s = define_smacro(tok_text(smac->expansion), casesense,
2945 expansion, tmpl);
2946 smac->in_progress = false;
2947 return s;
2951 smac->name = nasm_strdup(mname);
2952 smac->casesense = casesense;
2953 smac->expansion = expansion;
2954 smac->expand = smacro_expand_default;
2955 if (tmpl) {
2956 smac->nparam = tmpl->nparam;
2957 smac->params = tmpl->params;
2958 smac->alias = tmpl->alias;
2959 smac->greedy = tmpl->greedy;
2960 if (tmpl->expand)
2961 smac->expand = tmpl->expand;
2963 if (list_option('s')) {
2964 list_smacro_def((smac->alias ? PP_DEFALIAS : PP_DEFINE)
2965 + !casesense, ctx, smac);
2967 return smac;
2969 fail:
2970 free_tlist(expansion);
2971 if (tmpl)
2972 free_smacro_members(tmpl);
2973 return NULL;
2977 * Undefine an smacro
2979 static void undef_smacro(const char *mname, bool undefalias)
2981 SMacro **smhead, *s, **sp;
2982 struct hash_table *smtbl;
2983 Context *ctx;
2985 ctx = get_ctx(mname, &mname);
2986 smtbl = ctx ? &ctx->localmac : &smacros;
2987 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
2989 if (smhead) {
2991 * We now have a macro name... go hunt for it.
2993 sp = smhead;
2994 while ((s = *sp) != NULL) {
2995 if (!mstrcmp(s->name, mname, s->casesense)) {
2996 if (s->alias && !undefalias) {
2997 if (!do_aliases)
2998 continue;
2999 if (s->in_progress) {
3000 nasm_nonfatal("macro alias loop");
3001 } else {
3002 s->in_progress = true;
3003 undef_smacro(tok_text(s->expansion), false);
3004 s->in_progress = false;
3006 } else {
3007 if (list_option('d'))
3008 list_smacro_def(s->alias ? PP_UNDEFALIAS : PP_UNDEF,
3009 ctx, s);
3010 *sp = s->next;
3011 free_smacro(s);
3013 } else {
3014 sp = &s->next;
3021 * Parse a mmacro specification.
3023 static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
3025 tline = tline->next;
3026 tline = skip_white(tline);
3027 tline = expand_id(tline);
3028 if (!tok_type(tline, TOK_ID)) {
3029 nasm_nonfatal("`%s' expects a macro name", directive);
3030 return false;
3033 #if 0
3034 def->prev = NULL;
3035 #endif
3036 def->name = dup_text(tline);
3037 def->plus = false;
3038 def->nolist = false;
3039 def->nparam_min = 0;
3040 def->nparam_max = 0;
3042 tline = expand_smacro(tline->next);
3043 tline = skip_white(tline);
3044 if (!tok_type(tline, TOK_NUMBER))
3045 nasm_nonfatal("`%s' expects a parameter count", directive);
3046 else
3047 def->nparam_min = def->nparam_max = read_param_count(tok_text(tline));
3048 if (tline && tok_is(tline->next, '-')) {
3049 tline = tline->next->next;
3050 if (tok_is(tline, '*')) {
3051 def->nparam_max = INT_MAX;
3052 } else if (!tok_type(tline, TOK_NUMBER)) {
3053 nasm_nonfatal("`%s' expects a parameter count after `-'", directive);
3054 } else {
3055 def->nparam_max = read_param_count(tok_text(tline));
3056 if (def->nparam_min > def->nparam_max) {
3057 nasm_nonfatal("minimum parameter count exceeds maximum");
3058 def->nparam_max = def->nparam_min;
3062 if (tline && tok_is(tline->next, '+')) {
3063 tline = tline->next;
3064 def->plus = true;
3066 if (tline && tok_type(tline->next, TOK_ID) &&
3067 tline->next->len == 7 &&
3068 !nasm_stricmp(tline->next->text.a, ".nolist")) {
3069 tline = tline->next;
3070 def->nolist = !list_option('f') || istk->nolist;
3074 * Handle default parameters.
3076 if (tline && tline->next) {
3077 def->dlist = tline->next;
3078 tline->next = NULL;
3079 count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
3080 } else {
3081 def->dlist = NULL;
3082 def->defaults = NULL;
3084 def->expansion = NULL;
3086 if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
3087 !def->plus) {
3089 *!macro-defaults [on] macros with more default than optional parameters
3090 *! warns when a macro has more default parameters than optional parameters.
3091 *! See \k{mlmacdef} for why might want to disable this warning.
3093 nasm_warn(WARN_MACRO_DEFAULTS,
3094 "too many default macro parameters in macro `%s'", def->name);
3097 return true;
3102 * Decode a size directive
3104 static int parse_size(const char *str) {
3105 static const char *size_names[] =
3106 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
3107 static const int sizes[] =
3108 { 0, 1, 4, 16, 8, 10, 2, 32 };
3109 return str ? sizes[bsii(str, size_names, ARRAY_SIZE(size_names))+1] : 0;
3113 * Process a preprocessor %pragma directive. Currently there are none.
3114 * Gets passed the token list starting with the "preproc" token from
3115 * "%pragma preproc".
3117 static void do_pragma_preproc(Token *tline)
3119 /* Skip to the real stuff */
3120 tline = tline->next;
3121 tline = skip_white(tline);
3122 if (!tline)
3123 return;
3125 (void)tline; /* Nothing else to do at present */
3128 static bool is_macro_id(const Token *t)
3130 return tok_type(t, TOK_ID) || tok_type(t, TOK_LOCAL_MACRO);
3133 static const char *get_id(Token **tp, const char *dname)
3135 const char *id;
3136 Token *t = *tp;
3138 t = t->next; /* Skip directive */
3139 t = skip_white(t);
3140 t = expand_id(t);
3142 if (!is_macro_id(t)) {
3143 nasm_nonfatal("`%s' expects a macro identifier", dname);
3144 return NULL;
3147 id = tok_text(t);
3148 t = skip_white(t);
3149 *tp = t;
3150 return id;
3153 /* Parse a %use package name and find the package. Set *err on syntax error. */
3154 static const struct use_package *
3155 get_use_pkg(Token *t, const char *dname, const char **name)
3157 const char *id;
3159 t = skip_white(t);
3160 t = expand_smacro(t);
3162 *name = NULL;
3164 if (!t) {
3165 nasm_nonfatal("`%s' expects a package name, got end of line", dname);
3166 return NULL;
3167 } else if (t->type != TOK_ID && t->type != TOK_STRING) {
3168 nasm_nonfatal("`%s' expects a package name, got `%s'",
3169 dname, tok_text(t));
3170 return NULL;
3173 *name = id = unquote_token(t);
3175 t = t->next;
3176 t = skip_white(t);
3177 if (t)
3178 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
3180 return nasm_find_use_package(id);
3184 * find and process preprocessor directive in passed line
3185 * Find out if a line contains a preprocessor directive, and deal
3186 * with it if so.
3188 * If a directive _is_ found, it is the responsibility of this routine
3189 * (and not the caller) to free_tlist() the line.
3191 * @param tline a pointer to the current tokeninzed line linked list
3192 * @param output if this directive generated output
3193 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
3196 static int do_directive(Token *tline, Token **output)
3198 enum preproc_token i;
3199 int j;
3200 bool err;
3201 int nparam;
3202 bool nolist;
3203 bool casesense;
3204 int k, m;
3205 int offset;
3206 const char *p;
3207 char *q, *qbuf;
3208 const char *found_path;
3209 const char *mname;
3210 struct ppscan pps;
3211 Include *inc;
3212 Context *ctx;
3213 Cond *cond;
3214 MMacro *mmac, **mmhead;
3215 Token *t = NULL, *tt, *macro_start, *last, *origline;
3216 Line *l;
3217 struct tokenval tokval;
3218 expr *evalresult;
3219 int64_t count;
3220 size_t len;
3221 errflags severity;
3222 const char *dname; /* Name of directive, for messages */
3224 *output = NULL; /* No output generated */
3225 origline = tline;
3227 tline = skip_white(tline);
3228 if (!tline || !tok_type(tline, TOK_PREPROC_ID))
3229 return NO_DIRECTIVE_FOUND;
3231 dname = tok_text(tline);
3232 if (dname[1] == '%')
3233 return NO_DIRECTIVE_FOUND;
3235 i = pp_token_hash(dname);
3237 casesense = true;
3238 if (PP_HAS_CASE(i) & PP_INSENSITIVE(i)) {
3239 casesense = false;
3240 i--;
3244 * If we're in a non-emitting branch of a condition construct,
3245 * or walking to the end of an already terminated %rep block,
3246 * we should ignore all directives except for condition
3247 * directives.
3249 if (((istk->conds && !emitting(istk->conds->state)) ||
3250 (istk->mstk.mstk && !istk->mstk.mstk->in_progress)) &&
3251 !is_condition(i)) {
3252 return NO_DIRECTIVE_FOUND;
3256 * If we're defining a macro or reading a %rep block, we should
3257 * ignore all directives except for %macro/%imacro (which nest),
3258 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
3259 * If we're in a %rep block, another %rep nests, so should be let through.
3261 if (defining && i != PP_MACRO && i != PP_RMACRO &&
3262 i != PP_ENDMACRO && i != PP_ENDM &&
3263 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
3264 return NO_DIRECTIVE_FOUND;
3267 if (defining) {
3268 if (i == PP_MACRO || i == PP_RMACRO) {
3269 nested_mac_count++;
3270 return NO_DIRECTIVE_FOUND;
3271 } else if (nested_mac_count > 0) {
3272 if (i == PP_ENDMACRO) {
3273 nested_mac_count--;
3274 return NO_DIRECTIVE_FOUND;
3277 if (!defining->name) {
3278 if (i == PP_REP) {
3279 nested_rep_count++;
3280 return NO_DIRECTIVE_FOUND;
3281 } else if (nested_rep_count > 0) {
3282 if (i == PP_ENDREP) {
3283 nested_rep_count--;
3284 return NO_DIRECTIVE_FOUND;
3290 switch (i) {
3291 default:
3292 nasm_nonfatal("unknown preprocessor directive `%s'", dname);
3293 return NO_DIRECTIVE_FOUND; /* didn't get it */
3295 case PP_PRAGMA:
3297 * %pragma namespace options...
3299 * The namespace "preproc" is reserved for the preprocessor;
3300 * all other namespaces generate a [pragma] assembly directive.
3302 * Invalid %pragmas are ignored and may have different
3303 * meaning in future versions of NASM.
3305 t = tline;
3306 tline = tline->next;
3307 t->next = NULL;
3308 tline = zap_white(expand_smacro(tline));
3309 if (tok_type(tline, TOK_ID)) {
3310 if (!nasm_stricmp(tok_text(tline), "preproc")) {
3311 /* Preprocessor pragma */
3312 do_pragma_preproc(tline);
3313 free_tlist(tline);
3314 } else {
3315 /* Build the assembler directive */
3317 /* Append bracket to the end of the output */
3318 for (t = tline; t->next; t = t->next)
3320 t->next = make_tok_char(NULL, ']');
3322 /* Prepend "[pragma " */
3323 t = new_White(tline);
3324 t = new_Token(t, TOK_ID, "pragma", 6);
3325 t = make_tok_char(t, '[');
3326 tline = t;
3327 *output = tline;
3330 break;
3332 case PP_STACKSIZE:
3333 /* Directive to tell NASM what the default stack size is. The
3334 * default is for a 16-bit stack, and this can be overriden with
3335 * %stacksize large.
3337 tline = skip_white(tline->next);
3338 if (!tline || tline->type != TOK_ID) {
3339 nasm_nonfatal("`%s' missing size parameter", dname);
3341 if (nasm_stricmp(tok_text(tline), "flat") == 0) {
3342 /* All subsequent ARG directives are for a 32-bit stack */
3343 StackSize = 4;
3344 StackPointer = "ebp";
3345 ArgOffset = 8;
3346 LocalOffset = 0;
3347 } else if (nasm_stricmp(tok_text(tline), "flat64") == 0) {
3348 /* All subsequent ARG directives are for a 64-bit stack */
3349 StackSize = 8;
3350 StackPointer = "rbp";
3351 ArgOffset = 16;
3352 LocalOffset = 0;
3353 } else if (nasm_stricmp(tok_text(tline), "large") == 0) {
3354 /* All subsequent ARG directives are for a 16-bit stack,
3355 * far function call.
3357 StackSize = 2;
3358 StackPointer = "bp";
3359 ArgOffset = 4;
3360 LocalOffset = 0;
3361 } else if (nasm_stricmp(tok_text(tline), "small") == 0) {
3362 /* All subsequent ARG directives are for a 16-bit stack,
3363 * far function call. We don't support near functions.
3365 StackSize = 2;
3366 StackPointer = "bp";
3367 ArgOffset = 6;
3368 LocalOffset = 0;
3369 } else {
3370 nasm_nonfatal("`%s' invalid size type", dname);
3372 break;
3374 case PP_ARG:
3375 /* TASM like ARG directive to define arguments to functions, in
3376 * the following form:
3378 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
3380 offset = ArgOffset;
3381 do {
3382 const char *arg;
3383 char directive[256];
3384 int size = StackSize;
3386 /* Find the argument name */
3387 tline = skip_white(tline->next);
3388 if (!tline || tline->type != TOK_ID) {
3389 nasm_nonfatal("`%s' missing argument parameter", dname);
3390 goto done;
3392 arg = tok_text(tline);
3394 /* Find the argument size type */
3395 tline = tline->next;
3396 if (!tok_is(tline, ':')) {
3397 nasm_nonfatal("syntax error processing `%s' directive", dname);
3398 goto done;
3400 tline = tline->next;
3401 if (!tok_type(tline, TOK_ID)) {
3402 nasm_nonfatal("`%s' missing size type parameter", dname);
3403 goto done;
3406 /* Allow macro expansion of type parameter */
3407 tt = tokenize(tok_text(tline));
3408 tt = expand_smacro(tt);
3409 size = parse_size(tok_text(tt));
3410 if (!size) {
3411 nasm_nonfatal("invalid size type for `%s' missing directive", dname);
3412 free_tlist(tt);
3413 goto done;
3415 free_tlist(tt);
3417 /* Round up to even stack slots */
3418 size = ALIGN(size, StackSize);
3420 /* Now define the macro for the argument */
3421 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
3422 arg, StackPointer, offset);
3423 do_directive(tokenize(directive), output);
3424 offset += size;
3426 /* Move to the next argument in the list */
3427 tline = skip_white(tline->next);
3428 } while (tok_is(tline, ','));
3429 ArgOffset = offset;
3430 break;
3432 case PP_LOCAL:
3433 /* TASM like LOCAL directive to define local variables for a
3434 * function, in the following form:
3436 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
3438 * The '= LocalSize' at the end is ignored by NASM, but is
3439 * required by TASM to define the local parameter size (and used
3440 * by the TASM macro package).
3442 offset = LocalOffset;
3443 do {
3444 const char *local;
3445 char directive[256];
3446 int size = StackSize;
3448 /* Find the argument name */
3449 tline = skip_white(tline->next);
3450 if (!tline || tline->type != TOK_ID) {
3451 nasm_nonfatal("`%s' missing argument parameter", dname);
3452 goto done;
3454 local = tok_text(tline);
3456 /* Find the argument size type */
3457 tline = tline->next;
3458 if (!tok_is(tline, ':')) {
3459 nasm_nonfatal("syntax error processing `%s' directive", dname);
3460 goto done;
3462 tline = tline->next;
3463 if (!tok_type(tline, TOK_ID)) {
3464 nasm_nonfatal("`%s' missing size type parameter", dname);
3465 goto done;
3468 /* Allow macro expansion of type parameter */
3469 tt = tokenize(tok_text(tline));
3470 tt = expand_smacro(tt);
3471 size = parse_size(tok_text(tt));
3472 if (!size) {
3473 nasm_nonfatal("invalid size type for `%s' missing directive", dname);
3474 free_tlist(tt);
3475 goto done;
3477 free_tlist(tt);
3479 /* Round up to even stack slots */
3480 size = ALIGN(size, StackSize);
3482 offset += size; /* Negative offset, increment before */
3484 /* Now define the macro for the argument */
3485 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
3486 local, StackPointer, offset);
3487 do_directive(tokenize(directive), output);
3489 /* Now define the assign to setup the enter_c macro correctly */
3490 snprintf(directive, sizeof(directive),
3491 "%%assign %%$localsize %%$localsize+%d", size);
3492 do_directive(tokenize(directive), output);
3494 /* Move to the next argument in the list */
3495 tline = skip_white(tline->next);
3496 } while (tok_is(tline, ','));
3497 LocalOffset = offset;
3498 break;
3500 case PP_CLEAR:
3501 if (tline->next)
3502 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
3503 free_macros();
3504 init_macros();
3505 break;
3507 case PP_DEPEND:
3508 t = tline->next = expand_smacro(tline->next);
3509 t = skip_white(t);
3510 if (!t || (t->type != TOK_STRING &&
3511 t->type != TOK_INTERNAL_STRING)) {
3512 nasm_nonfatal("`%s' expects a file name", dname);
3513 goto done;
3515 if (t->next)
3516 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
3518 strlist_add(deplist, unquote_token_cstr(t));
3519 goto done;
3521 case PP_INCLUDE:
3522 t = tline->next = expand_smacro(tline->next);
3523 t = skip_white(t);
3525 if (!t || (t->type != TOK_STRING &&
3526 t->type != TOK_INTERNAL_STRING)) {
3527 nasm_nonfatal("`%s' expects a file name", dname);
3528 goto done;
3530 if (t->next)
3531 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
3532 p = unquote_token_cstr(t);
3533 nasm_new(inc);
3534 inc->next = istk;
3535 found_path = NULL;
3536 inc->fp = inc_fopen(p, deplist, &found_path,
3537 (pp_mode == PP_DEPS)
3538 ? INC_OPTIONAL : INC_NEEDED, NF_TEXT);
3539 if (!inc->fp) {
3540 /* -MG given but file not found */
3541 nasm_free(inc);
3542 } else {
3543 inc->fname = src_set_fname(found_path ? found_path : p);
3544 inc->lineno = src_set_linnum(0);
3545 inc->lineinc = 1;
3546 inc->nolist = istk->nolist;
3547 istk = inc;
3548 lfmt->uplevel(LIST_INCLUDE, 0);
3550 break;
3552 case PP_USE:
3554 const struct use_package *pkg;
3555 const char *name;
3557 pkg = get_use_pkg(tline->next, dname, &name);
3558 if (!name)
3559 goto done;
3560 if (!pkg) {
3561 nasm_nonfatal("unknown `%s' package: `%s'", dname, name);
3562 } else if (!use_loaded[pkg->index]) {
3564 * Not already included, go ahead and include it.
3565 * Treat it as an include file for the purpose of
3566 * producing a listing.
3568 use_loaded[pkg->index] = true;
3569 stdmacpos = pkg->macros;
3570 nasm_new(inc);
3571 inc->next = istk;
3572 inc->fname = src_set_fname(NULL);
3573 inc->lineno = src_set_linnum(0);
3574 inc->nolist = !list_option('b') || istk->nolist;
3575 istk = inc;
3576 lfmt->uplevel(LIST_INCLUDE, 0);
3578 break;
3580 case PP_PUSH:
3581 case PP_REPL:
3582 case PP_POP:
3583 tline = tline->next;
3584 tline = skip_white(tline);
3585 tline = expand_id(tline);
3586 if (tline) {
3587 if (!tok_type(tline, TOK_ID)) {
3588 nasm_nonfatal("`%s' expects a context identifier",
3589 pp_directives[i]);
3590 goto done;
3592 if (tline->next)
3593 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored",
3594 pp_directives[i]);
3595 p = tok_text(tline);
3596 } else {
3597 p = NULL; /* Anonymous */
3600 if (i == PP_PUSH) {
3601 nasm_new(ctx);
3602 ctx->depth = cstk ? cstk->depth + 1 : 1;
3603 ctx->next = cstk;
3604 ctx->name = p ? nasm_strdup(p) : NULL;
3605 ctx->number = unique++;
3606 cstk = ctx;
3607 } else {
3608 /* %pop or %repl */
3609 if (!cstk) {
3610 nasm_nonfatal("`%s': context stack is empty",
3611 pp_directives[i]);
3612 } else if (i == PP_POP) {
3613 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
3614 nasm_nonfatal("`%s' in wrong context: %s, "
3615 "expected %s",
3616 dname, cstk->name ? cstk->name : "anonymous", p);
3617 else
3618 ctx_pop();
3619 } else {
3620 /* i == PP_REPL */
3621 nasm_free((char *)cstk->name);
3622 cstk->name = p ? nasm_strdup(p) : NULL;
3623 p = NULL;
3626 break;
3627 case PP_FATAL:
3628 severity = ERR_FATAL;
3629 goto issue_error;
3630 case PP_ERROR:
3631 severity = ERR_NONFATAL|ERR_PASS2;
3632 goto issue_error;
3633 case PP_WARNING:
3635 *!user [on] %warning directives
3636 *! controls output of \c{%warning} directives (see \k{pperror}).
3638 severity = ERR_WARNING|WARN_USER|ERR_PASS2;
3639 goto issue_error;
3641 issue_error:
3643 /* Only error out if this is the final pass */
3644 tline->next = expand_smacro(tline->next);
3645 tline = tline->next;
3646 tline = skip_white(tline);
3647 t = tline ? tline->next : NULL;
3648 t = skip_white(t);
3649 if (tok_type(tline, TOK_STRING) && !t) {
3650 /* The line contains only a quoted string */
3651 p = unquote_token(tline); /* Ignore NUL character truncation */
3652 nasm_error(severity, "%s", p);
3653 } else {
3654 /* Not a quoted string, or more than a quoted string */
3655 q = detoken(tline, false);
3656 nasm_error(severity, "%s", q);
3657 nasm_free(q);
3659 break;
3662 CASE_PP_IF:
3663 if (istk->conds && !emitting(istk->conds->state))
3664 j = COND_NEVER;
3665 else {
3666 j = if_condition(tline->next, i);
3667 tline->next = NULL; /* it got freed */
3669 cond = nasm_malloc(sizeof(Cond));
3670 cond->next = istk->conds;
3671 cond->state = j;
3672 istk->conds = cond;
3673 if(istk->mstk.mstk)
3674 istk->mstk.mstk->condcnt++;
3675 break;
3677 CASE_PP_ELIF:
3678 if (!istk->conds)
3679 nasm_fatal("`%s': no matching `%%if'", dname);
3680 switch(istk->conds->state) {
3681 case COND_IF_TRUE:
3682 istk->conds->state = COND_DONE;
3683 break;
3685 case COND_DONE:
3686 case COND_NEVER:
3687 break;
3689 case COND_ELSE_TRUE:
3690 case COND_ELSE_FALSE:
3691 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
3692 "`%%elif' after `%%else' ignored");
3693 istk->conds->state = COND_NEVER;
3694 break;
3696 case COND_IF_FALSE:
3698 * IMPORTANT: In the case of %if, we will already have
3699 * called expand_mmac_params(); however, if we're
3700 * processing an %elif we must have been in a
3701 * non-emitting mode, which would have inhibited
3702 * the normal invocation of expand_mmac_params().
3703 * Therefore, we have to do it explicitly here.
3705 j = if_condition(expand_mmac_params(tline->next), i);
3706 tline->next = NULL; /* it got freed */
3707 istk->conds->state = j;
3708 break;
3710 break;
3712 case PP_ELSE:
3713 if (tline->next)
3714 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
3715 "trailing garbage after `%%else' ignored");
3716 if (!istk->conds)
3717 nasm_fatal("`%%else: no matching `%%if'");
3718 switch(istk->conds->state) {
3719 case COND_IF_TRUE:
3720 case COND_DONE:
3721 istk->conds->state = COND_ELSE_FALSE;
3722 break;
3724 case COND_NEVER:
3725 break;
3727 case COND_IF_FALSE:
3728 istk->conds->state = COND_ELSE_TRUE;
3729 break;
3731 case COND_ELSE_TRUE:
3732 case COND_ELSE_FALSE:
3733 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
3734 "`%%else' after `%%else' ignored.");
3735 istk->conds->state = COND_NEVER;
3736 break;
3738 break;
3740 case PP_ENDIF:
3741 if (tline->next)
3742 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
3743 "trailing garbage after `%%endif' ignored");
3744 if (!istk->conds)
3745 nasm_fatal("`%%endif': no matching `%%if'");
3746 cond = istk->conds;
3747 istk->conds = cond->next;
3748 nasm_free(cond);
3749 if(istk->mstk.mstk)
3750 istk->mstk.mstk->condcnt--;
3751 break;
3753 case PP_RMACRO:
3754 case PP_MACRO:
3755 nasm_assert(!defining);
3756 nasm_new(defining);
3757 defining->casesense = casesense;
3758 defining->dstk.mmac = defining;
3759 if (i == PP_RMACRO)
3760 defining->max_depth = nasm_limit[LIMIT_MACRO_LEVELS];
3761 if (!parse_mmacro_spec(tline, defining, dname)) {
3762 nasm_free(defining);
3763 goto done;
3766 src_get(&defining->xline, &defining->fname);
3768 mmac = (MMacro *) hash_findix(&mmacros, defining->name);
3769 while (mmac) {
3770 if (!strcmp(mmac->name, defining->name) &&
3771 (mmac->nparam_min <= defining->nparam_max
3772 || defining->plus)
3773 && (defining->nparam_min <= mmac->nparam_max
3774 || mmac->plus)) {
3775 nasm_warn(WARN_OTHER, "redefining multi-line macro `%s'",
3776 defining->name);
3777 break;
3779 mmac = mmac->next;
3781 break;
3783 case PP_ENDM:
3784 case PP_ENDMACRO:
3785 if (!(defining && defining->name)) {
3786 nasm_nonfatal("`%s': not defining a macro", tok_text(tline));
3787 goto done;
3789 mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
3790 defining->next = *mmhead;
3791 *mmhead = defining;
3792 defining = NULL;
3793 break;
3795 case PP_EXITMACRO:
3797 * We must search along istk->expansion until we hit a
3798 * macro-end marker for a macro with a name. Then we
3799 * bypass all lines between exitmacro and endmacro.
3801 list_for_each(l, istk->expansion)
3802 if (l->finishes && l->finishes->name)
3803 break;
3805 if (l) {
3807 * Remove all conditional entries relative to this
3808 * macro invocation. (safe to do in this context)
3810 for ( ; l->finishes->condcnt > 0; l->finishes->condcnt --) {
3811 cond = istk->conds;
3812 istk->conds = cond->next;
3813 nasm_free(cond);
3815 istk->expansion = l;
3816 } else {
3817 nasm_nonfatal("`%%exitmacro' not within `%%macro' block");
3819 break;
3821 case PP_UNIMACRO:
3822 casesense = false;
3823 /* fall through */
3824 case PP_UNMACRO:
3826 MMacro **mmac_p;
3827 MMacro spec;
3829 nasm_zero(spec);
3830 spec.casesense = casesense;
3831 if (!parse_mmacro_spec(tline, &spec, dname)) {
3832 goto done;
3834 mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
3835 while (mmac_p && *mmac_p) {
3836 mmac = *mmac_p;
3837 if (mmac->casesense == spec.casesense &&
3838 !mstrcmp(mmac->name, spec.name, spec.casesense) &&
3839 mmac->nparam_min == spec.nparam_min &&
3840 mmac->nparam_max == spec.nparam_max &&
3841 mmac->plus == spec.plus) {
3842 *mmac_p = mmac->next;
3843 free_mmacro(mmac);
3844 } else {
3845 mmac_p = &mmac->next;
3848 free_tlist(spec.dlist);
3849 break;
3852 case PP_ROTATE:
3853 while (tok_white(tline->next))
3854 tline = tline->next;
3855 if (!tline->next) {
3856 free_tlist(origline);
3857 nasm_nonfatal("`%%rotate' missing rotate count");
3858 return DIRECTIVE_FOUND;
3860 t = expand_smacro(tline->next);
3861 tline->next = NULL;
3862 pps.tptr = tline = t;
3863 pps.ntokens = -1;
3864 tokval.t_type = TOKEN_INVALID;
3865 evalresult =
3866 evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
3867 free_tlist(tline);
3868 if (!evalresult)
3869 return DIRECTIVE_FOUND;
3870 if (tokval.t_type)
3871 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
3872 if (!is_simple(evalresult)) {
3873 nasm_nonfatal("non-constant value given to `%%rotate'");
3874 return DIRECTIVE_FOUND;
3876 mmac = istk->mstk.mmac;
3877 if (!mmac) {
3878 nasm_nonfatal("`%%rotate' invoked outside a macro call");
3879 } else if (mmac->nparam == 0) {
3880 nasm_nonfatal("`%%rotate' invoked within macro without parameters");
3881 } else {
3882 int rotate = mmac->rotate + reloc_value(evalresult);
3884 rotate %= (int)mmac->nparam;
3885 if (rotate < 0)
3886 rotate += mmac->nparam;
3888 mmac->rotate = rotate;
3890 break;
3892 case PP_REP:
3894 MMacro *tmp_defining;
3896 nolist = false;
3897 tline = skip_white(tline->next);
3898 if (tok_type(tline, TOK_ID) && tline->len == 7 &&
3899 !nasm_memicmp(tline->text.a, ".nolist", 7)) {
3900 nolist = !list_option('f') || istk->nolist;
3901 tline = skip_white(tline->next);
3904 if (tline) {
3905 pps.tptr = expand_smacro(tline);
3906 pps.ntokens = -1;
3907 tokval.t_type = TOKEN_INVALID;
3908 /* XXX: really critical?! */
3909 evalresult =
3910 evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
3911 if (!evalresult)
3912 goto done;
3913 if (tokval.t_type)
3914 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
3915 if (!is_simple(evalresult)) {
3916 nasm_nonfatal("non-constant value given to `%%rep'");
3917 goto done;
3919 count = reloc_value(evalresult);
3920 if (count > nasm_limit[LIMIT_REP]) {
3921 nasm_nonfatal("`%%rep' count %"PRId64" exceeds limit (currently %"PRId64")",
3922 count, nasm_limit[LIMIT_REP]);
3923 count = 0;
3924 } else if (count < 0) {
3926 *!negative-rep [on] regative %rep count
3927 *! warns about negative counts given to the \c{%rep}
3928 *! preprocessor directive.
3930 nasm_warn(ERR_PASS2|WARN_NEGATIVE_REP,
3931 "negative `%%rep' count: %"PRId64, count);
3932 count = 0;
3933 } else {
3934 count++;
3936 } else {
3937 nasm_nonfatal("`%%rep' expects a repeat count");
3938 count = 0;
3940 tmp_defining = defining;
3941 nasm_new(defining);
3942 defining->nolist = nolist;
3943 defining->in_progress = count;
3944 defining->mstk = istk->mstk;
3945 defining->dstk.mstk = tmp_defining;
3946 defining->dstk.mmac = tmp_defining ? tmp_defining->dstk.mmac : NULL;
3947 src_get(&defining->xline, &defining->fname);
3948 break;
3951 case PP_ENDREP:
3952 if (!defining || defining->name) {
3953 nasm_nonfatal("`%%endrep': no matching `%%rep'");
3954 goto done;
3958 * Now we have a "macro" defined - although it has no name
3959 * and we won't be entering it in the hash tables - we must
3960 * push a macro-end marker for it on to istk->expansion.
3961 * After that, it will take care of propagating itself (a
3962 * macro-end marker line for a macro which is really a %rep
3963 * block will cause the macro to be re-expanded, complete
3964 * with another macro-end marker to ensure the process
3965 * continues) until the whole expansion is forcibly removed
3966 * from istk->expansion by a %exitrep.
3968 nasm_new(l);
3969 l->next = istk->expansion;
3970 l->finishes = defining;
3971 l->first = NULL;
3972 istk->expansion = l;
3974 istk->mstk.mstk = defining;
3976 lfmt->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
3977 defining = defining->dstk.mstk;
3978 break;
3980 case PP_EXITREP:
3982 * We must search along istk->expansion until we hit a
3983 * macro-end marker for a macro with no name. Then we set
3984 * its `in_progress' flag to 0.
3986 list_for_each(l, istk->expansion)
3987 if (l->finishes && !l->finishes->name)
3988 break;
3990 if (l)
3991 l->finishes->in_progress = 0;
3992 else
3993 nasm_nonfatal("`%%exitrep' not within `%%rep' block");
3994 break;
3996 case PP_DEFINE:
3997 case PP_XDEFINE:
3998 case PP_DEFALIAS:
4000 SMacro tmpl;
4001 Token **lastp;
4003 if (!(mname = get_id(&tline, dname)))
4004 goto done;
4006 nasm_zero(tmpl);
4007 lastp = &tline->next;
4008 nparam = parse_smacro_template(&lastp, &tmpl);
4009 tline = *lastp;
4010 *lastp = NULL;
4012 if (unlikely(i == PP_DEFALIAS)) {
4013 macro_start = tline;
4014 if (!is_macro_id(macro_start)) {
4015 nasm_nonfatal("`%s' expects a macro identifier to alias",
4016 dname);
4017 goto done;
4019 tt = macro_start->next;
4020 macro_start->next = NULL;
4021 tline = tline->next;
4022 tline = skip_white(tline);
4023 if (tline && tline->type) {
4024 nasm_warn(WARN_OTHER,
4025 "trailing garbage after aliasing identifier ignored");
4027 free_tlist(tt);
4028 tmpl.alias = true;
4029 } else {
4030 /* Expand the macro definition now for %xdefine and %ixdefine */
4031 if (i == PP_XDEFINE)
4032 tline = expand_smacro(tline);
4034 /* Reverse expansion list and mark parameter tokens */
4035 macro_start = NULL;
4036 t = tline;
4037 while (t) {
4038 if (t->type == TOK_ID) {
4039 const char *ttext = tok_text(t);
4040 size_t tlen = t->len;
4041 for (i = 0; i < nparam; i++) {
4042 if (tmpl.params[i].name.len == t->len &&
4043 !memcmp(ttext, tok_text(&tmpl.params[i].name), tlen)) {
4044 t->type = tok_smac_param(i);
4045 break;
4049 tt = t->next;
4050 t->next = macro_start;
4051 macro_start = t;
4052 t = tt;
4057 * Good. We now have a macro name, a parameter count, and a
4058 * token list (in reverse order) for an expansion. We ought
4059 * to be OK just to create an SMacro, store it, and let
4060 * free_tlist have the rest of the line (which we have
4061 * carefully re-terminated after chopping off the expansion
4062 * from the end).
4064 define_smacro(mname, casesense, macro_start, &tmpl);
4065 break;
4068 case PP_UNDEF:
4069 case PP_UNDEFALIAS:
4070 if (!(mname = get_id(&tline, dname)))
4071 goto done;
4072 if (tline->next)
4073 nasm_warn(WARN_OTHER, "trailing garbage after macro name ignored");
4075 undef_smacro(mname, i == PP_UNDEFALIAS);
4076 break;
4078 case PP_DEFSTR:
4079 if (!(mname = get_id(&tline, dname)))
4080 goto done;
4082 last = tline;
4083 tline = expand_smacro(tline->next);
4084 last->next = NULL;
4086 tline = zap_white(tline);
4087 q = detoken(tline, false);
4088 macro_start = make_tok_qstr(NULL, q);
4089 nasm_free(q);
4092 * We now have a macro name, an implicit parameter count of
4093 * zero, and a string token to use as an expansion. Create
4094 * and store an SMacro.
4096 define_smacro(mname, casesense, macro_start, NULL);
4097 break;
4099 case PP_DEFTOK:
4100 if (!(mname = get_id(&tline, dname)))
4101 goto done;
4103 last = tline;
4104 tline = expand_smacro(tline->next);
4105 last->next = NULL;
4107 t = skip_white(tline);
4108 /* t should now point to the string */
4109 if (!tok_type(t, TOK_STRING)) {
4110 nasm_nonfatal("`%s' requires string as second parameter", dname);
4111 free_tlist(tline);
4112 goto done;
4116 * Convert the string to a token stream. Note that smacros
4117 * are stored with the token stream reversed, so we have to
4118 * reverse the output of tokenize().
4120 macro_start = reverse_tokens(tokenize(unquote_token_cstr(t)));
4123 * We now have a macro name, an implicit parameter count of
4124 * zero, and a numeric token to use as an expansion. Create
4125 * and store an SMacro.
4127 define_smacro(mname, casesense, macro_start, NULL);
4128 free_tlist(tline);
4129 break;
4131 case PP_PATHSEARCH:
4133 const char *found_path;
4135 if (!(mname = get_id(&tline, dname)))
4136 goto done;
4138 last = tline;
4139 tline = expand_smacro(tline->next);
4140 last->next = NULL;
4142 t = skip_white(tline);
4143 if (!t || (t->type != TOK_STRING &&
4144 t->type != TOK_INTERNAL_STRING)) {
4145 nasm_nonfatal("`%s' expects a file name", dname);
4146 free_tlist(tline);
4147 goto done;
4149 if (t->next)
4150 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
4152 p = unquote_token_cstr(t);
4154 inc_fopen(p, NULL, &found_path, INC_PROBE, NF_BINARY);
4155 if (!found_path)
4156 found_path = p;
4157 macro_start = make_tok_qstr(NULL, found_path);
4160 * We now have a macro name, an implicit parameter count of
4161 * zero, and a string token to use as an expansion. Create
4162 * and store an SMacro.
4164 define_smacro(mname, casesense, macro_start, NULL);
4165 free_tlist(tline);
4166 break;
4169 case PP_STRLEN:
4170 if (!(mname = get_id(&tline, dname)))
4171 goto done;
4173 last = tline;
4174 tline = expand_smacro(tline->next);
4175 last->next = NULL;
4177 t = skip_white(tline);
4178 /* t should now point to the string */
4179 if (!tok_type(t, TOK_STRING)) {
4180 nasm_nonfatal("`%s' requires string as second parameter", dname);
4181 free_tlist(tline);
4182 free_tlist(origline);
4183 return DIRECTIVE_FOUND;
4186 unquote_token(t);
4187 macro_start = make_tok_num(NULL, t->len);
4190 * We now have a macro name, an implicit parameter count of
4191 * zero, and a numeric token to use as an expansion. Create
4192 * and store an SMacro.
4194 define_smacro(mname, casesense, macro_start, NULL);
4195 free_tlist(tline);
4196 free_tlist(origline);
4197 return DIRECTIVE_FOUND;
4199 case PP_STRCAT:
4200 if (!(mname = get_id(&tline, dname)))
4201 goto done;
4203 last = tline;
4204 tline = expand_smacro(tline->next);
4205 last->next = NULL;
4207 len = 0;
4208 list_for_each(t, tline) {
4209 switch (t->type) {
4210 case TOK_WHITESPACE:
4211 break;
4212 case TOK_STRING:
4213 unquote_token(t);
4214 len += t->len;
4215 break;
4216 case TOK_OTHER:
4217 if (tok_is(t, ',')) /* permit comma separators */
4218 break;
4219 /* else fall through */
4220 default:
4221 nasm_nonfatal("non-string passed to `%s': %s", dname,
4222 tok_text(t));
4223 free_tlist(tline);
4224 goto done;
4228 q = qbuf = nasm_malloc(len);
4229 list_for_each(t, tline) {
4230 if (t->type == TOK_INTERNAL_STRING)
4231 q = mempcpy(q, tok_text(t), t->len);
4235 * We now have a macro name, an implicit parameter count of
4236 * zero, and a numeric token to use as an expansion. Create
4237 * and store an SMacro.
4239 macro_start = make_tok_qstr(NULL, qbuf);
4240 nasm_free(qbuf);
4241 define_smacro(mname, casesense, macro_start, NULL);
4242 free_tlist(tline);
4243 break;
4245 case PP_SUBSTR:
4247 int64_t start, count;
4248 const char *txt;
4249 size_t len;
4251 if (!(mname = get_id(&tline, dname)))
4252 goto done;
4254 last = tline;
4255 tline = expand_smacro(tline->next);
4256 last->next = NULL;
4258 if (tline) /* skip expanded id */
4259 t = tline->next;
4261 t = skip_white(t);
4263 /* t should now point to the string */
4264 if (!tok_type(t, TOK_STRING)) {
4265 nasm_nonfatal("`%s' requires string as second parameter", dname);
4266 free_tlist(tline);
4267 goto done;
4270 pps.tptr = t->next;
4271 pps.ntokens = -1;
4272 tokval.t_type = TOKEN_INVALID;
4273 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
4274 if (!evalresult) {
4275 free_tlist(tline);
4276 goto done;
4277 } else if (!is_simple(evalresult)) {
4278 nasm_nonfatal("non-constant value given to `%s'", dname);
4279 free_tlist(tline);
4280 goto done;
4282 start = evalresult->value - 1;
4284 pps.tptr = skip_white(pps.tptr);
4285 if (!pps.tptr) {
4286 count = 1; /* Backwards compatibility: one character */
4287 } else {
4288 tokval.t_type = TOKEN_INVALID;
4289 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
4290 if (!evalresult) {
4291 free_tlist(tline);
4292 goto done;
4293 } else if (!is_simple(evalresult)) {
4294 nasm_nonfatal("non-constant value given to `%s'", dname);
4295 free_tlist(tline);
4296 goto done;
4298 count = evalresult->value;
4301 unquote_token(t);
4302 len = t->len;
4304 /* make start and count being in range */
4305 if (start < 0)
4306 start = 0;
4307 if (count < 0)
4308 count = len + count + 1 - start;
4309 if (start + count > (int64_t)len)
4310 count = len - start;
4311 if (!len || count < 0 || start >=(int64_t)len)
4312 start = -1, count = 0; /* empty string */
4314 txt = (start < 0) ? "" : tok_text(t) + start;
4315 len = count;
4316 macro_start = make_tok_qstr(NULL, txt);
4319 * We now have a macro name, an implicit parameter count of
4320 * zero, and a numeric token to use as an expansion. Create
4321 * and store an SMacro.
4323 define_smacro(mname, casesense, macro_start, NULL);
4324 free_tlist(tline);
4325 break;
4328 case PP_ASSIGN:
4329 if (!(mname = get_id(&tline, dname)))
4330 goto done;
4332 last = tline;
4333 tline = expand_smacro(tline->next);
4334 last->next = NULL;
4336 pps.tptr = tline;
4337 pps.ntokens = -1;
4338 tokval.t_type = TOKEN_INVALID;
4339 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
4340 free_tlist(tline);
4341 if (!evalresult)
4342 goto done;
4344 if (tokval.t_type)
4345 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
4347 if (!is_simple(evalresult)) {
4348 nasm_nonfatal("non-constant value given to `%s'", dname);
4349 free_tlist(origline);
4350 return DIRECTIVE_FOUND;
4353 macro_start = make_tok_num(NULL, reloc_value(evalresult));
4356 * We now have a macro name, an implicit parameter count of
4357 * zero, and a numeric token to use as an expansion. Create
4358 * and store an SMacro.
4360 define_smacro(mname, casesense, macro_start, NULL);
4361 break;
4363 case PP_ALIASES:
4364 tline = tline->next;
4365 tline = expand_smacro(tline);
4366 do_aliases = pp_get_boolean_option(tline, do_aliases);
4367 break;
4369 case PP_LINE:
4371 * Syntax is `%line nnn[+mmm] [filename]'
4373 if (unlikely(pp_noline))
4374 goto done;
4376 tline = tline->next;
4377 tline = skip_white(tline);
4378 if (!tok_type(tline, TOK_NUMBER)) {
4379 nasm_nonfatal("`%s' expects line number", dname);
4380 goto done;
4382 k = readnum(tok_text(tline), &err);
4383 m = 1;
4384 tline = tline->next;
4385 if (tok_is(tline, '+')) {
4386 tline = tline->next;
4387 if (!tok_type(tline, TOK_NUMBER)) {
4388 nasm_nonfatal("`%s' expects line increment", dname);
4389 goto done;
4391 m = readnum(tok_text(tline), &err);
4392 tline = tline->next;
4394 tline = skip_white(tline);
4395 src_set_linnum(k);
4396 istk->lineinc = m;
4397 if (tline) {
4398 char *fname = detoken(tline, false);
4399 src_set_fname(fname);
4400 nasm_free(fname);
4402 break;
4405 done:
4406 free_tlist(origline);
4407 return DIRECTIVE_FOUND;
4411 * Ensure that a macro parameter contains a condition code and
4412 * nothing else. Return the condition code index if so, or -1
4413 * otherwise.
4415 static int find_cc(Token * t)
4417 Token *tt;
4419 if (!t)
4420 return -1; /* Probably a %+ without a space */
4422 t = skip_white(t);
4423 if (!tok_type(t, TOK_ID))
4424 return -1;
4425 tt = t->next;
4426 tt = skip_white(tt);
4427 if (tok_isnt(tt, ','))
4428 return -1;
4430 return bsii(tok_text(t), (const char **)conditions,
4431 ARRAY_SIZE(conditions));
4434 static inline bool pp_concat_match(const Token *t, unsigned int mask)
4436 return t && (PP_CONCAT_MASK(t->type) & mask);
4440 * This routines walks over tokens strem and handles tokens
4441 * pasting, if @handle_explicit passed then explicit pasting
4442 * term is handled, otherwise -- implicit pastings only.
4443 * The @m array can contain a series of token types which are
4444 * executed as separate passes.
4446 static bool paste_tokens(Token **head, const struct tokseq_match *m,
4447 size_t mnum, bool handle_explicit)
4449 Token *tok, *t, *next, **prev_next, **prev_nonspace;
4450 bool pasted = false;
4451 char *buf, *p;
4452 size_t len, i;
4455 * The last token before pasting. We need it
4456 * to be able to connect new handled tokens.
4457 * In other words if there were a tokens stream
4459 * A -> B -> C -> D
4461 * and we've joined tokens B and C, the resulting
4462 * stream should be
4464 * A -> BC -> D
4466 tok = *head;
4467 prev_next = prev_nonspace = head;
4469 if (tok_white(tok) || tok_type(tok, TOK_PASTE))
4470 prev_nonspace = NULL;
4472 while (tok && (next = tok->next)) {
4473 bool did_paste = false;
4475 switch (tok->type) {
4476 case TOK_WHITESPACE:
4477 /* Zap redundant whitespaces */
4478 tok->next = next = zap_white(next);
4479 break;
4481 case TOK_PASTE:
4482 /* Explicit pasting */
4483 if (!handle_explicit)
4484 break;
4486 /* Left pasting token is start of line */
4487 if (!prev_nonspace) {
4488 nasm_nonfatal("No lvalue found on pasting");
4489 tok = delete_Token(tok);
4490 break;
4493 did_paste = true;
4495 prev_next = prev_nonspace;
4496 t = *prev_nonspace;
4498 /* Delete leading whitespace */
4499 next = zap_white(t->next);
4501 /* Delete the %+ token itself */
4502 nasm_assert(next == tok);
4503 next = delete_Token(next);
4505 /* Delete trailing whitespace */
4506 next = zap_white(next);
4509 * No ending token, this might happen in two
4510 * cases
4512 * 1) There indeed no right token at all
4513 * 2) There is a bare "%define ID" statement,
4514 * and @ID does expand to whitespace.
4516 * So technically we need to do a grammar analysis
4517 * in another stage of parsing, but for now lets don't
4518 * change the behaviour people used to. Simply allow
4519 * whitespace after paste token.
4521 if (!next) {
4522 *prev_nonspace = tok = NULL; /* End of line */
4523 break;
4526 p = buf = nasm_malloc(t->len + next->len + 1);
4527 p = mempcpy(p, tok_text(t), t->len);
4528 p = mempcpy(p, tok_text(next), next->len);
4529 *p = '\0';
4530 delete_Token(t);
4531 t = tokenize(buf);
4532 nasm_free(buf);
4534 if (unlikely(!t)) {
4536 * No output at all? Replace with a single whitespace.
4537 * This should never happen.
4539 t = new_White(NULL);
4542 *prev_nonspace = tok = t;
4543 while (t->next)
4544 t = t->next; /* Find the last token produced */
4546 /* Delete the second token and attach to the end of the list */
4547 t->next = delete_Token(next);
4549 /* We want to restart from the head of the pasted token */
4550 next = tok;
4551 break;
4553 default:
4554 /* implicit pasting */
4555 for (i = 0; i < mnum; i++) {
4556 if (pp_concat_match(tok, m[i].mask_head))
4557 break;
4560 if (i >= mnum)
4561 break;
4563 len = tok->len;
4564 while (pp_concat_match(next, m[i].mask_tail)) {
4565 len += next->len;
4566 next = next->next;
4569 /* No match or no text to process */
4570 if (len == tok->len)
4571 break;
4573 p = buf = nasm_malloc(len + 1);
4574 while (tok != next) {
4575 p = mempcpy(p, tok_text(tok), tok->len);
4576 tok = delete_Token(tok);
4578 *p = '\0';
4579 *prev_next = tok = t = tokenize(buf);
4580 nasm_free(buf);
4583 * Connect pasted into original stream,
4584 * ie A -> new-tokens -> B
4586 while (t->next)
4587 t = t->next;
4588 t->next = next;
4589 prev_next = prev_nonspace = &t->next;
4590 did_paste = true;
4591 break;
4594 if (did_paste) {
4595 pasted = true;
4596 } else {
4597 prev_next = &tok->next;
4598 if (next && next->type != TOK_WHITESPACE && next->type != TOK_PASTE)
4599 prev_nonspace = prev_next;
4602 tok = next;
4605 return pasted;
4609 * Computes the proper rotation of mmacro parameters
4611 static int mmac_rotate(const MMacro *mac, unsigned int n)
4613 if (--n < mac->nparam)
4614 n = (n + mac->rotate) % mac->nparam;
4616 return n+1;
4620 * expands to a list of tokens from %{x:y}
4622 static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
4624 Token *t = tline, **tt, *tm, *head;
4625 char *pos;
4626 int fst, lst, j, i;
4628 pos = strchr(tok_text(tline), ':');
4629 nasm_assert(pos);
4631 lst = atoi(pos + 1);
4632 fst = atoi(tok_text(tline) + 1);
4635 * only macros params are accounted so
4636 * if someone passes %0 -- we reject such
4637 * value(s)
4639 if (lst == 0 || fst == 0)
4640 goto err;
4642 /* the values should be sane */
4643 if ((fst > (int)mac->nparam || fst < (-(int)mac->nparam)) ||
4644 (lst > (int)mac->nparam || lst < (-(int)mac->nparam)))
4645 goto err;
4647 fst = fst < 0 ? fst + (int)mac->nparam + 1: fst;
4648 lst = lst < 0 ? lst + (int)mac->nparam + 1: lst;
4650 /* count from zero */
4651 fst--, lst--;
4654 * It will be at least one token. Note we
4655 * need to scan params until separator, otherwise
4656 * only first token will be passed.
4658 j = (fst + mac->rotate) % mac->nparam;
4659 tm = mac->params[j+1];
4660 if (!tm)
4661 goto err;
4662 head = dup_Token(NULL, tm);
4663 tt = &head->next, tm = tm->next;
4664 while (tok_isnt(tm, ',')) {
4665 t = dup_Token(NULL, tm);
4666 *tt = t, tt = &t->next, tm = tm->next;
4669 if (fst < lst) {
4670 for (i = fst + 1; i <= lst; i++) {
4671 t = make_tok_char(NULL, ',');
4672 *tt = t, tt = &t->next;
4673 j = (i + mac->rotate) % mac->nparam;
4674 tm = mac->params[j+1];
4675 while (tok_isnt(tm, ',')) {
4676 t = dup_Token(NULL, tm);
4677 *tt = t, tt = &t->next, tm = tm->next;
4680 } else {
4681 for (i = fst - 1; i >= lst; i--) {
4682 t = make_tok_char(NULL, ',');
4683 *tt = t, tt = &t->next;
4684 j = (i + mac->rotate) % mac->nparam;
4685 tm = mac->params[j+1];
4686 while (!tok_isnt(tm, ',')) {
4687 t = dup_Token(NULL, tm);
4688 *tt = t, tt = &t->next, tm = tm->next;
4693 *last = tt;
4694 return head;
4696 err:
4697 nasm_nonfatal("`%%{%s}': macro parameters out of range",
4698 tok_text(tline) + 1);
4699 return NULL;
4703 * Expand MMacro-local things: parameter references (%0, %n, %+n,
4704 * %-n) and MMacro-local identifiers (%%foo) as well as
4705 * macro indirection (%[...]) and range (%{..:..}).
4707 static Token *expand_mmac_params(Token * tline)
4709 Token **tail, *thead;
4710 bool changed = false;
4711 MMacro *mac = istk->mstk.mmac;
4713 tail = &thead;
4714 thead = NULL;
4716 while (tline) {
4717 bool change;
4718 Token *t = tline;
4719 const char *text = tok_text(t);
4720 int type = t->type;
4722 tline = tline->next;
4723 t->next = NULL;
4725 switch (type) {
4726 case TOK_LOCAL_SYMBOL:
4727 type = TOK_ID;
4728 text = nasm_asprintf("..@%"PRIu64".%s", mac->unique, text+2);
4729 change = true;
4730 break;
4731 case TOK_MMACRO_PARAM:
4733 Token *tt = NULL;
4735 change = true;
4737 if (!mac) {
4738 nasm_nonfatal("`%s': not in a macro call", text);
4739 text = NULL;
4740 break;
4743 if (strchr(text, ':')) {
4745 * seems we have a parameters range here
4747 Token *head, **last;
4748 head = expand_mmac_params_range(mac, t, &last);
4749 if (head) {
4750 *tail = head;
4751 *last = tline;
4752 text = NULL;
4754 break;
4757 switch (text[1]) {
4759 * We have to make a substitution of one of the
4760 * forms %1, %-1, %+1, %%foo, %0, %00.
4762 case '0':
4763 if (!text[2]) {
4764 type = TOK_NUMBER;
4765 text = nasm_asprintf("%d", mac->nparam);
4766 break;
4768 if (text[2] != '0' || text[3])
4769 goto invalid;
4770 /* a possible captured label == mac->params[0] */
4771 /* fall through */
4772 default:
4774 unsigned long n;
4775 char *ep;
4777 n = strtoul(text + 1, &ep, 10);
4778 if (unlikely(*ep))
4779 goto invalid;
4781 if (n <= mac->nparam) {
4782 n = mmac_rotate(mac, n);
4783 dup_tlistn(mac->params[n], mac->paramlen[n], &tail);
4785 text = NULL;
4786 break;
4788 case '-':
4789 case '+':
4791 int cc;
4792 unsigned long n;
4793 char *ep;
4795 text = NULL;
4797 n = strtoul(tok_text(t) + 2, &ep, 10);
4798 if (unlikely(*ep))
4799 goto invalid;
4801 if (n && n < mac->nparam) {
4802 n = mmac_rotate(mac, n);
4803 tt = mac->params[n];
4805 cc = find_cc(tt);
4806 if (cc == -1) {
4807 nasm_nonfatal("macro parameter `%s' is not a condition code",
4808 tok_text(t));
4809 text = NULL;
4810 break;
4813 type = TOK_ID;
4814 if (text[1] == '-') {
4815 int ncc = inverse_ccs[cc];
4816 if (unlikely(ncc == -1)) {
4817 nasm_nonfatal("condition code `%s' is not invertible",
4818 conditions[cc]);
4819 break;
4821 cc = ncc;
4823 text = nasm_strdup(conditions[cc]);
4824 break;
4827 invalid:
4828 nasm_nonfatal("invalid macro parameter: `%s'", text);
4829 text = NULL;
4830 break;
4832 break;
4835 case TOK_PREPROC_Q:
4836 if (mac) {
4837 type = TOK_ID;
4838 text = nasm_strdup(mac->iname);
4839 change = true;
4840 } else {
4841 change = false;
4843 break;
4845 case TOK_PREPROC_QQ:
4846 if (mac) {
4847 type = TOK_ID;
4848 text = nasm_strdup(mac->name);
4849 change = true;
4850 } else {
4851 change = false;
4853 break;
4855 case TOK_INDIRECT:
4857 Token *tt;
4859 tt = tokenize(tok_text(t));
4860 tt = expand_mmac_params(tt);
4861 tt = expand_smacro(tt);
4862 /* Why dup_tlist() here? We should own tt... */
4863 dup_tlist(tt, &tail);
4864 text = NULL;
4865 change = true;
4866 break;
4869 default:
4870 change = false;
4871 break;
4874 if (change) {
4875 if (!text) {
4876 delete_Token(t);
4877 } else {
4878 *tail = t;
4879 tail = &t->next;
4880 set_text(t, text, tok_strlen(text));
4881 t->type = type;
4883 changed = true;
4884 } else {
4885 *tail = t;
4886 tail = &t->next;
4890 *tail = NULL;
4892 if (changed) {
4893 const struct tokseq_match t[] = {
4895 PP_CONCAT_MASK(TOK_ID) |
4896 PP_CONCAT_MASK(TOK_FLOAT), /* head */
4897 PP_CONCAT_MASK(TOK_ID) |
4898 PP_CONCAT_MASK(TOK_NUMBER) |
4899 PP_CONCAT_MASK(TOK_FLOAT) |
4900 PP_CONCAT_MASK(TOK_OTHER) /* tail */
4903 PP_CONCAT_MASK(TOK_NUMBER), /* head */
4904 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
4907 paste_tokens(&thead, t, ARRAY_SIZE(t), false);
4910 return thead;
4913 static Token *expand_smacro_noreset(Token * tline);
4916 * Expand *one* single-line macro instance. If the first token is not
4917 * a macro at all, it is simply copied to the output and the pointer
4918 * advanced. tpp should be a pointer to a pointer (usually the next
4919 * pointer of the previous token) to the first token. **tpp is updated
4920 * to point to the first token of the expansion, and *tpp updated to
4921 * point to the next pointer of the last token of the expansion.
4923 * If the expansion is empty, *tpp will be unchanged but **tpp will
4924 * be advanced past the macro call.
4926 * Return the macro expanded, or NULL if no expansion took place.
4928 static SMacro *expand_one_smacro(Token ***tpp)
4930 Token **params = NULL;
4931 const char *mname;
4932 Token *mstart = **tpp;
4933 Token *tline = mstart;
4934 SMacro *head, *m;
4935 int i;
4936 Token *t, *tup, *tafter;
4937 int nparam = 0;
4938 bool cond_comma;
4940 if (!tline)
4941 return false; /* Empty line, nothing to do */
4943 mname = tok_text(mstart);
4945 smacro_deadman.total--;
4946 smacro_deadman.levels--;
4948 if (unlikely(smacro_deadman.total < 0 || smacro_deadman.levels < 0)) {
4949 if (unlikely(!smacro_deadman.triggered)) {
4950 nasm_nonfatal("interminable macro recursion");
4951 smacro_deadman.triggered = true;
4953 goto not_a_macro;
4954 } else if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID) {
4955 head = (SMacro *)hash_findix(&smacros, mname);
4956 } else if (tline->type == TOK_LOCAL_MACRO) {
4957 Context *ctx = get_ctx(mname, &mname);
4958 head = ctx ? (SMacro *)hash_findix(&ctx->localmac, mname) : NULL;
4959 } else {
4960 goto not_a_macro;
4964 * We've hit an identifier of some sort. First check whether the
4965 * identifier is a single-line macro at all, then think about
4966 * checking for parameters if necessary.
4968 list_for_each(m, head) {
4969 if (unlikely(m->alias && !do_aliases))
4970 continue;
4971 if (!mstrcmp(m->name, mname, m->casesense))
4972 break;
4975 if (!m) {
4976 goto not_a_macro;
4979 /* Parse parameters, if applicable */
4981 params = NULL;
4982 nparam = 0;
4984 if (m->nparam == 0) {
4986 * Simple case: the macro is parameterless.
4987 * Nothing to parse; the expansion code will
4988 * drop the macro name token.
4990 } else {
4992 * Complicated case: at least one macro with this name
4993 * exists and takes parameters. We must find the
4994 * parameters in the call, count them, find the SMacro
4995 * that corresponds to that form of the macro call, and
4996 * substitute for the parameters when we expand. What a
4997 * pain.
4999 Token *t;
5000 int paren, brackets;
5002 tline = tline->next;
5003 tline = skip_white(tline);
5004 if (!tok_is(tline, '(')) {
5006 * This macro wasn't called with parameters: ignore
5007 * the call. (Behaviour borrowed from gnu cpp.)
5009 goto not_a_macro;
5012 paren = 1;
5013 nparam = 1;
5014 brackets = 0;
5015 t = tline; /* tline points to leading ( */
5017 while (paren) {
5018 t = t->next;
5020 if (!t) {
5021 nasm_nonfatal("macro call expects terminating `)'");
5022 goto not_a_macro;
5025 if (t->type != TOK_OTHER || t->len != 1)
5026 continue;
5028 switch (t->text.a[0]) {
5029 case ',':
5030 if (!brackets)
5031 nparam++;
5032 break;
5034 case '{':
5035 brackets++;
5036 break;
5038 case '}':
5039 if (brackets > 0)
5040 brackets--;
5041 break;
5043 case '(':
5044 if (!brackets)
5045 paren++;
5046 break;
5048 case ')':
5049 if (!brackets)
5050 paren--;
5051 break;
5053 default:
5054 break; /* Normal token */
5059 * Look for a macro matching in both name and parameter count.
5060 * We already know any matches cannot be anywhere before the
5061 * current position of "m", so there is no reason to
5062 * backtrack.
5064 while (1) {
5065 if (!m) {
5067 *!macro-params-single [on] single-line macro calls with wrong parameter count
5068 *! warns about \i{single-line macros} being invoked
5069 *! with the wrong number of parameters.
5071 nasm_warn(WARN_MACRO_PARAMS_SINGLE,
5072 "single-line macro `%s' exists, "
5073 "but not taking %d parameter%s",
5074 mname, nparam, (nparam == 1) ? "" : "s");
5075 goto not_a_macro;
5078 if (!mstrcmp(m->name, mname, m->casesense)) {
5079 if (nparam == m->nparam)
5080 break; /* It's good */
5081 if (m->greedy && nparam >= m->nparam-1)
5082 break; /* Also good */
5084 m = m->next;
5088 if (m->in_progress)
5089 goto not_a_macro;
5091 /* Expand the macro */
5092 m->in_progress = true;
5094 if (nparam) {
5095 /* Extract parameters */
5096 Token **phead, **pep;
5097 int white = 0;
5098 int brackets = 0;
5099 int paren;
5100 bool bracketed = false;
5101 bool bad_bracket = false;
5102 enum sparmflags flags;
5104 nparam = m->nparam;
5105 paren = 1;
5106 nasm_newn(params, nparam);
5107 i = 0;
5108 flags = m->params[i].flags;
5109 phead = pep = &params[i];
5110 *pep = NULL;
5112 while (paren) {
5113 bool skip;
5114 char ch;
5116 tline = tline->next;
5118 if (!tline)
5119 nasm_nonfatal("macro call expects terminating `)'");
5121 ch = 0;
5122 skip = false;
5125 switch (tline->type) {
5126 case TOK_OTHER:
5127 if (tline->len == 1)
5128 ch = tline->text.a[0];
5129 break;
5131 case TOK_WHITESPACE:
5132 if (!(flags & SPARM_NOSTRIP)) {
5133 if (brackets || *phead)
5134 white++; /* Keep interior whitespace */
5135 skip = true;
5137 break;
5139 default:
5140 break;
5143 switch (ch) {
5144 case ',':
5145 if (!brackets && !(flags & SPARM_GREEDY)) {
5146 i++;
5147 nasm_assert(i < nparam);
5148 phead = pep = &params[i];
5149 *pep = NULL;
5150 bracketed = false;
5151 skip = true;
5152 flags = m->params[i].flags;
5154 break;
5156 case '{':
5157 if (!bracketed) {
5158 bracketed = !*phead && !(flags & SPARM_NOSTRIP);
5159 skip = bracketed;
5161 brackets++;
5162 break;
5164 case '}':
5165 if (brackets > 0) {
5166 if (!--brackets)
5167 skip = bracketed;
5169 break;
5171 case '(':
5172 if (!brackets)
5173 paren++;
5174 break;
5176 case ')':
5177 if (!brackets) {
5178 paren--;
5179 if (!paren) {
5180 skip = true;
5181 i++; /* Found last argument */
5184 break;
5186 default:
5187 break; /* Normal token */
5190 if (!skip) {
5191 Token *t;
5193 bad_bracket |= bracketed && !brackets;
5195 if (white) {
5196 *pep = t = new_White(NULL);
5197 pep = &t->next;
5198 white = 0;
5200 *pep = t = dup_Token(NULL, tline);
5201 pep = &t->next;
5206 * Possible further processing of parameters. Note that the
5207 * ordering matters here.
5209 for (i = 0; i < nparam; i++) {
5210 enum sparmflags flags = m->params[i].flags;
5212 if (flags & SPARM_EVAL) {
5213 /* Evaluate this parameter as a number */
5214 struct ppscan pps;
5215 struct tokenval tokval;
5216 expr *evalresult;
5217 Token *eval_param;
5219 pps.tptr = eval_param = expand_smacro_noreset(params[i]);
5220 pps.ntokens = -1;
5221 tokval.t_type = TOKEN_INVALID;
5222 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
5224 free_tlist(eval_param);
5225 params[i] = NULL;
5227 if (!evalresult) {
5228 /* Nothing meaningful to do */
5229 } else if (tokval.t_type) {
5230 nasm_nonfatal("invalid expression in parameter %d of macro `%s'", i, m->name);
5231 } else if (!is_simple(evalresult)) {
5232 nasm_nonfatal("non-constant expression in parameter %d of macro `%s'", i, m->name);
5233 } else {
5234 params[i] = make_tok_num(NULL, reloc_value(evalresult));
5238 if (flags & SPARM_STR) {
5239 /* Convert expansion to a quoted string */
5240 char *arg;
5241 Token *qs;
5243 qs = expand_smacro_noreset(params[i]);
5244 arg = detoken(qs, false);
5245 free_tlist(qs);
5246 params[i] = make_tok_qstr(NULL, arg);
5247 nasm_free(arg);
5252 /* Note: we own the expansion this returns. */
5253 t = m->expand(m, params, nparam);
5255 tafter = tline->next; /* Skip past the macro call */
5256 tline->next = NULL; /* Truncate list at the macro call end */
5257 tline = tafter;
5259 tup = NULL;
5260 cond_comma = false;
5262 while (t) {
5263 enum pp_token_type type = t->type;
5264 Token *tnext = t->next;
5266 switch (type) {
5267 case TOK_PREPROC_Q:
5268 delete_Token(t);
5269 t = dup_Token(tline, mstart);
5270 break;
5272 case TOK_PREPROC_QQ:
5274 size_t mlen = strlen(m->name);
5275 size_t len;
5276 char *p;
5278 t->type = mstart->type;
5279 if (t->type == TOK_LOCAL_MACRO) {
5280 const char *psp; /* prefix start pointer */
5281 const char *pep; /* prefix end pointer */
5282 size_t plen;
5284 psp = tok_text(mstart);
5285 get_ctx(psp, &pep);
5286 plen = pep - psp;
5288 len = mlen + plen;
5289 p = nasm_malloc(len + 1);
5290 p = mempcpy(p, psp, plen);
5291 } else {
5292 len = mlen;
5293 p = nasm_malloc(len + 1);
5295 p = mempcpy(p, m->name, mlen);
5296 *p = '\0';
5297 set_text_free(t, p, len);
5299 t->next = tline;
5300 break;
5303 case TOK_COND_COMMA:
5304 delete_Token(t);
5305 t = cond_comma ? make_tok_char(tline, ',') : NULL;
5306 break;
5308 case TOK_ID:
5309 case TOK_PREPROC_ID:
5310 case TOK_LOCAL_MACRO:
5313 * Chain this into the target line *before* expanding,
5314 * that way we pick up any arguments to the new macro call,
5315 * if applicable.
5317 Token **tp = &t;
5318 t->next = tline;
5319 expand_one_smacro(&tp);
5320 tline = *tp; /* First token left after any macro call */
5321 break;
5323 default:
5324 if (is_smac_param(t->type)) {
5325 int param = smac_nparam(t->type);
5326 nasm_assert(!tup && param < nparam);
5327 delete_Token(t);
5328 t = NULL;
5329 tup = tnext;
5330 tnext = dup_tlist_reverse(params[param], NULL);
5331 cond_comma = false;
5332 } else {
5333 t->next = tline;
5337 if (t) {
5338 Token *endt = tline;
5340 tline = t;
5341 while (!cond_comma && t && t != endt)
5342 cond_comma = t->type != TOK_WHITESPACE;
5345 if (tnext) {
5346 t = tnext;
5347 } else {
5348 t = tup;
5349 tup = NULL;
5353 **tpp = tline;
5354 for (t = tline; t != tafter; t = t->next)
5355 *tpp = &t->next;
5357 m->in_progress = false;
5359 /* Don't do this until after expansion or we will clobber mname */
5360 free_tlist(mstart);
5361 goto done;
5364 * No macro expansion needed; roll back to mstart (if necessary)
5365 * and then advance to the next input token. Note that this is
5366 * by far the common case!
5368 not_a_macro:
5369 *tpp = &mstart->next;
5370 m = NULL;
5371 done:
5372 smacro_deadman.levels++;
5373 if (unlikely(params))
5374 free_tlist_array(params, nparam);
5375 return m;
5379 * Expand all single-line macro calls made in the given line.
5380 * Return the expanded version of the line. The original is deemed
5381 * to be destroyed in the process. (In reality we'll just move
5382 * Tokens from input to output a lot of the time, rather than
5383 * actually bothering to destroy and replicate.)
5385 static Token *expand_smacro(Token *tline)
5387 smacro_deadman.total = nasm_limit[LIMIT_MACRO_TOKENS];
5388 smacro_deadman.levels = nasm_limit[LIMIT_MACRO_LEVELS];
5389 smacro_deadman.triggered = false;
5390 return expand_smacro_noreset(tline);
5393 static Token *expand_smacro_noreset(Token *org_tline)
5395 Token *tline;
5396 bool expanded;
5398 if (!org_tline)
5399 return NULL; /* Empty input */
5402 * Trick: we should avoid changing the start token pointer since it can
5403 * be contained in "next" field of other token. Because of this
5404 * we allocate a copy of first token and work with it; at the end of
5405 * routine we copy it back
5407 tline = dup_Token(org_tline->next, org_tline);
5410 * Pretend that we always end up doing expansion on the first pass;
5411 * that way %+ get processed. However, if we process %+ before the
5412 * first pass, we end up with things like MACRO %+ TAIL trying to
5413 * look up the macro "MACROTAIL", which we don't want.
5415 expanded = true;
5416 while (true) {
5417 static const struct tokseq_match tmatch[] = {
5419 PP_CONCAT_MASK(TOK_ID) |
5420 PP_CONCAT_MASK(TOK_LOCAL_MACRO) |
5421 PP_CONCAT_MASK(TOK_ENVIRON) |
5422 PP_CONCAT_MASK(TOK_PREPROC_ID), /* head */
5423 PP_CONCAT_MASK(TOK_ID) |
5424 PP_CONCAT_MASK(TOK_LOCAL_MACRO) |
5425 PP_CONCAT_MASK(TOK_ENVIRON) |
5426 PP_CONCAT_MASK(TOK_PREPROC_ID) |
5427 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
5430 Token **tail = &tline;
5432 while (*tail) /* main token loop */
5433 expanded |= !!expand_one_smacro(&tail);
5435 if (!expanded)
5436 break; /* Done! */
5439 * Now scan the entire line and look for successive TOK_IDs
5440 * that resulted after expansion (they can't be produced by
5441 * tokenize()). The successive TOK_IDs should be concatenated.
5442 * Also we look for %+ tokens and concatenate the tokens
5443 * before and after them (without white spaces in between).
5445 if (!paste_tokens(&tline, tmatch, ARRAY_SIZE(tmatch), true))
5446 break; /* Done again! */
5448 expanded = false;
5451 if (!tline) {
5453 * The expression expanded to empty line;
5454 * we can't return NULL because of the "trick" above.
5455 * Just set the line to a single WHITESPACE token.
5458 tline = new_White(NULL);
5461 steal_Token(org_tline, tline);
5462 org_tline->next = tline->next;
5463 delete_Token(tline);
5465 return org_tline;
5469 * Similar to expand_smacro but used exclusively with macro identifiers
5470 * right before they are fetched in. The reason is that there can be
5471 * identifiers consisting of several subparts. We consider that if there
5472 * are more than one element forming the name, user wants a expansion,
5473 * otherwise it will be left as-is. Example:
5475 * %define %$abc cde
5477 * the identifier %$abc will be left as-is so that the handler for %define
5478 * will suck it and define the corresponding value. Other case:
5480 * %define _%$abc cde
5482 * In this case user wants name to be expanded *before* %define starts
5483 * working, so we'll expand %$abc into something (if it has a value;
5484 * otherwise it will be left as-is) then concatenate all successive
5485 * PP_IDs into one.
5487 static Token *expand_id(Token * tline)
5489 Token *cur, *oldnext = NULL;
5491 if (!tline || !tline->next)
5492 return tline;
5494 cur = tline;
5495 while (cur->next &&
5496 (cur->next->type == TOK_ID || cur->next->type == TOK_PREPROC_ID ||
5497 cur->next->type == TOK_LOCAL_MACRO || cur->next->type == TOK_NUMBER))
5498 cur = cur->next;
5500 /* If identifier consists of just one token, don't expand */
5501 if (cur == tline)
5502 return tline;
5504 if (cur) {
5505 oldnext = cur->next; /* Detach the tail past identifier */
5506 cur->next = NULL; /* so that expand_smacro stops here */
5509 tline = expand_smacro(tline);
5511 if (cur) {
5512 /* expand_smacro possibly changhed tline; re-scan for EOL */
5513 cur = tline;
5514 while (cur && cur->next)
5515 cur = cur->next;
5516 if (cur)
5517 cur->next = oldnext;
5520 return tline;
5524 * Determine whether the given line constitutes a multi-line macro
5525 * call, and return the MMacro structure called if so. Doesn't have
5526 * to check for an initial label - that's taken care of in
5527 * expand_mmacro - but must check numbers of parameters. Guaranteed
5528 * to be called with tline->type == TOK_ID, so the putative macro
5529 * name is easy to find.
5531 static MMacro *is_mmacro(Token * tline, int *nparamp, Token ***params_array)
5533 MMacro *head, *m;
5534 Token **params;
5535 int nparam;
5536 const char *finding = tok_text(tline);
5538 head = (MMacro *) hash_findix(&mmacros, finding);
5541 * Efficiency: first we see if any macro exists with the given
5542 * name which isn't already excluded by macro cycle removal.
5543 * (The cycle removal test here helps optimize the case of wrapping
5544 * instructions, and is cheap to do here.)
5546 * If not, we can return NULL immediately. _Then_ we
5547 * count the parameters, and then we look further along the
5548 * list if necessary to find the proper MMacro.
5550 list_for_each(m, head) {
5551 if (!mstrcmp(m->name, finding, m->casesense) &&
5552 (m->in_progress != 1 || m->max_depth > 0))
5553 break; /* Found something that needs consideration */
5555 if (!m)
5556 return NULL;
5559 * OK, we have a potential macro. Count and demarcate the
5560 * parameters.
5562 count_mmac_params(tline->next, &nparam, &params);
5565 * So we know how many parameters we've got. Find the MMacro
5566 * structure that handles this number.
5568 while (m) {
5569 if (m->nparam_min <= nparam
5570 && (m->plus || nparam <= m->nparam_max)) {
5572 * This one is right. Just check if cycle removal
5573 * prohibits us using it before we actually celebrate...
5575 if (m->in_progress > m->max_depth) {
5576 if (m->max_depth > 0) {
5577 nasm_warn(WARN_OTHER, "reached maximum recursion depth of %i",
5578 m->max_depth);
5580 nasm_free(params);
5581 return NULL;
5584 * It's right, and we can use it. Add its default
5585 * parameters to the end of our list if necessary.
5587 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
5588 int newnparam = m->nparam_min + m->ndefs;
5589 params = nasm_realloc(params, sizeof(*params) * (newnparam+2));
5590 memcpy(&params[nparam+1], &m->defaults[nparam+1-m->nparam_min],
5591 (newnparam - nparam) * sizeof(*params));
5592 nparam = newnparam;
5595 * If we've gone over the maximum parameter count (and
5596 * we're in Plus mode), ignore parameters beyond
5597 * nparam_max.
5599 if (m->plus && nparam > m->nparam_max)
5600 nparam = m->nparam_max;
5603 * If nparam was adjusted above, make sure the list is still
5604 * NULL-terminated.
5606 params[nparam+1] = NULL;
5608 /* Done! */
5609 *params_array = params;
5610 *nparamp = nparam;
5611 return m;
5614 * This one wasn't right: look for the next one with the
5615 * same name.
5617 list_for_each(m, m->next)
5618 if (!mstrcmp(m->name, tok_text(tline), m->casesense))
5619 break;
5623 * After all that, we didn't find one with the right number of
5624 * parameters. Issue a warning, and fail to expand the macro.
5626 *!macro-params-multi [on] multi-line macro calls with wrong parameter count
5627 *! warns about \i{multi-line macros} being invoked
5628 *! with the wrong number of parameters. See \k{mlmacover} for an
5629 *! example of why you might want to disable this warning.
5631 nasm_warn(WARN_MACRO_PARAMS_MULTI,
5632 "multi-line macro `%s' exists, but not taking %d parameter%s",
5633 tok_text(tline), nparam, (nparam == 1) ? "" : "s");
5634 nasm_free(params);
5635 return NULL;
5639 #if 0
5642 * Save MMacro invocation specific fields in
5643 * preparation for a recursive macro expansion
5645 static void push_mmacro(MMacro *m)
5647 MMacroInvocation *i;
5649 i = nasm_malloc(sizeof(MMacroInvocation));
5650 i->prev = m->prev;
5651 i->params = m->params;
5652 i->iline = m->iline;
5653 i->nparam = m->nparam;
5654 i->rotate = m->rotate;
5655 i->paramlen = m->paramlen;
5656 i->unique = m->unique;
5657 i->condcnt = m->condcnt;
5658 m->prev = i;
5663 * Restore MMacro invocation specific fields that were
5664 * saved during a previous recursive macro expansion
5666 static void pop_mmacro(MMacro *m)
5668 MMacroInvocation *i;
5670 if (m->prev) {
5671 i = m->prev;
5672 m->prev = i->prev;
5673 m->params = i->params;
5674 m->iline = i->iline;
5675 m->nparam = i->nparam;
5676 m->rotate = i->rotate;
5677 m->paramlen = i->paramlen;
5678 m->unique = i->unique;
5679 m->condcnt = i->condcnt;
5680 nasm_free(i);
5684 #endif
5687 * List an mmacro call with arguments (-Lm option)
5689 static void list_mmacro_call(const MMacro *m)
5691 const char prefix[] = " ;;; [macro] ";
5692 size_t namelen, size;
5693 char *buf, *p;
5694 unsigned int i;
5695 const Token *t;
5697 namelen = strlen(m->iname);
5698 size = namelen + sizeof(prefix); /* Includes final null (from prefix) */
5700 for (i = 1; i <= m->nparam; i++) {
5701 int j = 0;
5702 size += 3; /* Braces and space/comma */
5703 list_for_each(t, m->params[i]) {
5704 if (j++ >= m->paramlen[i])
5705 break;
5706 size += (t->type == TOK_WHITESPACE) ? 1 : t->len;
5710 buf = p = nasm_malloc(size);
5711 p = mempcpy(p, prefix, sizeof(prefix) - 1);
5712 p = mempcpy(p, m->iname, namelen);
5713 *p++ = ' ';
5715 for (i = 1; i <= m->nparam; i++) {
5716 int j = 0;
5717 *p++ = '{';
5718 list_for_each(t, m->params[i]) {
5719 if (j++ >= m->paramlen[i])
5720 break;
5721 p = mempcpy(p, tok_text(t), t->len);
5723 *p++ = '}';
5724 *p++ = ',';
5727 *--p = '\0'; /* Replace last delimeter with null */
5728 lfmt->line(LIST_MACRO, -1, buf);
5729 nasm_free(buf);
5733 * Expand the multi-line macro call made by the given line, if
5734 * there is one to be expanded. If there is, push the expansion on
5735 * istk->expansion and return 1. Otherwise return 0.
5737 static int expand_mmacro(Token * tline)
5739 Token *startline = tline;
5740 Token *label = NULL;
5741 bool dont_prepend = false;
5742 Token **params, *t, *tt;
5743 MMacro *m;
5744 Line *l, *ll;
5745 int i, *paramlen;
5746 const char *mname;
5747 int nparam = 0;
5749 t = tline;
5750 t = skip_white(t);
5751 /* if (!tok_type(t, TOK_ID)) Lino 02/25/02 */
5752 if (!tok_type(t, TOK_ID) && !tok_type(t, TOK_LOCAL_MACRO))
5753 return 0;
5754 m = is_mmacro(t, &nparam, &params);
5755 if (m) {
5756 mname = tok_text(t);
5757 } else {
5758 Token *last;
5760 * We have an id which isn't a macro call. We'll assume
5761 * it might be a label; we'll also check to see if a
5762 * colon follows it. Then, if there's another id after
5763 * that lot, we'll check it again for macro-hood.
5765 label = last = t;
5766 t = t->next;
5767 if (tok_white(t))
5768 last = t, t = t->next;
5769 if (tok_is(t, ':')) {
5770 dont_prepend = true;
5771 last = t, t = t->next;
5772 if (tok_white(t))
5773 last = t, t = t->next;
5775 if (!tok_type(t, TOK_ID) || !(m = is_mmacro(t, &nparam, &params)))
5776 return 0;
5777 last->next = NULL;
5778 mname = tok_text(t);
5779 tline = t;
5782 if (unlikely(mmacro_deadman.total >= nasm_limit[LIMIT_MMACROS] ||
5783 mmacro_deadman.levels >= nasm_limit[LIMIT_MACRO_LEVELS])) {
5784 if (!mmacro_deadman.triggered) {
5785 nasm_nonfatal("interminable multiline macro recursion");
5786 mmacro_deadman.triggered = true;
5788 return 0;
5791 mmacro_deadman.total++;
5792 mmacro_deadman.levels++;
5795 * Fix up the parameters: this involves stripping leading and
5796 * trailing whitespace, then stripping braces if they are
5797 * present.
5799 nasm_newn(paramlen, nparam+1);
5801 nasm_assert(params[nparam+1] == NULL);
5803 for (i = 1; (t = params[i]); i++) {
5804 bool braced = false;
5805 int brace = 0;
5806 int white = 0;
5807 bool comma = !m->plus || i < nparam;
5809 t = skip_white(t);
5810 if (tok_is(t, '{')) {
5811 t = t->next;
5812 brace = 1;
5813 braced = true;
5814 comma = false;
5817 params[i] = t;
5818 for (; t; t = t->next) {
5819 if (tok_white(t)) {
5820 white++;
5821 continue;
5824 if (t->type == TOK_OTHER && t->len == 1) {
5825 switch (t->text.a[0]) {
5826 case ',':
5827 if (comma && !brace)
5828 goto endparam;
5829 break;
5831 case '{':
5832 brace++;
5833 break;
5835 case '}':
5836 brace--;
5837 if (braced && !brace) {
5838 paramlen[i] += white;
5839 goto endparam;
5841 break;
5843 default:
5844 break;
5848 paramlen[i] += white + 1;
5849 white = 0;
5851 endparam:
5856 * OK, we have a MMacro structure together with a set of
5857 * parameters. We must now go through the expansion and push
5858 * copies of each Line on to istk->expansion. Substitution of
5859 * parameter tokens and macro-local tokens doesn't get done
5860 * until the single-line macro substitution process; this is
5861 * because delaying them allows us to change the semantics
5862 * later through %rotate and give the right semantics for
5863 * nested mmacros.
5865 * First, push an end marker on to istk->expansion, mark this
5866 * macro as in progress, and set up its invocation-specific
5867 * variables.
5869 nasm_new(ll);
5870 ll->next = istk->expansion;
5871 ll->finishes = m;
5872 istk->expansion = ll;
5875 * Save the previous MMacro expansion in the case of
5876 * macro recursion
5878 #if 0
5879 if (m->max_depth && m->in_progress)
5880 push_mmacro(m);
5881 #endif
5883 m->in_progress ++;
5884 m->params = params;
5885 m->iline = tline;
5886 m->iname = nasm_strdup(mname);
5887 m->nparam = nparam;
5888 m->rotate = 0;
5889 m->paramlen = paramlen;
5890 m->unique = unique++;
5891 m->lineno = 0;
5892 m->condcnt = 0;
5894 m->mstk = istk->mstk;
5895 istk->mstk.mstk = istk->mstk.mmac = m;
5897 list_for_each(l, m->expansion) {
5898 nasm_new(ll);
5899 ll->next = istk->expansion;
5900 istk->expansion = ll;
5901 ll->first = dup_tlist(l->first, NULL);
5905 * If we had a label, and this macro definition does not include
5906 * a %00, push it on as the first line of, ot
5907 * the macro expansion.
5909 if (label) {
5911 * We had a label. If this macro contains an %00 parameter,
5912 * save the value as a special parameter (which is what it
5913 * is), otherwise push it as the first line of the macro
5914 * expansion.
5916 if (m->capture_label) {
5917 params[0] = dup_Token(NULL, label);
5918 paramlen[0] = 1;
5919 free_tlist(startline);
5920 } else {
5921 nasm_new(ll);
5922 ll->finishes = NULL;
5923 ll->next = istk->expansion;
5924 istk->expansion = ll;
5925 ll->first = startline;
5926 if (!dont_prepend) {
5927 while (label->next)
5928 label = label->next;
5929 label->next = tt = make_tok_char(NULL, ':');
5934 lfmt->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
5936 if (list_option('m') && !m->nolist)
5937 list_mmacro_call(m);
5939 return 1;
5943 * This function decides if an error message should be suppressed.
5944 * It will never be called with a severity level of ERR_FATAL or
5945 * higher.
5947 static bool pp_suppress_error(errflags severity)
5950 * If we're in a dead branch of IF or something like it, ignore the error.
5951 * However, because %else etc are evaluated in the state context
5952 * of the previous branch, errors might get lost:
5953 * %if 0 ... %else trailing garbage ... %endif
5954 * So %else etc should set the ERR_PP_PRECOND flag.
5956 if (istk && istk->conds &&
5957 ((severity & ERR_PP_PRECOND) ?
5958 istk->conds->state == COND_NEVER :
5959 !emitting(istk->conds->state)))
5960 return true;
5962 return false;
5965 static Token *
5966 stdmac_file(const SMacro *s, Token **params, int nparams)
5968 (void)s;
5969 (void)params;
5970 (void)nparams;
5972 return make_tok_qstr(NULL, src_get_fname());
5975 static Token *
5976 stdmac_line(const SMacro *s, Token **params, int nparams)
5978 (void)s;
5979 (void)params;
5980 (void)nparams;
5982 return make_tok_num(NULL, src_get_linnum());
5985 static Token *
5986 stdmac_bits(const SMacro *s, Token **params, int nparams)
5988 (void)s;
5989 (void)params;
5990 (void)nparams;
5992 return make_tok_num(NULL, globalbits);
5995 static Token *
5996 stdmac_ptr(const SMacro *s, Token **params, int nparams)
5998 (void)s;
5999 (void)params;
6000 (void)nparams;
6002 switch (globalbits) {
6003 case 16:
6004 return new_Token(NULL, TOK_ID, "word", 4);
6005 case 32:
6006 return new_Token(NULL, TOK_ID, "dword", 5);
6007 case 64:
6008 return new_Token(NULL, TOK_ID, "qword", 5);
6009 default:
6010 panic();
6014 /* Add magic standard macros */
6015 struct magic_macros {
6016 const char *name;
6017 int nparam;
6018 ExpandSMacro func;
6020 static const struct magic_macros magic_macros[] =
6022 { "__?FILE?__", 0, stdmac_file },
6023 { "__?LINE?__", 0, stdmac_line },
6024 { "__?BITS?__", 0, stdmac_bits },
6025 { "__?PTR?__", 0, stdmac_ptr },
6026 { NULL, 0, NULL }
6029 static void pp_add_magic_stdmac(void)
6031 const struct magic_macros *m;
6032 SMacro tmpl;
6034 nasm_zero(tmpl);
6036 for (m = magic_macros; m->name; m++) {
6037 tmpl.nparam = m->nparam;
6038 tmpl.expand = m->func;
6039 define_smacro(m->name, true, NULL, &tmpl);
6043 static void
6044 pp_reset(const char *file, enum preproc_mode mode, struct strlist *dep_list)
6046 int apass;
6047 struct Include *inc;
6049 cstk = NULL;
6050 defining = NULL;
6051 nested_mac_count = 0;
6052 nested_rep_count = 0;
6053 init_macros();
6054 unique = 0;
6055 deplist = dep_list;
6056 pp_mode = mode;
6057 do_aliases = true;
6059 if (!use_loaded)
6060 use_loaded = nasm_malloc(use_package_count * sizeof(bool));
6061 memset(use_loaded, 0, use_package_count * sizeof(bool));
6063 /* First set up the top level input file */
6064 nasm_new(istk);
6065 istk->fp = nasm_open_read(file, NF_TEXT);
6066 src_set(0, file);
6067 istk->lineinc = 1;
6068 if (!istk->fp)
6069 nasm_fatalf(ERR_NOFILE, "unable to open input file `%s'", file);
6071 strlist_add(deplist, file);
6074 * Set up the stdmac packages as a virtual include file,
6075 * indicated by a null file pointer.
6077 nasm_new(inc);
6078 inc->next = istk;
6079 inc->fname = src_set_fname(NULL);
6080 inc->nolist = !list_option('b');
6081 istk = inc;
6082 lfmt->uplevel(LIST_INCLUDE, 0);
6084 pp_add_magic_stdmac();
6086 if (tasm_compatible_mode)
6087 pp_add_stdmac(nasm_stdmac_tasm);
6089 pp_add_stdmac(nasm_stdmac_nasm);
6090 pp_add_stdmac(nasm_stdmac_version);
6092 if (extrastdmac)
6093 pp_add_stdmac(extrastdmac);
6095 stdmacpos = stdmacros[0];
6096 stdmacnext = &stdmacros[1];
6098 do_predef = true;
6101 * Define the __?PASS?__ macro. This is defined here unlike all the
6102 * other builtins, because it is special -- it varies between
6103 * passes -- but there is really no particular reason to make it
6104 * magic.
6106 * 0 = dependencies only
6107 * 1 = preparatory passes
6108 * 2 = final pass
6109 * 3 = preproces only
6111 switch (mode) {
6112 case PP_NORMAL:
6113 apass = pass_final() ? 2 : 1;
6114 break;
6115 case PP_DEPS:
6116 apass = 0;
6117 break;
6118 case PP_PREPROC:
6119 apass = 3;
6120 break;
6121 default:
6122 panic();
6125 define_smacro("__?PASS?__", true, make_tok_num(NULL, apass), NULL);
6128 static void pp_init(void)
6133 * Get a line of tokens. If we popped the macro expansion/include stack,
6134 * we return a pointer to the dummy token tok_pop; at that point if
6135 * istk is NULL then we have reached end of input;
6137 static Token tok_pop; /* Dummy token placeholder */
6139 static Token *pp_tokline(void)
6141 while (true) {
6142 Line *l = istk->expansion;
6143 Token *tline = NULL;
6144 Token *dtline;
6147 * Fetch a tokenized line, either from the macro-expansion
6148 * buffer or from the input file.
6150 tline = NULL;
6151 while (l && l->finishes) {
6152 MMacro *fm = l->finishes;
6154 if (!fm->name && fm->in_progress > 1) {
6156 * This is a macro-end marker for a macro with no
6157 * name, which means it's not really a macro at all
6158 * but a %rep block, and the `in_progress' field is
6159 * more than 1, meaning that we still need to
6160 * repeat. (1 means the natural last repetition; 0
6161 * means termination by %exitrep.) We have
6162 * therefore expanded up to the %endrep, and must
6163 * push the whole block on to the expansion buffer
6164 * again. We don't bother to remove the macro-end
6165 * marker: we'd only have to generate another one
6166 * if we did.
6168 fm->in_progress--;
6169 list_for_each(l, fm->expansion) {
6170 Token *t, *tt, **tail;
6171 Line *ll;
6173 nasm_new(ll);
6174 ll->next = istk->expansion;
6175 tail = &ll->first;
6177 list_for_each(t, l->first) {
6178 if (t->len) {
6179 tt = *tail = dup_Token(NULL, t);
6180 tail = &tt->next;
6183 istk->expansion = ll;
6185 break;
6186 } else {
6187 MMacro *m = istk->mstk.mstk;
6190 * Check whether a `%rep' was started and not ended
6191 * within this macro expansion. This can happen and
6192 * should be detected. It's a fatal error because
6193 * I'm too confused to work out how to recover
6194 * sensibly from it.
6196 if (defining) {
6197 if (defining->name)
6198 nasm_panic("defining with name in expansion");
6199 else if (m->name)
6200 nasm_fatal("`%%rep' without `%%endrep' within"
6201 " expansion of macro `%s'", m->name);
6205 * FIXME: investigate the relationship at this point between
6206 * istk->mstk.mstk and fm
6208 istk->mstk = m->mstk;
6209 if (m->name) {
6211 * This was a real macro call, not a %rep, and
6212 * therefore the parameter information needs to
6213 * be freed and the iteration count/nesting
6214 * depth adjusted.
6217 if (!--mmacro_deadman.levels) {
6219 * If all mmacro processing done,
6220 * clear all counters and the deadman
6221 * message trigger.
6223 nasm_zero(mmacro_deadman); /* Clear all counters */
6226 #if 0
6227 if (m->prev) {
6228 pop_mmacro(m);
6229 fm->in_progress --;
6230 } else
6231 #endif
6233 nasm_free(m->params);
6234 free_tlist(m->iline);
6235 nasm_free(m->paramlen);
6236 fm->in_progress = 0;
6241 * FIXME It is incorrect to always free_mmacro here.
6242 * It leads to usage-after-free.
6244 * https://bugzilla.nasm.us/show_bug.cgi?id=3392414
6246 #if 0
6247 else
6248 free_mmacro(m);
6249 #endif
6251 istk->expansion = l->next;
6252 nasm_free(l);
6253 lfmt->downlevel(LIST_MACRO);
6254 return &tok_pop;
6257 do { /* until we get a line we can use */
6258 char *line;
6260 if (istk->expansion) { /* from a macro expansion */
6261 Line *l = istk->expansion;
6262 int32_t lineno;
6264 if (istk->mstk.mstk) {
6265 istk->mstk.mstk->lineno++;
6266 if (istk->mstk.mstk->fname)
6267 lineno = istk->mstk.mstk->lineno +
6268 istk->mstk.mstk->xline;
6269 else
6270 lineno = 0; /* Defined at init time or builtin */
6271 } else {
6272 lineno = src_get_linnum();
6275 tline = l->first;
6276 istk->expansion = l->next;
6277 nasm_free(l);
6279 line = detoken(tline, false);
6280 if (!istk->nolist)
6281 lfmt->line(LIST_MACRO, lineno, line);
6282 nasm_free(line);
6283 } else if ((line = read_line())) {
6284 line = prepreproc(line);
6285 tline = tokenize(line);
6286 nasm_free(line);
6287 } else {
6289 * The current file has ended; work down the istk
6291 Include *i = istk;
6292 if (i->fp)
6293 fclose(i->fp);
6294 if (i->conds) {
6295 /* nasm_error can't be conditionally suppressed */
6296 nasm_fatal("expected `%%endif' before end of file");
6298 /* only set line and file name if there's a next node */
6299 if (i->next)
6300 src_set(i->lineno, i->fname);
6301 istk = i->next;
6302 lfmt->downlevel(LIST_INCLUDE);
6303 nasm_free(i);
6304 return &tok_pop;
6306 } while (0);
6309 * We must expand MMacro parameters and MMacro-local labels
6310 * _before_ we plunge into directive processing, to cope
6311 * with things like `%define something %1' such as STRUC
6312 * uses. Unless we're _defining_ a MMacro, in which case
6313 * those tokens should be left alone to go into the
6314 * definition; and unless we're in a non-emitting
6315 * condition, in which case we don't want to meddle with
6316 * anything.
6318 if (!defining && !(istk->conds && !emitting(istk->conds->state))
6319 && !(istk->mstk.mstk && !istk->mstk.mstk->in_progress)) {
6320 tline = expand_mmac_params(tline);
6324 * Check the line to see if it's a preprocessor directive.
6326 if (do_directive(tline, &dtline) == DIRECTIVE_FOUND) {
6327 if (dtline)
6328 return dtline;
6329 } else if (defining) {
6331 * We're defining a multi-line macro. We emit nothing
6332 * at all, and just
6333 * shove the tokenized line on to the macro definition.
6335 MMacro *mmac = defining->dstk.mmac;
6337 Line *l = nasm_malloc(sizeof(Line));
6338 l->next = defining->expansion;
6339 l->first = tline;
6340 l->finishes = NULL;
6341 defining->expansion = l;
6344 * Remember if this mmacro expansion contains %00:
6345 * if it does, we will have to handle leading labels
6346 * specially.
6348 if (mmac) {
6349 const Token *t;
6350 list_for_each(t, tline) {
6351 if (!memcmp(t->text.a, "%00", 4))
6352 mmac->capture_label = true;
6355 } else if (istk->conds && !emitting(istk->conds->state)) {
6357 * We're in a non-emitting branch of a condition block.
6358 * Emit nothing at all, not even a blank line: when we
6359 * emerge from the condition we'll give a line-number
6360 * directive so we keep our place correctly.
6362 free_tlist(tline);
6363 } else if (istk->mstk.mstk && !istk->mstk.mstk->in_progress) {
6365 * We're in a %rep block which has been terminated, so
6366 * we're walking through to the %endrep without
6367 * emitting anything. Emit nothing at all, not even a
6368 * blank line: when we emerge from the %rep block we'll
6369 * give a line-number directive so we keep our place
6370 * correctly.
6372 free_tlist(tline);
6373 } else {
6374 tline = expand_smacro(tline);
6375 if (!expand_mmacro(tline))
6376 return tline;
6381 static char *pp_getline(void)
6383 char *line = NULL;
6384 Token *tline;
6386 while (true) {
6387 tline = pp_tokline();
6388 if (tline == &tok_pop) {
6390 * We popped the macro/include stack. If istk is empty,
6391 * we are at end of input, otherwise just loop back.
6393 if (!istk)
6394 break;
6395 } else {
6397 * De-tokenize the line and emit it.
6399 line = detoken(tline, true);
6400 free_tlist(tline);
6401 break;
6405 if (list_option('e') && istk && !istk->nolist && line && line[0]) {
6406 char *buf = nasm_strcat(" ;;; ", line);
6407 lfmt->line(LIST_MACRO, -1, buf);
6408 nasm_free(buf);
6411 return line;
6414 static void pp_cleanup_pass(void)
6416 if (defining) {
6417 if (defining->name) {
6418 nasm_nonfatal("end of file while still defining macro `%s'",
6419 defining->name);
6420 } else {
6421 nasm_nonfatal("end of file while still in %%rep");
6424 free_mmacro(defining);
6425 defining = NULL;
6428 while (cstk)
6429 ctx_pop();
6430 free_macros();
6431 while (istk) {
6432 Include *i = istk;
6433 istk = istk->next;
6434 fclose(i->fp);
6435 nasm_free(i);
6437 while (cstk)
6438 ctx_pop();
6439 src_set_fname(NULL);
6442 static void pp_cleanup_session(void)
6444 nasm_free(use_loaded);
6445 free_llist(predef);
6446 predef = NULL;
6447 delete_Blocks();
6448 ipath_list = NULL;
6451 static void pp_include_path(struct strlist *list)
6453 ipath_list = list;
6456 static void pp_pre_include(char *fname)
6458 Token *inc, *space, *name;
6459 Line *l;
6461 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
6462 space = new_White(name);
6463 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
6465 l = nasm_malloc(sizeof(Line));
6466 l->next = predef;
6467 l->first = inc;
6468 l->finishes = NULL;
6469 predef = l;
6472 static void pp_pre_define(char *definition)
6474 Token *def, *space;
6475 Line *l;
6476 char *equals;
6478 equals = strchr(definition, '=');
6479 space = new_White(NULL);
6480 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
6481 if (equals)
6482 *equals = ' ';
6483 space->next = tokenize(definition);
6484 if (equals)
6485 *equals = '=';
6487 /* We can't predefine a TOK_LOCAL_MACRO for obvious reasons... */
6488 if (space->next->type != TOK_PREPROC_ID &&
6489 space->next->type != TOK_ID)
6490 nasm_warn(WARN_OTHER, "pre-defining non ID `%s\'\n", definition);
6492 l = nasm_malloc(sizeof(Line));
6493 l->next = predef;
6494 l->first = def;
6495 l->finishes = NULL;
6496 predef = l;
6499 static void pp_pre_undefine(char *definition)
6501 Token *def, *space;
6502 Line *l;
6504 space = new_White(NULL);
6505 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
6506 space->next = tokenize(definition);
6508 l = nasm_malloc(sizeof(Line));
6509 l->next = predef;
6510 l->first = def;
6511 l->finishes = NULL;
6512 predef = l;
6515 /* Insert an early preprocessor command that doesn't need special handling */
6516 static void pp_pre_command(const char *what, char *string)
6518 char *cmd;
6519 Token *def, *space;
6520 Line *l;
6522 def = tokenize(string);
6523 if (what) {
6524 space = new_White(def);
6525 cmd = nasm_strcat(what[0] == '%' ? "" : "%", what);
6526 def = new_Token(space, TOK_PREPROC_ID, cmd, nasm_last_string_len());
6527 nasm_free(cmd);
6530 l = nasm_malloc(sizeof(Line));
6531 l->next = predef;
6532 l->first = def;
6533 l->finishes = NULL;
6534 predef = l;
6537 static void pp_add_stdmac(macros_t *macros)
6539 macros_t **mp;
6541 /* Find the end of the list and avoid duplicates */
6542 for (mp = stdmacros; *mp; mp++) {
6543 if (*mp == macros)
6544 return; /* Nothing to do */
6547 nasm_assert(mp < &stdmacros[ARRAY_SIZE(stdmacros)-1]);
6549 *mp = macros;
6552 static void pp_extra_stdmac(macros_t *macros)
6554 extrastdmac = macros;
6557 /* Create a numeric token */
6558 static Token *make_tok_num(Token *next, int64_t val)
6560 char numbuf[32];
6561 int len = snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
6562 return new_Token(next, TOK_NUMBER, numbuf, len);
6565 /* Create a quoted string token */
6566 static Token *make_tok_qstr(Token *next, const char *str)
6568 size_t len = strlen(str);
6569 char *p = nasm_quote(str, &len);
6570 return new_Token_free(next, TOK_STRING, p, len);
6573 /* Create a single-character operator token */
6574 static Token *make_tok_char(Token *next, char op)
6576 Token *t = new_Token(next, TOK_OTHER, NULL, 1);
6577 t->text.a[0] = op;
6578 return t;
6581 static void pp_list_one_macro(MMacro *m, errflags severity)
6583 if (!m)
6584 return;
6586 /* We need to print the mstk.mmac list in reverse order */
6587 pp_list_one_macro(m->mstk.mmac, severity);
6589 if (m->name && !m->nolist) {
6590 src_set(m->xline + m->lineno, m->fname);
6591 nasm_error(severity, "... from macro `%s' defined", m->name);
6595 static void pp_error_list_macros(errflags severity)
6597 struct src_location saved;
6599 severity |= ERR_PP_LISTMACRO | ERR_NO_SEVERITY | ERR_HERE;
6600 saved = src_where();
6602 if (istk)
6603 pp_list_one_macro(istk->mstk.mmac, severity);
6605 src_update(saved);
6608 const struct preproc_ops nasmpp = {
6609 pp_init,
6610 pp_reset,
6611 pp_getline,
6612 pp_cleanup_pass,
6613 pp_cleanup_session,
6614 pp_extra_stdmac,
6615 pp_pre_define,
6616 pp_pre_undefine,
6617 pp_pre_include,
6618 pp_pre_command,
6619 pp_include_path,
6620 pp_error_list_macros,
6621 pp_suppress_error