1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2020 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
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
46 * read_line gets raw text from stdmacpos, or predef, or current input file
47 * tokenize converts to tokens
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
79 typedef struct SMacro SMacro
;
80 typedef struct MMacro MMacro
;
81 typedef struct MMacroInvocation MMacroInvocation
;
82 typedef struct Context Context
;
83 typedef struct Token Token
;
84 typedef struct Line Line
;
85 typedef struct Include Include
;
86 typedef struct Cond Cond
;
89 * This is the internal form which we break input lines up into.
90 * Typically stored in linked lists.
92 * Note that `type' serves a double meaning: TOK_SMAC_START_PARAMS is
93 * not necessarily used as-is, but is also used to encode the number
94 * and expansion type of substituted parameter. So in the definition
96 * %define a(x,=y) ( (x) & ~(y) )
98 * the token representing `x' will have its type changed to
99 * tok_smac_param(0) but the one representing `y' will be
100 * tok_smac_param(1); see the accessor functions below.
102 * TOK_INTERNAL_STRING is a string which has been unquoted, but should
103 * be treated as if it was a quoted string. The code is free to change
104 * one into the other at will. TOK_NAKED_STRING is a text token which
105 * should be treated as a string, but which MUST NOT be turned into a
106 * quoted string. TOK_INTERNAL_STRINGs can contain any character,
107 * including NUL, but TOK_NAKED_STRING must be a valid C string.
110 TOK_NONE
= 0, TOK_WHITESPACE
, TOK_COMMENT
,
111 TOK_CORRUPT
, /* Token text modified in an unsafe manner, now bogus */
112 TOK_BLOCK
, /* Storage block pointer, not a real token */
114 TOK_PREPROC_ID
, TOK_MMACRO_PARAM
, TOK_LOCAL_SYMBOL
,
115 TOK_LOCAL_MACRO
, TOK_ENVIRON
, TOK_STRING
,
116 TOK_NUMBER
, TOK_FLOAT
, TOK_OTHER
,
117 TOK_INTERNAL_STRING
, TOK_NAKED_STRING
,
118 TOK_PREPROC_Q
, TOK_PREPROC_QQ
,
120 TOK_COND_COMMA
, /* %, */
121 TOK_INDIRECT
, /* %[...] */
122 TOK_XDEF_PARAM
, /* Used during %xdefine processing */
123 TOK_SMAC_START_PARAMS
, /* MUST BE LAST IN THE LIST!!! */
124 TOK_MAX
= INT_MAX
/* Keep compiler from reducing the range */
127 static inline enum pp_token_type
tok_smac_param(int param
)
129 return TOK_SMAC_START_PARAMS
+ param
;
131 static int smac_nparam(enum pp_token_type toktype
)
133 return toktype
- TOK_SMAC_START_PARAMS
;
135 static bool is_smac_param(enum pp_token_type toktype
)
137 return toktype
>= TOK_SMAC_START_PARAMS
;
140 #define PP_CONCAT_MASK(x) (1U << (x))
142 struct tokseq_match
{
148 * This is tuned so struct Token should be 64 bytes on 64-bit
149 * systems and 32 bytes on 32-bit systems. It enables them
150 * to be nicely cache aligned, and the text to still be kept
151 * inline for nearly all tokens.
153 * We prohibit tokens of length > MAX_TEXT even though
154 * length here is an unsigned int; this avoids problems
155 * if the length is passed through an interface with type "int",
156 * and is absurdly large anyway.
158 * For the text mode, in pointer mode the pointer is stored at the end
159 * of the union and the pad field is cleared. This allows short tokens
160 * to be unconditionally tested for by only looking at the first text
161 * bytes and not examining the type or len fields.
163 #define INLINE_TEXT (7*sizeof(char *)-sizeof(enum pp_token_type)-sizeof(unsigned int)-1)
164 #define MAX_TEXT (INT_MAX-2)
168 enum pp_token_type type
;
171 char a
[INLINE_TEXT
+1];
173 char pad
[INLINE_TEXT
+1 - sizeof(char *)];
180 * Note on the storage of both SMacro and MMacros: the hash table
181 * indexes them case-insensitively, and we then have to go through a
182 * linked list of potential case aliases (and, for MMacros, parameter
183 * ranges); this is to preserve the matching semantics of the earlier
184 * code. If the number of case aliases for a specific macro is a
185 * performance issue, you may want to reconsider your coding style.
189 * Function call tp obtain the expansion of an smacro
191 typedef Token
*(*ExpandSMacro
)(const SMacro
*s
, Token
**params
, int nparams
);
194 * Store the definition of a single-line macro.
198 SPARM_EVAL
= 1, /* Evaluate as a numeric expression (=) */
199 SPARM_STR
= 2, /* Convert to quoted string ($) */
200 SPARM_NOSTRIP
= 4, /* Don't strip braces (!) */
201 SPARM_GREEDY
= 8 /* Greedy final parameter (+) */
206 enum sparmflags flags
;
210 SMacro
*next
; /* MUST BE FIRST - see free_smacro() */
215 struct smac_param
*params
;
220 bool alias
; /* This is an alias macro */
224 * Store the definition of a multi-line macro. This is also used to
225 * store the interiors of `%rep...%endrep' blocks, which are
226 * effectively self-re-invoking multi-line macros which simply
227 * don't have a name or bother to appear in the hash tables. %rep
228 * blocks are signified by having a NULL `name' field.
230 * In a MMacro describing a `%rep' block, the `in_progress' field
231 * isn't merely boolean, but gives the number of repeats left to
234 * The `next' field is used for storing MMacros in hash tables; the
235 * `next_active' field is for stacking them on istk entries.
237 * When a MMacro is being expanded, `params', `iline', `nparam',
238 * `paramlen', `rotate' and `unique' are local to the invocation.
242 * Expansion stack. Note that .mmac can point back to the macro itself,
243 * whereas .mstk cannot.
246 MMacro
*mstk
; /* Any expansion, real macro or not */
247 MMacro
*mmac
; /* Highest level actual mmacro */
253 MMacroInvocation
*prev
; /* previous invocation */
256 int nparam_min
, nparam_max
;
258 bool plus
; /* is the last parameter greedy? */
259 bool nolist
; /* is this macro listing-inhibited? */
260 bool capture_label
; /* macro definition has %00; capture label */
261 int32_t in_progress
; /* is this macro currently being expanded? */
262 int32_t max_depth
; /* maximum number of recursive expansions allowed */
263 Token
*dlist
; /* All defaults as one list */
264 Token
**defaults
; /* Parameter default pointers */
265 int ndefs
; /* number of default parameters */
268 struct mstk mstk
; /* Macro expansion stack */
269 struct mstk dstk
; /* Macro definitions stack */
270 Token
**params
; /* actual parameters */
271 Token
*iline
; /* invocation line */
272 unsigned int nparam
, rotate
;
273 char *iname
; /* name invoked as */
276 int lineno
; /* Current line number on expansion */
277 uint64_t condcnt
; /* number of if blocks... */
279 const char *fname
; /* File where defined */
280 int32_t xline
; /* First line in macro */
284 /* Store the definition of a multi-line macro, as defined in a
285 * previous recursive macro expansion.
289 struct MMacroInvocation
{
290 MMacroInvocation
*prev
; /* previous invocation */
291 Token
**params
; /* actual parameters */
292 Token
*iline
; /* invocation line */
293 unsigned int nparam
, rotate
;
302 * The context stack is composed of a linked list of these.
307 struct hash_table localmac
;
313 static inline const char *tok_text(const struct Token
*t
)
315 return (t
->len
<= INLINE_TEXT
) ? t
->text
.a
: t
->text
.p
.ptr
;
319 * Returns a mutable pointer to the text buffer. The text can be changed,
320 * but the length MUST NOT CHANGE, in either direction; nor is it permitted
321 * to pad with null characters to create an artificially shorter string.
323 static inline char *tok_text_buf(struct Token
*t
)
325 return (t
->len
<= INLINE_TEXT
) ? t
->text
.a
: t
->text
.p
.ptr
;
328 static inline unsigned int tok_check_len(size_t len
)
330 if (unlikely(len
> MAX_TEXT
))
331 nasm_fatal("impossibly large token");
336 static inline bool tok_text_match(const struct Token
*a
, const struct Token
*b
)
338 return a
->len
== b
->len
&& !memcmp(tok_text(a
), tok_text(b
), a
->len
);
341 static inline bool tok_match(const struct Token
*a
, const struct Token
*b
)
343 return a
->type
== b
->type
&& tok_text_match(a
, b
);
346 /* strlen() variant useful for set_text() and its variants */
347 static size_t tok_strlen(const char *str
)
349 return strnlen(str
, MAX_TEXT
+1);
353 * Set the text field to a copy of the given string; the length if
354 * not given should be obtained with tok_strlen().
356 static Token
*set_text(struct Token
*t
, const char *text
, size_t len
)
360 if (t
->len
> INLINE_TEXT
)
361 nasm_free(t
->text
.p
.ptr
);
363 nasm_zero(t
->text
.a
);
365 t
->len
= tok_check_len(len
);
366 textp
= (len
> INLINE_TEXT
)
367 ? (t
->text
.p
.ptr
= nasm_malloc(len
+1)) : t
->text
.a
;
368 memcpy(textp
, text
, len
+1);
373 * Set the text field to the existing pre-allocated string, either
374 * taking over or freeing the allocation in the process.
376 static Token
*set_text_free(struct Token
*t
, char *text
, unsigned int len
)
378 if (t
->len
> INLINE_TEXT
)
379 nasm_free(t
->text
.p
.ptr
);
381 nasm_zero(t
->text
.a
);
383 t
->len
= tok_check_len(len
);
384 if (len
> INLINE_TEXT
) {
385 t
->text
.p
.ptr
= text
;
387 memcpy(t
->text
.a
, text
, len
+1);
395 * Allocate a new buffer containing a copy of the text field
398 static char *dup_text(const struct Token
*t
)
400 size_t size
= t
->len
+ 1;
401 char *p
= nasm_malloc(size
);
403 return memcpy(p
, tok_text(t
), size
);
407 * Multi-line macro definitions are stored as a linked list of
408 * these, which is essentially a container to allow several linked
411 * Note that in this module, linked lists are treated as stacks
412 * wherever possible. For this reason, Lines are _pushed_ on to the
413 * `expansion' field in MMacro structures, so that the linked list,
414 * if walked, would give the macro lines in reverse order; this
415 * means that we can walk the list when expanding a macro, and thus
416 * push the lines on to the `expansion' field in _istk_ in reverse
417 * order (so that when popped back off they are in the right
418 * order). It may seem cockeyed, and it relies on my design having
419 * an even number of steps in, but it works...
421 * Some of these structures, rather than being actual lines, are
422 * markers delimiting the end of the expansion of a given macro.
423 * This is for use in the cycle-tracking and %rep-handling code.
424 * Such structures have `finishes' non-NULL, and `first' NULL. All
425 * others have `finishes' NULL, but `first' may still be NULL if
435 * To handle an arbitrary level of file inclusion, we maintain a
436 * stack (ie linked list) of these things.
450 * File real name hash, so we don't have to re-search the include
451 * path for every pass (and potentially more than that if a file
452 * is used more than once.)
454 struct hash_table FileHash
;
457 * Counters to trap on insane macro recursion or processing.
458 * Note: for smacros these count *down*, for mmacros they count *up*.
461 int64_t total
; /* Total number of macros/tokens */
462 int64_t levels
; /* Descent depth across all macros */
463 bool triggered
; /* Already triggered, no need for error msg */
466 static struct deadman smacro_deadman
, mmacro_deadman
;
469 * Conditional assembly: we maintain a separate stack of these for
470 * each level of file inclusion. (The only reason we keep the
471 * stacks separate is to ensure that a stray `%endif' in a file
472 * included from within the true branch of a `%if' won't terminate
473 * it and cause confusion: instead, rightly, it'll cause an error.)
477 * These states are for use just after %if or %elif: IF_TRUE
478 * means the condition has evaluated to truth so we are
479 * currently emitting, whereas IF_FALSE means we are not
480 * currently emitting but will start doing so if a %else comes
481 * up. In these states, all directives are admissible: %elif,
482 * %else and %endif. (And of course %if.)
484 COND_IF_TRUE
, COND_IF_FALSE
,
486 * These states come up after a %else: ELSE_TRUE means we're
487 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
488 * any %elif or %else will cause an error.
490 COND_ELSE_TRUE
, COND_ELSE_FALSE
,
492 * These states mean that we're not emitting now, and also that
493 * nothing until %endif will be emitted at all. COND_DONE is
494 * used when we've had our moment of emission
495 * and have now started seeing %elifs. COND_NEVER is used when
496 * the condition construct in question is contained within a
497 * non-emitting branch of a larger condition construct,
498 * or if there is an error.
500 COND_DONE
, COND_NEVER
504 enum cond_state state
;
506 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
509 * These defines are used as the possible return values for do_directive
511 #define NO_DIRECTIVE_FOUND 0
512 #define DIRECTIVE_FOUND 1
515 * Condition codes. Note that we use c_ prefix not C_ because C_ is
516 * used in nasm.h for the "real" condition codes. At _this_ level,
517 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
518 * ones, so we need a different enum...
520 static const char * const conditions
[] = {
521 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
522 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
523 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
526 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
527 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
528 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_RCXZ
, c_S
, c_Z
,
531 static const enum pp_conds inverse_ccs
[] = {
532 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
533 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_E
, c_G
, c_GE
, c_L
, c_LE
, c_O
, c_P
, c_S
,
534 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, -1, c_NS
, c_NZ
540 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
541 static int is_condition(enum preproc_token arg
)
543 return PP_IS_COND(arg
) || (arg
== PP_ELSE
) || (arg
== PP_ENDIF
);
546 /* For TASM compatibility we need to be able to recognise TASM compatible
547 * conditional compilation directives. Using the NASM pre-processor does
548 * not work, so we look for them specifically from the following list and
549 * then jam in the equivalent NASM directive into the input stream.
553 TM_ARG
, TM_ELIF
, TM_ELSE
, TM_ENDIF
, TM_IF
, TM_IFDEF
, TM_IFDIFI
,
554 TM_IFNDEF
, TM_INCLUDE
, TM_LOCAL
557 static const char * const tasm_directives
[] = {
558 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
559 "ifndef", "include", "local"
562 static int StackSize
= 4;
563 static const char *StackPointer
= "ebp";
564 static int ArgOffset
= 8;
565 static int LocalOffset
= 0;
567 static Context
*cstk
;
568 static Include
*istk
;
569 static const struct strlist
*ipath_list
;
570 static bool do_aliases
;
572 static struct strlist
*deplist
;
574 static uint64_t unique
; /* unique identifier numbers */
576 static Line
*predef
= NULL
;
577 static bool do_predef
;
578 static enum preproc_mode pp_mode
;
581 * The current set of multi-line macros we have defined.
583 static struct hash_table mmacros
;
586 * The current set of single-line macros we have defined.
588 static struct hash_table smacros
;
591 * The multi-line macro we are currently defining, or the %rep
592 * block we are currently reading, if any.
594 static MMacro
*defining
;
596 static uint64_t nested_mac_count
;
597 static uint64_t nested_rep_count
;
600 * The number of macro parameters to allocate space for at a time.
602 #define PARAM_DELTA 16
605 * The standard macro set: defined in macros.c in a set of arrays.
606 * This gives our position in any macro set, while we are processing it.
607 * The stdmacset is an array of such macro sets.
609 static macros_t
*stdmacpos
;
610 static macros_t
**stdmacnext
;
611 static macros_t
*stdmacros
[8];
612 static macros_t
*extrastdmac
;
615 * Map of which %use packages have been loaded
617 static bool *use_loaded
;
620 * Forward declarations.
622 static void pp_add_stdmac(macros_t
*macros
);
623 static Token
*expand_mmac_params(Token
* tline
);
624 static Token
*expand_smacro(Token
* tline
);
625 static Token
*expand_id(Token
* tline
);
626 static Context
*get_ctx(const char *name
, const char **namep
);
627 static Token
*make_tok_num(Token
*next
, int64_t val
);
628 static Token
*make_tok_qstr(Token
*next
, const char *str
);
629 static Token
*make_tok_qstr_len(Token
*next
, const char *str
, size_t len
);
630 static Token
*make_tok_char(Token
*next
, char op
);
631 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
632 const char *text
, size_t txtlen
);
633 static Token
*new_Token_free(Token
* next
, enum pp_token_type type
,
634 char *text
, size_t txtlen
);
635 static Token
*dup_Token(Token
*next
, const Token
*src
);
636 static Token
*new_White(Token
*next
);
637 static Token
*delete_Token(Token
*t
);
638 static Token
*steal_Token(Token
*dst
, Token
*src
);
639 static const struct use_package
*
640 get_use_pkg(Token
*t
, const char *dname
, const char **name
);
641 static void mark_smac_params(Token
*tline
, const SMacro
*tmpl
,
642 enum pp_token_type type
);
644 /* Safe test for token type, false on x == NULL */
645 static inline bool tok_type(const Token
*x
, enum pp_token_type t
)
647 return x
&& x
->type
== t
;
650 /* Whitespace token? */
651 static inline bool tok_white(const Token
*x
)
653 return tok_type(x
, TOK_WHITESPACE
);
656 /* Skip past any whitespace */
657 static inline Token
*skip_white(Token
*x
)
665 /* Delete any whitespace */
666 static Token
*zap_white(Token
*x
)
675 * Single special character tests. The use of & rather than && is intentional; it
676 * tells the compiler that it is safe to access text.a[1] unconditionally; hopefully
677 * a smart compiler should turn it into a 16-bit memory reference.
679 static inline bool tok_is(const Token
*x
, char c
)
681 return x
&& ((x
->text
.a
[0] == c
) & !x
->text
.a
[1]);
684 /* True if any other kind of token that "c", but not NULL */
685 static inline bool tok_isnt(const Token
*x
, char c
)
687 return x
&& !((x
->text
.a
[0] == c
) & !x
->text
.a
[1]);
691 * Unquote a token if it is a string, and set its type to
692 * TOK_INTERNAL_STRING.
694 static const char *unquote_token(Token
*t
)
696 if (t
->type
!= TOK_STRING
)
699 t
->type
= TOK_INTERNAL_STRING
;
701 if (t
->len
> INLINE_TEXT
) {
702 char *p
= t
->text
.p
.ptr
;
704 t
->len
= nasm_unquote(p
, NULL
);
706 if (t
->len
<= INLINE_TEXT
) {
707 nasm_zero(t
->text
.a
);
708 memcpy(t
->text
.a
, p
, t
->len
);
715 t
->len
= nasm_unquote(t
->text
.a
, NULL
);
721 * Same as unquote_token(), but error out if the resulting string
722 * contains unacceptable control characters.
724 static const char *unquote_token_cstr(Token
*t
)
726 if (t
->type
!= TOK_STRING
)
729 t
->type
= TOK_INTERNAL_STRING
;
731 if (t
->len
> INLINE_TEXT
) {
732 char *p
= t
->text
.p
.ptr
;
734 t
->len
= nasm_unquote_cstr(p
, NULL
);
736 if (t
->len
<= INLINE_TEXT
) {
737 nasm_zero(t
->text
.a
);
738 memcpy(t
->text
.a
, p
, t
->len
);
745 t
->len
= nasm_unquote_cstr(t
->text
.a
, NULL
);
751 * Convert a TOK_INTERNAL_STRING token to a quoted
754 static Token
*quote_any_token(Token
*t
);
755 static inline Token
*quote_token(Token
*t
)
757 if (likely(!tok_is(t
, TOK_INTERNAL_STRING
)))
760 return quote_any_token(t
);
764 * Convert *any* kind of token to a quoted
767 static Token
*quote_any_token(Token
*t
)
772 p
= nasm_quote(tok_text(t
), &len
);
773 t
->type
= TOK_STRING
;
774 return set_text_free(t
, p
, len
);
778 * In-place reverse a list of tokens.
780 static Token
*reverse_tokens(Token
*t
)
796 * getenv() variant operating on an input token
798 static const char *pp_getenv(const Token
*t
, bool warn
)
800 const char *txt
= tok_text(t
);
803 bool is_string
= false;
810 txt
+= 2; /* Skip leading %! */
811 is_string
= nasm_isquote(*txt
);
818 case TOK_INTERNAL_STRING
:
819 case TOK_NAKED_STRING
:
829 buf
= nasm_strdup(txt
);
830 nasm_unquote_cstr(buf
, NULL
);
837 *!environment [on] nonexistent environment variable
838 *! warns if a nonexistent environment variable
839 *! is accessed using the \c{%!} preprocessor
840 *! construct (see \k{getenv}.) Such environment
841 *! variables are treated as empty (with this
842 *! warning issued) starting in NASM 2.15;
843 *! earlier versions of NASM would treat this as
846 nasm_warn(WARN_ENVIRONMENT
, "nonexistent environment variable `%s'", txt
);
857 * Handle TASM specific directives, which do not contain a % in
858 * front of them. We do it here because I could not find any other
859 * place to do it for the moment, and it is a hack (ideally it would
860 * be nice to be able to use the NASM pre-processor to do it).
862 static char *check_tasm_directive(char *line
)
864 int32_t i
, j
, k
, m
, len
;
865 char *p
, *q
, *oldline
, oldchar
;
867 p
= nasm_skip_spaces(line
);
869 /* Binary search for the directive name */
871 j
= ARRAY_SIZE(tasm_directives
);
872 q
= nasm_skip_word(p
);
879 m
= nasm_stricmp(p
, tasm_directives
[k
]);
881 /* We have found a directive, so jam a % in front of it
882 * so that NASM will then recognise it as one if it's own.
887 line
= nasm_malloc(len
+ 2);
889 if (k
== TM_IFDIFI
) {
891 * NASM does not recognise IFDIFI, so we convert
892 * it to %if 0. This is not used in NASM
893 * compatible code, but does need to parse for the
894 * TASM macro package.
896 strcpy(line
+ 1, "if 0");
898 memcpy(line
+ 1, p
, len
+ 1);
913 * The pre-preprocessing stage... This function translates line
914 * number indications as they emerge from GNU cpp (`# lineno "file"
915 * flags') into NASM preprocessor line number indications (`%line
918 static char *prepreproc(char *line
)
921 char *fname
, *oldline
;
923 if (line
[0] == '#' && line
[1] == ' ') {
926 lineno
= atoi(fname
);
927 fname
+= strspn(fname
, "0123456789 ");
930 fnlen
= strcspn(fname
, "\"");
931 line
= nasm_malloc(20 + fnlen
);
932 snprintf(line
, 20 + fnlen
, "%%line %d %.*s", lineno
, fnlen
, fname
);
935 if (tasm_compatible_mode
)
936 return check_tasm_directive(line
);
941 * Free a linked list of tokens.
943 static void free_tlist(Token
* list
)
946 list
= delete_Token(list
);
950 * Free a linked list of lines.
952 static void free_llist(Line
* list
)
955 list_for_each_safe(l
, tmp
, list
) {
956 free_tlist(l
->first
);
962 * Free an array of linked lists of tokens
964 static void free_tlist_array(Token
**array
, size_t nlists
)
966 Token
**listp
= array
;
969 free_tlist(*listp
++);
975 * Duplicate a linked list of tokens.
977 static Token
*dup_tlist(const Token
*list
, Token
***tailp
)
979 Token
*newlist
= NULL
;
980 Token
**tailpp
= &newlist
;
983 list_for_each(t
, list
) {
985 *tailpp
= nt
= dup_Token(NULL
, t
);
998 * Duplicate a linked list of tokens with a maximum count
1000 static Token
*dup_tlistn(const Token
*list
, size_t cnt
, Token
***tailp
)
1002 Token
*newlist
= NULL
;
1003 Token
**tailpp
= &newlist
;
1006 list_for_each(t
, list
) {
1010 *tailpp
= nt
= dup_Token(NULL
, t
);
1024 * Duplicate a linked list of tokens in reverse order
1026 static Token
*dup_tlist_reverse(const Token
*list
, Token
*tail
)
1030 list_for_each(t
, list
)
1031 tail
= dup_Token(tail
, t
);
1039 static void free_mmacro(MMacro
* m
)
1042 free_tlist(m
->dlist
);
1043 nasm_free(m
->defaults
);
1044 free_llist(m
->expansion
);
1049 * Clear or free an SMacro
1051 static void free_smacro_members(SMacro
*s
)
1055 for (i
= 0; i
< s
->nparam
; i
++) {
1056 if (s
->params
[i
].name
.len
> INLINE_TEXT
)
1057 nasm_free(s
->params
[i
].name
.text
.p
.ptr
);
1059 nasm_free(s
->params
);
1062 free_tlist(s
->expansion
);
1065 static void clear_smacro(SMacro
*s
)
1067 free_smacro_members(s
);
1068 /* Wipe everything except the next pointer */
1069 memset(&s
->next
+ 1, 0, sizeof *s
- sizeof s
->next
);
1075 static void free_smacro(SMacro
*s
)
1077 free_smacro_members(s
);
1082 * Free all currently defined macros, and free the hash tables
1084 static void free_smacro_table(struct hash_table
*smt
)
1086 struct hash_iterator it
;
1087 const struct hash_node
*np
;
1089 hash_for_each(smt
, it
, np
) {
1091 SMacro
*s
= np
->data
;
1092 nasm_free((void *)np
->key
);
1093 list_for_each_safe(s
, tmp
, s
)
1099 static void free_mmacro_table(struct hash_table
*mmt
)
1101 struct hash_iterator it
;
1102 const struct hash_node
*np
;
1104 hash_for_each(mmt
, it
, np
) {
1106 MMacro
*m
= np
->data
;
1107 nasm_free((void *)np
->key
);
1108 list_for_each_safe(m
, tmp
, m
)
1114 static void free_macros(void)
1116 free_smacro_table(&smacros
);
1117 free_mmacro_table(&mmacros
);
1121 * Initialize the hash tables
1123 static void init_macros(void)
1128 * Pop the context stack.
1130 static void ctx_pop(void)
1135 free_smacro_table(&c
->localmac
);
1136 nasm_free((char *)c
->name
);
1141 * Search for a key in the hash index; adding it if necessary
1142 * (in which case we initialize the data pointer to NULL.)
1145 hash_findi_add(struct hash_table
*hash
, const char *str
)
1147 struct hash_insert hi
;
1150 size_t l
= strlen(str
) + 1;
1152 r
= hash_findib(hash
, str
, l
, &hi
);
1156 strx
= nasm_malloc(l
); /* Use a more efficient allocator here? */
1157 memcpy(strx
, str
, l
);
1158 return hash_add(&hi
, strx
, NULL
);
1162 * Like hash_findi, but returns the data element rather than a pointer
1163 * to it. Used only when not adding a new element, hence no third
1167 hash_findix(struct hash_table
*hash
, const char *str
)
1171 p
= hash_findi(hash
, str
, NULL
);
1172 return p
? *p
: NULL
;
1176 * read line from standart macros set,
1177 * if there no more left -- return NULL
1179 static char *line_from_stdmac(void)
1182 const unsigned char *p
= stdmacpos
;
1190 * 32-126 is ASCII, 127 is end of line, 128-31 are directives
1191 * (allowed to wrap around) corresponding to PP_* tokens 0-159.
1193 while ((c
= *p
++) != 127) {
1194 uint8_t ndir
= c
- 128;
1196 len
+= pp_directives_len
[ndir
] + 1;
1201 line
= nasm_malloc(len
+ 1);
1204 while ((c
= *stdmacpos
++) != 127) {
1205 uint8_t ndir
= c
- 128;
1206 if (ndir
< 256-96) {
1207 memcpy(q
, pp_directives
[ndir
], pp_directives_len
[ndir
]);
1208 q
+= pp_directives_len
[ndir
];
1217 if (*stdmacpos
== 127) {
1218 /* This was the last of this particular macro set */
1221 stdmacpos
= *stdmacnext
++;
1222 } else if (do_predef
) {
1226 * Nasty hack: here we push the contents of
1227 * `predef' on to the top-level expansion stack,
1228 * since this is the most convenient way to
1229 * implement the pre-include and pre-define
1232 list_for_each(pd
, predef
) {
1234 l
->next
= istk
->expansion
;
1235 l
->first
= dup_tlist(pd
->first
, NULL
);
1238 istk
->expansion
= l
;
1248 * Read a line from a file. Return NULL on end of file.
1250 static char *line_from_file(FILE *f
)
1253 unsigned int size
, next
;
1254 const unsigned int delta
= 512;
1255 const unsigned int pad
= 8;
1256 unsigned int nr_cont
= 0;
1262 p
= buffer
= nasm_malloc(size
);
1295 case 032: /* ^Z = legacy MS-DOS end of file mark */
1302 if (next
== '\r' || next
== '\n') {
1310 if (p
>= (buffer
+ size
- pad
)) {
1311 buffer
= nasm_realloc(buffer
, size
+ delta
);
1312 p
= buffer
+ size
- pad
;
1319 lineno
= src_get_linnum() + istk
->lineinc
+
1320 (nr_cont
* istk
->lineinc
);
1321 src_set_linnum(lineno
);
1327 * Common read routine regardless of source
1329 static char *read_line(void)
1335 line
= line_from_file(f
);
1337 line
= line_from_stdmac();
1343 lfmt
->line(LIST_READ
, src_get_linnum(), line
);
1349 * Tokenize a line of text. This is a very simple process since we
1350 * don't need to parse the value out of e.g. numeric tokens: we
1351 * simply split one string into many.
1353 static Token
*tokenize(const char *line
)
1355 enum pp_token_type type
;
1357 Token
*t
, **tail
= &list
;
1360 const char *p
= line
;
1361 const char *ep
= NULL
; /* End of token, for trimming the end */
1363 char firstchar
= *p
; /* Can be used to override the first char */
1367 * Preprocessor construct; find the end of the token.
1368 * Classification is handled later, because %{...} can be
1369 * used to create any preprocessor token.
1372 if (*p
== '+' && !nasm_isdigit(p
[1])) {
1375 } else if (nasm_isdigit(*p
) ||
1376 ((*p
== '-' || *p
== '+') && nasm_isdigit(p
[1]))) {
1380 while (nasm_isdigit(*p
));
1381 } else if (*p
== '{' || *p
== '[') {
1382 /* %{...} or %[...] */
1383 char firstchar
= *p
;
1384 char endchar
= *p
+ 2; /* } or ] */
1386 line
+= (*p
++ == '{'); /* Skip { but not [ (yet) */
1388 if (*p
== firstchar
) {
1390 } else if (*p
== endchar
) {
1392 } else if (nasm_isquote(*p
)) {
1393 p
= nasm_skip_string(p
);
1397 * *p can have been advanced to a null character by
1398 * nasm_skip_string()
1401 nasm_warn(WARN_OTHER
, "unterminated %%%c construct",
1407 ep
= lvl
? p
: p
-1; /* Terminal character not part of token */
1408 } else if (*p
== '?') {
1413 } else if (*p
== '!') {
1414 /* Environment variable reference */
1416 if (nasm_isidchar(*p
)) {
1420 while (nasm_isidchar(*p
));
1421 } else if (nasm_isquote(*p
)) {
1422 p
= nasm_skip_string(p
);
1426 nasm_nonfatalf(ERR_PASS1
, "unterminated %%! string");
1428 /* %! without anything else... */
1430 } else if (*p
== ',') {
1431 /* Conditional comma */
1433 } else if (nasm_isidchar(*p
) ||
1434 ((*p
== '%' || *p
== '$') && nasm_isidchar(p
[1]))) {
1435 /* Identifier or some sort */
1439 while (nasm_isidchar(*p
));
1440 } else if (*p
== '%') {
1449 /* Classify here, to handle %{...} correctly */
1451 type
= TOK_OTHER
; /* % operator */
1457 type
= (toklen
== 2) ? TOK_PASTE
: TOK_MMACRO_PARAM
;
1461 type
= TOK_MMACRO_PARAM
;
1466 type
= TOK_PREPROC_Q
;
1467 else if (toklen
== 3 && line
[2] == '?')
1468 type
= TOK_PREPROC_QQ
;
1470 type
= TOK_PREPROC_ID
;
1474 type
= (toklen
== 2) ? TOK_OTHER
: TOK_ENVIRON
;
1478 type
= (toklen
== 2) ? TOK_OTHER
: TOK_LOCAL_SYMBOL
;
1482 type
= (toklen
== 2) ? TOK_OTHER
: TOK_LOCAL_MACRO
;
1486 line
+= 2; /* Skip %[ */
1487 firstchar
= *line
; /* Don't clobber */
1489 type
= TOK_INDIRECT
;
1493 type
= (toklen
== 2) ? TOK_COND_COMMA
: TOK_PREPROC_ID
;
1500 type
= TOK_PREPROC_ID
;
1504 type
= TOK_MMACRO_PARAM
; /* %{:..} */
1508 if (nasm_isdigit(c0
))
1509 type
= TOK_MMACRO_PARAM
;
1510 else if (nasm_isidchar(c0
) || toklen
> 2)
1511 type
= TOK_PREPROC_ID
;
1517 } else if (nasm_isidstart(*p
) || (*p
== '$' && nasm_isidstart(p
[1]))) {
1519 * An identifier. This includes the ? operator, which is
1520 * treated as a keyword, not as a special character
1524 while (nasm_isidchar(*++p
))
1526 } else if (nasm_isquote(*p
)) {
1531 p
= nasm_skip_string(p
);
1536 nasm_warn(WARN_OTHER
, "unterminated string");
1537 /* Handling unterminated strings by UNV */
1540 } else if (p
[0] == '$' && p
[1] == '$') {
1541 type
= TOK_OTHER
; /* TOKEN_BASE */
1543 } else if (nasm_isnumstart(*p
)) {
1544 bool is_hex
= false;
1545 bool is_float
= false;
1561 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
1563 if (*p
== '+' || *p
== '-') {
1565 * e can only be followed by +/- if it is either a
1566 * prefixed hex number or a floating-point number
1571 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
1573 } else if (c
== 'P' || c
== 'p') {
1575 if (*p
== '+' || *p
== '-')
1577 } else if (nasm_isnumchar(c
))
1578 ; /* just advance */
1579 else if (c
== '.') {
1581 * we need to deal with consequences of the legacy
1582 * parser, like "1.nolist" being two tokens
1583 * (TOK_NUMBER, TOK_ID) here; at least give it
1584 * a shot for now. In the future, we probably need
1585 * a flex-based scanner with proper pattern matching
1586 * to do it as well as it can be done. Nothing in
1587 * the world is going to help the person who wants
1588 * 0x123.p16 interpreted as two tokens, though.
1594 if (nasm_isdigit(*r
) || (is_hex
&& nasm_isxdigit(*r
)) ||
1595 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
1596 (*r
== 'p' || *r
== 'P')) {
1600 break; /* Terminate the token */
1604 p
--; /* Point to first character beyond number */
1606 if (p
== line
+1 && *line
== '$') {
1607 type
= TOK_OTHER
; /* TOKEN_HERE */
1609 if (has_e
&& !is_hex
) {
1610 /* 1e13 is floating-point, but 1e13h is not */
1614 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
1616 } else if (nasm_isspace(*p
)) {
1617 type
= TOK_WHITESPACE
;
1618 p
= nasm_skip_spaces(p
);
1620 * Whitespace just before end-of-line is discarded by
1621 * pretending it's a comment; whitespace just before a
1622 * comment gets lumped into the comment.
1624 if (!*p
|| *p
== ';') {
1629 } else if (*p
== ';') {
1635 * Anything else is an operator of some kind. We check
1636 * for all the double-character operators (>>, <<, //,
1637 * %%, <=, >=, ==, !=, <>, &&, ||, ^^) and the triple-
1638 * character operators (<<<, >>>, <=>) but anything
1639 * else is a single-character operator.
1648 } else if (*p
== '=') {
1658 } else if (*p
== '=') {
1662 } else if (*p
== '>') {
1677 /* These operators can be doubled but nothing else */
1687 if (type
== TOK_WHITESPACE
) {
1688 *tail
= t
= new_White(NULL
);
1690 } else if (type
!= TOK_COMMENT
) {
1693 *tail
= t
= new_Token(NULL
, type
, line
, ep
- line
);
1694 *tok_text_buf(t
) = firstchar
; /* E.g. %{foo} -> {foo -> %foo */
1703 * Tokens are allocated in blocks to improve speed. Set the blocksize
1704 * to 0 to use regular nasm_malloc(); this is useful for debugging.
1706 * alloc_Token() returns a zero-initialized token structure.
1708 #define TOKEN_BLOCKSIZE 4096
1712 static Token
*freeTokens
= NULL
;
1713 static Token
*tokenblocks
= NULL
;
1715 static Token
*alloc_Token(void)
1717 Token
*t
= freeTokens
;
1723 nasm_newn(block
, TOKEN_BLOCKSIZE
);
1726 * The first entry in each array are a linked list of
1727 * block allocations and is not used for data.
1729 block
[0].next
= tokenblocks
;
1730 block
[0].type
= TOK_BLOCK
;
1731 tokenblocks
= block
;
1734 * Add the rest to the free list
1736 for (i
= 2; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1737 block
[i
].next
= &block
[i
+1];
1739 freeTokens
= &block
[2];
1742 * Return the topmost usable token
1747 freeTokens
= t
->next
;
1752 static Token
*delete_Token(Token
*t
)
1754 Token
*next
= t
->next
;
1757 t
->next
= freeTokens
;
1763 static void delete_Blocks(void)
1765 Token
*block
, *blocktmp
;
1767 list_for_each_safe(block
, blocktmp
, tokenblocks
)
1770 freeTokens
= tokenblocks
= NULL
;
1775 static inline Token
*alloc_Token(void)
1782 static Token
*delete_Token(Token
*t
)
1784 Token
*next
= t
->next
;
1789 static inline void delete_Blocks(void)
1797 * this function creates a new Token and passes a pointer to it
1798 * back to the caller. It sets the type, text, and next pointer elements.
1800 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
1801 const char *text
, size_t txtlen
)
1803 Token
*t
= alloc_Token();
1808 if (type
== TOK_WHITESPACE
) {
1812 if (text
&& text
[0] && !txtlen
)
1813 txtlen
= tok_strlen(text
);
1815 t
->len
= tok_check_len(txtlen
);
1818 textp
= (txtlen
> INLINE_TEXT
)
1819 ? (t
->text
.p
.ptr
= nasm_malloc(txtlen
+1)) : t
->text
.a
;
1820 memcpy(textp
, text
, txtlen
);
1821 textp
[txtlen
] = '\0'; /* In case we needed malloc() */
1824 * Allocate a buffer but do not fill it. The caller
1825 * can fill in text, but must not change the length.
1826 * The filled in text must be exactly txtlen once
1827 * the buffer is filled and before the token is added
1828 * to any line lists.
1830 if (txtlen
> INLINE_TEXT
)
1831 t
->text
.p
.ptr
= nasm_zalloc(txtlen
+1);
1838 * Same as new_Token(), but text belongs to the new token and is
1839 * either taken over or freed. This function MUST be called
1840 * with valid txt and txtlen, unlike new_Token().
1842 static Token
*new_Token_free(Token
* next
, enum pp_token_type type
,
1843 char *text
, size_t txtlen
)
1845 Token
*t
= alloc_Token();
1849 t
->len
= tok_check_len(txtlen
);
1851 if (txtlen
<= INLINE_TEXT
) {
1852 memcpy(t
->text
.a
, text
, txtlen
);
1855 t
->text
.p
.ptr
= text
;
1861 static Token
*dup_Token(Token
*next
, const Token
*src
)
1863 Token
*t
= alloc_Token();
1865 memcpy(t
, src
, sizeof *src
);
1868 if (t
->len
> INLINE_TEXT
) {
1869 t
->text
.p
.ptr
= nasm_malloc(t
->len
+ 1);
1870 memcpy(t
->text
.p
.ptr
, src
->text
.p
.ptr
, t
->len
+1);
1876 static Token
*new_White(Token
*next
)
1878 Token
*t
= alloc_Token();
1881 t
->type
= TOK_WHITESPACE
;
1889 * This *transfers* the content from one token to another, leaving the
1890 * next pointer of the latter intact. Unlike dup_Token(), the old
1891 * token is destroyed, except for its next pointer, and the text
1892 * pointer allocation, if any, is simply transferred.
1894 static Token
*steal_Token(Token
*dst
, Token
*src
)
1896 /* Overwrite everything except the next pointers */
1897 memcpy((char *)dst
+ sizeof(Token
*), (char *)src
+ sizeof(Token
*),
1898 sizeof(Token
) - sizeof(Token
*));
1900 /* Clear the donor token */
1901 memset((char *)src
+ sizeof(Token
*), 0, sizeof(Token
) - sizeof(Token
*));
1907 * Convert a line of tokens back into text. This modifies the list
1908 * by expanding environment variables.
1910 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1911 * are also transformed into ..@ctxnum.xxx
1913 static char *detoken(Token
* tlist
, bool expand_locals
)
1919 list_for_each(t
, tlist
) {
1923 const char *v
= pp_getenv(t
, true);
1924 set_text(t
, v
, tok_strlen(v
));
1925 t
->type
= TOK_NAKED_STRING
;
1929 case TOK_LOCAL_MACRO
:
1930 case TOK_LOCAL_SYMBOL
:
1931 if (expand_locals
) {
1934 Context
*ctx
= get_ctx(tok_text(t
), &q
);
1936 p
= nasm_asprintf("..@%"PRIu64
".%s", ctx
->number
, q
);
1937 set_text_free(t
, p
, nasm_last_string_len());
1944 break; /* No modifications */
1947 if (debug_level(2)) {
1948 unsigned int t_len
= t
->len
;
1949 unsigned int s_len
= tok_strlen(tok_text(t
));
1950 if (t_len
!= s_len
) {
1951 nasm_panic("assertion failed: token \"%s\" type %u len %u has t->len %u\n",
1952 tok_text(t
), t
->type
, s_len
, t_len
);
1960 p
= line
= nasm_malloc(len
+ 1);
1962 list_for_each(t
, tlist
)
1963 p
= mempcpy(p
, tok_text(t
), t
->len
);
1970 * A scanner, suitable for use by the expression evaluator, which
1971 * operates on a line of Tokens. Expects a pointer to a pointer to
1972 * the first token in the line to be passed in as its private_data
1975 * FIX: This really needs to be unified with stdscan.
1982 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1984 struct ppscan
*pps
= private_data
;
1989 if (pps
->ntokens
&& (tline
= pps
->tptr
)) {
1991 pps
->tptr
= tline
->next
;
1995 return tokval
->t_type
= TOKEN_EOS
;
1997 } while (tline
->type
== TOK_WHITESPACE
|| tline
->type
== TOK_COMMENT
);
1999 txt
= tok_text(tline
);
2000 tokval
->t_charptr
= (char *)txt
; /* Fix this */
2002 if (txt
[0] == '$') {
2004 return tokval
->t_type
= TOKEN_HERE
;
2005 } else if (txt
[1] == '$' && !txt
[2]) {
2006 return tokval
->t_type
= TOKEN_BASE
;
2007 } else if (tline
->type
== TOK_ID
) {
2008 tokval
->t_charptr
++;
2009 return tokval
->t_type
= TOKEN_ID
;
2013 switch (tline
->type
) {
2015 if (tline
->len
== 1)
2016 return tokval
->t_type
= txt
[0];
2019 return nasm_token_hash(txt
, tokval
);
2024 tokval
->t_integer
= readnum(txt
, &rn_error
);
2026 return tokval
->t_type
= TOKEN_ERRNUM
;
2028 return tokval
->t_type
= TOKEN_NUM
;
2032 return tokval
->t_type
= TOKEN_FLOAT
;
2035 tokval
->t_charptr
= (char *)unquote_token(tline
);
2036 tokval
->t_inttwo
= tline
->len
;
2037 return tokval
->t_type
= TOKEN_STR
;
2042 * 1. An expression (true if nonzero 0)
2043 * 2. The keywords true, on, yes for true
2044 * 3. The keywords false, off, no for false
2045 * 4. An empty line, for true
2047 * On error, return defval (usually the previous value)
2049 static bool pp_get_boolean_option(Token
*tline
, bool defval
)
2051 static const char * const noyes
[] = {
2057 struct tokenval tokval
;
2060 tline
= skip_white(tline
);
2064 if (tline
->type
== TOK_ID
) {
2066 const char *txt
= tok_text(tline
);
2068 for (i
= 0; i
< ARRAY_SIZE(noyes
); i
++)
2069 if (!nasm_stricmp(txt
, noyes
[i
]))
2076 tokval
.t_type
= TOKEN_INVALID
;
2077 evalresult
= evaluate(ppscan
, &pps
, &tokval
, NULL
, true, NULL
);
2083 nasm_warn(WARN_OTHER
, "trailing garbage after expression ignored");
2084 if (!is_really_simple(evalresult
)) {
2085 nasm_nonfatal("boolean flag expression must be a constant");
2089 return reloc_value(evalresult
) != 0;
2093 * Compare a string to the name of an existing macro; this is a
2094 * simple wrapper which calls either strcmp or nasm_stricmp
2095 * depending on the value of the `casesense' parameter.
2097 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
2099 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
2103 * Compare a string to the name of an existing macro; this is a
2104 * simple wrapper which calls either strcmp or nasm_stricmp
2105 * depending on the value of the `casesense' parameter.
2107 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
2109 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
2113 * Return the Context structure associated with a %$ token. Return
2114 * NULL, having _already_ reported an error condition, if the
2115 * context stack isn't deep enough for the supplied number of $
2118 * If "namep" is non-NULL, set it to the pointer to the macro name
2119 * tail, i.e. the part beyond %$...
2121 static Context
*get_ctx(const char *name
, const char **namep
)
2129 if (!name
|| name
[0] != '%' || name
[1] != '$')
2133 nasm_nonfatal("`%s': context stack is empty", name
);
2140 while (ctx
&& *name
== '$') {
2146 nasm_nonfatal("`%s': context stack is only"
2147 " %d level%s deep", name
, i
, (i
== 1 ? "" : "s"));
2158 * Open an include file. This routine must always return a valid
2159 * file pointer if it returns - it's responsible for throwing an
2160 * ERR_FATAL and bombing out completely if not. It should also try
2161 * the include path one by one until it finds the file or reaches
2162 * the end of the path.
2164 * Note: for INC_PROBE the function returns NULL at all times;
2165 * instead look for the
2168 INC_NEEDED
, /* File must exist */
2169 INC_OPTIONAL
, /* Missing is OK */
2170 INC_PROBE
/* Only an existence probe */
2173 /* This is conducts a full pathname search */
2174 static FILE *inc_fopen_search(const char *file
, char **slpath
,
2175 enum incopen_mode omode
, enum file_flags fmode
)
2177 const struct strlist_entry
*ip
= strlist_head(ipath_list
);
2179 const char *prefix
= "";
2184 sp
= nasm_catfile(prefix
, file
);
2185 if (omode
== INC_PROBE
) {
2187 found
= nasm_file_exists(sp
);
2189 fp
= nasm_open_read(sp
, fmode
);
2190 found
= (fp
!= NULL
);
2210 * Open a file, or test for the presence of one (depending on omode),
2211 * considering the include path.
2213 static FILE *inc_fopen(const char *file
,
2214 struct strlist
*dhead
,
2215 const char **found_path
,
2216 enum incopen_mode omode
,
2217 enum file_flags fmode
)
2219 struct hash_insert hi
;
2224 hp
= hash_find(&FileHash
, file
, &hi
);
2227 if (path
|| omode
!= INC_NEEDED
) {
2228 strlist_add(dhead
, path
? path
: file
);
2231 /* Need to do the actual path search */
2232 fp
= inc_fopen_search(file
, &path
, omode
, fmode
);
2234 /* Positive or negative result */
2235 hash_add(&hi
, nasm_strdup(file
), path
);
2238 * Add file to dependency path.
2240 if (path
|| omode
!= INC_NEEDED
)
2241 strlist_add(dhead
, file
);
2244 if (path
&& !fp
&& omode
!= INC_PROBE
)
2245 fp
= nasm_open_read(path
, fmode
);
2247 if (omode
== INC_NEEDED
&& !fp
) {
2251 nasm_nonfatal("unable to open include file `%s': %s",
2252 file
, strerror(errno
));
2262 * Opens an include or input file. Public version, for use by modules
2263 * that get a file:lineno pair and need to look at the file again
2264 * (e.g. the CodeView debug backend). Returns NULL on failure.
2266 FILE *pp_input_fopen(const char *filename
, enum file_flags mode
)
2268 return inc_fopen(filename
, NULL
, NULL
, INC_OPTIONAL
, mode
);
2272 * Determine if we should warn on defining a single-line macro of
2273 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
2274 * return true if _any_ single-line macro of that name is defined.
2275 * Otherwise, will return true if a single-line macro with either
2276 * `nparam' or no parameters is defined.
2278 * If a macro with precisely the right number of parameters is
2279 * defined, or nparam is -1, the address of the definition structure
2280 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
2281 * is NULL, no action will be taken regarding its contents, and no
2284 * Note that this is also called with nparam zero to resolve
2288 smacro_defined(Context
*ctx
, const char *name
, int nparam
, SMacro
**defn
,
2289 bool nocase
, bool find_alias
)
2291 struct hash_table
*smtbl
;
2294 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2297 m
= (SMacro
*) hash_findix(smtbl
, name
);
2300 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
2301 (nparam
<= 0 || m
->nparam
== 0 || nparam
== m
->nparam
||
2302 (m
->greedy
&& nparam
>= m
->nparam
-1))) {
2303 if (m
->alias
&& !find_alias
) {
2305 name
= tok_text(m
->expansion
);
2312 *defn
= (nparam
== m
->nparam
|| nparam
== -1) ? m
: NULL
;
2322 /* param should be a natural number [0; INT_MAX] */
2323 static int read_param_count(const char *str
)
2328 result
= readnum(str
, &err
);
2329 if (result
< 0 || result
> INT_MAX
) {
2331 nasm_nonfatal("parameter count `%s' is out of bounds [%d; %d]",
2334 nasm_nonfatal("unable to parse parameter count `%s'", str
);
2339 * Count and mark off the parameters in a multi-line macro call.
2340 * This is called both from within the multi-line macro expansion
2341 * code, and also to mark off the default parameters when provided
2342 * in a %macro definition line.
2344 * Note that we need space in the params array for parameter 0 being
2345 * a possible captured label as well as the final NULL.
2347 static void count_mmac_params(Token
* t
, int *nparamp
, Token
***paramsp
)
2353 paramsize
= PARAM_DELTA
;
2354 params
= nasm_malloc(paramsize
* sizeof(*params
));
2357 while ((t
= skip_white(t
))) {
2358 /* 2 slots for captured label and NULL */
2359 if (nparam
+2 >= paramsize
) {
2360 paramsize
+= PARAM_DELTA
;
2361 params
= nasm_realloc(params
, sizeof(*params
) * paramsize
);
2363 params
[++nparam
] = t
;
2364 if (tok_is(t
, '{')) {
2366 while (brace
&& (t
= t
->next
)) {
2367 brace
+= tok_is(t
, '{');
2368 brace
-= tok_is(t
, '}');
2373 * Now we've found the closing brace, look further
2376 t
= skip_white(t
->next
);
2377 if (tok_isnt(t
, ','))
2378 nasm_nonfatal("braces do not enclose all of macro parameter");
2380 nasm_nonfatal("expecting closing brace in macro parameter");
2384 while (tok_isnt(t
, ','))
2387 if (t
) /* got a comma */
2388 t
= t
->next
; /* eat the comma */
2391 params
[nparam
+1] = NULL
;
2397 * Determine whether one of the various `if' conditions is true or
2400 * We must free the tline we get passed.
2402 static enum cond_state
if_condition(Token
* tline
, enum preproc_token ct
)
2405 Token
*t
, *tt
, *origline
;
2407 struct tokenval tokval
;
2409 enum pp_token_type needtype
;
2410 const char *dname
= pp_directives
[ct
];
2411 bool casesense
= true;
2412 enum preproc_token cond
= PP_COND(ct
);
2418 j
= false; /* have we matched yet? */
2420 tline
= skip_white(tline
);
2423 if (tline
->type
!= TOK_ID
) {
2424 nasm_nonfatal("`%s' expects context identifiers",
2428 if (cstk
&& cstk
->name
&& !nasm_stricmp(tok_text(tline
), cstk
->name
))
2430 tline
= tline
->next
;
2437 bool alias
= cond
== PP_IFDEFALIAS
;
2442 j
= false; /* have we matched yet? */
2444 tline
= skip_white(tline
);
2445 if (!tline
|| (tline
->type
!= TOK_ID
&&
2446 tline
->type
!= TOK_LOCAL_MACRO
)) {
2447 nasm_nonfatal("`%s' expects macro identifiers",
2452 mname
= tok_text(tline
);
2453 ctx
= get_ctx(mname
, &mname
);
2454 if (smacro_defined(ctx
, mname
, 0, &smac
, true, alias
) && smac
2455 && smac
->alias
== alias
) {
2459 tline
= tline
->next
;
2465 tline
= expand_smacro(tline
);
2466 j
= false; /* have we matched yet? */
2468 tline
= skip_white(tline
);
2469 if (!tline
|| (tline
->type
!= TOK_ID
&&
2470 tline
->type
!= TOK_STRING
&&
2471 tline
->type
!= TOK_INTERNAL_STRING
&&
2472 tline
->type
!= TOK_ENVIRON
)) {
2473 nasm_nonfatal("`%s' expects environment variable names",
2478 j
|= !!pp_getenv(tline
, false);
2479 tline
= tline
->next
;
2487 tline
= expand_smacro(tline
);
2489 while (tok_isnt(tt
, ','))
2492 nasm_nonfatal("`%s' expects two comma-separated arguments",
2497 j
= true; /* assume equality unless proved not */
2498 while (tok_isnt(t
, ',') && tt
) {
2499 unsigned int l1
, l2
;
2500 const char *t1
, *t2
;
2502 if (tok_is(tt
, ',')) {
2503 nasm_nonfatal("`%s': more than one comma on line",
2507 if (t
->type
== TOK_WHITESPACE
) {
2511 if (tt
->type
== TOK_WHITESPACE
) {
2515 if (tt
->type
!= t
->type
) {
2516 j
= false; /* found mismatching tokens */
2520 t1
= unquote_token(t
);
2521 t2
= unquote_token(tt
);
2525 if (l1
!= l2
|| mmemcmp(t1
, t2
, l1
, casesense
)) {
2533 if (!tok_is(t
, ',') || tt
)
2534 j
= false; /* trailing gunk on one end or other */
2540 MMacro searching
, *mmac
;
2542 tline
= skip_white(tline
);
2543 tline
= expand_id(tline
);
2544 if (!tok_type(tline
, TOK_ID
)) {
2545 nasm_nonfatal("`%s' expects a macro name", dname
);
2548 nasm_zero(searching
);
2549 searching
.name
= dup_text(tline
);
2550 searching
.casesense
= true;
2551 searching
.nparam_min
= 0;
2552 searching
.nparam_max
= INT_MAX
;
2553 tline
= expand_smacro(tline
->next
);
2554 tline
= skip_white(tline
);
2556 } else if (!tok_type(tline
, TOK_NUMBER
)) {
2557 nasm_nonfatal("`%s' expects a parameter count or nothing",
2560 searching
.nparam_min
= searching
.nparam_max
=
2561 read_param_count(tok_text(tline
));
2563 if (tline
&& tok_is(tline
->next
, '-')) {
2564 tline
= tline
->next
->next
;
2565 if (tok_is(tline
, '*'))
2566 searching
.nparam_max
= INT_MAX
;
2567 else if (!tok_type(tline
, TOK_NUMBER
))
2568 nasm_nonfatal("`%s' expects a parameter count after `-'",
2571 searching
.nparam_max
= read_param_count(tok_text(tline
));
2572 if (searching
.nparam_min
> searching
.nparam_max
) {
2573 nasm_nonfatal("minimum parameter count exceeds maximum");
2574 searching
.nparam_max
= searching
.nparam_min
;
2578 if (tline
&& tok_is(tline
->next
, '+')) {
2579 tline
= tline
->next
;
2580 searching
.plus
= true;
2582 mmac
= (MMacro
*) hash_findix(&mmacros
, searching
.name
);
2584 if (!strcmp(mmac
->name
, searching
.name
) &&
2585 (mmac
->nparam_min
<= searching
.nparam_max
2587 && (searching
.nparam_min
<= mmac
->nparam_max
2594 if (tline
&& tline
->next
)
2595 nasm_warn(WARN_OTHER
, "trailing garbage after %%ifmacro ignored");
2596 nasm_free(searching
.name
);
2605 needtype
= TOK_NUMBER
;
2608 needtype
= TOK_STRING
;
2612 t
= tline
= expand_smacro(tline
);
2614 while (tok_white(t
) ||
2615 (needtype
== TOK_NUMBER
&& (tok_is(t
, '-') | tok_is(t
, '+'))))
2618 j
= tok_type(t
, needtype
);
2622 tline
= expand_smacro(tline
);
2623 t
= skip_white(tline
);
2627 t
= skip_white(t
->next
); /* Skip the actual token + whitespace */
2633 tline
= expand_smacro(tline
);
2634 t
= skip_white(tline
);
2635 j
= !t
; /* Should be empty */
2639 pps
.tptr
= tline
= expand_smacro(tline
);
2641 tokval
.t_type
= TOKEN_INVALID
;
2642 evalresult
= evaluate(ppscan
, &pps
, &tokval
, NULL
, true, NULL
);
2646 nasm_warn(WARN_OTHER
, "trailing garbage after expression ignored");
2647 if (!is_simple(evalresult
)) {
2648 nasm_nonfatal("non-constant value given to `%s'",
2652 j
= reloc_value(evalresult
) != 0;
2658 const struct use_package
*pkg
;
2661 pkg
= get_use_pkg(tline
, dname
, &name
);
2665 j
= pkg
&& ((cond
== PP_IFUSABLE
) | use_loaded
[pkg
->index
]);
2670 nasm_nonfatal("unknown preprocessor directive `%s'", dname
);
2674 free_tlist(origline
);
2675 return (j
^ PP_COND_NEGATIVE(ct
)) ? COND_IF_TRUE
: COND_IF_FALSE
;
2678 free_tlist(origline
);
2683 * Default smacro expansion routine: just returns a copy of the
2687 smacro_expand_default(const SMacro
*s
, Token
**params
, int nparams
)
2692 return dup_tlist(s
->expansion
, NULL
);
2696 * Emit a macro defintion or undef to the listing file, if
2697 * desired. This is similar to detoken(), but it handles the reverse
2698 * expansion list, does not expand %! or local variable tokens, and
2699 * does some special handling for macro parameters.
2702 list_smacro_def(enum preproc_token op
, const Context
*ctx
, const SMacro
*m
)
2705 size_t namelen
, size
;
2707 char *context_prefix
= NULL
;
2710 namelen
= strlen(m
->name
);
2711 size
= namelen
+ 2; /* Include room for space after name + NUL */
2714 int context_depth
= cstk
->depth
- ctx
->depth
+ 1;
2716 nasm_asprintf("[%s::%"PRIu64
"] %%%-*s",
2717 ctx
->name
? ctx
->name
: "",
2718 ctx
->number
, context_depth
, "");
2720 context_len
= nasm_last_string_len();
2721 memset(context_prefix
+ context_len
- context_depth
,
2722 '$', context_depth
);
2723 size
+= context_len
;
2726 list_for_each(t
, m
->expansion
)
2731 * Space for ( and either , or ) around each
2732 * parameter, plus up to 4 flags.
2736 size
+= 1 + 4 * m
->nparam
;
2737 for (i
= 0; i
< m
->nparam
; i
++)
2738 size
+= m
->params
[i
].name
.len
;
2741 def
= nasm_malloc(size
);
2745 list_for_each(t
, m
->expansion
) {
2747 memcpy(p
, tok_text(t
), t
->len
);
2756 for (i
= m
->nparam
-1; i
>= 0; i
--) {
2757 enum sparmflags flags
= m
->params
[i
].flags
;
2758 if (flags
& SPARM_GREEDY
)
2760 p
-= m
->params
[i
].name
.len
;
2761 memcpy(p
, tok_text(&m
->params
[i
].name
), m
->params
[i
].name
.len
);
2763 if (flags
& SPARM_NOSTRIP
)
2765 if (flags
& SPARM_STR
)
2767 if (flags
& SPARM_EVAL
)
2771 *p
= '('; /* First parameter starts with ( not , */
2775 memcpy(p
, m
->name
, namelen
);
2777 if (context_prefix
) {
2779 memcpy(p
, context_prefix
, context_len
);
2780 nasm_free(context_prefix
);
2783 nasm_listmsg("%s %s", pp_directives
[op
], p
);
2788 * Parse smacro arguments, return argument count. If the tmpl argument
2789 * is set, set the nparam, greedy and params field in the template.
2790 * *tpp is updated to point to the pointer to the first token after the
2793 * The text values from any argument tokens are "stolen" and the
2794 * corresponding text fields set to NULL.
2796 static int parse_smacro_template(Token
***tpp
, SMacro
*tmpl
)
2799 enum sparmflags flags
;
2800 struct smac_param
*params
= NULL
;
2802 bool greedy
= false;
2808 * DO NOT skip whitespace here, or we won't be able to distinguish:
2810 * %define foo (a,b) ; no arguments, (a,b) is the expansion
2811 * %define bar(a,b) ; two arguments, empty expansion
2813 * This ambiguity was inherited from C.
2816 if (!tok_is(t
, '('))
2824 /* Count parameters first */
2825 sparam
= parse_smacro_template(&txpp
, NULL
);
2827 goto finish
; /* No parameters, we're done */
2828 nasm_newn(params
, sparam
);
2831 /* Skip leading paren */
2840 if (!t
|| !t
->type
) {
2842 nasm_nonfatal("`)' expected to terminate macro template");
2844 nasm_nonfatal("parameter identifier expected");
2858 switch (t
->text
.a
[0]) {
2860 flags
|= SPARM_EVAL
;
2866 flags
|= SPARM_NOSTRIP
;
2869 flags
|= SPARM_GREEDY
;
2874 nasm_nonfatal("greedy parameter must be last");
2879 steal_Token(¶ms
[nparam
].name
, name
);
2880 params
[nparam
].flags
= flags
;
2885 done
= t
->text
.a
[0] == ')';
2892 case TOK_WHITESPACE
:
2898 nasm_nonfatal("garbage `%s' in macro parameter list", tok_text(t
));
2909 while (t
&& t
->type
== TOK_WHITESPACE
) {
2915 tmpl
->nparam
= nparam
;
2916 tmpl
->greedy
= greedy
;
2917 tmpl
->params
= params
;
2923 * Common code for defining an smacro. The tmpl argument, if not NULL,
2924 * contains any macro parameters that aren't explicit arguments;
2925 * those are the more uncommon macro variants.
2927 static SMacro
*define_smacro(const char *mname
, bool casesense
,
2928 Token
*expansion
, SMacro
*tmpl
)
2930 SMacro
*smac
, **smhead
;
2931 struct hash_table
*smtbl
;
2933 bool defining_alias
= false;
2934 unsigned int nparam
= 0;
2937 defining_alias
= tmpl
->alias
;
2938 nparam
= tmpl
->nparam
;
2939 if (nparam
&& !defining_alias
)
2940 mark_smac_params(expansion
, tmpl
, 0);
2944 ctx
= get_ctx(mname
, &mname
);
2946 if (!smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
, true)) {
2947 /* Create a new macro */
2948 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2949 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
2951 smac
->next
= *smhead
;
2955 nasm_warn(WARN_OTHER
, "single-line macro `%s' defined both with and"
2956 " without parameters", mname
);
2958 * Some instances of the old code considered this a failure,
2959 * some others didn't. What is the right thing to do here?
2962 } else if (!smac
->alias
|| !do_aliases
|| defining_alias
) {
2964 * We're redefining, so we have to take over an
2965 * existing SMacro structure. This means freeing
2966 * what was already in it, but not the structure itself.
2970 } else if (smac
->in_progress
) {
2971 nasm_nonfatal("macro alias loop");
2974 /* It is an alias macro; follow the alias link */
2977 smac
->in_progress
= true;
2978 s
= define_smacro(tok_text(smac
->expansion
), casesense
,
2980 smac
->in_progress
= false;
2985 smac
->name
= nasm_strdup(mname
);
2986 smac
->casesense
= casesense
;
2987 smac
->expansion
= expansion
;
2988 smac
->expand
= smacro_expand_default
;
2990 smac
->nparam
= tmpl
->nparam
;
2991 smac
->params
= tmpl
->params
;
2992 smac
->alias
= tmpl
->alias
;
2993 smac
->greedy
= tmpl
->greedy
;
2995 smac
->expand
= tmpl
->expand
;
2997 if (list_option('s')) {
2998 list_smacro_def((smac
->alias
? PP_DEFALIAS
: PP_DEFINE
)
2999 + !casesense
, ctx
, smac
);
3004 free_tlist(expansion
);
3006 free_smacro_members(tmpl
);
3011 * Undefine an smacro
3013 static void undef_smacro(const char *mname
, bool undefalias
)
3015 SMacro
**smhead
, *s
, **sp
;
3016 struct hash_table
*smtbl
;
3019 ctx
= get_ctx(mname
, &mname
);
3020 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
3021 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
3025 * We now have a macro name... go hunt for it.
3028 while ((s
= *sp
) != NULL
) {
3029 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
3030 if (s
->alias
&& !undefalias
) {
3032 if (s
->in_progress
) {
3033 nasm_nonfatal("macro alias loop");
3035 s
->in_progress
= true;
3036 undef_smacro(tok_text(s
->expansion
), false);
3037 s
->in_progress
= false;
3041 if (list_option('d'))
3042 list_smacro_def(s
->alias
? PP_UNDEFALIAS
: PP_UNDEF
,
3055 * Parse a mmacro specification.
3057 static bool parse_mmacro_spec(Token
*tline
, MMacro
*def
, const char *directive
)
3059 tline
= tline
->next
;
3060 tline
= skip_white(tline
);
3061 tline
= expand_id(tline
);
3062 if (!tok_type(tline
, TOK_ID
)) {
3063 nasm_nonfatal("`%s' expects a macro name", directive
);
3070 def
->name
= dup_text(tline
);
3072 def
->nolist
= false;
3073 def
->nparam_min
= 0;
3074 def
->nparam_max
= 0;
3076 tline
= expand_smacro(tline
->next
);
3077 tline
= skip_white(tline
);
3078 if (!tok_type(tline
, TOK_NUMBER
))
3079 nasm_nonfatal("`%s' expects a parameter count", directive
);
3081 def
->nparam_min
= def
->nparam_max
= read_param_count(tok_text(tline
));
3082 if (tline
&& tok_is(tline
->next
, '-')) {
3083 tline
= tline
->next
->next
;
3084 if (tok_is(tline
, '*')) {
3085 def
->nparam_max
= INT_MAX
;
3086 } else if (!tok_type(tline
, TOK_NUMBER
)) {
3087 nasm_nonfatal("`%s' expects a parameter count after `-'", directive
);
3089 def
->nparam_max
= read_param_count(tok_text(tline
));
3090 if (def
->nparam_min
> def
->nparam_max
) {
3091 nasm_nonfatal("minimum parameter count exceeds maximum");
3092 def
->nparam_max
= def
->nparam_min
;
3096 if (tline
&& tok_is(tline
->next
, '+')) {
3097 tline
= tline
->next
;
3100 if (tline
&& tok_type(tline
->next
, TOK_ID
) &&
3101 tline
->next
->len
== 7 &&
3102 !nasm_stricmp(tline
->next
->text
.a
, ".nolist")) {
3103 tline
= tline
->next
;
3104 def
->nolist
= !list_option('f') || istk
->nolist
;
3108 * Handle default parameters.
3110 if (tline
&& tline
->next
) {
3111 def
->dlist
= tline
->next
;
3113 count_mmac_params(def
->dlist
, &def
->ndefs
, &def
->defaults
);
3116 def
->defaults
= NULL
;
3118 def
->expansion
= NULL
;
3120 if (def
->defaults
&& def
->ndefs
> def
->nparam_max
- def
->nparam_min
&&
3123 *!macro-defaults [on] macros with more default than optional parameters
3124 *! warns when a macro has more default parameters than optional parameters.
3125 *! See \k{mlmacdef} for why might want to disable this warning.
3127 nasm_warn(WARN_MACRO_DEFAULTS
,
3128 "too many default macro parameters in macro `%s'", def
->name
);
3136 * Decode a size directive
3138 static int parse_size(const char *str
) {
3139 static const char *size_names
[] =
3140 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
3141 static const int sizes
[] =
3142 { 0, 1, 4, 16, 8, 10, 2, 32 };
3143 return str
? sizes
[bsii(str
, size_names
, ARRAY_SIZE(size_names
))+1] : 0;
3147 * Process a preprocessor %pragma directive. Currently there are none.
3148 * Gets passed the token list starting with the "preproc" token from
3149 * "%pragma preproc".
3151 static void do_pragma_preproc(Token
*tline
)
3153 /* Skip to the real stuff */
3154 tline
= tline
->next
;
3155 tline
= skip_white(tline
);
3159 (void)tline
; /* Nothing else to do at present */
3162 static bool is_macro_id(const Token
*t
)
3164 return tok_type(t
, TOK_ID
) || tok_type(t
, TOK_LOCAL_MACRO
);
3167 static const char *get_id(Token
**tp
, const char *dname
)
3172 t
= t
->next
; /* Skip directive */
3176 if (!is_macro_id(t
)) {
3177 nasm_nonfatal("`%s' expects a macro identifier", dname
);
3187 /* Parse a %use package name and find the package. Set *err on syntax error. */
3188 static const struct use_package
*
3189 get_use_pkg(Token
*t
, const char *dname
, const char **name
)
3194 t
= expand_smacro(t
);
3199 nasm_nonfatal("`%s' expects a package name, got end of line", dname
);
3201 } else if (t
->type
!= TOK_ID
&& t
->type
!= TOK_STRING
) {
3202 nasm_nonfatal("`%s' expects a package name, got `%s'",
3203 dname
, tok_text(t
));
3207 *name
= id
= unquote_token(t
);
3212 nasm_warn(WARN_OTHER
, "trailing garbage after `%s' ignored", dname
);
3214 return nasm_find_use_package(id
);
3218 * Mark parameter tokens in an smacro definition. If the type argument
3219 * is 0, create smac param tokens, otherwise use the type specified;
3220 * normally this is used for TOK_XDEF_PARAM, which is used to protect
3221 * parameter tokens during expansion during %xdefine.
3223 * tmpl may not be NULL here.
3225 static void mark_smac_params(Token
*tline
, const SMacro
*tmpl
,
3226 enum pp_token_type type
)
3228 const struct smac_param
*params
= tmpl
->params
;
3229 int nparam
= tmpl
->nparam
;
3233 list_for_each(t
, tline
) {
3234 if (t
->type
!= TOK_ID
&& t
->type
!= TOK_XDEF_PARAM
)
3237 for (i
= 0; i
< nparam
; i
++) {
3238 if (tok_text_match(t
, ¶ms
[i
].name
))
3239 t
->type
= type
? type
: tok_smac_param(i
);
3245 * find and process preprocessor directive in passed line
3246 * Find out if a line contains a preprocessor directive, and deal
3249 * If a directive _is_ found, it is the responsibility of this routine
3250 * (and not the caller) to free_tlist() the line.
3252 * @param tline a pointer to the current tokeninzed line linked list
3253 * @param output if this directive generated output
3254 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
3257 static int do_directive(Token
*tline
, Token
**output
)
3259 enum preproc_token op
;
3268 const char *found_path
;
3274 MMacro
*mmac
, **mmhead
;
3275 Token
*t
= NULL
, *tt
, *macro_start
, *last
, *origline
;
3277 struct tokenval tokval
;
3282 const char *dname
; /* Name of directive, for messages */
3284 *output
= NULL
; /* No output generated */
3287 tline
= skip_white(tline
);
3288 if (!tline
|| !tok_type(tline
, TOK_PREPROC_ID
))
3289 return NO_DIRECTIVE_FOUND
;
3291 dname
= tok_text(tline
);
3292 if (dname
[1] == '%')
3293 return NO_DIRECTIVE_FOUND
;
3295 op
= pp_token_hash(dname
);
3298 if (PP_HAS_CASE(op
) & PP_INSENSITIVE(op
)) {
3304 * If we're in a non-emitting branch of a condition construct,
3305 * or walking to the end of an already terminated %rep block,
3306 * we should ignore all directives except for condition
3309 if (((istk
->conds
&& !emitting(istk
->conds
->state
)) ||
3310 (istk
->mstk
.mstk
&& !istk
->mstk
.mstk
->in_progress
)) &&
3311 !is_condition(op
)) {
3312 return NO_DIRECTIVE_FOUND
;
3316 * If we're defining a macro or reading a %rep block, we should
3317 * ignore all directives except for %macro/%imacro (which nest),
3318 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
3319 * If we're in a %rep block, another %rep nests, so should be let through.
3321 if (defining
&& op
!= PP_MACRO
&& op
!= PP_RMACRO
&&
3322 op
!= PP_ENDMACRO
&& op
!= PP_ENDM
&&
3323 (defining
->name
|| (op
!= PP_ENDREP
&& op
!= PP_REP
))) {
3324 return NO_DIRECTIVE_FOUND
;
3328 if (op
== PP_MACRO
|| op
== PP_RMACRO
) {
3330 return NO_DIRECTIVE_FOUND
;
3331 } else if (nested_mac_count
> 0) {
3332 if (op
== PP_ENDMACRO
) {
3334 return NO_DIRECTIVE_FOUND
;
3337 if (!defining
->name
) {
3340 return NO_DIRECTIVE_FOUND
;
3341 } else if (nested_rep_count
> 0) {
3342 if (op
== PP_ENDREP
) {
3344 return NO_DIRECTIVE_FOUND
;
3352 nasm_nonfatal("unknown preprocessor directive `%s'", dname
);
3353 return NO_DIRECTIVE_FOUND
; /* didn't get it */
3357 * %pragma namespace options...
3359 * The namespace "preproc" is reserved for the preprocessor;
3360 * all other namespaces generate a [pragma] assembly directive.
3362 * Invalid %pragmas are ignored and may have different
3363 * meaning in future versions of NASM.
3366 tline
= tline
->next
;
3368 tline
= zap_white(expand_smacro(tline
));
3369 if (tok_type(tline
, TOK_ID
)) {
3370 if (!nasm_stricmp(tok_text(tline
), "preproc")) {
3371 /* Preprocessor pragma */
3372 do_pragma_preproc(tline
);
3375 /* Build the assembler directive */
3377 /* Append bracket to the end of the output */
3378 for (t
= tline
; t
->next
; t
= t
->next
)
3380 t
->next
= make_tok_char(NULL
, ']');
3382 /* Prepend "[pragma " */
3383 t
= new_White(tline
);
3384 t
= new_Token(t
, TOK_ID
, "pragma", 6);
3385 t
= make_tok_char(t
, '[');
3393 /* Directive to tell NASM what the default stack size is. The
3394 * default is for a 16-bit stack, and this can be overriden with
3397 tline
= skip_white(tline
->next
);
3398 if (!tline
|| tline
->type
!= TOK_ID
) {
3399 nasm_nonfatal("`%s' missing size parameter", dname
);
3401 if (nasm_stricmp(tok_text(tline
), "flat") == 0) {
3402 /* All subsequent ARG directives are for a 32-bit stack */
3404 StackPointer
= "ebp";
3407 } else if (nasm_stricmp(tok_text(tline
), "flat64") == 0) {
3408 /* All subsequent ARG directives are for a 64-bit stack */
3410 StackPointer
= "rbp";
3413 } else if (nasm_stricmp(tok_text(tline
), "large") == 0) {
3414 /* All subsequent ARG directives are for a 16-bit stack,
3415 * far function call.
3418 StackPointer
= "bp";
3421 } else if (nasm_stricmp(tok_text(tline
), "small") == 0) {
3422 /* All subsequent ARG directives are for a 16-bit stack,
3423 * far function call. We don't support near functions.
3426 StackPointer
= "bp";
3430 nasm_nonfatal("`%s' invalid size type", dname
);
3435 /* TASM like ARG directive to define arguments to functions, in
3436 * the following form:
3438 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
3443 char directive
[256];
3444 int size
= StackSize
;
3446 /* Find the argument name */
3447 tline
= skip_white(tline
->next
);
3448 if (!tline
|| tline
->type
!= TOK_ID
) {
3449 nasm_nonfatal("`%s' missing argument parameter", dname
);
3452 arg
= tok_text(tline
);
3454 /* Find the argument size type */
3455 tline
= tline
->next
;
3456 if (!tok_is(tline
, ':')) {
3457 nasm_nonfatal("syntax error processing `%s' directive", dname
);
3460 tline
= tline
->next
;
3461 if (!tok_type(tline
, TOK_ID
)) {
3462 nasm_nonfatal("`%s' missing size type parameter", dname
);
3466 /* Allow macro expansion of type parameter */
3467 tt
= tokenize(tok_text(tline
));
3468 tt
= expand_smacro(tt
);
3469 size
= parse_size(tok_text(tt
));
3471 nasm_nonfatal("invalid size type for `%s' missing directive", dname
);
3477 /* Round up to even stack slots */
3478 size
= ALIGN(size
, StackSize
);
3480 /* Now define the macro for the argument */
3481 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
3482 arg
, StackPointer
, offset
);
3483 do_directive(tokenize(directive
), output
);
3486 /* Move to the next argument in the list */
3487 tline
= skip_white(tline
->next
);
3488 } while (tok_is(tline
, ','));
3493 /* TASM like LOCAL directive to define local variables for a
3494 * function, in the following form:
3496 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
3498 * The '= LocalSize' at the end is ignored by NASM, but is
3499 * required by TASM to define the local parameter size (and used
3500 * by the TASM macro package).
3502 offset
= LocalOffset
;
3505 char directive
[256];
3506 int size
= StackSize
;
3508 /* Find the argument name */
3509 tline
= skip_white(tline
->next
);
3510 if (!tline
|| tline
->type
!= TOK_ID
) {
3511 nasm_nonfatal("`%s' missing argument parameter", dname
);
3514 local
= tok_text(tline
);
3516 /* Find the argument size type */
3517 tline
= tline
->next
;
3518 if (!tok_is(tline
, ':')) {
3519 nasm_nonfatal("syntax error processing `%s' directive", dname
);
3522 tline
= tline
->next
;
3523 if (!tok_type(tline
, TOK_ID
)) {
3524 nasm_nonfatal("`%s' missing size type parameter", dname
);
3528 /* Allow macro expansion of type parameter */
3529 tt
= tokenize(tok_text(tline
));
3530 tt
= expand_smacro(tt
);
3531 size
= parse_size(tok_text(tt
));
3533 nasm_nonfatal("invalid size type for `%s' missing directive", dname
);
3539 /* Round up to even stack slots */
3540 size
= ALIGN(size
, StackSize
);
3542 offset
+= size
; /* Negative offset, increment before */
3544 /* Now define the macro for the argument */
3545 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
3546 local
, StackPointer
, offset
);
3547 do_directive(tokenize(directive
), output
);
3549 /* Now define the assign to setup the enter_c macro correctly */
3550 snprintf(directive
, sizeof(directive
),
3551 "%%assign %%$localsize %%$localsize+%d", size
);
3552 do_directive(tokenize(directive
), output
);
3554 /* Move to the next argument in the list */
3555 tline
= skip_white(tline
->next
);
3556 } while (tok_is(tline
, ','));
3557 LocalOffset
= offset
;
3562 nasm_warn(WARN_OTHER
, "trailing garbage after `%s' ignored", dname
);
3568 t
= tline
->next
= expand_smacro(tline
->next
);
3570 if (!t
|| (t
->type
!= TOK_STRING
&&
3571 t
->type
!= TOK_INTERNAL_STRING
)) {
3572 nasm_nonfatal("`%s' expects a file name", dname
);
3576 nasm_warn(WARN_OTHER
, "trailing garbage after `%s' ignored", dname
);
3578 strlist_add(deplist
, unquote_token_cstr(t
));
3582 t
= tline
->next
= expand_smacro(tline
->next
);
3585 if (!t
|| (t
->type
!= TOK_STRING
&&
3586 t
->type
!= TOK_INTERNAL_STRING
)) {
3587 nasm_nonfatal("`%s' expects a file name", dname
);
3591 nasm_warn(WARN_OTHER
, "trailing garbage after `%s' ignored", dname
);
3592 p
= unquote_token_cstr(t
);
3596 inc
->fp
= inc_fopen(p
, deplist
, &found_path
,
3597 (pp_mode
== PP_DEPS
)
3598 ? INC_OPTIONAL
: INC_NEEDED
, NF_TEXT
);
3600 /* -MG given but file not found */
3603 inc
->fname
= src_set_fname(found_path
? found_path
: p
);
3604 inc
->lineno
= src_set_linnum(0);
3606 inc
->nolist
= istk
->nolist
;
3608 lfmt
->uplevel(LIST_INCLUDE
, 0);
3614 const struct use_package
*pkg
;
3617 pkg
= get_use_pkg(tline
->next
, dname
, &name
);
3621 nasm_nonfatal("unknown `%s' package: `%s'", dname
, name
);
3622 } else if (!use_loaded
[pkg
->index
]) {
3624 * Not already included, go ahead and include it.
3625 * Treat it as an include file for the purpose of
3626 * producing a listing.
3628 use_loaded
[pkg
->index
] = true;
3629 stdmacpos
= pkg
->macros
;
3632 inc
->fname
= src_set_fname(NULL
);
3633 inc
->lineno
= src_set_linnum(0);
3634 inc
->nolist
= !list_option('b') || istk
->nolist
;
3636 lfmt
->uplevel(LIST_INCLUDE
, 0);
3643 tline
= tline
->next
;
3644 tline
= skip_white(tline
);
3645 tline
= expand_id(tline
);
3647 if (!tok_type(tline
, TOK_ID
)) {
3648 nasm_nonfatal("`%s' expects a context identifier", dname
);
3652 nasm_warn(WARN_OTHER
, "trailing garbage after `%s' ignored",
3654 p
= tok_text(tline
);
3656 p
= NULL
; /* Anonymous */
3659 if (op
== PP_PUSH
) {
3661 ctx
->depth
= cstk
? cstk
->depth
+ 1 : 1;
3663 ctx
->name
= p
? nasm_strdup(p
) : NULL
;
3664 ctx
->number
= unique
++;
3669 nasm_nonfatal("`%s': context stack is empty", dname
);
3670 } else if (op
== PP_POP
) {
3671 if (p
&& (!cstk
->name
|| nasm_stricmp(p
, cstk
->name
)))
3672 nasm_nonfatal("`%s' in wrong context: %s, "
3674 dname
, cstk
->name
? cstk
->name
: "anonymous", p
);
3679 nasm_free((char *)cstk
->name
);
3680 cstk
->name
= p
? nasm_strdup(p
) : NULL
;
3686 severity
= ERR_FATAL
;
3689 severity
= ERR_NONFATAL
|ERR_PASS2
;
3693 *!user [on] %warning directives
3694 *! controls output of \c{%warning} directives (see \k{pperror}).
3696 severity
= ERR_WARNING
|WARN_USER
|ERR_PASS2
;
3701 /* Only error out if this is the final pass */
3702 tline
->next
= expand_smacro(tline
->next
);
3703 tline
= tline
->next
;
3704 tline
= skip_white(tline
);
3705 t
= tline
? tline
->next
: NULL
;
3707 if (tok_type(tline
, TOK_STRING
) && !t
) {
3708 /* The line contains only a quoted string */
3709 p
= unquote_token(tline
); /* Ignore NUL character truncation */
3710 nasm_error(severity
, "%s", p
);
3712 /* Not a quoted string, or more than a quoted string */
3713 q
= detoken(tline
, false);
3714 nasm_error(severity
, "%s", q
);
3721 if (istk
->conds
&& !emitting(istk
->conds
->state
))
3724 j
= if_condition(tline
->next
, op
);
3725 tline
->next
= NULL
; /* it got freed */
3727 cond
= nasm_malloc(sizeof(Cond
));
3728 cond
->next
= istk
->conds
;
3732 istk
->mstk
.mstk
->condcnt
++;
3737 nasm_fatal("`%s': no matching `%%if'", dname
);
3738 switch(istk
->conds
->state
) {
3740 istk
->conds
->state
= COND_DONE
;
3747 case COND_ELSE_TRUE
:
3748 case COND_ELSE_FALSE
:
3749 nasm_warn(WARN_OTHER
|ERR_PP_PRECOND
,
3750 "`%%elif' after `%%else' ignored");
3751 istk
->conds
->state
= COND_NEVER
;
3756 * IMPORTANT: In the case of %if, we will already have
3757 * called expand_mmac_params(); however, if we're
3758 * processing an %elif we must have been in a
3759 * non-emitting mode, which would have inhibited
3760 * the normal invocation of expand_mmac_params().
3761 * Therefore, we have to do it explicitly here.
3763 j
= if_condition(expand_mmac_params(tline
->next
), op
);
3764 tline
->next
= NULL
; /* it got freed */
3765 istk
->conds
->state
= j
;
3772 nasm_warn(WARN_OTHER
|ERR_PP_PRECOND
,
3773 "trailing garbage after `%%else' ignored");
3775 nasm_fatal("`%%else: no matching `%%if'");
3776 switch(istk
->conds
->state
) {
3779 istk
->conds
->state
= COND_ELSE_FALSE
;
3786 istk
->conds
->state
= COND_ELSE_TRUE
;
3789 case COND_ELSE_TRUE
:
3790 case COND_ELSE_FALSE
:
3791 nasm_warn(WARN_OTHER
|ERR_PP_PRECOND
,
3792 "`%%else' after `%%else' ignored.");
3793 istk
->conds
->state
= COND_NEVER
;
3800 nasm_warn(WARN_OTHER
|ERR_PP_PRECOND
,
3801 "trailing garbage after `%%endif' ignored");
3803 nasm_fatal("`%%endif': no matching `%%if'");
3805 istk
->conds
= cond
->next
;
3808 istk
->mstk
.mstk
->condcnt
--;
3816 nasm_assert(!defining
);
3818 def
->casesense
= casesense
;
3819 def
->dstk
.mmac
= defining
;
3820 if (op
== PP_RMACRO
)
3821 def
->max_depth
= nasm_limit
[LIMIT_MACRO_LEVELS
];
3822 if (!parse_mmacro_spec(tline
, def
, dname
)) {
3828 src_get(&defining
->xline
, &defining
->fname
);
3830 mmac
= (MMacro
*) hash_findix(&mmacros
, defining
->name
);
3832 if (!strcmp(mmac
->name
, defining
->name
) &&
3833 (mmac
->nparam_min
<= defining
->nparam_max
3835 && (defining
->nparam_min
<= mmac
->nparam_max
3837 nasm_warn(WARN_OTHER
, "redefining multi-line macro `%s'",
3848 if (!(defining
&& defining
->name
)) {
3849 nasm_nonfatal("`%s': not defining a macro", tok_text(tline
));
3852 mmhead
= (MMacro
**) hash_findi_add(&mmacros
, defining
->name
);
3853 defining
->next
= *mmhead
;
3860 * We must search along istk->expansion until we hit a
3861 * macro-end marker for a macro with a name. Then we
3862 * bypass all lines between exitmacro and endmacro.
3864 list_for_each(l
, istk
->expansion
)
3865 if (l
->finishes
&& l
->finishes
->name
)
3870 * Remove all conditional entries relative to this
3871 * macro invocation. (safe to do in this context)
3873 for ( ; l
->finishes
->condcnt
> 0; l
->finishes
->condcnt
--) {
3875 istk
->conds
= cond
->next
;
3878 istk
->expansion
= l
;
3880 nasm_nonfatal("`%%exitmacro' not within `%%macro' block");
3893 spec
.casesense
= casesense
;
3894 if (!parse_mmacro_spec(tline
, &spec
, dname
)) {
3897 mmac_p
= (MMacro
**) hash_findi(&mmacros
, spec
.name
, NULL
);
3898 while (mmac_p
&& *mmac_p
) {
3900 if (mmac
->casesense
== spec
.casesense
&&
3901 !mstrcmp(mmac
->name
, spec
.name
, spec
.casesense
) &&
3902 mmac
->nparam_min
== spec
.nparam_min
&&
3903 mmac
->nparam_max
== spec
.nparam_max
&&
3904 mmac
->plus
== spec
.plus
) {
3905 *mmac_p
= mmac
->next
;
3908 mmac_p
= &mmac
->next
;
3911 free_tlist(spec
.dlist
);
3916 while (tok_white(tline
->next
))
3917 tline
= tline
->next
;
3919 free_tlist(origline
);
3920 nasm_nonfatal("`%%rotate' missing rotate count");
3921 return DIRECTIVE_FOUND
;
3923 t
= expand_smacro(tline
->next
);
3925 pps
.tptr
= tline
= t
;
3927 tokval
.t_type
= TOKEN_INVALID
;
3929 evaluate(ppscan
, &pps
, &tokval
, NULL
, true, NULL
);
3932 return DIRECTIVE_FOUND
;
3934 nasm_warn(WARN_OTHER
, "trailing garbage after expression ignored");
3935 if (!is_simple(evalresult
)) {
3936 nasm_nonfatal("non-constant value given to `%%rotate'");
3937 return DIRECTIVE_FOUND
;
3939 mmac
= istk
->mstk
.mmac
;
3941 nasm_nonfatal("`%%rotate' invoked outside a macro call");
3942 } else if (mmac
->nparam
== 0) {
3943 nasm_nonfatal("`%%rotate' invoked within macro without parameters");
3945 int rotate
= mmac
->rotate
+ reloc_value(evalresult
);
3947 rotate
%= (int)mmac
->nparam
;
3949 rotate
+= mmac
->nparam
;
3951 mmac
->rotate
= rotate
;
3957 MMacro
*tmp_defining
;
3960 tline
= skip_white(tline
->next
);
3961 if (tok_type(tline
, TOK_ID
) && tline
->len
== 7 &&
3962 !nasm_memicmp(tline
->text
.a
, ".nolist", 7)) {
3963 nolist
= !list_option('f') || istk
->nolist
;
3964 tline
= skip_white(tline
->next
);
3968 pps
.tptr
= expand_smacro(tline
);
3970 tokval
.t_type
= TOKEN_INVALID
;
3971 /* XXX: really critical?! */
3973 evaluate(ppscan
, &pps
, &tokval
, NULL
, true, NULL
);
3977 nasm_warn(WARN_OTHER
, "trailing garbage after expression ignored");
3978 if (!is_simple(evalresult
)) {
3979 nasm_nonfatal("non-constant value given to `%%rep'");
3982 count
= reloc_value(evalresult
);
3983 if (count
> nasm_limit
[LIMIT_REP
]) {
3984 nasm_nonfatal("`%%rep' count %"PRId64
" exceeds limit (currently %"PRId64
")",
3985 count
, nasm_limit
[LIMIT_REP
]);
3987 } else if (count
< 0) {
3989 *!negative-rep [on] regative %rep count
3990 *! warns about negative counts given to the \c{%rep}
3991 *! preprocessor directive.
3993 nasm_warn(ERR_PASS2
|WARN_NEGATIVE_REP
,
3994 "negative `%%rep' count: %"PRId64
, count
);
4000 nasm_nonfatal("`%%rep' expects a repeat count");
4003 tmp_defining
= defining
;
4005 defining
->nolist
= nolist
;
4006 defining
->in_progress
= count
;
4007 defining
->mstk
= istk
->mstk
;
4008 defining
->dstk
.mstk
= tmp_defining
;
4009 defining
->dstk
.mmac
= tmp_defining
? tmp_defining
->dstk
.mmac
: NULL
;
4010 src_get(&defining
->xline
, &defining
->fname
);
4015 if (!defining
|| defining
->name
) {
4016 nasm_nonfatal("`%%endrep': no matching `%%rep'");
4021 * Now we have a "macro" defined - although it has no name
4022 * and we won't be entering it in the hash tables - we must
4023 * push a macro-end marker for it on to istk->expansion.
4024 * After that, it will take care of propagating itself (a
4025 * macro-end marker line for a macro which is really a %rep
4026 * block will cause the macro to be re-expanded, complete
4027 * with another macro-end marker to ensure the process
4028 * continues) until the whole expansion is forcibly removed
4029 * from istk->expansion by a %exitrep.
4032 l
->next
= istk
->expansion
;
4033 l
->finishes
= defining
;
4035 istk
->expansion
= l
;
4037 istk
->mstk
.mstk
= defining
;
4039 lfmt
->uplevel(defining
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
, 0);
4040 defining
= defining
->dstk
.mstk
;
4045 * We must search along istk->expansion until we hit a
4046 * macro-end marker for a macro with no name. Then we set
4047 * its `in_progress' flag to 0.
4049 list_for_each(l
, istk
->expansion
)
4050 if (l
->finishes
&& !l
->finishes
->name
)
4054 l
->finishes
->in_progress
= 0;
4056 nasm_nonfatal("`%%exitrep' not within `%%rep' block");
4067 if (!(mname
= get_id(&tline
, dname
)))
4071 lastp
= &tline
->next
;
4072 nparam
= parse_smacro_template(&lastp
, &tmpl
);
4076 if (unlikely(op
== PP_DEFALIAS
)) {
4077 macro_start
= tline
;
4078 if (!is_macro_id(macro_start
)) {
4079 nasm_nonfatal("`%s' expects a macro identifier to alias",
4083 tt
= macro_start
->next
;
4084 macro_start
->next
= NULL
;
4085 tline
= tline
->next
;
4086 tline
= skip_white(tline
);
4087 if (tline
&& tline
->type
) {
4088 nasm_warn(WARN_OTHER
,
4089 "trailing garbage after aliasing identifier ignored");
4094 if (op
== PP_XDEFINE
) {
4095 /* Protect macro parameter tokens */
4097 mark_smac_params(tline
, &tmpl
, TOK_XDEF_PARAM
);
4098 tline
= expand_smacro(tline
);
4100 /* NB: Does this still make sense? */
4101 macro_start
= reverse_tokens(tline
);
4105 * Good. We now have a macro name, a parameter count, and a
4106 * token list (in reverse order) for an expansion. We ought
4107 * to be OK just to create an SMacro, store it, and let
4108 * free_tlist have the rest of the line (which we have
4109 * carefully re-terminated after chopping off the expansion
4112 define_smacro(mname
, casesense
, macro_start
, &tmpl
);
4118 if (!(mname
= get_id(&tline
, dname
)))
4121 nasm_warn(WARN_OTHER
, "trailing garbage after macro name ignored");
4123 undef_smacro(mname
, op
== PP_UNDEFALIAS
);
4127 if (!(mname
= get_id(&tline
, dname
)))
4131 tline
= expand_smacro(tline
->next
);
4134 tline
= zap_white(tline
);
4135 q
= detoken(tline
, false);
4136 macro_start
= make_tok_qstr(NULL
, q
);
4140 * We now have a macro name, an implicit parameter count of
4141 * zero, and a string token to use as an expansion. Create
4142 * and store an SMacro.
4144 define_smacro(mname
, casesense
, macro_start
, NULL
);
4148 if (!(mname
= get_id(&tline
, dname
)))
4152 tline
= expand_smacro(tline
->next
);
4155 t
= skip_white(tline
);
4156 /* t should now point to the string */
4157 if (!tok_type(t
, TOK_STRING
)) {
4158 nasm_nonfatal("`%s' requires string as second parameter", dname
);
4164 * Convert the string to a token stream. Note that smacros
4165 * are stored with the token stream reversed, so we have to
4166 * reverse the output of tokenize().
4168 macro_start
= reverse_tokens(tokenize(unquote_token_cstr(t
)));
4171 * We now have a macro name, an implicit parameter count of
4172 * zero, and a numeric token to use as an expansion. Create
4173 * and store an SMacro.
4175 define_smacro(mname
, casesense
, macro_start
, NULL
);
4181 const char *found_path
;
4183 if (!(mname
= get_id(&tline
, dname
)))
4187 tline
= expand_smacro(tline
->next
);
4190 t
= skip_white(tline
);
4191 if (!t
|| (t
->type
!= TOK_STRING
&&
4192 t
->type
!= TOK_INTERNAL_STRING
)) {
4193 nasm_nonfatal("`%s' expects a file name", dname
);
4198 nasm_warn(WARN_OTHER
, "trailing garbage after `%s' ignored", dname
);
4200 p
= unquote_token_cstr(t
);
4202 inc_fopen(p
, NULL
, &found_path
, INC_PROBE
, NF_BINARY
);
4205 macro_start
= make_tok_qstr(NULL
, found_path
);
4208 * We now have a macro name, an implicit parameter count of
4209 * zero, and a string token to use as an expansion. Create
4210 * and store an SMacro.
4212 define_smacro(mname
, casesense
, macro_start
, NULL
);
4218 if (!(mname
= get_id(&tline
, dname
)))
4222 tline
= expand_smacro(tline
->next
);
4225 t
= skip_white(tline
);
4226 /* t should now point to the string */
4227 if (!tok_type(t
, TOK_STRING
)) {
4228 nasm_nonfatal("`%s' requires string as second parameter", dname
);
4230 free_tlist(origline
);
4231 return DIRECTIVE_FOUND
;
4235 macro_start
= make_tok_num(NULL
, t
->len
);
4238 * We now have a macro name, an implicit parameter count of
4239 * zero, and a numeric token to use as an expansion. Create
4240 * and store an SMacro.
4242 define_smacro(mname
, casesense
, macro_start
, NULL
);
4244 free_tlist(origline
);
4245 return DIRECTIVE_FOUND
;
4248 if (!(mname
= get_id(&tline
, dname
)))
4252 tline
= expand_smacro(tline
->next
);
4256 list_for_each(t
, tline
) {
4258 case TOK_WHITESPACE
:
4265 if (tok_is(t
, ',')) /* permit comma separators */
4267 /* else fall through */
4269 nasm_nonfatal("non-string passed to `%s': %s", dname
,
4276 q
= qbuf
= nasm_malloc(len
+1);
4277 list_for_each(t
, tline
) {
4278 if (t
->type
== TOK_INTERNAL_STRING
)
4279 q
= mempcpy(q
, tok_text(t
), t
->len
);
4284 * We now have a macro name, an implicit parameter count of
4285 * zero, and a numeric token to use as an expansion. Create
4286 * and store an SMacro.
4288 macro_start
= make_tok_qstr_len(NULL
, qbuf
, len
);
4290 define_smacro(mname
, casesense
, macro_start
, NULL
);
4296 int64_t start
, count
;
4300 if (!(mname
= get_id(&tline
, dname
)))
4304 tline
= expand_smacro(tline
->next
);
4307 if (tline
) /* skip expanded id */
4312 /* t should now point to the string */
4313 if (!tok_type(t
, TOK_STRING
)) {
4314 nasm_nonfatal("`%s' requires string as second parameter", dname
);
4321 tokval
.t_type
= TOKEN_INVALID
;
4322 evalresult
= evaluate(ppscan
, &pps
, &tokval
, NULL
, true, NULL
);
4326 } else if (!is_simple(evalresult
)) {
4327 nasm_nonfatal("non-constant value given to `%s'", dname
);
4331 start
= evalresult
->value
- 1;
4333 pps
.tptr
= skip_white(pps
.tptr
);
4335 count
= 1; /* Backwards compatibility: one character */
4337 tokval
.t_type
= TOKEN_INVALID
;
4338 evalresult
= evaluate(ppscan
, &pps
, &tokval
, NULL
, true, NULL
);
4342 } else if (!is_simple(evalresult
)) {
4343 nasm_nonfatal("non-constant value given to `%s'", dname
);
4347 count
= evalresult
->value
;
4353 /* make start and count being in range */
4357 count
= len
+ count
+ 1 - start
;
4358 if (start
+ count
> (int64_t)len
)
4359 count
= len
- start
;
4360 if (!len
|| count
< 0 || start
>=(int64_t)len
)
4361 start
= -1, count
= 0; /* empty string */
4363 txt
= (start
< 0) ? "" : tok_text(t
) + start
;
4365 macro_start
= make_tok_qstr_len(NULL
, txt
, len
);
4368 * We now have a macro name, an implicit parameter count of
4369 * zero, and a numeric token to use as an expansion. Create
4370 * and store an SMacro.
4372 define_smacro(mname
, casesense
, macro_start
, NULL
);
4378 if (!(mname
= get_id(&tline
, dname
)))
4382 tline
= expand_smacro(tline
->next
);
4387 tokval
.t_type
= TOKEN_INVALID
;
4388 evalresult
= evaluate(ppscan
, &pps
, &tokval
, NULL
, true, NULL
);
4394 nasm_warn(WARN_OTHER
, "trailing garbage after expression ignored");
4396 if (!is_simple(evalresult
)) {
4397 nasm_nonfatal("non-constant value given to `%s'", dname
);
4398 free_tlist(origline
);
4399 return DIRECTIVE_FOUND
;
4402 macro_start
= make_tok_num(NULL
, reloc_value(evalresult
));
4405 * We now have a macro name, an implicit parameter count of
4406 * zero, and a numeric token to use as an expansion. Create
4407 * and store an SMacro.
4409 define_smacro(mname
, casesense
, macro_start
, NULL
);
4413 tline
= tline
->next
;
4414 tline
= expand_smacro(tline
);
4415 do_aliases
= pp_get_boolean_option(tline
, do_aliases
);
4420 * Syntax is `%line nnn[+mmm] [filename]'
4422 if (unlikely(pp_noline
))
4425 tline
= tline
->next
;
4426 tline
= skip_white(tline
);
4427 if (!tok_type(tline
, TOK_NUMBER
)) {
4428 nasm_nonfatal("`%s' expects line number", dname
);
4431 k
= readnum(tok_text(tline
), &err
);
4433 tline
= tline
->next
;
4434 if (tok_is(tline
, '+')) {
4435 tline
= tline
->next
;
4436 if (!tok_type(tline
, TOK_NUMBER
)) {
4437 nasm_nonfatal("`%s' expects line increment", dname
);
4440 m
= readnum(tok_text(tline
), &err
);
4441 tline
= tline
->next
;
4443 tline
= skip_white(tline
);
4447 char *fname
= detoken(tline
, false);
4448 src_set_fname(fname
);
4455 free_tlist(origline
);
4456 return DIRECTIVE_FOUND
;
4460 * Ensure that a macro parameter contains a condition code and
4461 * nothing else. Return the condition code index if so, or -1
4464 static int find_cc(Token
* t
)
4469 return -1; /* Probably a %+ without a space */
4472 if (!tok_type(t
, TOK_ID
))
4475 tt
= skip_white(tt
);
4476 if (tok_isnt(tt
, ','))
4479 return bsii(tok_text(t
), (const char **)conditions
,
4480 ARRAY_SIZE(conditions
));
4483 static inline bool pp_concat_match(const Token
*t
, unsigned int mask
)
4485 return t
&& (PP_CONCAT_MASK(t
->type
) & mask
);
4489 * This routines walks over tokens strem and handles tokens
4490 * pasting, if @handle_explicit passed then explicit pasting
4491 * term is handled, otherwise -- implicit pastings only.
4492 * The @m array can contain a series of token types which are
4493 * executed as separate passes.
4495 static bool paste_tokens(Token
**head
, const struct tokseq_match
*m
,
4496 size_t mnum
, bool handle_explicit
)
4498 Token
*tok
, *t
, *next
, **prev_next
, **prev_nonspace
;
4499 bool pasted
= false;
4504 * The last token before pasting. We need it
4505 * to be able to connect new handled tokens.
4506 * In other words if there were a tokens stream
4510 * and we've joined tokens B and C, the resulting
4516 prev_next
= prev_nonspace
= head
;
4518 if (tok_white(tok
) || tok_type(tok
, TOK_PASTE
))
4519 prev_nonspace
= NULL
;
4521 while (tok
&& (next
= tok
->next
)) {
4522 bool did_paste
= false;
4524 switch (tok
->type
) {
4525 case TOK_WHITESPACE
:
4526 /* Zap redundant whitespaces */
4527 tok
->next
= next
= zap_white(next
);
4531 /* Explicit pasting */
4532 if (!handle_explicit
)
4535 /* Left pasting token is start of line */
4536 if (!prev_nonspace
) {
4537 nasm_nonfatal("No lvalue found on pasting");
4538 tok
= delete_Token(tok
);
4544 prev_next
= prev_nonspace
;
4547 /* Delete leading whitespace */
4548 next
= zap_white(t
->next
);
4550 /* Delete the %+ token itself */
4551 nasm_assert(next
== tok
);
4552 next
= delete_Token(next
);
4554 /* Delete trailing whitespace */
4555 next
= zap_white(next
);
4558 * No ending token, this might happen in two
4561 * 1) There indeed no right token at all
4562 * 2) There is a bare "%define ID" statement,
4563 * and @ID does expand to whitespace.
4565 * So technically we need to do a grammar analysis
4566 * in another stage of parsing, but for now lets don't
4567 * change the behaviour people used to. Simply allow
4568 * whitespace after paste token.
4571 *prev_nonspace
= tok
= NULL
; /* End of line */
4575 p
= buf
= nasm_malloc(t
->len
+ next
->len
+ 1);
4576 p
= mempcpy(p
, tok_text(t
), t
->len
);
4577 p
= mempcpy(p
, tok_text(next
), next
->len
);
4585 * No output at all? Replace with a single whitespace.
4586 * This should never happen.
4588 t
= new_White(NULL
);
4591 *prev_nonspace
= tok
= t
;
4593 t
= t
->next
; /* Find the last token produced */
4595 /* Delete the second token and attach to the end of the list */
4596 t
->next
= delete_Token(next
);
4598 /* We want to restart from the head of the pasted token */
4603 /* implicit pasting */
4604 for (i
= 0; i
< mnum
; i
++) {
4605 if (pp_concat_match(tok
, m
[i
].mask_head
))
4613 while (pp_concat_match(next
, m
[i
].mask_tail
)) {
4618 /* No match or no text to process */
4619 if (len
== tok
->len
)
4622 p
= buf
= nasm_malloc(len
+ 1);
4623 while (tok
!= next
) {
4624 p
= mempcpy(p
, tok_text(tok
), tok
->len
);
4625 tok
= delete_Token(tok
);
4628 *prev_next
= tok
= t
= tokenize(buf
);
4632 * Connect pasted into original stream,
4633 * ie A -> new-tokens -> B
4638 prev_next
= prev_nonspace
= &t
->next
;
4646 prev_next
= &tok
->next
;
4647 if (next
&& next
->type
!= TOK_WHITESPACE
&& next
->type
!= TOK_PASTE
)
4648 prev_nonspace
= prev_next
;
4658 * Computes the proper rotation of mmacro parameters
4660 static int mmac_rotate(const MMacro
*mac
, unsigned int n
)
4662 if (--n
< mac
->nparam
)
4663 n
= (n
+ mac
->rotate
) % mac
->nparam
;
4669 * expands to a list of tokens from %{x:y}
4671 static Token
*expand_mmac_params_range(MMacro
*mac
, Token
*tline
, Token
***last
)
4673 Token
*t
= tline
, **tt
, *tm
, *head
;
4677 pos
= strchr(tok_text(tline
), ':');
4680 lst
= atoi(pos
+ 1);
4681 fst
= atoi(tok_text(tline
) + 1);
4684 * only macros params are accounted so
4685 * if someone passes %0 -- we reject such
4688 if (lst
== 0 || fst
== 0)
4691 /* the values should be sane */
4692 if ((fst
> (int)mac
->nparam
|| fst
< (-(int)mac
->nparam
)) ||
4693 (lst
> (int)mac
->nparam
|| lst
< (-(int)mac
->nparam
)))
4696 fst
= fst
< 0 ? fst
+ (int)mac
->nparam
+ 1: fst
;
4697 lst
= lst
< 0 ? lst
+ (int)mac
->nparam
+ 1: lst
;
4699 /* count from zero */
4703 * It will be at least one token. Note we
4704 * need to scan params until separator, otherwise
4705 * only first token will be passed.
4707 j
= (fst
+ mac
->rotate
) % mac
->nparam
;
4708 tm
= mac
->params
[j
+1];
4711 head
= dup_Token(NULL
, tm
);
4712 tt
= &head
->next
, tm
= tm
->next
;
4713 while (tok_isnt(tm
, ',')) {
4714 t
= dup_Token(NULL
, tm
);
4715 *tt
= t
, tt
= &t
->next
, tm
= tm
->next
;
4719 for (i
= fst
+ 1; i
<= lst
; i
++) {
4720 t
= make_tok_char(NULL
, ',');
4721 *tt
= t
, tt
= &t
->next
;
4722 j
= (i
+ mac
->rotate
) % mac
->nparam
;
4723 tm
= mac
->params
[j
+1];
4724 while (tok_isnt(tm
, ',')) {
4725 t
= dup_Token(NULL
, tm
);
4726 *tt
= t
, tt
= &t
->next
, tm
= tm
->next
;
4730 for (i
= fst
- 1; i
>= lst
; i
--) {
4731 t
= make_tok_char(NULL
, ',');
4732 *tt
= t
, tt
= &t
->next
;
4733 j
= (i
+ mac
->rotate
) % mac
->nparam
;
4734 tm
= mac
->params
[j
+1];
4735 while (!tok_isnt(tm
, ',')) {
4736 t
= dup_Token(NULL
, tm
);
4737 *tt
= t
, tt
= &t
->next
, tm
= tm
->next
;
4746 nasm_nonfatal("`%%{%s}': macro parameters out of range",
4747 tok_text(tline
) + 1);
4752 * Expand MMacro-local things: parameter references (%0, %n, %+n,
4753 * %-n) and MMacro-local identifiers (%%foo) as well as
4754 * macro indirection (%[...]) and range (%{..:..}).
4756 static Token
*expand_mmac_params(Token
* tline
)
4758 Token
**tail
, *thead
;
4759 bool changed
= false;
4760 MMacro
*mac
= istk
->mstk
.mmac
;
4767 bool err_not_mac
= false;
4769 const char *text
= tok_text(t
);
4772 tline
= tline
->next
;
4776 case TOK_LOCAL_SYMBOL
:
4785 text
= nasm_asprintf("..@%"PRIu64
".%s", mac
->unique
, text
+2);
4787 case TOK_MMACRO_PARAM
:
4798 if (strchr(text
, ':')) {
4800 * seems we have a parameters range here
4802 Token
*head
, **last
;
4803 head
= expand_mmac_params_range(mac
, t
, &last
);
4814 * We have to make a substitution of one of the
4815 * forms %1, %-1, %+1, %%foo, %0, %00.
4820 text
= nasm_asprintf("%d", mac
->nparam
);
4823 if (text
[2] != '0' || text
[3])
4825 /* a possible captured label == mac->params[0] */
4832 n
= strtoul(text
+ 1, &ep
, 10);
4836 if (n
<= mac
->nparam
) {
4837 n
= mmac_rotate(mac
, n
);
4838 dup_tlistn(mac
->params
[n
], mac
->paramlen
[n
], &tail
);
4850 n
= strtoul(tok_text(t
) + 2, &ep
, 10);
4854 if (n
&& n
<= mac
->nparam
) {
4855 n
= mmac_rotate(mac
, n
);
4856 tt
= mac
->params
[n
];
4860 nasm_nonfatal("macro parameter `%s' is not a condition code",
4867 if (text
[1] == '-') {
4868 int ncc
= inverse_ccs
[cc
];
4869 if (unlikely(ncc
== -1)) {
4870 nasm_nonfatal("condition code `%s' is not invertible",
4876 text
= nasm_strdup(conditions
[cc
]);
4881 nasm_nonfatal("invalid macro parameter: `%s'", text
);
4891 text
= nasm_strdup(mac
->iname
);
4898 case TOK_PREPROC_QQ
:
4901 text
= nasm_strdup(mac
->name
);
4912 tt
= tokenize(tok_text(t
));
4913 tt
= expand_mmac_params(tt
);
4914 tt
= expand_smacro(tt
);
4915 /* Why dup_tlist() here? We should own tt... */
4916 dup_tlist(tt
, &tail
);
4928 nasm_nonfatal("`%s': not in a macro call", text
);
4939 set_text(t
, text
, tok_strlen(text
));
4952 const struct tokseq_match t
[] = {
4954 PP_CONCAT_MASK(TOK_ID
) |
4955 PP_CONCAT_MASK(TOK_FLOAT
), /* head */
4956 PP_CONCAT_MASK(TOK_ID
) |
4957 PP_CONCAT_MASK(TOK_NUMBER
) |
4958 PP_CONCAT_MASK(TOK_FLOAT
) |
4959 PP_CONCAT_MASK(TOK_OTHER
) /* tail */
4962 PP_CONCAT_MASK(TOK_NUMBER
), /* head */
4963 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4966 paste_tokens(&thead
, t
, ARRAY_SIZE(t
), false);
4972 static Token
*expand_smacro_noreset(Token
* tline
);
4975 * Expand *one* single-line macro instance. If the first token is not
4976 * a macro at all, it is simply copied to the output and the pointer
4977 * advanced. tpp should be a pointer to a pointer (usually the next
4978 * pointer of the previous token) to the first token. **tpp is updated
4979 * to point to the first token of the expansion, and *tpp updated to
4980 * point to the next pointer of the last token of the expansion.
4982 * If the expansion is empty, *tpp will be unchanged but **tpp will
4983 * be advanced past the macro call.
4985 * Return the macro expanded, or NULL if no expansion took place.
4987 static SMacro
*expand_one_smacro(Token
***tpp
)
4989 Token
**params
= NULL
;
4991 Token
*mstart
= **tpp
;
4992 Token
*tline
= mstart
;
4995 Token
*t
, *tup
, *tafter
;
5000 return false; /* Empty line, nothing to do */
5002 mname
= tok_text(mstart
);
5004 smacro_deadman
.total
--;
5005 smacro_deadman
.levels
--;
5007 if (unlikely(smacro_deadman
.total
< 0 || smacro_deadman
.levels
< 0)) {
5008 if (unlikely(!smacro_deadman
.triggered
)) {
5009 nasm_nonfatal("interminable macro recursion");
5010 smacro_deadman
.triggered
= true;
5013 } else if (tline
->type
== TOK_ID
|| tline
->type
== TOK_PREPROC_ID
) {
5014 head
= (SMacro
*)hash_findix(&smacros
, mname
);
5015 } else if (tline
->type
== TOK_LOCAL_MACRO
) {
5016 Context
*ctx
= get_ctx(mname
, &mname
);
5017 head
= ctx
? (SMacro
*)hash_findix(&ctx
->localmac
, mname
) : NULL
;
5023 * We've hit an identifier of some sort. First check whether the
5024 * identifier is a single-line macro at all, then think about
5025 * checking for parameters if necessary.
5027 list_for_each(m
, head
) {
5028 if (unlikely(m
->alias
&& !do_aliases
))
5030 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
5038 /* Parse parameters, if applicable */
5043 if (m
->nparam
== 0) {
5045 * Simple case: the macro is parameterless.
5046 * Nothing to parse; the expansion code will
5047 * drop the macro name token.
5051 * Complicated case: at least one macro with this name
5052 * exists and takes parameters. We must find the
5053 * parameters in the call, count them, find the SMacro
5054 * that corresponds to that form of the macro call, and
5055 * substitute for the parameters when we expand. What a
5059 int paren
, brackets
;
5061 tline
= tline
->next
;
5062 tline
= skip_white(tline
);
5063 if (!tok_is(tline
, '(')) {
5065 * This macro wasn't called with parameters: ignore
5066 * the call. (Behaviour borrowed from gnu cpp.)
5074 t
= tline
; /* tline points to leading ( */
5080 nasm_nonfatal("macro call expects terminating `)'");
5084 if (t
->type
!= TOK_OTHER
|| t
->len
!= 1)
5087 switch (t
->text
.a
[0]) {
5113 break; /* Normal token */
5118 * Look for a macro matching in both name and parameter count.
5119 * We already know any matches cannot be anywhere before the
5120 * current position of "m", so there is no reason to
5126 *!macro-params-single [on] single-line macro calls with wrong parameter count
5127 *! warns about \i{single-line macros} being invoked
5128 *! with the wrong number of parameters.
5130 nasm_warn(WARN_MACRO_PARAMS_SINGLE
|ERR_HOLD
,
5131 "single-line macro `%s' exists, "
5132 "but not taking %d parameter%s",
5133 mname
, nparam
, (nparam
== 1) ? "" : "s");
5137 if (!mstrcmp(m
->name
, mname
, m
->casesense
)) {
5138 if (nparam
== m
->nparam
)
5139 break; /* It's good */
5140 if (m
->greedy
&& nparam
>= m
->nparam
-1)
5141 break; /* Also good */
5150 /* Expand the macro */
5151 m
->in_progress
= true;
5154 /* Extract parameters */
5155 Token
**phead
, **pep
;
5159 bool bracketed
= false;
5160 bool bad_bracket
= false;
5161 enum sparmflags flags
;
5165 nasm_newn(params
, nparam
);
5167 flags
= m
->params
[i
].flags
;
5168 phead
= pep
= ¶ms
[i
];
5175 tline
= tline
->next
;
5178 nasm_nonfatal("macro call expects terminating `)'");
5184 switch (tline
->type
) {
5186 if (tline
->len
== 1)
5187 ch
= tline
->text
.a
[0];
5190 case TOK_WHITESPACE
:
5191 if (!(flags
& SPARM_NOSTRIP
)) {
5192 if (brackets
|| *phead
)
5193 white
++; /* Keep interior whitespace */
5204 if (!brackets
&& !(flags
& SPARM_GREEDY
)) {
5206 nasm_assert(i
< nparam
);
5207 phead
= pep
= ¶ms
[i
];
5211 flags
= m
->params
[i
].flags
;
5217 bracketed
= !*phead
&& !(flags
& SPARM_NOSTRIP
);
5240 i
++; /* Found last argument */
5246 break; /* Normal token */
5252 bad_bracket
|= bracketed
&& !brackets
;
5255 *pep
= t
= new_White(NULL
);
5259 *pep
= t
= dup_Token(NULL
, tline
);
5265 * Possible further processing of parameters. Note that the
5266 * ordering matters here.
5268 for (i
= 0; i
< nparam
; i
++) {
5269 enum sparmflags flags
= m
->params
[i
].flags
;
5271 if (flags
& SPARM_EVAL
) {
5272 /* Evaluate this parameter as a number */
5274 struct tokenval tokval
;
5278 pps
.tptr
= eval_param
= expand_smacro_noreset(params
[i
]);
5280 tokval
.t_type
= TOKEN_INVALID
;
5281 evalresult
= evaluate(ppscan
, &pps
, &tokval
, NULL
, true, NULL
);
5283 free_tlist(eval_param
);
5287 /* Nothing meaningful to do */
5288 } else if (tokval
.t_type
) {
5289 nasm_nonfatal("invalid expression in parameter %d of macro `%s'", i
, m
->name
);
5290 } else if (!is_simple(evalresult
)) {
5291 nasm_nonfatal("non-constant expression in parameter %d of macro `%s'", i
, m
->name
);
5293 params
[i
] = make_tok_num(NULL
, reloc_value(evalresult
));
5297 if (flags
& SPARM_STR
) {
5298 /* Convert expansion to a quoted string */
5302 qs
= expand_smacro_noreset(params
[i
]);
5303 arg
= detoken(qs
, false);
5305 params
[i
] = make_tok_qstr(NULL
, arg
);
5311 /* Note: we own the expansion this returns. */
5312 t
= m
->expand(m
, params
, nparam
);
5314 tafter
= tline
->next
; /* Skip past the macro call */
5315 tline
->next
= NULL
; /* Truncate list at the macro call end */
5322 enum pp_token_type type
= t
->type
;
5323 Token
*tnext
= t
->next
;
5328 t
= dup_Token(tline
, mstart
);
5331 case TOK_PREPROC_QQ
:
5333 size_t mlen
= strlen(m
->name
);
5337 t
->type
= mstart
->type
;
5338 if (t
->type
== TOK_LOCAL_MACRO
) {
5339 const char *psp
; /* prefix start pointer */
5340 const char *pep
; /* prefix end pointer */
5343 psp
= tok_text(mstart
);
5348 p
= nasm_malloc(len
+ 1);
5349 p
= mempcpy(p
, psp
, plen
);
5352 p
= nasm_malloc(len
+ 1);
5354 p
= mempcpy(p
, m
->name
, mlen
);
5356 set_text_free(t
, p
, len
);
5362 case TOK_COND_COMMA
:
5364 t
= cond_comma
? make_tok_char(tline
, ',') : NULL
;
5368 case TOK_PREPROC_ID
:
5369 case TOK_LOCAL_MACRO
:
5372 * Chain this into the target line *before* expanding,
5373 * that way we pick up any arguments to the new macro call,
5378 expand_one_smacro(&tp
);
5379 tline
= *tp
; /* First token left after any macro call */
5383 if (is_smac_param(t
->type
)) {
5384 int param
= smac_nparam(t
->type
);
5385 nasm_assert(!tup
&& param
< nparam
);
5389 tnext
= dup_tlist_reverse(params
[param
], NULL
);
5397 Token
*endt
= tline
;
5400 while (!cond_comma
&& t
&& t
!= endt
) {
5401 cond_comma
= t
->type
!= TOK_WHITESPACE
;
5415 for (t
= tline
; t
&& t
!= tafter
; t
= t
->next
)
5418 m
->in_progress
= false;
5420 /* Don't do this until after expansion or we will clobber mname */
5425 * No macro expansion needed; roll back to mstart (if necessary)
5426 * and then advance to the next input token. Note that this is
5427 * by far the common case!
5430 *tpp
= &mstart
->next
;
5433 smacro_deadman
.levels
++;
5434 if (unlikely(params
))
5435 free_tlist_array(params
, nparam
);
5440 * Expand all single-line macro calls made in the given line.
5441 * Return the expanded version of the line. The original is deemed
5442 * to be destroyed in the process. (In reality we'll just move
5443 * Tokens from input to output a lot of the time, rather than
5444 * actually bothering to destroy and replicate.)
5446 static Token
*expand_smacro(Token
*tline
)
5448 smacro_deadman
.total
= nasm_limit
[LIMIT_MACRO_TOKENS
];
5449 smacro_deadman
.levels
= nasm_limit
[LIMIT_MACRO_LEVELS
];
5450 smacro_deadman
.triggered
= false;
5451 return expand_smacro_noreset(tline
);
5454 static Token
*expand_smacro_noreset(Token
*org_tline
)
5458 errhold errhold
; /* Hold warning/errors during expansion */
5461 return NULL
; /* Empty input */
5464 * Trick: we should avoid changing the start token pointer since it can
5465 * be contained in "next" field of other token. Because of this
5466 * we allocate a copy of first token and work with it; at the end of
5467 * routine we copy it back
5469 tline
= dup_Token(org_tline
->next
, org_tline
);
5472 * Pretend that we always end up doing expansion on the first pass;
5473 * that way %+ get processed. However, if we process %+ before the
5474 * first pass, we end up with things like MACRO %+ TAIL trying to
5475 * look up the macro "MACROTAIL", which we don't want.
5480 static const struct tokseq_match tmatch
[] = {
5482 PP_CONCAT_MASK(TOK_ID
) |
5483 PP_CONCAT_MASK(TOK_LOCAL_MACRO
) |
5484 PP_CONCAT_MASK(TOK_ENVIRON
) |
5485 PP_CONCAT_MASK(TOK_PREPROC_ID
), /* head */
5486 PP_CONCAT_MASK(TOK_ID
) |
5487 PP_CONCAT_MASK(TOK_LOCAL_MACRO
) |
5488 PP_CONCAT_MASK(TOK_ENVIRON
) |
5489 PP_CONCAT_MASK(TOK_PREPROC_ID
) |
5490 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
5493 Token
**tail
= &tline
;
5494 errhold
= nasm_error_hold_push();
5497 * We hold warnings/errors until we are done this this loop. It is
5498 * possible for nuisance warnings to appear that disappear on later
5501 errhold
= nasm_error_hold_push();
5502 while (*tail
) /* main token loop */
5503 expanded
|= !!expand_one_smacro(&tail
);
5509 * Now scan the entire line and look for successive TOK_IDs
5510 * that resulted after expansion (they can't be produced by
5511 * tokenize()). The successive TOK_IDs should be concatenated.
5512 * Also we look for %+ tokens and concatenate the tokens
5513 * before and after them (without white spaces in between).
5515 if (!paste_tokens(&tline
, tmatch
, ARRAY_SIZE(tmatch
), true))
5516 break; /* Done again! */
5519 nasm_error_hold_pop(errhold
, false);
5521 nasm_error_hold_pop(errhold
, true);
5525 * The expression expanded to empty line;
5526 * we can't return NULL because of the "trick" above.
5527 * Just set the line to a single WHITESPACE token.
5530 tline
= new_White(NULL
);
5533 steal_Token(org_tline
, tline
);
5534 org_tline
->next
= tline
->next
;
5535 delete_Token(tline
);
5541 * Similar to expand_smacro but used exclusively with macro identifiers
5542 * right before they are fetched in. The reason is that there can be
5543 * identifiers consisting of several subparts. We consider that if there
5544 * are more than one element forming the name, user wants a expansion,
5545 * otherwise it will be left as-is. Example:
5549 * the identifier %$abc will be left as-is so that the handler for %define
5550 * will suck it and define the corresponding value. Other case:
5552 * %define _%$abc cde
5554 * In this case user wants name to be expanded *before* %define starts
5555 * working, so we'll expand %$abc into something (if it has a value;
5556 * otherwise it will be left as-is) then concatenate all successive
5559 static Token
*expand_id(Token
* tline
)
5561 Token
*cur
, *oldnext
= NULL
;
5563 if (!tline
|| !tline
->next
)
5568 (cur
->next
->type
== TOK_ID
|| cur
->next
->type
== TOK_PREPROC_ID
||
5569 cur
->next
->type
== TOK_LOCAL_MACRO
|| cur
->next
->type
== TOK_NUMBER
))
5572 /* If identifier consists of just one token, don't expand */
5577 oldnext
= cur
->next
; /* Detach the tail past identifier */
5578 cur
->next
= NULL
; /* so that expand_smacro stops here */
5581 tline
= expand_smacro(tline
);
5584 /* expand_smacro possibly changhed tline; re-scan for EOL */
5586 while (cur
&& cur
->next
)
5589 cur
->next
= oldnext
;
5596 * Determine whether the given line constitutes a multi-line macro
5597 * call, and return the MMacro structure called if so. Doesn't have
5598 * to check for an initial label - that's taken care of in
5599 * expand_mmacro - but must check numbers of parameters. Guaranteed
5600 * to be called with tline->type == TOK_ID, so the putative macro
5601 * name is easy to find.
5603 static MMacro
*is_mmacro(Token
* tline
, int *nparamp
, Token
***params_array
)
5608 const char *finding
= tok_text(tline
);
5610 head
= (MMacro
*) hash_findix(&mmacros
, finding
);
5613 * Efficiency: first we see if any macro exists with the given
5614 * name which isn't already excluded by macro cycle removal.
5615 * (The cycle removal test here helps optimize the case of wrapping
5616 * instructions, and is cheap to do here.)
5618 * If not, we can return NULL immediately. _Then_ we
5619 * count the parameters, and then we look further along the
5620 * list if necessary to find the proper MMacro.
5622 list_for_each(m
, head
) {
5623 if (!mstrcmp(m
->name
, finding
, m
->casesense
) &&
5624 (m
->in_progress
!= 1 || m
->max_depth
> 0))
5625 break; /* Found something that needs consideration */
5631 * OK, we have a potential macro. Count and demarcate the
5634 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
5637 * So we know how many parameters we've got. Find the MMacro
5638 * structure that handles this number.
5641 if (m
->nparam_min
<= nparam
5642 && (m
->plus
|| nparam
<= m
->nparam_max
)) {
5644 * This one is right. Just check if cycle removal
5645 * prohibits us using it before we actually celebrate...
5647 if (m
->in_progress
> m
->max_depth
) {
5648 if (m
->max_depth
> 0) {
5649 nasm_warn(WARN_OTHER
, "reached maximum recursion depth of %i",
5656 * It's right, and we can use it. Add its default
5657 * parameters to the end of our list if necessary.
5659 if (m
->defaults
&& nparam
< m
->nparam_min
+ m
->ndefs
) {
5660 int newnparam
= m
->nparam_min
+ m
->ndefs
;
5661 params
= nasm_realloc(params
, sizeof(*params
) * (newnparam
+2));
5662 memcpy(¶ms
[nparam
+1], &m
->defaults
[nparam
+1-m
->nparam_min
],
5663 (newnparam
- nparam
) * sizeof(*params
));
5667 * If we've gone over the maximum parameter count (and
5668 * we're in Plus mode), ignore parameters beyond
5671 if (m
->plus
&& nparam
> m
->nparam_max
)
5672 nparam
= m
->nparam_max
;
5675 * If nparam was adjusted above, make sure the list is still
5678 params
[nparam
+1] = NULL
;
5681 *params_array
= params
;
5686 * This one wasn't right: look for the next one with the
5689 list_for_each(m
, m
->next
)
5690 if (!mstrcmp(m
->name
, tok_text(tline
), m
->casesense
))
5695 * After all that, we didn't find one with the right number of
5696 * parameters. Issue a warning, and fail to expand the macro.
5698 *!macro-params-multi [on] multi-line macro calls with wrong parameter count
5699 *! warns about \i{multi-line macros} being invoked
5700 *! with the wrong number of parameters. See \k{mlmacover} for an
5701 *! example of why you might want to disable this warning.
5703 nasm_warn(WARN_MACRO_PARAMS_MULTI
,
5704 "multi-line macro `%s' exists, but not taking %d parameter%s",
5705 tok_text(tline
), nparam
, (nparam
== 1) ? "" : "s");
5714 * Save MMacro invocation specific fields in
5715 * preparation for a recursive macro expansion
5717 static void push_mmacro(MMacro
*m
)
5719 MMacroInvocation
*i
;
5721 i
= nasm_malloc(sizeof(MMacroInvocation
));
5723 i
->params
= m
->params
;
5724 i
->iline
= m
->iline
;
5725 i
->nparam
= m
->nparam
;
5726 i
->rotate
= m
->rotate
;
5727 i
->paramlen
= m
->paramlen
;
5728 i
->unique
= m
->unique
;
5729 i
->condcnt
= m
->condcnt
;
5735 * Restore MMacro invocation specific fields that were
5736 * saved during a previous recursive macro expansion
5738 static void pop_mmacro(MMacro
*m
)
5740 MMacroInvocation
*i
;
5745 m
->params
= i
->params
;
5746 m
->iline
= i
->iline
;
5747 m
->nparam
= i
->nparam
;
5748 m
->rotate
= i
->rotate
;
5749 m
->paramlen
= i
->paramlen
;
5750 m
->unique
= i
->unique
;
5751 m
->condcnt
= i
->condcnt
;
5759 * List an mmacro call with arguments (-Lm option)
5761 static void list_mmacro_call(const MMacro
*m
)
5763 const char prefix
[] = " ;;; [macro] ";
5764 size_t namelen
, size
;
5769 namelen
= strlen(m
->iname
);
5770 size
= namelen
+ sizeof(prefix
); /* Includes final null (from prefix) */
5772 for (i
= 1; i
<= m
->nparam
; i
++) {
5774 size
+= 3; /* Braces and space/comma */
5775 list_for_each(t
, m
->params
[i
]) {
5776 if (j
++ >= m
->paramlen
[i
])
5778 size
+= (t
->type
== TOK_WHITESPACE
) ? 1 : t
->len
;
5782 buf
= p
= nasm_malloc(size
);
5783 p
= mempcpy(p
, prefix
, sizeof(prefix
) - 1);
5784 p
= mempcpy(p
, m
->iname
, namelen
);
5787 for (i
= 1; i
<= m
->nparam
; i
++) {
5790 list_for_each(t
, m
->params
[i
]) {
5791 if (j
++ >= m
->paramlen
[i
])
5793 p
= mempcpy(p
, tok_text(t
), t
->len
);
5799 *--p
= '\0'; /* Replace last delimeter with null */
5800 lfmt
->line(LIST_MACRO
, -1, buf
);
5805 * Expand the multi-line macro call made by the given line, if
5806 * there is one to be expanded. If there is, push the expansion on
5807 * istk->expansion and return 1. Otherwise return 0.
5809 static int expand_mmacro(Token
* tline
)
5811 Token
*startline
= tline
;
5812 Token
*label
= NULL
;
5813 bool dont_prepend
= false;
5814 Token
**params
, *t
, *tt
;
5823 /* if (!tok_type(t, TOK_ID)) Lino 02/25/02 */
5824 if (!tok_type(t
, TOK_ID
) && !tok_type(t
, TOK_LOCAL_MACRO
))
5826 m
= is_mmacro(t
, &nparam
, ¶ms
);
5828 mname
= tok_text(t
);
5832 * We have an id which isn't a macro call. We'll assume
5833 * it might be a label; we'll also check to see if a
5834 * colon follows it. Then, if there's another id after
5835 * that lot, we'll check it again for macro-hood.
5840 last
= t
, t
= t
->next
;
5841 if (tok_is(t
, ':')) {
5842 dont_prepend
= true;
5843 last
= t
, t
= t
->next
;
5845 last
= t
, t
= t
->next
;
5847 if (!tok_type(t
, TOK_ID
) || !(m
= is_mmacro(t
, &nparam
, ¶ms
)))
5850 mname
= tok_text(t
);
5854 if (unlikely(mmacro_deadman
.total
>= nasm_limit
[LIMIT_MMACROS
] ||
5855 mmacro_deadman
.levels
>= nasm_limit
[LIMIT_MACRO_LEVELS
])) {
5856 if (!mmacro_deadman
.triggered
) {
5857 nasm_nonfatal("interminable multiline macro recursion");
5858 mmacro_deadman
.triggered
= true;
5863 mmacro_deadman
.total
++;
5864 mmacro_deadman
.levels
++;
5867 * Fix up the parameters: this involves stripping leading and
5868 * trailing whitespace, then stripping braces if they are
5871 nasm_newn(paramlen
, nparam
+1);
5873 nasm_assert(params
[nparam
+1] == NULL
);
5875 for (i
= 1; (t
= params
[i
]); i
++) {
5876 bool braced
= false;
5879 bool comma
= !m
->plus
|| i
< nparam
;
5882 if (tok_is(t
, '{')) {
5890 for (; t
; t
= t
->next
) {
5896 if (t
->type
== TOK_OTHER
&& t
->len
== 1) {
5897 switch (t
->text
.a
[0]) {
5899 if (comma
&& !brace
)
5909 if (braced
&& !brace
) {
5910 paramlen
[i
] += white
;
5920 paramlen
[i
] += white
+ 1;
5928 * OK, we have a MMacro structure together with a set of
5929 * parameters. We must now go through the expansion and push
5930 * copies of each Line on to istk->expansion. Substitution of
5931 * parameter tokens and macro-local tokens doesn't get done
5932 * until the single-line macro substitution process; this is
5933 * because delaying them allows us to change the semantics
5934 * later through %rotate and give the right semantics for
5937 * First, push an end marker on to istk->expansion, mark this
5938 * macro as in progress, and set up its invocation-specific
5942 ll
->next
= istk
->expansion
;
5944 istk
->expansion
= ll
;
5947 * Save the previous MMacro expansion in the case of
5951 if (m
->max_depth
&& m
->in_progress
)
5958 m
->iname
= nasm_strdup(mname
);
5961 m
->paramlen
= paramlen
;
5962 m
->unique
= unique
++;
5966 m
->mstk
= istk
->mstk
;
5967 istk
->mstk
.mstk
= istk
->mstk
.mmac
= m
;
5969 list_for_each(l
, m
->expansion
) {
5971 ll
->next
= istk
->expansion
;
5972 istk
->expansion
= ll
;
5973 ll
->first
= dup_tlist(l
->first
, NULL
);
5977 * If we had a label, and this macro definition does not include
5978 * a %00, push it on as the first line of, ot
5979 * the macro expansion.
5983 * We had a label. If this macro contains an %00 parameter,
5984 * save the value as a special parameter (which is what it
5985 * is), otherwise push it as the first line of the macro
5988 if (m
->capture_label
) {
5989 params
[0] = dup_Token(NULL
, label
);
5991 free_tlist(startline
);
5994 ll
->finishes
= NULL
;
5995 ll
->next
= istk
->expansion
;
5996 istk
->expansion
= ll
;
5997 ll
->first
= startline
;
5998 if (!dont_prepend
) {
6000 label
= label
->next
;
6001 label
->next
= tt
= make_tok_char(NULL
, ':');
6006 lfmt
->uplevel(m
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
, 0);
6008 if (list_option('m') && !m
->nolist
)
6009 list_mmacro_call(m
);
6015 * This function decides if an error message should be suppressed.
6016 * It will never be called with a severity level of ERR_FATAL or
6019 static bool pp_suppress_error(errflags severity
)
6022 * If we're in a dead branch of IF or something like it, ignore the error.
6023 * However, because %else etc are evaluated in the state context
6024 * of the previous branch, errors might get lost:
6025 * %if 0 ... %else trailing garbage ... %endif
6026 * So %else etc should set the ERR_PP_PRECOND flag.
6028 if (istk
&& istk
->conds
&&
6029 ((severity
& ERR_PP_PRECOND
) ?
6030 istk
->conds
->state
== COND_NEVER
:
6031 !emitting(istk
->conds
->state
)))
6038 stdmac_file(const SMacro
*s
, Token
**params
, int nparams
)
6044 return make_tok_qstr(NULL
, src_get_fname());
6048 stdmac_line(const SMacro
*s
, Token
**params
, int nparams
)
6054 return make_tok_num(NULL
, src_get_linnum());
6058 stdmac_bits(const SMacro
*s
, Token
**params
, int nparams
)
6064 return make_tok_num(NULL
, globalbits
);
6068 stdmac_ptr(const SMacro
*s
, Token
**params
, int nparams
)
6074 switch (globalbits
) {
6076 return new_Token(NULL
, TOK_ID
, "word", 4);
6078 return new_Token(NULL
, TOK_ID
, "dword", 5);
6080 return new_Token(NULL
, TOK_ID
, "qword", 5);
6086 /* Add magic standard macros */
6087 struct magic_macros
{
6092 static const struct magic_macros magic_macros
[] =
6094 { "__?FILE?__", 0, stdmac_file
},
6095 { "__?LINE?__", 0, stdmac_line
},
6096 { "__?BITS?__", 0, stdmac_bits
},
6097 { "__?PTR?__", 0, stdmac_ptr
},
6101 static void pp_add_magic_stdmac(void)
6103 const struct magic_macros
*m
;
6108 for (m
= magic_macros
; m
->name
; m
++) {
6109 tmpl
.nparam
= m
->nparam
;
6110 tmpl
.expand
= m
->func
;
6111 define_smacro(m
->name
, true, NULL
, &tmpl
);
6116 pp_reset(const char *file
, enum preproc_mode mode
, struct strlist
*dep_list
)
6119 struct Include
*inc
;
6123 nested_mac_count
= 0;
6124 nested_rep_count
= 0;
6132 use_loaded
= nasm_malloc(use_package_count
* sizeof(bool));
6133 memset(use_loaded
, 0, use_package_count
* sizeof(bool));
6135 /* First set up the top level input file */
6137 istk
->fp
= nasm_open_read(file
, NF_TEXT
);
6141 nasm_fatalf(ERR_NOFILE
, "unable to open input file `%s'", file
);
6143 strlist_add(deplist
, file
);
6146 * Set up the stdmac packages as a virtual include file,
6147 * indicated by a null file pointer.
6151 inc
->fname
= src_set_fname(NULL
);
6152 inc
->nolist
= !list_option('b');
6154 lfmt
->uplevel(LIST_INCLUDE
, 0);
6156 pp_add_magic_stdmac();
6158 if (tasm_compatible_mode
)
6159 pp_add_stdmac(nasm_stdmac_tasm
);
6161 pp_add_stdmac(nasm_stdmac_nasm
);
6162 pp_add_stdmac(nasm_stdmac_version
);
6165 pp_add_stdmac(extrastdmac
);
6167 stdmacpos
= stdmacros
[0];
6168 stdmacnext
= &stdmacros
[1];
6173 * Define the __?PASS?__ macro. This is defined here unlike all the
6174 * other builtins, because it is special -- it varies between
6175 * passes -- but there is really no particular reason to make it
6178 * 0 = dependencies only
6179 * 1 = preparatory passes
6181 * 3 = preproces only
6185 apass
= pass_final() ? 2 : 1;
6197 define_smacro("__?PASS?__", true, make_tok_num(NULL
, apass
), NULL
);
6200 static void pp_init(void)
6205 * Get a line of tokens. If we popped the macro expansion/include stack,
6206 * we return a pointer to the dummy token tok_pop; at that point if
6207 * istk is NULL then we have reached end of input;
6209 static Token tok_pop
; /* Dummy token placeholder */
6211 static Token
*pp_tokline(void)
6214 Line
*l
= istk
->expansion
;
6215 Token
*tline
= NULL
;
6219 * Fetch a tokenized line, either from the macro-expansion
6220 * buffer or from the input file.
6223 while (l
&& l
->finishes
) {
6224 MMacro
*fm
= l
->finishes
;
6226 if (!fm
->name
&& fm
->in_progress
> 1) {
6228 * This is a macro-end marker for a macro with no
6229 * name, which means it's not really a macro at all
6230 * but a %rep block, and the `in_progress' field is
6231 * more than 1, meaning that we still need to
6232 * repeat. (1 means the natural last repetition; 0
6233 * means termination by %exitrep.) We have
6234 * therefore expanded up to the %endrep, and must
6235 * push the whole block on to the expansion buffer
6236 * again. We don't bother to remove the macro-end
6237 * marker: we'd only have to generate another one
6241 list_for_each(l
, fm
->expansion
) {
6242 Token
*t
, *tt
, **tail
;
6245 istk
->mstk
.mstk
->lineno
= 0;
6247 ll
->next
= istk
->expansion
;
6250 list_for_each(t
, l
->first
) {
6252 tt
= *tail
= dup_Token(NULL
, t
);
6256 istk
->expansion
= ll
;
6260 MMacro
*m
= istk
->mstk
.mstk
;
6263 * Check whether a `%rep' was started and not ended
6264 * within this macro expansion. This can happen and
6265 * should be detected. It's a fatal error because
6266 * I'm too confused to work out how to recover
6271 nasm_panic("defining with name in expansion");
6273 nasm_fatal("`%%rep' without `%%endrep' within"
6274 " expansion of macro `%s'", m
->name
);
6278 * FIXME: investigate the relationship at this point between
6279 * istk->mstk.mstk and fm
6281 istk
->mstk
= m
->mstk
;
6284 * This was a real macro call, not a %rep, and
6285 * therefore the parameter information needs to
6286 * be freed and the iteration count/nesting
6290 if (!--mmacro_deadman
.levels
) {
6292 * If all mmacro processing done,
6293 * clear all counters and the deadman
6296 nasm_zero(mmacro_deadman
); /* Clear all counters */
6306 nasm_free(m
->params
);
6307 free_tlist(m
->iline
);
6308 nasm_free(m
->paramlen
);
6309 fm
->in_progress
= 0;
6314 * FIXME It is incorrect to always free_mmacro here.
6315 * It leads to usage-after-free.
6317 * https://bugzilla.nasm.us/show_bug.cgi?id=3392414
6324 istk
->expansion
= l
->next
;
6326 lfmt
->downlevel(LIST_MACRO
);
6330 do { /* until we get a line we can use */
6333 if (istk
->expansion
) { /* from a macro expansion */
6334 Line
*l
= istk
->expansion
;
6337 if (istk
->mstk
.mstk
) {
6338 istk
->mstk
.mstk
->lineno
++;
6339 if (istk
->mstk
.mstk
->fname
)
6340 lineno
= istk
->mstk
.mstk
->lineno
+
6341 istk
->mstk
.mstk
->xline
;
6343 lineno
= 0; /* Defined at init time or builtin */
6345 lineno
= src_get_linnum();
6349 istk
->expansion
= l
->next
;
6352 line
= detoken(tline
, false);
6354 lfmt
->line(LIST_MACRO
, lineno
, line
);
6356 } else if ((line
= read_line())) {
6357 line
= prepreproc(line
);
6358 tline
= tokenize(line
);
6362 * The current file has ended; work down the istk
6368 /* nasm_error can't be conditionally suppressed */
6369 nasm_fatal("expected `%%endif' before end of file");
6371 /* only set line and file name if there's a next node */
6373 src_set(i
->lineno
, i
->fname
);
6375 lfmt
->downlevel(LIST_INCLUDE
);
6382 * We must expand MMacro parameters and MMacro-local labels
6383 * _before_ we plunge into directive processing, to cope
6384 * with things like `%define something %1' such as STRUC
6385 * uses. Unless we're _defining_ a MMacro, in which case
6386 * those tokens should be left alone to go into the
6387 * definition; and unless we're in a non-emitting
6388 * condition, in which case we don't want to meddle with
6391 if (!defining
&& !(istk
->conds
&& !emitting(istk
->conds
->state
))
6392 && !(istk
->mstk
.mstk
&& !istk
->mstk
.mstk
->in_progress
)) {
6393 tline
= expand_mmac_params(tline
);
6397 * Check the line to see if it's a preprocessor directive.
6399 if (do_directive(tline
, &dtline
) == DIRECTIVE_FOUND
) {
6402 } else if (defining
) {
6404 * We're defining a multi-line macro. We emit nothing
6406 * shove the tokenized line on to the macro definition.
6408 MMacro
*mmac
= defining
->dstk
.mmac
;
6410 Line
*l
= nasm_malloc(sizeof(Line
));
6411 l
->next
= defining
->expansion
;
6414 defining
->expansion
= l
;
6417 * Remember if this mmacro expansion contains %00:
6418 * if it does, we will have to handle leading labels
6423 list_for_each(t
, tline
) {
6424 if (!memcmp(t
->text
.a
, "%00", 4))
6425 mmac
->capture_label
= true;
6428 } else if (istk
->conds
&& !emitting(istk
->conds
->state
)) {
6430 * We're in a non-emitting branch of a condition block.
6431 * Emit nothing at all, not even a blank line: when we
6432 * emerge from the condition we'll give a line-number
6433 * directive so we keep our place correctly.
6436 } else if (istk
->mstk
.mstk
&& !istk
->mstk
.mstk
->in_progress
) {
6438 * We're in a %rep block which has been terminated, so
6439 * we're walking through to the %endrep without
6440 * emitting anything. Emit nothing at all, not even a
6441 * blank line: when we emerge from the %rep block we'll
6442 * give a line-number directive so we keep our place
6447 tline
= expand_smacro(tline
);
6448 if (!expand_mmacro(tline
))
6454 static char *pp_getline(void)
6460 tline
= pp_tokline();
6461 if (tline
== &tok_pop
) {
6463 * We popped the macro/include stack. If istk is empty,
6464 * we are at end of input, otherwise just loop back.
6470 * De-tokenize the line and emit it.
6472 line
= detoken(tline
, true);
6478 if (list_option('e') && istk
&& !istk
->nolist
&& line
&& line
[0]) {
6479 char *buf
= nasm_strcat(" ;;; ", line
);
6480 lfmt
->line(LIST_MACRO
, -1, buf
);
6487 static void pp_cleanup_pass(void)
6490 if (defining
->name
) {
6491 nasm_nonfatal("end of file while still defining macro `%s'",
6494 nasm_nonfatal("end of file while still in %%rep");
6497 free_mmacro(defining
);
6512 src_set_fname(NULL
);
6515 static void pp_cleanup_session(void)
6517 nasm_free(use_loaded
);
6524 static void pp_include_path(struct strlist
*list
)
6529 static void pp_pre_include(char *fname
)
6531 Token
*inc
, *space
, *name
;
6534 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
6535 space
= new_White(name
);
6536 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
6538 l
= nasm_malloc(sizeof(Line
));
6545 static void pp_pre_define(char *definition
)
6551 equals
= strchr(definition
, '=');
6552 space
= new_White(NULL
);
6553 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
6556 space
->next
= tokenize(definition
);
6560 /* We can't predefine a TOK_LOCAL_MACRO for obvious reasons... */
6561 if (space
->next
->type
!= TOK_PREPROC_ID
&&
6562 space
->next
->type
!= TOK_ID
)
6563 nasm_warn(WARN_OTHER
, "pre-defining non ID `%s\'\n", definition
);
6565 l
= nasm_malloc(sizeof(Line
));
6572 static void pp_pre_undefine(char *definition
)
6577 space
= new_White(NULL
);
6578 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
6579 space
->next
= tokenize(definition
);
6581 l
= nasm_malloc(sizeof(Line
));
6588 /* Insert an early preprocessor command that doesn't need special handling */
6589 static void pp_pre_command(const char *what
, char *string
)
6595 def
= tokenize(string
);
6597 space
= new_White(def
);
6598 cmd
= nasm_strcat(what
[0] == '%' ? "" : "%", what
);
6599 def
= new_Token(space
, TOK_PREPROC_ID
, cmd
, nasm_last_string_len());
6603 l
= nasm_malloc(sizeof(Line
));
6610 static void pp_add_stdmac(macros_t
*macros
)
6614 /* Find the end of the list and avoid duplicates */
6615 for (mp
= stdmacros
; *mp
; mp
++) {
6617 return; /* Nothing to do */
6620 nasm_assert(mp
< &stdmacros
[ARRAY_SIZE(stdmacros
)-1]);
6625 static void pp_extra_stdmac(macros_t
*macros
)
6627 extrastdmac
= macros
;
6630 /* Create a numeric token */
6631 static Token
*make_tok_num(Token
*next
, int64_t val
)
6634 int len
= snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
6635 return new_Token(next
, TOK_NUMBER
, numbuf
, len
);
6638 /* Create a quoted string token */
6639 static Token
*make_tok_qstr_len(Token
*next
, const char *str
, size_t len
)
6641 char *p
= nasm_quote(str
, &len
);
6642 return new_Token_free(next
, TOK_STRING
, p
, len
);
6644 static Token
*make_tok_qstr(Token
*next
, const char *str
)
6646 return make_tok_qstr_len(next
, str
, strlen(str
));
6649 /* Create a single-character operator token */
6650 static Token
*make_tok_char(Token
*next
, char op
)
6652 Token
*t
= new_Token(next
, TOK_OTHER
, NULL
, 1);
6657 static void pp_list_one_macro(MMacro
*m
, errflags severity
)
6662 /* We need to print the mstk.mmac list in reverse order */
6663 pp_list_one_macro(m
->mstk
.mmac
, severity
);
6665 if (m
->name
&& !m
->nolist
) {
6666 src_set(m
->xline
+ m
->lineno
, m
->fname
);
6667 nasm_error(severity
, "... from macro `%s' defined", m
->name
);
6671 static void pp_error_list_macros(errflags severity
)
6673 struct src_location saved
;
6675 severity
|= ERR_PP_LISTMACRO
| ERR_NO_SEVERITY
| ERR_HERE
;
6676 saved
= src_where();
6679 pp_list_one_macro(istk
->mstk
.mmac
, severity
);
6684 const struct preproc_ops nasmpp
= {
6696 pp_error_list_macros
,