1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2017 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
85 typedef struct SMacro SMacro
;
86 typedef struct MMacro MMacro
;
87 typedef struct MMacroInvocation MMacroInvocation
;
88 typedef struct Context Context
;
89 typedef struct Token Token
;
90 typedef struct Blocks Blocks
;
91 typedef struct Line Line
;
92 typedef struct Include Include
;
93 typedef struct Cond Cond
;
94 typedef struct IncPath IncPath
;
97 * Note on the storage of both SMacro and MMacros: the hash table
98 * indexes them case-insensitively, and we then have to go through a
99 * linked list of potential case aliases (and, for MMacros, parameter
100 * ranges); this is to preserve the matching semantics of the earlier
101 * code. If the number of case aliases for a specific macro is a
102 * performance issue, you may want to reconsider your coding style.
106 * Store the definition of a single-line macro.
118 * Store the definition of a multi-line macro. This is also used to
119 * store the interiors of `%rep...%endrep' blocks, which are
120 * effectively self-re-invoking multi-line macros which simply
121 * don't have a name or bother to appear in the hash tables. %rep
122 * blocks are signified by having a NULL `name' field.
124 * In a MMacro describing a `%rep' block, the `in_progress' field
125 * isn't merely boolean, but gives the number of repeats left to
128 * The `next' field is used for storing MMacros in hash tables; the
129 * `next_active' field is for stacking them on istk entries.
131 * When a MMacro is being expanded, `params', `iline', `nparam',
132 * `paramlen', `rotate' and `unique' are local to the invocation.
136 MMacroInvocation
*prev
; /* previous invocation */
138 int nparam_min
, nparam_max
;
140 bool plus
; /* is the last parameter greedy? */
141 bool nolist
; /* is this macro listing-inhibited? */
142 int64_t in_progress
; /* is this macro currently being expanded? */
143 int32_t max_depth
; /* maximum number of recursive expansions allowed */
144 Token
*dlist
; /* All defaults as one list */
145 Token
**defaults
; /* Parameter default pointers */
146 int ndefs
; /* number of default parameters */
150 MMacro
*rep_nest
; /* used for nesting %rep */
151 Token
**params
; /* actual parameters */
152 Token
*iline
; /* invocation line */
153 unsigned int nparam
, rotate
;
156 int lineno
; /* Current line number on expansion */
157 uint64_t condcnt
; /* number of if blocks... */
159 const char *fname
; /* File where defined */
160 int32_t xline
; /* First line in macro */
164 /* Store the definition of a multi-line macro, as defined in a
165 * previous recursive macro expansion.
167 struct MMacroInvocation
{
168 MMacroInvocation
*prev
; /* previous invocation */
169 Token
**params
; /* actual parameters */
170 Token
*iline
; /* invocation line */
171 unsigned int nparam
, rotate
;
179 * The context stack is composed of a linked list of these.
184 struct hash_table localmac
;
189 * This is the internal form which we break input lines up into.
190 * Typically stored in linked lists.
192 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
193 * necessarily used as-is, but is intended to denote the number of
194 * the substituted parameter. So in the definition
196 * %define a(x,y) ( (x) & ~(y) )
198 * the token representing `x' will have its type changed to
199 * TOK_SMAC_PARAM, but the one representing `y' will be
202 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
203 * which doesn't need quotes around it. Used in the pre-include
204 * mechanism as an alternative to trying to find a sensible type of
205 * quote to use on the filename we were passed.
208 TOK_NONE
= 0, TOK_WHITESPACE
, TOK_COMMENT
, TOK_ID
,
209 TOK_PREPROC_ID
, TOK_STRING
,
210 TOK_NUMBER
, TOK_FLOAT
, TOK_SMAC_END
, TOK_OTHER
,
212 TOK_PREPROC_Q
, TOK_PREPROC_QQ
,
214 TOK_INDIRECT
, /* %[...] */
215 TOK_SMAC_PARAM
, /* MUST BE LAST IN THE LIST!!! */
216 TOK_MAX
= INT_MAX
/* Keep compiler from reducing the range */
219 #define PP_CONCAT_MASK(x) (1 << (x))
220 #define PP_CONCAT_MATCH(t, mask) (PP_CONCAT_MASK((t)->type) & mask)
222 struct tokseq_match
{
231 SMacro
*mac
; /* associated macro for TOK_SMAC_END */
232 size_t len
; /* scratch length field */
233 } a
; /* Auxiliary data */
234 enum pp_token_type type
;
238 * Multi-line macro definitions are stored as a linked list of
239 * these, which is essentially a container to allow several linked
242 * Note that in this module, linked lists are treated as stacks
243 * wherever possible. For this reason, Lines are _pushed_ on to the
244 * `expansion' field in MMacro structures, so that the linked list,
245 * if walked, would give the macro lines in reverse order; this
246 * means that we can walk the list when expanding a macro, and thus
247 * push the lines on to the `expansion' field in _istk_ in reverse
248 * order (so that when popped back off they are in the right
249 * order). It may seem cockeyed, and it relies on my design having
250 * an even number of steps in, but it works...
252 * Some of these structures, rather than being actual lines, are
253 * markers delimiting the end of the expansion of a given macro.
254 * This is for use in the cycle-tracking and %rep-handling code.
255 * Such structures have `finishes' non-NULL, and `first' NULL. All
256 * others have `finishes' NULL, but `first' may still be NULL if
266 * To handle an arbitrary level of file inclusion, we maintain a
267 * stack (ie linked list) of these things.
276 MMacro
*mstk
; /* stack of active macros/reps */
280 * Include search path. This is simply a list of strings which get
281 * prepended, in turn, to the name of an include file, in an
282 * attempt to find the file if it's not in the current directory.
290 * File real name hash, so we don't have to re-search the include
291 * path for every pass (and potentially more than that if a file
292 * is used more than once.)
294 struct hash_table FileHash
;
297 * Conditional assembly: we maintain a separate stack of these for
298 * each level of file inclusion. (The only reason we keep the
299 * stacks separate is to ensure that a stray `%endif' in a file
300 * included from within the true branch of a `%if' won't terminate
301 * it and cause confusion: instead, rightly, it'll cause an error.)
309 * These states are for use just after %if or %elif: IF_TRUE
310 * means the condition has evaluated to truth so we are
311 * currently emitting, whereas IF_FALSE means we are not
312 * currently emitting but will start doing so if a %else comes
313 * up. In these states, all directives are admissible: %elif,
314 * %else and %endif. (And of course %if.)
316 COND_IF_TRUE
, COND_IF_FALSE
,
318 * These states come up after a %else: ELSE_TRUE means we're
319 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
320 * any %elif or %else will cause an error.
322 COND_ELSE_TRUE
, COND_ELSE_FALSE
,
324 * These states mean that we're not emitting now, and also that
325 * nothing until %endif will be emitted at all. COND_DONE is
326 * used when we've had our moment of emission
327 * and have now started seeing %elifs. COND_NEVER is used when
328 * the condition construct in question is contained within a
329 * non-emitting branch of a larger condition construct,
330 * or if there is an error.
332 COND_DONE
, COND_NEVER
334 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
337 * These defines are used as the possible return values for do_directive
339 #define NO_DIRECTIVE_FOUND 0
340 #define DIRECTIVE_FOUND 1
343 * This define sets the upper limit for smacro and recursive mmacro
346 #define DEADMAN_LIMIT (1 << 20)
349 #define REP_LIMIT ((INT64_C(1) << 62))
352 * Condition codes. Note that we use c_ prefix not C_ because C_ is
353 * used in nasm.h for the "real" condition codes. At _this_ level,
354 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
355 * ones, so we need a different enum...
357 static const char * const conditions
[] = {
358 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
359 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
360 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
363 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
364 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
365 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_RCXZ
, c_S
, c_Z
,
368 static const enum pp_conds inverse_ccs
[] = {
369 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
370 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
,
371 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, -1, c_NS
, c_NZ
377 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
378 static int is_condition(enum preproc_token arg
)
380 return PP_IS_COND(arg
) || (arg
== PP_ELSE
) || (arg
== PP_ENDIF
);
383 /* For TASM compatibility we need to be able to recognise TASM compatible
384 * conditional compilation directives. Using the NASM pre-processor does
385 * not work, so we look for them specifically from the following list and
386 * then jam in the equivalent NASM directive into the input stream.
390 TM_ARG
, TM_ELIF
, TM_ELSE
, TM_ENDIF
, TM_IF
, TM_IFDEF
, TM_IFDIFI
,
391 TM_IFNDEF
, TM_INCLUDE
, TM_LOCAL
394 static const char * const tasm_directives
[] = {
395 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
396 "ifndef", "include", "local"
399 static int StackSize
= 4;
400 static const char *StackPointer
= "ebp";
401 static int ArgOffset
= 8;
402 static int LocalOffset
= 0;
404 static Context
*cstk
;
405 static Include
*istk
;
406 static IncPath
*ipath
= NULL
;
408 static int pass
; /* HACK: pass 0 = generate dependencies only */
409 static StrList
**dephead
;
411 static uint64_t unique
; /* unique identifier numbers */
413 static Line
*predef
= NULL
;
414 static bool do_predef
;
417 * The current set of multi-line macros we have defined.
419 static struct hash_table mmacros
;
422 * The current set of single-line macros we have defined.
424 static struct hash_table smacros
;
427 * The multi-line macro we are currently defining, or the %rep
428 * block we are currently reading, if any.
430 static MMacro
*defining
;
432 static uint64_t nested_mac_count
;
433 static uint64_t nested_rep_count
;
436 * The number of macro parameters to allocate space for at a time.
438 #define PARAM_DELTA 16
441 * The standard macro set: defined in macros.c in a set of arrays.
442 * This gives our position in any macro set, while we are processing it.
443 * The stdmacset is an array of such macro sets.
445 static macros_t
*stdmacpos
;
446 static macros_t
**stdmacnext
;
447 static macros_t
*stdmacros
[8];
448 static macros_t
*extrastdmac
;
451 * Tokens are allocated in blocks to improve speed
453 #define TOKEN_BLOCKSIZE 4096
454 static Token
*freeTokens
= NULL
;
460 static Blocks blocks
= { NULL
, NULL
};
463 * Forward declarations.
465 static void pp_add_stdmac(macros_t
*macros
);
466 static Token
*expand_mmac_params(Token
* tline
);
467 static Token
*expand_smacro(Token
* tline
);
468 static Token
*expand_id(Token
* tline
);
469 static Context
*get_ctx(const char *name
, const char **namep
);
470 static void make_tok_num(Token
* tok
, int64_t val
);
471 static void pp_verror(int severity
, const char *fmt
, va_list ap
);
472 static vefunc real_verror
;
473 static void *new_Block(size_t size
);
474 static void delete_Blocks(void);
475 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
476 const char *text
, int txtlen
);
477 static Token
*delete_Token(Token
* t
);
480 * Macros for safe checking of token pointers, avoid *(NULL)
482 #define tok_type_(x,t) ((x) && (x)->type == (t))
483 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
484 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
485 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
488 * nasm_unquote with error if the string contains NUL characters.
489 * If the string contains NUL characters, issue an error and return
490 * the C len, i.e. truncate at the NUL.
492 static size_t nasm_unquote_cstr(char *qstr
, enum preproc_token directive
)
494 size_t len
= nasm_unquote(qstr
, NULL
);
495 size_t clen
= strlen(qstr
);
498 nasm_error(ERR_NONFATAL
, "NUL character in `%s' directive",
499 pp_directives
[directive
]);
505 * In-place reverse a list of tokens.
507 static Token
*reverse_tokens(Token
*t
)
523 * Handle TASM specific directives, which do not contain a % in
524 * front of them. We do it here because I could not find any other
525 * place to do it for the moment, and it is a hack (ideally it would
526 * be nice to be able to use the NASM pre-processor to do it).
528 static char *check_tasm_directive(char *line
)
530 int32_t i
, j
, k
, m
, len
;
531 char *p
, *q
, *oldline
, oldchar
;
533 p
= nasm_skip_spaces(line
);
535 /* Binary search for the directive name */
537 j
= ARRAY_SIZE(tasm_directives
);
538 q
= nasm_skip_word(p
);
545 m
= nasm_stricmp(p
, tasm_directives
[k
]);
547 /* We have found a directive, so jam a % in front of it
548 * so that NASM will then recognise it as one if it's own.
553 line
= nasm_malloc(len
+ 2);
555 if (k
== TM_IFDIFI
) {
557 * NASM does not recognise IFDIFI, so we convert
558 * it to %if 0. This is not used in NASM
559 * compatible code, but does need to parse for the
560 * TASM macro package.
562 strcpy(line
+ 1, "if 0");
564 memcpy(line
+ 1, p
, len
+ 1);
579 * The pre-preprocessing stage... This function translates line
580 * number indications as they emerge from GNU cpp (`# lineno "file"
581 * flags') into NASM preprocessor line number indications (`%line
584 static char *prepreproc(char *line
)
587 char *fname
, *oldline
;
589 if (line
[0] == '#' && line
[1] == ' ') {
592 lineno
= atoi(fname
);
593 fname
+= strspn(fname
, "0123456789 ");
596 fnlen
= strcspn(fname
, "\"");
597 line
= nasm_malloc(20 + fnlen
);
598 snprintf(line
, 20 + fnlen
, "%%line %d %.*s", lineno
, fnlen
, fname
);
601 if (tasm_compatible_mode
)
602 return check_tasm_directive(line
);
607 * Free a linked list of tokens.
609 static void free_tlist(Token
* list
)
612 list
= delete_Token(list
);
616 * Free a linked list of lines.
618 static void free_llist(Line
* list
)
621 list_for_each_safe(l
, tmp
, list
) {
622 free_tlist(l
->first
);
630 static void free_mmacro(MMacro
* m
)
633 free_tlist(m
->dlist
);
634 nasm_free(m
->defaults
);
635 free_llist(m
->expansion
);
640 * Free all currently defined macros, and free the hash tables
642 static void free_smacro_table(struct hash_table
*smt
)
646 struct hash_tbl_node
*it
= NULL
;
648 while ((s
= hash_iterate(smt
, &it
, &key
)) != NULL
) {
649 nasm_free((void *)key
);
650 list_for_each_safe(s
, tmp
, s
) {
652 free_tlist(s
->expansion
);
659 static void free_mmacro_table(struct hash_table
*mmt
)
663 struct hash_tbl_node
*it
= NULL
;
666 while ((m
= hash_iterate(mmt
, &it
, &key
)) != NULL
) {
667 nasm_free((void *)key
);
668 list_for_each_safe(m
,tmp
, m
)
674 static void free_macros(void)
676 free_smacro_table(&smacros
);
677 free_mmacro_table(&mmacros
);
681 * Initialize the hash tables
683 static void init_macros(void)
685 hash_init(&smacros
, HASH_LARGE
);
686 hash_init(&mmacros
, HASH_LARGE
);
690 * Pop the context stack.
692 static void ctx_pop(void)
697 free_smacro_table(&c
->localmac
);
703 * Search for a key in the hash index; adding it if necessary
704 * (in which case we initialize the data pointer to NULL.)
707 hash_findi_add(struct hash_table
*hash
, const char *str
)
709 struct hash_insert hi
;
713 r
= hash_findi(hash
, str
, &hi
);
717 strx
= nasm_strdup(str
); /* Use a more efficient allocator here? */
718 return hash_add(&hi
, strx
, NULL
);
722 * Like hash_findi, but returns the data element rather than a pointer
723 * to it. Used only when not adding a new element, hence no third
727 hash_findix(struct hash_table
*hash
, const char *str
)
731 p
= hash_findi(hash
, str
, NULL
);
732 return p
? *p
: NULL
;
736 * read line from standart macros set,
737 * if there no more left -- return NULL
739 static char *line_from_stdmac(void)
742 const unsigned char *p
= stdmacpos
;
751 len
+= pp_directives_len
[c
- 0x80] + 1;
756 line
= nasm_malloc(len
+ 1);
758 while ((c
= *stdmacpos
++)) {
760 memcpy(q
, pp_directives
[c
- 0x80], pp_directives_len
[c
- 0x80]);
761 q
+= pp_directives_len
[c
- 0x80];
771 /* This was the last of this particular macro set */
774 stdmacpos
= *stdmacnext
++;
775 } else if (do_predef
) {
777 Token
*head
, **tail
, *t
;
780 * Nasty hack: here we push the contents of
781 * `predef' on to the top-level expansion stack,
782 * since this is the most convenient way to
783 * implement the pre-include and pre-define
786 list_for_each(pd
, predef
) {
789 list_for_each(t
, pd
->first
) {
790 *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
791 tail
= &(*tail
)->next
;
794 l
= nasm_malloc(sizeof(Line
));
795 l
->next
= istk
->expansion
;
808 static char *read_line(void)
810 unsigned int size
, c
, next
;
811 const unsigned int delta
= 512;
812 const unsigned int pad
= 8;
813 unsigned int nr_cont
= 0;
817 /* Standart macros set (predefined) goes first */
818 p
= line_from_stdmac();
823 p
= buffer
= nasm_malloc(size
);
827 if ((int)(c
) == EOF
) {
834 next
= fgetc(istk
->fp
);
836 ungetc(next
, istk
->fp
);
851 next
= fgetc(istk
->fp
);
852 ungetc(next
, istk
->fp
);
853 if (next
== '\r' || next
== '\n') {
861 if (c
== '\r' || c
== '\n') {
866 if (p
>= (buffer
+ size
- pad
)) {
867 buffer
= nasm_realloc(buffer
, size
+ delta
);
868 p
= buffer
+ size
- pad
;
872 *p
++ = (unsigned char)c
;
880 src_set_linnum(src_get_linnum() + istk
->lineinc
+
881 (nr_cont
* istk
->lineinc
));
884 * Handle spurious ^Z, which may be inserted into source files
885 * by some file transfer utilities.
887 buffer
[strcspn(buffer
, "\032")] = '\0';
889 lfmt
->line(LIST_READ
, buffer
);
895 * Tokenize a line of text. This is a very simple process since we
896 * don't need to parse the value out of e.g. numeric tokens: we
897 * simply split one string into many.
899 static Token
*tokenize(char *line
)
902 enum pp_token_type type
;
904 Token
*t
, **tail
= &list
;
910 if (*p
== '+' && !nasm_isdigit(p
[1])) {
913 } else if (nasm_isdigit(*p
) ||
914 ((*p
== '-' || *p
== '+') && nasm_isdigit(p
[1]))) {
918 while (nasm_isdigit(*p
));
919 type
= TOK_PREPROC_ID
;
920 } else if (*p
== '{') {
929 nasm_error(ERR_WARNING
| ERR_PASS1
,
930 "unterminated %%{ construct");
934 type
= TOK_PREPROC_ID
;
935 } else if (*p
== '[') {
937 line
+= 2; /* Skip the leading %[ */
939 while (lvl
&& (c
= *p
++)) {
951 p
= nasm_skip_string(p
- 1);
963 nasm_error(ERR_NONFATAL
|ERR_PASS1
,
964 "unterminated %%[ construct");
966 } else if (*p
== '?') {
967 type
= TOK_PREPROC_Q
; /* %? */
970 type
= TOK_PREPROC_QQ
; /* %?? */
973 } else if (*p
== '!') {
974 type
= TOK_PREPROC_ID
;
980 while (isidchar(*p
));
981 } else if (*p
== '\'' || *p
== '\"' || *p
== '`') {
982 p
= nasm_skip_string(p
);
986 nasm_error(ERR_NONFATAL
|ERR_PASS1
,
987 "unterminated %%! string");
989 /* %! without string or identifier */
990 type
= TOK_OTHER
; /* Legacy behavior... */
992 } else if (isidchar(*p
) ||
993 ((*p
== '!' || *p
== '%' || *p
== '$') &&
998 while (isidchar(*p
));
999 type
= TOK_PREPROC_ID
;
1005 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
1008 while (*p
&& isidchar(*p
))
1010 } else if (*p
== '\'' || *p
== '"' || *p
== '`') {
1015 p
= nasm_skip_string(p
);
1020 nasm_error(ERR_WARNING
|ERR_PASS1
, "unterminated string");
1021 /* Handling unterminated strings by UNV */
1024 } else if (p
[0] == '$' && p
[1] == '$') {
1025 type
= TOK_OTHER
; /* TOKEN_BASE */
1027 } else if (isnumstart(*p
)) {
1028 bool is_hex
= false;
1029 bool is_float
= false;
1045 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
1047 if (*p
== '+' || *p
== '-') {
1049 * e can only be followed by +/- if it is either a
1050 * prefixed hex number or a floating-point number
1055 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
1057 } else if (c
== 'P' || c
== 'p') {
1059 if (*p
== '+' || *p
== '-')
1061 } else if (isnumchar(c
))
1062 ; /* just advance */
1063 else if (c
== '.') {
1065 * we need to deal with consequences of the legacy
1066 * parser, like "1.nolist" being two tokens
1067 * (TOK_NUMBER, TOK_ID) here; at least give it
1068 * a shot for now. In the future, we probably need
1069 * a flex-based scanner with proper pattern matching
1070 * to do it as well as it can be done. Nothing in
1071 * the world is going to help the person who wants
1072 * 0x123.p16 interpreted as two tokens, though.
1078 if (nasm_isdigit(*r
) || (is_hex
&& nasm_isxdigit(*r
)) ||
1079 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
1080 (*r
== 'p' || *r
== 'P')) {
1084 break; /* Terminate the token */
1088 p
--; /* Point to first character beyond number */
1090 if (p
== line
+1 && *line
== '$') {
1091 type
= TOK_OTHER
; /* TOKEN_HERE */
1093 if (has_e
&& !is_hex
) {
1094 /* 1e13 is floating-point, but 1e13h is not */
1098 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
1100 } else if (nasm_isspace(*p
)) {
1101 type
= TOK_WHITESPACE
;
1102 p
= nasm_skip_spaces(p
);
1104 * Whitespace just before end-of-line is discarded by
1105 * pretending it's a comment; whitespace just before a
1106 * comment gets lumped into the comment.
1108 if (!*p
|| *p
== ';') {
1113 } else if (*p
== ';') {
1119 * Anything else is an operator of some kind. We check
1120 * for all the double-character operators (>>, <<, //,
1121 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1122 * else is a single-character operator.
1125 if ((p
[0] == '>' && p
[1] == '>') ||
1126 (p
[0] == '<' && p
[1] == '<') ||
1127 (p
[0] == '/' && p
[1] == '/') ||
1128 (p
[0] == '<' && p
[1] == '=') ||
1129 (p
[0] == '>' && p
[1] == '=') ||
1130 (p
[0] == '=' && p
[1] == '=') ||
1131 (p
[0] == '!' && p
[1] == '=') ||
1132 (p
[0] == '<' && p
[1] == '>') ||
1133 (p
[0] == '&' && p
[1] == '&') ||
1134 (p
[0] == '|' && p
[1] == '|') ||
1135 (p
[0] == '^' && p
[1] == '^')) {
1141 /* Handling unterminated string by UNV */
1144 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1145 t->text[p-line] = *line;
1149 if (type
!= TOK_COMMENT
) {
1150 *tail
= t
= new_Token(NULL
, type
, line
, p
- line
);
1159 * this function allocates a new managed block of memory and
1160 * returns a pointer to the block. The managed blocks are
1161 * deleted only all at once by the delete_Blocks function.
1163 static void *new_Block(size_t size
)
1165 Blocks
*b
= &blocks
;
1167 /* first, get to the end of the linked list */
1170 /* now allocate the requested chunk */
1171 b
->chunk
= nasm_malloc(size
);
1173 /* now allocate a new block for the next request */
1174 b
->next
= nasm_zalloc(sizeof(Blocks
));
1179 * this function deletes all managed blocks of memory
1181 static void delete_Blocks(void)
1183 Blocks
*a
, *b
= &blocks
;
1186 * keep in mind that the first block, pointed to by blocks
1187 * is a static and not dynamically allocated, so we don't
1192 nasm_free(b
->chunk
);
1198 memset(&blocks
, 0, sizeof(blocks
));
1202 * this function creates a new Token and passes a pointer to it
1203 * back to the caller. It sets the type and text elements, and
1204 * also the a.mac and next elements to NULL.
1206 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
1207 const char *text
, int txtlen
)
1213 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1214 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1215 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1216 freeTokens
[i
].next
= NULL
;
1219 freeTokens
= t
->next
;
1223 if (type
== TOK_WHITESPACE
|| !text
) {
1227 txtlen
= strlen(text
);
1228 t
->text
= nasm_malloc(txtlen
+1);
1229 memcpy(t
->text
, text
, txtlen
);
1230 t
->text
[txtlen
] = '\0';
1235 static Token
*delete_Token(Token
* t
)
1237 Token
*next
= t
->next
;
1239 t
->next
= freeTokens
;
1245 * Convert a line of tokens back into text.
1246 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1247 * will be transformed into ..@ctxnum.xxx
1249 static char *detoken(Token
* tlist
, bool expand_locals
)
1256 list_for_each(t
, tlist
) {
1257 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
1262 if (*v
== '\'' || *v
== '\"' || *v
== '`') {
1263 size_t len
= nasm_unquote(v
, NULL
);
1264 size_t clen
= strlen(v
);
1267 nasm_error(ERR_NONFATAL
| ERR_PASS1
,
1268 "NUL character in %%! string");
1274 char *p
= getenv(v
);
1276 nasm_error(ERR_NONFATAL
| ERR_PASS1
,
1277 "nonexistent environment variable `%s'", v
);
1279 * FIXME We better should investigate if accessing
1280 * ->text[1] without ->text[0] is safe enough.
1282 t
->text
= nasm_zalloc(2);
1284 t
->text
= nasm_strdup(p
);
1289 /* Expand local macros here and not during preprocessing */
1290 if (expand_locals
&&
1291 t
->type
== TOK_PREPROC_ID
&& t
->text
&&
1292 t
->text
[0] == '%' && t
->text
[1] == '$') {
1295 Context
*ctx
= get_ctx(t
->text
, &q
);
1298 snprintf(buffer
, sizeof(buffer
), "..@%"PRIu32
".", ctx
->number
);
1299 p
= nasm_strcat(buffer
, q
);
1304 if (t
->type
== TOK_WHITESPACE
)
1307 len
+= strlen(t
->text
);
1310 p
= line
= nasm_malloc(len
+ 1);
1312 list_for_each(t
, tlist
) {
1313 if (t
->type
== TOK_WHITESPACE
) {
1315 } else if (t
->text
) {
1327 * A scanner, suitable for use by the expression evaluator, which
1328 * operates on a line of Tokens. Expects a pointer to a pointer to
1329 * the first token in the line to be passed in as its private_data
1332 * FIX: This really needs to be unified with stdscan.
1334 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1336 Token
**tlineptr
= private_data
;
1338 char ourcopy
[MAX_KEYWORD
+1], *p
, *r
, *s
;
1342 *tlineptr
= tline
? tline
->next
: NULL
;
1343 } while (tline
&& (tline
->type
== TOK_WHITESPACE
||
1344 tline
->type
== TOK_COMMENT
));
1347 return tokval
->t_type
= TOKEN_EOS
;
1349 tokval
->t_charptr
= tline
->text
;
1351 if (tline
->text
[0] == '$' && !tline
->text
[1])
1352 return tokval
->t_type
= TOKEN_HERE
;
1353 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[2])
1354 return tokval
->t_type
= TOKEN_BASE
;
1356 if (tline
->type
== TOK_ID
) {
1357 p
= tokval
->t_charptr
= tline
->text
;
1359 tokval
->t_charptr
++;
1360 return tokval
->t_type
= TOKEN_ID
;
1363 for (r
= p
, s
= ourcopy
; *r
; r
++) {
1364 if (r
>= p
+MAX_KEYWORD
)
1365 return tokval
->t_type
= TOKEN_ID
; /* Not a keyword */
1366 *s
++ = nasm_tolower(*r
);
1369 /* right, so we have an identifier sitting in temp storage. now,
1370 * is it actually a register or instruction name, or what? */
1371 return nasm_token_hash(ourcopy
, tokval
);
1374 if (tline
->type
== TOK_NUMBER
) {
1376 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
1377 tokval
->t_charptr
= tline
->text
;
1379 return tokval
->t_type
= TOKEN_ERRNUM
;
1381 return tokval
->t_type
= TOKEN_NUM
;
1384 if (tline
->type
== TOK_FLOAT
) {
1385 return tokval
->t_type
= TOKEN_FLOAT
;
1388 if (tline
->type
== TOK_STRING
) {
1391 bq
= tline
->text
[0];
1392 tokval
->t_charptr
= tline
->text
;
1393 tokval
->t_inttwo
= nasm_unquote(tline
->text
, &ep
);
1395 if (ep
[0] != bq
|| ep
[1] != '\0')
1396 return tokval
->t_type
= TOKEN_ERRSTR
;
1398 return tokval
->t_type
= TOKEN_STR
;
1401 if (tline
->type
== TOK_OTHER
) {
1402 if (!strcmp(tline
->text
, "<<"))
1403 return tokval
->t_type
= TOKEN_SHL
;
1404 if (!strcmp(tline
->text
, ">>"))
1405 return tokval
->t_type
= TOKEN_SHR
;
1406 if (!strcmp(tline
->text
, "//"))
1407 return tokval
->t_type
= TOKEN_SDIV
;
1408 if (!strcmp(tline
->text
, "%%"))
1409 return tokval
->t_type
= TOKEN_SMOD
;
1410 if (!strcmp(tline
->text
, "=="))
1411 return tokval
->t_type
= TOKEN_EQ
;
1412 if (!strcmp(tline
->text
, "<>"))
1413 return tokval
->t_type
= TOKEN_NE
;
1414 if (!strcmp(tline
->text
, "!="))
1415 return tokval
->t_type
= TOKEN_NE
;
1416 if (!strcmp(tline
->text
, "<="))
1417 return tokval
->t_type
= TOKEN_LE
;
1418 if (!strcmp(tline
->text
, ">="))
1419 return tokval
->t_type
= TOKEN_GE
;
1420 if (!strcmp(tline
->text
, "&&"))
1421 return tokval
->t_type
= TOKEN_DBL_AND
;
1422 if (!strcmp(tline
->text
, "^^"))
1423 return tokval
->t_type
= TOKEN_DBL_XOR
;
1424 if (!strcmp(tline
->text
, "||"))
1425 return tokval
->t_type
= TOKEN_DBL_OR
;
1429 * We have no other options: just return the first character of
1432 return tokval
->t_type
= tline
->text
[0];
1436 * Compare a string to the name of an existing macro; this is a
1437 * simple wrapper which calls either strcmp or nasm_stricmp
1438 * depending on the value of the `casesense' parameter.
1440 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
1442 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
1446 * Compare a string to the name of an existing macro; this is a
1447 * simple wrapper which calls either strcmp or nasm_stricmp
1448 * depending on the value of the `casesense' parameter.
1450 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
1452 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
1456 * Return the Context structure associated with a %$ token. Return
1457 * NULL, having _already_ reported an error condition, if the
1458 * context stack isn't deep enough for the supplied number of $
1461 * If "namep" is non-NULL, set it to the pointer to the macro name
1462 * tail, i.e. the part beyond %$...
1464 static Context
*get_ctx(const char *name
, const char **namep
)
1472 if (!name
|| name
[0] != '%' || name
[1] != '$')
1476 nasm_error(ERR_NONFATAL
, "`%s': context stack is empty", name
);
1483 while (ctx
&& *name
== '$') {
1489 nasm_error(ERR_NONFATAL
, "`%s': context stack is only"
1490 " %d level%s deep", name
, i
, (i
== 1 ? "" : "s"));
1501 * Open an include file. This routine must always return a valid
1502 * file pointer if it returns - it's responsible for throwing an
1503 * ERR_FATAL and bombing out completely if not. It should also try
1504 * the include path one by one until it finds the file or reaches
1505 * the end of the path.
1507 * Note: for INC_PROBE the function returns NULL at all times;
1508 * instead look for the
1511 INC_NEEDED
, /* File must exist */
1512 INC_OPTIONAL
, /* Missing is OK */
1513 INC_PROBE
/* Only an existence probe */
1516 /* This is conducts a full pathname search */
1517 static FILE *inc_fopen_search(const char *file
, StrList
**slpath
,
1518 enum incopen_mode omode
, enum file_flags fmode
)
1522 const IncPath
*ip
= ipath
;
1523 int len
= strlen(file
);
1524 size_t prefix_len
= 0;
1530 path_len
= prefix_len
+ len
+ 1;
1532 sl
= nasm_malloc(path_len
+ sizeof sl
->next
);
1533 memcpy(sl
->str
, prefix
, prefix_len
);
1534 memcpy(sl
->str
+prefix_len
, file
, len
+1);
1537 if (omode
== INC_PROBE
) {
1539 found
= nasm_file_exists(sl
->str
);
1541 fp
= nasm_open_read(sl
->str
, fmode
);
1542 found
= (fp
!= NULL
);
1555 prefix_len
= strlen(prefix
);
1561 * Open a file, or test for the presence of one (depending on omode),
1562 * considering the include path.
1564 static FILE *inc_fopen(const char *file
,
1566 const char **found_path
,
1567 enum incopen_mode omode
,
1568 enum file_flags fmode
)
1571 struct hash_insert hi
;
1576 hp
= hash_find(&FileHash
, file
, &hi
);
1579 if (path
|| omode
!= INC_NEEDED
) {
1580 nasm_add_string_to_strlist(dhead
, path
? path
: file
);
1583 /* Need to do the actual path search */
1587 fp
= inc_fopen_search(file
, &sl
, omode
, fmode
);
1589 file_len
= strlen(file
);
1592 /* Store negative result for this file */
1593 sl
= nasm_malloc(file_len
+ 1 + sizeof sl
->next
);
1594 memcpy(sl
->str
, file
, file_len
+1);
1600 file
= strchr(path
, '\0') - file_len
;
1603 hash_add(&hi
, file
, path
); /* Positive or negative result */
1606 * Add file to dependency path. The in_list() is needed
1607 * in case the file was already added with %depend.
1609 if (path
|| omode
!= INC_NEEDED
)
1610 nasm_add_to_strlist(dhead
, sl
);
1614 if (omode
== INC_NEEDED
)
1615 nasm_fatal(0, "unable to open include file `%s'", file
);
1623 if (!fp
&& omode
!= INC_PROBE
)
1624 fp
= nasm_open_read(path
, fmode
);
1633 * Opens an include or input file. Public version, for use by modules
1634 * that get a file:lineno pair and need to look at the file again
1635 * (e.g. the CodeView debug backend). Returns NULL on failure.
1637 FILE *pp_input_fopen(const char *filename
, enum file_flags mode
)
1639 return inc_fopen(filename
, NULL
, NULL
, INC_OPTIONAL
, mode
);
1643 * Determine if we should warn on defining a single-line macro of
1644 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1645 * return true if _any_ single-line macro of that name is defined.
1646 * Otherwise, will return true if a single-line macro with either
1647 * `nparam' or no parameters is defined.
1649 * If a macro with precisely the right number of parameters is
1650 * defined, or nparam is -1, the address of the definition structure
1651 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1652 * is NULL, no action will be taken regarding its contents, and no
1655 * Note that this is also called with nparam zero to resolve
1658 * If you already know which context macro belongs to, you can pass
1659 * the context pointer as first parameter; if you won't but name begins
1660 * with %$ the context will be automatically computed. If all_contexts
1661 * is true, macro will be searched in outer contexts as well.
1664 smacro_defined(Context
* ctx
, const char *name
, int nparam
, SMacro
** defn
,
1667 struct hash_table
*smtbl
;
1671 smtbl
= &ctx
->localmac
;
1672 } else if (name
[0] == '%' && name
[1] == '$') {
1674 ctx
= get_ctx(name
, &name
);
1676 return false; /* got to return _something_ */
1677 smtbl
= &ctx
->localmac
;
1681 m
= (SMacro
*) hash_findix(smtbl
, name
);
1684 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
1685 (nparam
<= 0 || m
->nparam
== 0 || nparam
== (int) m
->nparam
)) {
1687 if (nparam
== (int) m
->nparam
|| nparam
== -1)
1701 * Count and mark off the parameters in a multi-line macro call.
1702 * This is called both from within the multi-line macro expansion
1703 * code, and also to mark off the default parameters when provided
1704 * in a %macro definition line.
1706 static void count_mmac_params(Token
* t
, int *nparam
, Token
*** params
)
1708 int paramsize
, brace
;
1710 *nparam
= paramsize
= 0;
1713 /* +1: we need space for the final NULL */
1714 if (*nparam
+1 >= paramsize
) {
1715 paramsize
+= PARAM_DELTA
;
1716 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
1720 if (tok_is_(t
, "{"))
1722 (*params
)[(*nparam
)++] = t
;
1724 while (brace
&& (t
= t
->next
) != NULL
) {
1725 if (tok_is_(t
, "{"))
1727 else if (tok_is_(t
, "}"))
1733 * Now we've found the closing brace, look further
1738 if (tok_isnt_(t
, ",")) {
1739 nasm_error(ERR_NONFATAL
,
1740 "braces do not enclose all of macro parameter");
1741 while (tok_isnt_(t
, ","))
1746 while (tok_isnt_(t
, ","))
1749 if (t
) { /* got a comma/brace */
1750 t
= t
->next
; /* eat the comma */
1756 * Determine whether one of the various `if' conditions is true or
1759 * We must free the tline we get passed.
1761 static bool if_condition(Token
* tline
, enum preproc_token ct
)
1763 enum pp_conditional i
= PP_COND(ct
);
1765 Token
*t
, *tt
, **tptr
, *origline
;
1766 struct tokenval tokval
;
1768 enum pp_token_type needtype
;
1775 j
= false; /* have we matched yet? */
1780 if (tline
->type
!= TOK_ID
) {
1781 nasm_error(ERR_NONFATAL
,
1782 "`%s' expects context identifiers", pp_directives
[ct
]);
1783 free_tlist(origline
);
1786 if (cstk
&& cstk
->name
&& !nasm_stricmp(tline
->text
, cstk
->name
))
1788 tline
= tline
->next
;
1793 j
= false; /* have we matched yet? */
1796 if (!tline
|| (tline
->type
!= TOK_ID
&&
1797 (tline
->type
!= TOK_PREPROC_ID
||
1798 tline
->text
[1] != '$'))) {
1799 nasm_error(ERR_NONFATAL
,
1800 "`%s' expects macro identifiers", pp_directives
[ct
]);
1803 if (smacro_defined(NULL
, tline
->text
, 0, NULL
, true))
1805 tline
= tline
->next
;
1810 tline
= expand_smacro(tline
);
1811 j
= false; /* have we matched yet? */
1814 if (!tline
|| (tline
->type
!= TOK_ID
&&
1815 tline
->type
!= TOK_STRING
&&
1816 (tline
->type
!= TOK_PREPROC_ID
||
1817 tline
->text
[1] != '!'))) {
1818 nasm_error(ERR_NONFATAL
,
1819 "`%s' expects environment variable names",
1824 if (tline
->type
== TOK_PREPROC_ID
)
1825 p
+= 2; /* Skip leading %! */
1826 if (*p
== '\'' || *p
== '\"' || *p
== '`')
1827 nasm_unquote_cstr(p
, ct
);
1830 tline
= tline
->next
;
1836 tline
= expand_smacro(tline
);
1838 while (tok_isnt_(tt
, ","))
1841 nasm_error(ERR_NONFATAL
,
1842 "`%s' expects two comma-separated arguments",
1847 j
= true; /* assume equality unless proved not */
1848 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1849 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1850 nasm_error(ERR_NONFATAL
, "`%s': more than one comma on line",
1854 if (t
->type
== TOK_WHITESPACE
) {
1858 if (tt
->type
== TOK_WHITESPACE
) {
1862 if (tt
->type
!= t
->type
) {
1863 j
= false; /* found mismatching tokens */
1866 /* When comparing strings, need to unquote them first */
1867 if (t
->type
== TOK_STRING
) {
1868 size_t l1
= nasm_unquote(t
->text
, NULL
);
1869 size_t l2
= nasm_unquote(tt
->text
, NULL
);
1875 if (mmemcmp(t
->text
, tt
->text
, l1
, i
== PPC_IFIDN
)) {
1879 } else if (mstrcmp(tt
->text
, t
->text
, i
== PPC_IFIDN
) != 0) {
1880 j
= false; /* found mismatching tokens */
1887 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
1888 j
= false; /* trailing gunk on one end or other */
1894 MMacro searching
, *mmac
;
1897 tline
= expand_id(tline
);
1898 if (!tok_type_(tline
, TOK_ID
)) {
1899 nasm_error(ERR_NONFATAL
,
1900 "`%s' expects a macro name", pp_directives
[ct
]);
1903 searching
.name
= nasm_strdup(tline
->text
);
1904 searching
.casesense
= true;
1905 searching
.plus
= false;
1906 searching
.nolist
= false;
1907 searching
.in_progress
= 0;
1908 searching
.max_depth
= 0;
1909 searching
.rep_nest
= NULL
;
1910 searching
.nparam_min
= 0;
1911 searching
.nparam_max
= INT_MAX
;
1912 tline
= expand_smacro(tline
->next
);
1915 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
1916 nasm_error(ERR_NONFATAL
,
1917 "`%s' expects a parameter count or nothing",
1920 searching
.nparam_min
= searching
.nparam_max
=
1921 readnum(tline
->text
, &j
);
1923 nasm_error(ERR_NONFATAL
,
1924 "unable to parse parameter count `%s'",
1927 if (tline
&& tok_is_(tline
->next
, "-")) {
1928 tline
= tline
->next
->next
;
1929 if (tok_is_(tline
, "*"))
1930 searching
.nparam_max
= INT_MAX
;
1931 else if (!tok_type_(tline
, TOK_NUMBER
))
1932 nasm_error(ERR_NONFATAL
,
1933 "`%s' expects a parameter count after `-'",
1936 searching
.nparam_max
= readnum(tline
->text
, &j
);
1938 nasm_error(ERR_NONFATAL
,
1939 "unable to parse parameter count `%s'",
1941 if (searching
.nparam_min
> searching
.nparam_max
) {
1942 nasm_error(ERR_NONFATAL
,
1943 "minimum parameter count exceeds maximum");
1944 searching
.nparam_max
= searching
.nparam_min
;
1948 if (tline
&& tok_is_(tline
->next
, "+")) {
1949 tline
= tline
->next
;
1950 searching
.plus
= true;
1952 mmac
= (MMacro
*) hash_findix(&mmacros
, searching
.name
);
1954 if (!strcmp(mmac
->name
, searching
.name
) &&
1955 (mmac
->nparam_min
<= searching
.nparam_max
1957 && (searching
.nparam_min
<= mmac
->nparam_max
1964 if (tline
&& tline
->next
)
1965 nasm_error(ERR_WARNING
|ERR_PASS1
,
1966 "trailing garbage after %%ifmacro ignored");
1967 nasm_free(searching
.name
);
1976 needtype
= TOK_NUMBER
;
1979 needtype
= TOK_STRING
;
1983 t
= tline
= expand_smacro(tline
);
1985 while (tok_type_(t
, TOK_WHITESPACE
) ||
1986 (needtype
== TOK_NUMBER
&&
1987 tok_type_(t
, TOK_OTHER
) &&
1988 (t
->text
[0] == '-' || t
->text
[0] == '+') &&
1992 j
= tok_type_(t
, needtype
);
1996 t
= tline
= expand_smacro(tline
);
1997 while (tok_type_(t
, TOK_WHITESPACE
))
2002 t
= t
->next
; /* Skip the actual token */
2003 while (tok_type_(t
, TOK_WHITESPACE
))
2005 j
= !t
; /* Should be nothing left */
2010 t
= tline
= expand_smacro(tline
);
2011 while (tok_type_(t
, TOK_WHITESPACE
))
2014 j
= !t
; /* Should be empty */
2018 t
= tline
= expand_smacro(tline
);
2020 tokval
.t_type
= TOKEN_INVALID
;
2021 evalresult
= evaluate(ppscan
, tptr
, &tokval
,
2022 NULL
, pass
| CRITICAL
, NULL
);
2026 nasm_error(ERR_WARNING
|ERR_PASS1
,
2027 "trailing garbage after expression ignored");
2028 if (!is_simple(evalresult
)) {
2029 nasm_error(ERR_NONFATAL
,
2030 "non-constant value given to `%s'", pp_directives
[ct
]);
2033 j
= reloc_value(evalresult
) != 0;
2037 nasm_error(ERR_FATAL
,
2038 "preprocessor directive `%s' not yet implemented",
2043 free_tlist(origline
);
2044 return j
^ PP_NEGATIVE(ct
);
2047 free_tlist(origline
);
2052 * Common code for defining an smacro
2054 static bool define_smacro(Context
*ctx
, const char *mname
, bool casesense
,
2055 int nparam
, Token
*expansion
)
2057 SMacro
*smac
, **smhead
;
2058 struct hash_table
*smtbl
;
2060 if (smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
)) {
2062 nasm_error(ERR_WARNING
|ERR_PASS1
,
2063 "single-line macro `%s' defined both with and"
2064 " without parameters", mname
);
2066 * Some instances of the old code considered this a failure,
2067 * some others didn't. What is the right thing to do here?
2069 free_tlist(expansion
);
2070 return false; /* Failure */
2073 * We're redefining, so we have to take over an
2074 * existing SMacro structure. This means freeing
2075 * what was already in it.
2077 nasm_free(smac
->name
);
2078 free_tlist(smac
->expansion
);
2081 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2082 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
2083 smac
= nasm_malloc(sizeof(SMacro
));
2084 smac
->next
= *smhead
;
2087 smac
->name
= nasm_strdup(mname
);
2088 smac
->casesense
= casesense
;
2089 smac
->nparam
= nparam
;
2090 smac
->expansion
= expansion
;
2091 smac
->in_progress
= false;
2092 return true; /* Success */
2096 * Undefine an smacro
2098 static void undef_smacro(Context
*ctx
, const char *mname
)
2100 SMacro
**smhead
, *s
, **sp
;
2101 struct hash_table
*smtbl
;
2103 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2104 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
2108 * We now have a macro name... go hunt for it.
2111 while ((s
= *sp
) != NULL
) {
2112 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
2115 free_tlist(s
->expansion
);
2125 * Parse a mmacro specification.
2127 static bool parse_mmacro_spec(Token
*tline
, MMacro
*def
, const char *directive
)
2131 tline
= tline
->next
;
2133 tline
= expand_id(tline
);
2134 if (!tok_type_(tline
, TOK_ID
)) {
2135 nasm_error(ERR_NONFATAL
, "`%s' expects a macro name", directive
);
2140 def
->name
= nasm_strdup(tline
->text
);
2142 def
->nolist
= false;
2143 def
->in_progress
= 0;
2144 def
->rep_nest
= NULL
;
2145 def
->nparam_min
= 0;
2146 def
->nparam_max
= 0;
2148 tline
= expand_smacro(tline
->next
);
2150 if (!tok_type_(tline
, TOK_NUMBER
)) {
2151 nasm_error(ERR_NONFATAL
, "`%s' expects a parameter count", directive
);
2153 def
->nparam_min
= def
->nparam_max
=
2154 readnum(tline
->text
, &err
);
2156 nasm_error(ERR_NONFATAL
,
2157 "unable to parse parameter count `%s'", tline
->text
);
2159 if (tline
&& tok_is_(tline
->next
, "-")) {
2160 tline
= tline
->next
->next
;
2161 if (tok_is_(tline
, "*")) {
2162 def
->nparam_max
= INT_MAX
;
2163 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2164 nasm_error(ERR_NONFATAL
,
2165 "`%s' expects a parameter count after `-'", directive
);
2167 def
->nparam_max
= readnum(tline
->text
, &err
);
2169 nasm_error(ERR_NONFATAL
, "unable to parse parameter count `%s'",
2172 if (def
->nparam_min
> def
->nparam_max
) {
2173 nasm_error(ERR_NONFATAL
, "minimum parameter count exceeds maximum");
2174 def
->nparam_max
= def
->nparam_min
;
2178 if (tline
&& tok_is_(tline
->next
, "+")) {
2179 tline
= tline
->next
;
2182 if (tline
&& tok_type_(tline
->next
, TOK_ID
) &&
2183 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
2184 tline
= tline
->next
;
2189 * Handle default parameters.
2191 if (tline
&& tline
->next
) {
2192 def
->dlist
= tline
->next
;
2194 count_mmac_params(def
->dlist
, &def
->ndefs
, &def
->defaults
);
2197 def
->defaults
= NULL
;
2199 def
->expansion
= NULL
;
2201 if (def
->defaults
&& def
->ndefs
> def
->nparam_max
- def
->nparam_min
&&
2203 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MDP
,
2204 "too many default macro parameters");
2211 * Decode a size directive
2213 static int parse_size(const char *str
) {
2214 static const char *size_names
[] =
2215 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2216 static const int sizes
[] =
2217 { 0, 1, 4, 16, 8, 10, 2, 32 };
2219 return sizes
[bsii(str
, size_names
, ARRAY_SIZE(size_names
))+1];
2223 * Process a preprocessor %pragma directive. Currently there are none.
2224 * Gets passed the token list starting with the "preproc" token from
2225 * "%pragma preproc".
2227 static void do_pragma_preproc(Token
*tline
)
2229 /* Skip to the real stuff */
2230 tline
= tline
->next
;
2235 (void)tline
; /* Nothing else to do at present */
2239 * find and process preprocessor directive in passed line
2240 * Find out if a line contains a preprocessor directive, and deal
2243 * If a directive _is_ found, it is the responsibility of this routine
2244 * (and not the caller) to free_tlist() the line.
2246 * @param tline a pointer to the current tokeninzed line linked list
2247 * @param output if this directive generated output
2248 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2251 static int do_directive(Token
*tline
, char **output
)
2253 enum preproc_token i
;
2262 const char *found_path
;
2267 MMacro
*mmac
, **mmhead
;
2268 Token
*t
= NULL
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
2270 struct tokenval tokval
;
2272 MMacro
*tmp_defining
; /* Used when manipulating rep_nest */
2277 *output
= NULL
; /* No output generated */
2281 if (!tline
|| !tok_type_(tline
, TOK_PREPROC_ID
) ||
2282 (tline
->text
[1] == '%' || tline
->text
[1] == '$'
2283 || tline
->text
[1] == '!'))
2284 return NO_DIRECTIVE_FOUND
;
2286 i
= pp_token_hash(tline
->text
);
2289 * FIXME: We zap execution of PP_RMACRO, PP_IRMACRO, PP_EXITMACRO
2290 * since they are known to be buggy at moment, we need to fix them
2291 * in future release (2.09-2.10)
2293 if (i
== PP_RMACRO
|| i
== PP_IRMACRO
|| i
== PP_EXITMACRO
) {
2294 nasm_error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2296 return NO_DIRECTIVE_FOUND
;
2300 * If we're in a non-emitting branch of a condition construct,
2301 * or walking to the end of an already terminated %rep block,
2302 * we should ignore all directives except for condition
2305 if (((istk
->conds
&& !emitting(istk
->conds
->state
)) ||
2306 (istk
->mstk
&& !istk
->mstk
->in_progress
)) && !is_condition(i
)) {
2307 return NO_DIRECTIVE_FOUND
;
2311 * If we're defining a macro or reading a %rep block, we should
2312 * ignore all directives except for %macro/%imacro (which nest),
2313 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2314 * If we're in a %rep block, another %rep nests, so should be let through.
2316 if (defining
&& i
!= PP_MACRO
&& i
!= PP_IMACRO
&&
2317 i
!= PP_RMACRO
&& i
!= PP_IRMACRO
&&
2318 i
!= PP_ENDMACRO
&& i
!= PP_ENDM
&&
2319 (defining
->name
|| (i
!= PP_ENDREP
&& i
!= PP_REP
))) {
2320 return NO_DIRECTIVE_FOUND
;
2324 if (i
== PP_MACRO
|| i
== PP_IMACRO
||
2325 i
== PP_RMACRO
|| i
== PP_IRMACRO
) {
2327 return NO_DIRECTIVE_FOUND
;
2328 } else if (nested_mac_count
> 0) {
2329 if (i
== PP_ENDMACRO
) {
2331 return NO_DIRECTIVE_FOUND
;
2334 if (!defining
->name
) {
2337 return NO_DIRECTIVE_FOUND
;
2338 } else if (nested_rep_count
> 0) {
2339 if (i
== PP_ENDREP
) {
2341 return NO_DIRECTIVE_FOUND
;
2349 nasm_error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2351 return NO_DIRECTIVE_FOUND
; /* didn't get it */
2355 * %pragma namespace options...
2357 * The namespace "preproc" is reserved for the preprocessor;
2358 * all other namespaces generate a [pragma] assembly directive.
2360 * Invalid %pragmas are ignored and may have different
2361 * meaning in future versions of NASM.
2363 tline
= tline
->next
;
2365 tline
= expand_smacro(tline
);
2366 if (tok_type_(tline
, TOK_ID
)) {
2367 if (!nasm_stricmp(tline
->text
, "preproc")) {
2368 /* Preprocessor pragma */
2369 do_pragma_preproc(tline
);
2371 /* Build the assembler directive */
2372 t
= new_Token(NULL
, TOK_OTHER
, "[", 1);
2373 t
->next
= new_Token(NULL
, TOK_ID
, "pragma", 6);
2374 t
->next
->next
= new_Token(tline
, TOK_WHITESPACE
, NULL
, 0);
2376 for (t
= tline
; t
->next
; t
= t
->next
)
2378 t
->next
= new_Token(NULL
, TOK_OTHER
, "]", 1);
2379 /* true here can be revisited in the future */
2380 *output
= detoken(tline
, true);
2383 free_tlist(origline
);
2384 return DIRECTIVE_FOUND
;
2387 /* Directive to tell NASM what the default stack size is. The
2388 * default is for a 16-bit stack, and this can be overriden with
2391 tline
= tline
->next
;
2392 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2393 tline
= tline
->next
;
2394 if (!tline
|| tline
->type
!= TOK_ID
) {
2395 nasm_error(ERR_NONFATAL
, "`%%stacksize' missing size parameter");
2396 free_tlist(origline
);
2397 return DIRECTIVE_FOUND
;
2399 if (nasm_stricmp(tline
->text
, "flat") == 0) {
2400 /* All subsequent ARG directives are for a 32-bit stack */
2402 StackPointer
= "ebp";
2405 } else if (nasm_stricmp(tline
->text
, "flat64") == 0) {
2406 /* All subsequent ARG directives are for a 64-bit stack */
2408 StackPointer
= "rbp";
2411 } else if (nasm_stricmp(tline
->text
, "large") == 0) {
2412 /* All subsequent ARG directives are for a 16-bit stack,
2413 * far function call.
2416 StackPointer
= "bp";
2419 } else if (nasm_stricmp(tline
->text
, "small") == 0) {
2420 /* All subsequent ARG directives are for a 16-bit stack,
2421 * far function call. We don't support near functions.
2424 StackPointer
= "bp";
2428 nasm_error(ERR_NONFATAL
, "`%%stacksize' invalid size type");
2429 free_tlist(origline
);
2430 return DIRECTIVE_FOUND
;
2432 free_tlist(origline
);
2433 return DIRECTIVE_FOUND
;
2436 /* TASM like ARG directive to define arguments to functions, in
2437 * the following form:
2439 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2443 char *arg
, directive
[256];
2444 int size
= StackSize
;
2446 /* Find the argument name */
2447 tline
= tline
->next
;
2448 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2449 tline
= tline
->next
;
2450 if (!tline
|| tline
->type
!= TOK_ID
) {
2451 nasm_error(ERR_NONFATAL
, "`%%arg' missing argument parameter");
2452 free_tlist(origline
);
2453 return DIRECTIVE_FOUND
;
2457 /* Find the argument size type */
2458 tline
= tline
->next
;
2459 if (!tline
|| tline
->type
!= TOK_OTHER
2460 || tline
->text
[0] != ':') {
2461 nasm_error(ERR_NONFATAL
,
2462 "Syntax error processing `%%arg' directive");
2463 free_tlist(origline
);
2464 return DIRECTIVE_FOUND
;
2466 tline
= tline
->next
;
2467 if (!tline
|| tline
->type
!= TOK_ID
) {
2468 nasm_error(ERR_NONFATAL
, "`%%arg' missing size type parameter");
2469 free_tlist(origline
);
2470 return DIRECTIVE_FOUND
;
2473 /* Allow macro expansion of type parameter */
2474 tt
= tokenize(tline
->text
);
2475 tt
= expand_smacro(tt
);
2476 size
= parse_size(tt
->text
);
2478 nasm_error(ERR_NONFATAL
,
2479 "Invalid size type for `%%arg' missing directive");
2481 free_tlist(origline
);
2482 return DIRECTIVE_FOUND
;
2486 /* Round up to even stack slots */
2487 size
= ALIGN(size
, StackSize
);
2489 /* Now define the macro for the argument */
2490 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
2491 arg
, StackPointer
, offset
);
2492 do_directive(tokenize(directive
), output
);
2495 /* Move to the next argument in the list */
2496 tline
= tline
->next
;
2497 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2498 tline
= tline
->next
;
2499 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2501 free_tlist(origline
);
2502 return DIRECTIVE_FOUND
;
2505 /* TASM like LOCAL directive to define local variables for a
2506 * function, in the following form:
2508 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2510 * The '= LocalSize' at the end is ignored by NASM, but is
2511 * required by TASM to define the local parameter size (and used
2512 * by the TASM macro package).
2514 offset
= LocalOffset
;
2516 char *local
, directive
[256];
2517 int size
= StackSize
;
2519 /* Find the argument name */
2520 tline
= tline
->next
;
2521 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2522 tline
= tline
->next
;
2523 if (!tline
|| tline
->type
!= TOK_ID
) {
2524 nasm_error(ERR_NONFATAL
,
2525 "`%%local' missing argument parameter");
2526 free_tlist(origline
);
2527 return DIRECTIVE_FOUND
;
2529 local
= tline
->text
;
2531 /* Find the argument size type */
2532 tline
= tline
->next
;
2533 if (!tline
|| tline
->type
!= TOK_OTHER
2534 || tline
->text
[0] != ':') {
2535 nasm_error(ERR_NONFATAL
,
2536 "Syntax error processing `%%local' directive");
2537 free_tlist(origline
);
2538 return DIRECTIVE_FOUND
;
2540 tline
= tline
->next
;
2541 if (!tline
|| tline
->type
!= TOK_ID
) {
2542 nasm_error(ERR_NONFATAL
,
2543 "`%%local' missing size type parameter");
2544 free_tlist(origline
);
2545 return DIRECTIVE_FOUND
;
2548 /* Allow macro expansion of type parameter */
2549 tt
= tokenize(tline
->text
);
2550 tt
= expand_smacro(tt
);
2551 size
= parse_size(tt
->text
);
2553 nasm_error(ERR_NONFATAL
,
2554 "Invalid size type for `%%local' missing directive");
2556 free_tlist(origline
);
2557 return DIRECTIVE_FOUND
;
2561 /* Round up to even stack slots */
2562 size
= ALIGN(size
, StackSize
);
2564 offset
+= size
; /* Negative offset, increment before */
2566 /* Now define the macro for the argument */
2567 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
2568 local
, StackPointer
, offset
);
2569 do_directive(tokenize(directive
), output
);
2571 /* Now define the assign to setup the enter_c macro correctly */
2572 snprintf(directive
, sizeof(directive
),
2573 "%%assign %%$localsize %%$localsize+%d", size
);
2574 do_directive(tokenize(directive
), output
);
2576 /* Move to the next argument in the list */
2577 tline
= tline
->next
;
2578 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2579 tline
= tline
->next
;
2580 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2581 LocalOffset
= offset
;
2582 free_tlist(origline
);
2583 return DIRECTIVE_FOUND
;
2587 nasm_error(ERR_WARNING
|ERR_PASS1
,
2588 "trailing garbage after `%%clear' ignored");
2591 free_tlist(origline
);
2592 return DIRECTIVE_FOUND
;
2595 t
= tline
->next
= expand_smacro(tline
->next
);
2597 if (!t
|| (t
->type
!= TOK_STRING
&&
2598 t
->type
!= TOK_INTERNAL_STRING
)) {
2599 nasm_error(ERR_NONFATAL
, "`%%depend' expects a file name");
2600 free_tlist(origline
);
2601 return DIRECTIVE_FOUND
; /* but we did _something_ */
2604 nasm_error(ERR_WARNING
|ERR_PASS1
,
2605 "trailing garbage after `%%depend' ignored");
2607 if (t
->type
!= TOK_INTERNAL_STRING
)
2608 nasm_unquote_cstr(p
, i
);
2609 nasm_add_string_to_strlist(dephead
, p
);
2610 free_tlist(origline
);
2611 return DIRECTIVE_FOUND
;
2614 t
= tline
->next
= expand_smacro(tline
->next
);
2617 if (!t
|| (t
->type
!= TOK_STRING
&&
2618 t
->type
!= TOK_INTERNAL_STRING
)) {
2619 nasm_error(ERR_NONFATAL
, "`%%include' expects a file name");
2620 free_tlist(origline
);
2621 return DIRECTIVE_FOUND
; /* but we did _something_ */
2624 nasm_error(ERR_WARNING
|ERR_PASS1
,
2625 "trailing garbage after `%%include' ignored");
2627 if (t
->type
!= TOK_INTERNAL_STRING
)
2628 nasm_unquote_cstr(p
, i
);
2629 inc
= nasm_malloc(sizeof(Include
));
2633 inc
->fp
= inc_fopen(p
, dephead
, &found_path
,
2634 pass
== 0 ? INC_OPTIONAL
: INC_NEEDED
, NF_TEXT
);
2636 /* -MG given but file not found */
2639 inc
->fname
= src_set_fname(found_path
? found_path
: p
);
2640 inc
->lineno
= src_set_linnum(0);
2642 inc
->expansion
= NULL
;
2645 lfmt
->uplevel(LIST_INCLUDE
);
2647 free_tlist(origline
);
2648 return DIRECTIVE_FOUND
;
2652 static macros_t
*use_pkg
;
2653 const char *pkg_macro
= NULL
;
2655 tline
= tline
->next
;
2657 tline
= expand_id(tline
);
2659 if (!tline
|| (tline
->type
!= TOK_STRING
&&
2660 tline
->type
!= TOK_INTERNAL_STRING
&&
2661 tline
->type
!= TOK_ID
)) {
2662 nasm_error(ERR_NONFATAL
, "`%%use' expects a package name");
2663 free_tlist(origline
);
2664 return DIRECTIVE_FOUND
; /* but we did _something_ */
2667 nasm_error(ERR_WARNING
|ERR_PASS1
,
2668 "trailing garbage after `%%use' ignored");
2669 if (tline
->type
== TOK_STRING
)
2670 nasm_unquote_cstr(tline
->text
, i
);
2671 use_pkg
= nasm_stdmac_find_package(tline
->text
);
2673 nasm_error(ERR_NONFATAL
, "unknown `%%use' package: %s", tline
->text
);
2675 pkg_macro
= (char *)use_pkg
+ 1; /* The first string will be <%define>__USE_*__ */
2676 if (use_pkg
&& ! smacro_defined(NULL
, pkg_macro
, 0, NULL
, true)) {
2677 /* Not already included, go ahead and include it */
2678 stdmacpos
= use_pkg
;
2680 free_tlist(origline
);
2681 return DIRECTIVE_FOUND
;
2686 tline
= tline
->next
;
2688 tline
= expand_id(tline
);
2690 if (!tok_type_(tline
, TOK_ID
)) {
2691 nasm_error(ERR_NONFATAL
, "`%s' expects a context identifier",
2693 free_tlist(origline
);
2694 return DIRECTIVE_FOUND
; /* but we did _something_ */
2697 nasm_error(ERR_WARNING
|ERR_PASS1
,
2698 "trailing garbage after `%s' ignored",
2700 p
= nasm_strdup(tline
->text
);
2702 p
= NULL
; /* Anonymous */
2706 ctx
= nasm_malloc(sizeof(Context
));
2708 hash_init(&ctx
->localmac
, HASH_SMALL
);
2710 ctx
->number
= unique
++;
2715 nasm_error(ERR_NONFATAL
, "`%s': context stack is empty",
2717 } else if (i
== PP_POP
) {
2718 if (p
&& (!cstk
->name
|| nasm_stricmp(p
, cstk
->name
)))
2719 nasm_error(ERR_NONFATAL
, "`%%pop' in wrong context: %s, "
2721 cstk
->name
? cstk
->name
: "anonymous", p
);
2726 nasm_free(cstk
->name
);
2732 free_tlist(origline
);
2733 return DIRECTIVE_FOUND
;
2735 severity
= ERR_FATAL
;
2738 severity
= ERR_NONFATAL
;
2741 severity
= ERR_WARNING
|ERR_WARN_USER
;
2746 /* Only error out if this is the final pass */
2747 if (pass
!= 2 && i
!= PP_FATAL
)
2748 return DIRECTIVE_FOUND
;
2750 tline
->next
= expand_smacro(tline
->next
);
2751 tline
= tline
->next
;
2753 t
= tline
? tline
->next
: NULL
;
2755 if (tok_type_(tline
, TOK_STRING
) && !t
) {
2756 /* The line contains only a quoted string */
2758 nasm_unquote(p
, NULL
); /* Ignore NUL character truncation */
2759 nasm_error(severity
, "%s", p
);
2761 /* Not a quoted string, or more than a quoted string */
2762 p
= detoken(tline
, false);
2763 nasm_error(severity
, "%s", p
);
2766 free_tlist(origline
);
2767 return DIRECTIVE_FOUND
;
2771 if (istk
->conds
&& !emitting(istk
->conds
->state
))
2774 j
= if_condition(tline
->next
, i
);
2775 tline
->next
= NULL
; /* it got freed */
2776 j
= j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2778 cond
= nasm_malloc(sizeof(Cond
));
2779 cond
->next
= istk
->conds
;
2783 istk
->mstk
->condcnt
++;
2784 free_tlist(origline
);
2785 return DIRECTIVE_FOUND
;
2789 nasm_error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2790 switch(istk
->conds
->state
) {
2792 istk
->conds
->state
= COND_DONE
;
2799 case COND_ELSE_TRUE
:
2800 case COND_ELSE_FALSE
:
2801 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_PP_PRECOND
,
2802 "`%%elif' after `%%else' ignored");
2803 istk
->conds
->state
= COND_NEVER
;
2808 * IMPORTANT: In the case of %if, we will already have
2809 * called expand_mmac_params(); however, if we're
2810 * processing an %elif we must have been in a
2811 * non-emitting mode, which would have inhibited
2812 * the normal invocation of expand_mmac_params().
2813 * Therefore, we have to do it explicitly here.
2815 j
= if_condition(expand_mmac_params(tline
->next
), i
);
2816 tline
->next
= NULL
; /* it got freed */
2817 istk
->conds
->state
=
2818 j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2821 free_tlist(origline
);
2822 return DIRECTIVE_FOUND
;
2826 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_PP_PRECOND
,
2827 "trailing garbage after `%%else' ignored");
2829 nasm_fatal(0, "`%%else: no matching `%%if'");
2830 switch(istk
->conds
->state
) {
2833 istk
->conds
->state
= COND_ELSE_FALSE
;
2840 istk
->conds
->state
= COND_ELSE_TRUE
;
2843 case COND_ELSE_TRUE
:
2844 case COND_ELSE_FALSE
:
2845 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_PP_PRECOND
,
2846 "`%%else' after `%%else' ignored.");
2847 istk
->conds
->state
= COND_NEVER
;
2850 free_tlist(origline
);
2851 return DIRECTIVE_FOUND
;
2855 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_PP_PRECOND
,
2856 "trailing garbage after `%%endif' ignored");
2858 nasm_error(ERR_FATAL
, "`%%endif': no matching `%%if'");
2860 istk
->conds
= cond
->next
;
2863 istk
->mstk
->condcnt
--;
2864 free_tlist(origline
);
2865 return DIRECTIVE_FOUND
;
2872 nasm_error(ERR_FATAL
, "`%s': already defining a macro",
2874 return DIRECTIVE_FOUND
;
2876 defining
= nasm_zalloc(sizeof(MMacro
));
2877 defining
->max_depth
=
2878 (i
== PP_RMACRO
) || (i
== PP_IRMACRO
) ? DEADMAN_LIMIT
: 0;
2879 defining
->casesense
= (i
== PP_MACRO
) || (i
== PP_RMACRO
);
2880 if (!parse_mmacro_spec(tline
, defining
, pp_directives
[i
])) {
2881 nasm_free(defining
);
2883 return DIRECTIVE_FOUND
;
2886 src_get(&defining
->xline
, &defining
->fname
);
2888 mmac
= (MMacro
*) hash_findix(&mmacros
, defining
->name
);
2890 if (!strcmp(mmac
->name
, defining
->name
) &&
2891 (mmac
->nparam_min
<= defining
->nparam_max
2893 && (defining
->nparam_min
<= mmac
->nparam_max
2895 nasm_error(ERR_WARNING
|ERR_PASS1
,
2896 "redefining multi-line macro `%s'", defining
->name
);
2897 return DIRECTIVE_FOUND
;
2901 free_tlist(origline
);
2902 return DIRECTIVE_FOUND
;
2906 if (! (defining
&& defining
->name
)) {
2907 nasm_error(ERR_NONFATAL
, "`%s': not defining a macro", tline
->text
);
2908 return DIRECTIVE_FOUND
;
2910 mmhead
= (MMacro
**) hash_findi_add(&mmacros
, defining
->name
);
2911 defining
->next
= *mmhead
;
2914 free_tlist(origline
);
2915 return DIRECTIVE_FOUND
;
2919 * We must search along istk->expansion until we hit a
2920 * macro-end marker for a macro with a name. Then we
2921 * bypass all lines between exitmacro and endmacro.
2923 list_for_each(l
, istk
->expansion
)
2924 if (l
->finishes
&& l
->finishes
->name
)
2929 * Remove all conditional entries relative to this
2930 * macro invocation. (safe to do in this context)
2932 for ( ; l
->finishes
->condcnt
> 0; l
->finishes
->condcnt
--) {
2934 istk
->conds
= cond
->next
;
2937 istk
->expansion
= l
;
2939 nasm_error(ERR_NONFATAL
, "`%%exitmacro' not within `%%macro' block");
2941 free_tlist(origline
);
2942 return DIRECTIVE_FOUND
;
2950 spec
.casesense
= (i
== PP_UNMACRO
);
2951 if (!parse_mmacro_spec(tline
, &spec
, pp_directives
[i
])) {
2952 return DIRECTIVE_FOUND
;
2954 mmac_p
= (MMacro
**) hash_findi(&mmacros
, spec
.name
, NULL
);
2955 while (mmac_p
&& *mmac_p
) {
2957 if (mmac
->casesense
== spec
.casesense
&&
2958 !mstrcmp(mmac
->name
, spec
.name
, spec
.casesense
) &&
2959 mmac
->nparam_min
== spec
.nparam_min
&&
2960 mmac
->nparam_max
== spec
.nparam_max
&&
2961 mmac
->plus
== spec
.plus
) {
2962 *mmac_p
= mmac
->next
;
2965 mmac_p
= &mmac
->next
;
2968 free_tlist(origline
);
2969 free_tlist(spec
.dlist
);
2970 return DIRECTIVE_FOUND
;
2974 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
2975 tline
= tline
->next
;
2977 free_tlist(origline
);
2978 nasm_error(ERR_NONFATAL
, "`%%rotate' missing rotate count");
2979 return DIRECTIVE_FOUND
;
2981 t
= expand_smacro(tline
->next
);
2983 free_tlist(origline
);
2986 tokval
.t_type
= TOKEN_INVALID
;
2988 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, NULL
);
2991 return DIRECTIVE_FOUND
;
2993 nasm_error(ERR_WARNING
|ERR_PASS1
,
2994 "trailing garbage after expression ignored");
2995 if (!is_simple(evalresult
)) {
2996 nasm_error(ERR_NONFATAL
, "non-constant value given to `%%rotate'");
2997 return DIRECTIVE_FOUND
;
3000 while (mmac
&& !mmac
->name
) /* avoid mistaking %reps for macros */
3001 mmac
= mmac
->next_active
;
3003 nasm_error(ERR_NONFATAL
, "`%%rotate' invoked outside a macro call");
3004 } else if (mmac
->nparam
== 0) {
3005 nasm_error(ERR_NONFATAL
,
3006 "`%%rotate' invoked within macro without parameters");
3008 int rotate
= mmac
->rotate
+ reloc_value(evalresult
);
3010 rotate
%= (int)mmac
->nparam
;
3012 rotate
+= mmac
->nparam
;
3014 mmac
->rotate
= rotate
;
3016 return DIRECTIVE_FOUND
;
3021 tline
= tline
->next
;
3022 } while (tok_type_(tline
, TOK_WHITESPACE
));
3024 if (tok_type_(tline
, TOK_ID
) &&
3025 nasm_stricmp(tline
->text
, ".nolist") == 0) {
3028 tline
= tline
->next
;
3029 } while (tok_type_(tline
, TOK_WHITESPACE
));
3033 t
= expand_smacro(tline
);
3035 tokval
.t_type
= TOKEN_INVALID
;
3037 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, NULL
);
3039 free_tlist(origline
);
3040 return DIRECTIVE_FOUND
;
3043 nasm_error(ERR_WARNING
|ERR_PASS1
,
3044 "trailing garbage after expression ignored");
3045 if (!is_simple(evalresult
)) {
3046 nasm_error(ERR_NONFATAL
, "non-constant value given to `%%rep'");
3047 return DIRECTIVE_FOUND
;
3049 count
= reloc_value(evalresult
);
3050 if (count
>= REP_LIMIT
) {
3051 nasm_error(ERR_NONFATAL
, "`%%rep' value exceeds limit");
3056 nasm_error(ERR_NONFATAL
, "`%%rep' expects a repeat count");
3059 free_tlist(origline
);
3061 tmp_defining
= defining
;
3062 defining
= nasm_malloc(sizeof(MMacro
));
3063 defining
->prev
= NULL
;
3064 defining
->name
= NULL
; /* flags this macro as a %rep block */
3065 defining
->casesense
= false;
3066 defining
->plus
= false;
3067 defining
->nolist
= nolist
;
3068 defining
->in_progress
= count
;
3069 defining
->max_depth
= 0;
3070 defining
->nparam_min
= defining
->nparam_max
= 0;
3071 defining
->defaults
= NULL
;
3072 defining
->dlist
= NULL
;
3073 defining
->expansion
= NULL
;
3074 defining
->next_active
= istk
->mstk
;
3075 defining
->rep_nest
= tmp_defining
;
3076 return DIRECTIVE_FOUND
;
3079 if (!defining
|| defining
->name
) {
3080 nasm_error(ERR_NONFATAL
, "`%%endrep': no matching `%%rep'");
3081 return DIRECTIVE_FOUND
;
3085 * Now we have a "macro" defined - although it has no name
3086 * and we won't be entering it in the hash tables - we must
3087 * push a macro-end marker for it on to istk->expansion.
3088 * After that, it will take care of propagating itself (a
3089 * macro-end marker line for a macro which is really a %rep
3090 * block will cause the macro to be re-expanded, complete
3091 * with another macro-end marker to ensure the process
3092 * continues) until the whole expansion is forcibly removed
3093 * from istk->expansion by a %exitrep.
3095 l
= nasm_malloc(sizeof(Line
));
3096 l
->next
= istk
->expansion
;
3097 l
->finishes
= defining
;
3099 istk
->expansion
= l
;
3101 istk
->mstk
= defining
;
3103 lfmt
->uplevel(defining
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
3104 tmp_defining
= defining
;
3105 defining
= defining
->rep_nest
;
3106 free_tlist(origline
);
3107 return DIRECTIVE_FOUND
;
3111 * We must search along istk->expansion until we hit a
3112 * macro-end marker for a macro with no name. Then we set
3113 * its `in_progress' flag to 0.
3115 list_for_each(l
, istk
->expansion
)
3116 if (l
->finishes
&& !l
->finishes
->name
)
3120 l
->finishes
->in_progress
= 1;
3122 nasm_error(ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
3123 free_tlist(origline
);
3124 return DIRECTIVE_FOUND
;
3130 casesense
= (i
== PP_DEFINE
|| i
== PP_XDEFINE
);
3132 tline
= tline
->next
;
3134 tline
= expand_id(tline
);
3135 if (!tline
|| (tline
->type
!= TOK_ID
&&
3136 (tline
->type
!= TOK_PREPROC_ID
||
3137 tline
->text
[1] != '$'))) {
3138 nasm_error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3140 free_tlist(origline
);
3141 return DIRECTIVE_FOUND
;
3144 ctx
= get_ctx(tline
->text
, &mname
);
3146 param_start
= tline
= tline
->next
;
3149 /* Expand the macro definition now for %xdefine and %ixdefine */
3150 if ((i
== PP_XDEFINE
) || (i
== PP_IXDEFINE
))
3151 tline
= expand_smacro(tline
);
3153 if (tok_is_(tline
, "(")) {
3155 * This macro has parameters.
3158 tline
= tline
->next
;
3162 nasm_error(ERR_NONFATAL
, "parameter identifier expected");
3163 free_tlist(origline
);
3164 return DIRECTIVE_FOUND
;
3166 if (tline
->type
!= TOK_ID
) {
3167 nasm_error(ERR_NONFATAL
,
3168 "`%s': parameter identifier expected",
3170 free_tlist(origline
);
3171 return DIRECTIVE_FOUND
;
3173 tline
->type
= TOK_SMAC_PARAM
+ nparam
++;
3174 tline
= tline
->next
;
3176 if (tok_is_(tline
, ",")) {
3177 tline
= tline
->next
;
3179 if (!tok_is_(tline
, ")")) {
3180 nasm_error(ERR_NONFATAL
,
3181 "`)' expected to terminate macro template");
3182 free_tlist(origline
);
3183 return DIRECTIVE_FOUND
;
3189 tline
= tline
->next
;
3191 if (tok_type_(tline
, TOK_WHITESPACE
))
3192 last
= tline
, tline
= tline
->next
;
3197 if (t
->type
== TOK_ID
) {
3198 list_for_each(tt
, param_start
)
3199 if (tt
->type
>= TOK_SMAC_PARAM
&&
3200 !strcmp(tt
->text
, t
->text
))
3204 t
->next
= macro_start
;
3209 * Good. We now have a macro name, a parameter count, and a
3210 * token list (in reverse order) for an expansion. We ought
3211 * to be OK just to create an SMacro, store it, and let
3212 * free_tlist have the rest of the line (which we have
3213 * carefully re-terminated after chopping off the expansion
3216 define_smacro(ctx
, mname
, casesense
, nparam
, macro_start
);
3217 free_tlist(origline
);
3218 return DIRECTIVE_FOUND
;
3221 tline
= tline
->next
;
3223 tline
= expand_id(tline
);
3224 if (!tline
|| (tline
->type
!= TOK_ID
&&
3225 (tline
->type
!= TOK_PREPROC_ID
||
3226 tline
->text
[1] != '$'))) {
3227 nasm_error(ERR_NONFATAL
, "`%%undef' expects a macro identifier");
3228 free_tlist(origline
);
3229 return DIRECTIVE_FOUND
;
3232 nasm_error(ERR_WARNING
|ERR_PASS1
,
3233 "trailing garbage after macro name ignored");
3236 /* Find the context that symbol belongs to */
3237 ctx
= get_ctx(tline
->text
, &mname
);
3238 undef_smacro(ctx
, mname
);
3239 free_tlist(origline
);
3240 return DIRECTIVE_FOUND
;
3244 casesense
= (i
== PP_DEFSTR
);
3246 tline
= tline
->next
;
3248 tline
= expand_id(tline
);
3249 if (!tline
|| (tline
->type
!= TOK_ID
&&
3250 (tline
->type
!= TOK_PREPROC_ID
||
3251 tline
->text
[1] != '$'))) {
3252 nasm_error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3254 free_tlist(origline
);
3255 return DIRECTIVE_FOUND
;
3258 ctx
= get_ctx(tline
->text
, &mname
);
3260 tline
= expand_smacro(tline
->next
);
3263 while (tok_type_(tline
, TOK_WHITESPACE
))
3264 tline
= delete_Token(tline
);
3266 p
= detoken(tline
, false);
3267 macro_start
= nasm_malloc(sizeof(*macro_start
));
3268 macro_start
->next
= NULL
;
3269 macro_start
->text
= nasm_quote(p
, strlen(p
));
3270 macro_start
->type
= TOK_STRING
;
3271 macro_start
->a
.mac
= NULL
;
3275 * We now have a macro name, an implicit parameter count of
3276 * zero, and a string token to use as an expansion. Create
3277 * and store an SMacro.
3279 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3280 free_tlist(origline
);
3281 return DIRECTIVE_FOUND
;
3285 casesense
= (i
== PP_DEFTOK
);
3287 tline
= tline
->next
;
3289 tline
= expand_id(tline
);
3290 if (!tline
|| (tline
->type
!= TOK_ID
&&
3291 (tline
->type
!= TOK_PREPROC_ID
||
3292 tline
->text
[1] != '$'))) {
3293 nasm_error(ERR_NONFATAL
,
3294 "`%s' expects a macro identifier as first parameter",
3296 free_tlist(origline
);
3297 return DIRECTIVE_FOUND
;
3299 ctx
= get_ctx(tline
->text
, &mname
);
3301 tline
= expand_smacro(tline
->next
);
3305 while (tok_type_(t
, TOK_WHITESPACE
))
3307 /* t should now point to the string */
3308 if (!tok_type_(t
, TOK_STRING
)) {
3309 nasm_error(ERR_NONFATAL
,
3310 "`%s` requires string as second parameter",
3313 free_tlist(origline
);
3314 return DIRECTIVE_FOUND
;
3318 * Convert the string to a token stream. Note that smacros
3319 * are stored with the token stream reversed, so we have to
3320 * reverse the output of tokenize().
3322 nasm_unquote_cstr(t
->text
, i
);
3323 macro_start
= reverse_tokens(tokenize(t
->text
));
3326 * We now have a macro name, an implicit parameter count of
3327 * zero, and a numeric token to use as an expansion. Create
3328 * and store an SMacro.
3330 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3332 free_tlist(origline
);
3333 return DIRECTIVE_FOUND
;
3337 const char *found_path
;
3341 tline
= tline
->next
;
3343 tline
= expand_id(tline
);
3344 if (!tline
|| (tline
->type
!= TOK_ID
&&
3345 (tline
->type
!= TOK_PREPROC_ID
||
3346 tline
->text
[1] != '$'))) {
3347 nasm_error(ERR_NONFATAL
,
3348 "`%%pathsearch' expects a macro identifier as first parameter");
3349 free_tlist(origline
);
3350 return DIRECTIVE_FOUND
;
3352 ctx
= get_ctx(tline
->text
, &mname
);
3354 tline
= expand_smacro(tline
->next
);
3358 while (tok_type_(t
, TOK_WHITESPACE
))
3361 if (!t
|| (t
->type
!= TOK_STRING
&&
3362 t
->type
!= TOK_INTERNAL_STRING
)) {
3363 nasm_error(ERR_NONFATAL
, "`%%pathsearch' expects a file name");
3365 free_tlist(origline
);
3366 return DIRECTIVE_FOUND
; /* but we did _something_ */
3369 nasm_error(ERR_WARNING
|ERR_PASS1
,
3370 "trailing garbage after `%%pathsearch' ignored");
3372 if (t
->type
!= TOK_INTERNAL_STRING
)
3373 nasm_unquote(p
, NULL
);
3375 inc_fopen(p
, NULL
, &found_path
, INC_PROBE
, NF_BINARY
);
3378 macro_start
= nasm_malloc(sizeof(*macro_start
));
3379 macro_start
->next
= NULL
;
3380 macro_start
->text
= nasm_quote(found_path
, strlen(found_path
));
3381 macro_start
->type
= TOK_STRING
;
3382 macro_start
->a
.mac
= NULL
;
3385 * We now have a macro name, an implicit parameter count of
3386 * zero, and a string token to use as an expansion. Create
3387 * and store an SMacro.
3389 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3391 free_tlist(origline
);
3392 return DIRECTIVE_FOUND
;
3398 tline
= tline
->next
;
3400 tline
= expand_id(tline
);
3401 if (!tline
|| (tline
->type
!= TOK_ID
&&
3402 (tline
->type
!= TOK_PREPROC_ID
||
3403 tline
->text
[1] != '$'))) {
3404 nasm_error(ERR_NONFATAL
,
3405 "`%%strlen' expects a macro identifier as first parameter");
3406 free_tlist(origline
);
3407 return DIRECTIVE_FOUND
;
3409 ctx
= get_ctx(tline
->text
, &mname
);
3411 tline
= expand_smacro(tline
->next
);
3415 while (tok_type_(t
, TOK_WHITESPACE
))
3417 /* t should now point to the string */
3418 if (!tok_type_(t
, TOK_STRING
)) {
3419 nasm_error(ERR_NONFATAL
,
3420 "`%%strlen` requires string as second parameter");
3422 free_tlist(origline
);
3423 return DIRECTIVE_FOUND
;
3426 macro_start
= nasm_malloc(sizeof(*macro_start
));
3427 macro_start
->next
= NULL
;
3428 make_tok_num(macro_start
, nasm_unquote(t
->text
, NULL
));
3429 macro_start
->a
.mac
= NULL
;
3432 * We now have a macro name, an implicit parameter count of
3433 * zero, and a numeric token to use as an expansion. Create
3434 * and store an SMacro.
3436 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3438 free_tlist(origline
);
3439 return DIRECTIVE_FOUND
;
3444 tline
= tline
->next
;
3446 tline
= expand_id(tline
);
3447 if (!tline
|| (tline
->type
!= TOK_ID
&&
3448 (tline
->type
!= TOK_PREPROC_ID
||
3449 tline
->text
[1] != '$'))) {
3450 nasm_error(ERR_NONFATAL
,
3451 "`%%strcat' expects a macro identifier as first parameter");
3452 free_tlist(origline
);
3453 return DIRECTIVE_FOUND
;
3455 ctx
= get_ctx(tline
->text
, &mname
);
3457 tline
= expand_smacro(tline
->next
);
3461 list_for_each(t
, tline
) {
3463 case TOK_WHITESPACE
:
3466 len
+= t
->a
.len
= nasm_unquote(t
->text
, NULL
);
3469 if (!strcmp(t
->text
, ",")) /* permit comma separators */
3471 /* else fall through */
3473 nasm_error(ERR_NONFATAL
,
3474 "non-string passed to `%%strcat' (%d)", t
->type
);
3476 free_tlist(origline
);
3477 return DIRECTIVE_FOUND
;
3481 p
= pp
= nasm_malloc(len
);
3482 list_for_each(t
, tline
) {
3483 if (t
->type
== TOK_STRING
) {
3484 memcpy(p
, t
->text
, t
->a
.len
);
3490 * We now have a macro name, an implicit parameter count of
3491 * zero, and a numeric token to use as an expansion. Create
3492 * and store an SMacro.
3494 macro_start
= new_Token(NULL
, TOK_STRING
, NULL
, 0);
3495 macro_start
->text
= nasm_quote(pp
, len
);
3497 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3499 free_tlist(origline
);
3500 return DIRECTIVE_FOUND
;
3504 int64_t start
, count
;
3509 tline
= tline
->next
;
3511 tline
= expand_id(tline
);
3512 if (!tline
|| (tline
->type
!= TOK_ID
&&
3513 (tline
->type
!= TOK_PREPROC_ID
||
3514 tline
->text
[1] != '$'))) {
3515 nasm_error(ERR_NONFATAL
,
3516 "`%%substr' expects a macro identifier as first parameter");
3517 free_tlist(origline
);
3518 return DIRECTIVE_FOUND
;
3520 ctx
= get_ctx(tline
->text
, &mname
);
3522 tline
= expand_smacro(tline
->next
);
3525 if (tline
) /* skip expanded id */
3527 while (tok_type_(t
, TOK_WHITESPACE
))
3530 /* t should now point to the string */
3531 if (!tok_type_(t
, TOK_STRING
)) {
3532 nasm_error(ERR_NONFATAL
,
3533 "`%%substr` requires string as second parameter");
3535 free_tlist(origline
);
3536 return DIRECTIVE_FOUND
;
3541 tokval
.t_type
= TOKEN_INVALID
;
3542 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, NULL
);
3545 free_tlist(origline
);
3546 return DIRECTIVE_FOUND
;
3547 } else if (!is_simple(evalresult
)) {
3548 nasm_error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3550 free_tlist(origline
);
3551 return DIRECTIVE_FOUND
;
3553 start
= evalresult
->value
- 1;
3555 while (tok_type_(tt
, TOK_WHITESPACE
))
3558 count
= 1; /* Backwards compatibility: one character */
3560 tokval
.t_type
= TOKEN_INVALID
;
3561 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, NULL
);
3564 free_tlist(origline
);
3565 return DIRECTIVE_FOUND
;
3566 } else if (!is_simple(evalresult
)) {
3567 nasm_error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3569 free_tlist(origline
);
3570 return DIRECTIVE_FOUND
;
3572 count
= evalresult
->value
;
3575 len
= nasm_unquote(t
->text
, NULL
);
3577 /* make start and count being in range */
3581 count
= len
+ count
+ 1 - start
;
3582 if (start
+ count
> (int64_t)len
)
3583 count
= len
- start
;
3584 if (!len
|| count
< 0 || start
>=(int64_t)len
)
3585 start
= -1, count
= 0; /* empty string */
3587 macro_start
= nasm_malloc(sizeof(*macro_start
));
3588 macro_start
->next
= NULL
;
3589 macro_start
->text
= nasm_quote((start
< 0) ? "" : t
->text
+ start
, count
);
3590 macro_start
->type
= TOK_STRING
;
3591 macro_start
->a
.mac
= NULL
;
3594 * We now have a macro name, an implicit parameter count of
3595 * zero, and a numeric token to use as an expansion. Create
3596 * and store an SMacro.
3598 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3600 free_tlist(origline
);
3601 return DIRECTIVE_FOUND
;
3606 casesense
= (i
== PP_ASSIGN
);
3608 tline
= tline
->next
;
3610 tline
= expand_id(tline
);
3611 if (!tline
|| (tline
->type
!= TOK_ID
&&
3612 (tline
->type
!= TOK_PREPROC_ID
||
3613 tline
->text
[1] != '$'))) {
3614 nasm_error(ERR_NONFATAL
,
3615 "`%%%sassign' expects a macro identifier",
3616 (i
== PP_IASSIGN
? "i" : ""));
3617 free_tlist(origline
);
3618 return DIRECTIVE_FOUND
;
3620 ctx
= get_ctx(tline
->text
, &mname
);
3622 tline
= expand_smacro(tline
->next
);
3627 tokval
.t_type
= TOKEN_INVALID
;
3628 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, NULL
);
3631 free_tlist(origline
);
3632 return DIRECTIVE_FOUND
;
3636 nasm_error(ERR_WARNING
|ERR_PASS1
,
3637 "trailing garbage after expression ignored");
3639 if (!is_simple(evalresult
)) {
3640 nasm_error(ERR_NONFATAL
,
3641 "non-constant value given to `%%%sassign'",
3642 (i
== PP_IASSIGN
? "i" : ""));
3643 free_tlist(origline
);
3644 return DIRECTIVE_FOUND
;
3647 macro_start
= nasm_malloc(sizeof(*macro_start
));
3648 macro_start
->next
= NULL
;
3649 make_tok_num(macro_start
, reloc_value(evalresult
));
3650 macro_start
->a
.mac
= NULL
;
3653 * We now have a macro name, an implicit parameter count of
3654 * zero, and a numeric token to use as an expansion. Create
3655 * and store an SMacro.
3657 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3658 free_tlist(origline
);
3659 return DIRECTIVE_FOUND
;
3663 * Syntax is `%line nnn[+mmm] [filename]'
3665 tline
= tline
->next
;
3667 if (!tok_type_(tline
, TOK_NUMBER
)) {
3668 nasm_error(ERR_NONFATAL
, "`%%line' expects line number");
3669 free_tlist(origline
);
3670 return DIRECTIVE_FOUND
;
3672 k
= readnum(tline
->text
, &err
);
3674 tline
= tline
->next
;
3675 if (tok_is_(tline
, "+")) {
3676 tline
= tline
->next
;
3677 if (!tok_type_(tline
, TOK_NUMBER
)) {
3678 nasm_error(ERR_NONFATAL
, "`%%line' expects line increment");
3679 free_tlist(origline
);
3680 return DIRECTIVE_FOUND
;
3682 m
= readnum(tline
->text
, &err
);
3683 tline
= tline
->next
;
3689 char *fname
= detoken(tline
, false);
3690 src_set_fname(fname
);
3693 free_tlist(origline
);
3694 return DIRECTIVE_FOUND
;
3697 nasm_error(ERR_FATAL
,
3698 "preprocessor directive `%s' not yet implemented",
3700 return DIRECTIVE_FOUND
;
3705 * Ensure that a macro parameter contains a condition code and
3706 * nothing else. Return the condition code index if so, or -1
3709 static int find_cc(Token
* t
)
3714 return -1; /* Probably a %+ without a space */
3719 if (t
->type
!= TOK_ID
)
3723 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
3726 return bsii(t
->text
, (const char **)conditions
, ARRAY_SIZE(conditions
));
3730 * This routines walks over tokens strem and hadnles tokens
3731 * pasting, if @handle_explicit passed then explicit pasting
3732 * term is handled, otherwise -- implicit pastings only.
3734 static bool paste_tokens(Token
**head
, const struct tokseq_match
*m
,
3735 size_t mnum
, bool handle_explicit
)
3737 Token
*tok
, *next
, **prev_next
, **prev_nonspace
;
3738 bool pasted
= false;
3743 * The last token before pasting. We need it
3744 * to be able to connect new handled tokens.
3745 * In other words if there were a tokens stream
3749 * and we've joined tokens B and C, the resulting
3757 if (!tok_type_(tok
, TOK_WHITESPACE
) && !tok_type_(tok
, TOK_PASTE
))
3758 prev_nonspace
= head
;
3760 prev_nonspace
= NULL
;
3762 while (tok
&& (next
= tok
->next
)) {
3764 switch (tok
->type
) {
3765 case TOK_WHITESPACE
:
3766 /* Zap redundant whitespaces */
3767 while (tok_type_(next
, TOK_WHITESPACE
))
3768 next
= delete_Token(next
);
3773 /* Explicit pasting */
3774 if (!handle_explicit
)
3776 next
= delete_Token(tok
);
3778 while (tok_type_(next
, TOK_WHITESPACE
))
3779 next
= delete_Token(next
);
3784 /* Left pasting token is start of line */
3786 nasm_error(ERR_FATAL
, "No lvalue found on pasting");
3789 * No ending token, this might happen in two
3792 * 1) There indeed no right token at all
3793 * 2) There is a bare "%define ID" statement,
3794 * and @ID does expand to whitespace.
3796 * So technically we need to do a grammar analysis
3797 * in another stage of parsing, but for now lets don't
3798 * change the behaviour people used to. Simply allow
3799 * whitespace after paste token.
3803 * Zap ending space tokens and that's all.
3805 tok
= (*prev_nonspace
)->next
;
3806 while (tok_type_(tok
, TOK_WHITESPACE
))
3807 tok
= delete_Token(tok
);
3808 tok
= *prev_nonspace
;
3813 tok
= *prev_nonspace
;
3814 while (tok_type_(tok
, TOK_WHITESPACE
))
3815 tok
= delete_Token(tok
);
3816 len
= strlen(tok
->text
);
3817 len
+= strlen(next
->text
);
3819 p
= buf
= nasm_malloc(len
+ 1);
3820 strcpy(p
, tok
->text
);
3821 p
= strchr(p
, '\0');
3822 strcpy(p
, next
->text
);
3826 tok
= tokenize(buf
);
3829 *prev_nonspace
= tok
;
3830 while (tok
&& tok
->next
)
3833 tok
->next
= delete_Token(next
);
3835 /* Restart from pasted tokens head */
3836 tok
= *prev_nonspace
;
3840 /* implicit pasting */
3841 for (i
= 0; i
< mnum
; i
++) {
3842 if (!(PP_CONCAT_MATCH(tok
, m
[i
].mask_head
)))
3846 while (next
&& PP_CONCAT_MATCH(next
, m
[i
].mask_tail
)) {
3847 len
+= strlen(next
->text
);
3855 len
+= strlen(tok
->text
);
3856 p
= buf
= nasm_malloc(len
+ 1);
3858 strcpy(p
, tok
->text
);
3859 p
= strchr(p
, '\0');
3860 tok
= delete_Token(tok
);
3862 while (tok
!= next
) {
3863 if (PP_CONCAT_MATCH(tok
, m
[i
].mask_tail
)) {
3864 strcpy(p
, tok
->text
);
3865 p
= strchr(p
, '\0');
3867 tok
= delete_Token(tok
);
3870 tok
= tokenize(buf
);
3879 * Connect pasted into original stream,
3880 * ie A -> new-tokens -> B
3882 while (tok
&& tok
->next
)
3889 /* Restart from pasted tokens head */
3890 tok
= prev_next
? *prev_next
: *head
;
3896 prev_next
= &tok
->next
;
3899 !tok_type_(tok
->next
, TOK_WHITESPACE
) &&
3900 !tok_type_(tok
->next
, TOK_PASTE
))
3901 prev_nonspace
= prev_next
;
3910 * expands to a list of tokens from %{x:y}
3912 static Token
*expand_mmac_params_range(MMacro
*mac
, Token
*tline
, Token
***last
)
3914 Token
*t
= tline
, **tt
, *tm
, *head
;
3918 pos
= strchr(tline
->text
, ':');
3921 lst
= atoi(pos
+ 1);
3922 fst
= atoi(tline
->text
+ 1);
3925 * only macros params are accounted so
3926 * if someone passes %0 -- we reject such
3929 if (lst
== 0 || fst
== 0)
3932 /* the values should be sane */
3933 if ((fst
> (int)mac
->nparam
|| fst
< (-(int)mac
->nparam
)) ||
3934 (lst
> (int)mac
->nparam
|| lst
< (-(int)mac
->nparam
)))
3937 fst
= fst
< 0 ? fst
+ (int)mac
->nparam
+ 1: fst
;
3938 lst
= lst
< 0 ? lst
+ (int)mac
->nparam
+ 1: lst
;
3940 /* counted from zero */
3944 * It will be at least one token. Note we
3945 * need to scan params until separator, otherwise
3946 * only first token will be passed.
3948 tm
= mac
->params
[(fst
+ mac
->rotate
) % mac
->nparam
];
3949 head
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3950 tt
= &head
->next
, tm
= tm
->next
;
3951 while (tok_isnt_(tm
, ",")) {
3952 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3953 *tt
= t
, tt
= &t
->next
, tm
= tm
->next
;
3957 for (i
= fst
+ 1; i
<= lst
; i
++) {
3958 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
3959 *tt
= t
, tt
= &t
->next
;
3960 j
= (i
+ mac
->rotate
) % mac
->nparam
;
3961 tm
= mac
->params
[j
];
3962 while (tok_isnt_(tm
, ",")) {
3963 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3964 *tt
= t
, tt
= &t
->next
, tm
= tm
->next
;
3968 for (i
= fst
- 1; i
>= lst
; i
--) {
3969 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
3970 *tt
= t
, tt
= &t
->next
;
3971 j
= (i
+ mac
->rotate
) % mac
->nparam
;
3972 tm
= mac
->params
[j
];
3973 while (tok_isnt_(tm
, ",")) {
3974 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3975 *tt
= t
, tt
= &t
->next
, tm
= tm
->next
;
3984 nasm_error(ERR_NONFATAL
, "`%%{%s}': macro parameters out of range",
3990 * Expand MMacro-local things: parameter references (%0, %n, %+n,
3991 * %-n) and MMacro-local identifiers (%%foo) as well as
3992 * macro indirection (%[...]) and range (%{..:..}).
3994 static Token
*expand_mmac_params(Token
* tline
)
3996 Token
*t
, *tt
, **tail
, *thead
;
3997 bool changed
= false;
4004 if (tline
->type
== TOK_PREPROC_ID
&&
4005 (((tline
->text
[1] == '+' || tline
->text
[1] == '-') && tline
->text
[2]) ||
4006 (tline
->text
[1] >= '0' && tline
->text
[1] <= '9') ||
4007 tline
->text
[1] == '%')) {
4009 int type
= 0, cc
; /* type = 0 to placate optimisers */
4016 tline
= tline
->next
;
4019 while (mac
&& !mac
->name
) /* avoid mistaking %reps for macros */
4020 mac
= mac
->next_active
;
4022 nasm_error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
4024 pos
= strchr(t
->text
, ':');
4026 switch (t
->text
[1]) {
4028 * We have to make a substitution of one of the
4029 * forms %1, %-1, %+1, %%foo, %0.
4033 snprintf(tmpbuf
, sizeof(tmpbuf
), "%d", mac
->nparam
);
4034 text
= nasm_strdup(tmpbuf
);
4038 snprintf(tmpbuf
, sizeof(tmpbuf
), "..@%"PRIu64
".",
4040 text
= nasm_strcat(tmpbuf
, t
->text
+ 2);
4043 n
= atoi(t
->text
+ 2) - 1;
4044 if (n
>= mac
->nparam
)
4047 if (mac
->nparam
> 1)
4048 n
= (n
+ mac
->rotate
) % mac
->nparam
;
4049 tt
= mac
->params
[n
];
4053 nasm_error(ERR_NONFATAL
,
4054 "macro parameter %d is not a condition code",
4059 if (inverse_ccs
[cc
] == -1) {
4060 nasm_error(ERR_NONFATAL
,
4061 "condition code `%s' is not invertible",
4065 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
4069 n
= atoi(t
->text
+ 2) - 1;
4070 if (n
>= mac
->nparam
)
4073 if (mac
->nparam
> 1)
4074 n
= (n
+ mac
->rotate
) % mac
->nparam
;
4075 tt
= mac
->params
[n
];
4079 nasm_error(ERR_NONFATAL
,
4080 "macro parameter %d is not a condition code",
4085 text
= nasm_strdup(conditions
[cc
]);
4089 n
= atoi(t
->text
+ 1) - 1;
4090 if (n
>= mac
->nparam
)
4093 if (mac
->nparam
> 1)
4094 n
= (n
+ mac
->rotate
) % mac
->nparam
;
4095 tt
= mac
->params
[n
];
4098 for (i
= 0; i
< mac
->paramlen
[n
]; i
++) {
4099 *tail
= new_Token(NULL
, tt
->type
, tt
->text
, 0);
4100 tail
= &(*tail
)->next
;
4104 text
= NULL
; /* we've done it here */
4109 * seems we have a parameters range here
4111 Token
*head
, **last
;
4112 head
= expand_mmac_params_range(mac
, t
, &last
);
4133 } else if (tline
->type
== TOK_INDIRECT
) {
4135 tline
= tline
->next
;
4136 tt
= tokenize(t
->text
);
4137 tt
= expand_mmac_params(tt
);
4138 tt
= expand_smacro(tt
);
4141 tt
->a
.mac
= NULL
; /* Necessary? */
4149 tline
= tline
->next
;
4157 const struct tokseq_match t
[] = {
4159 PP_CONCAT_MASK(TOK_ID
) |
4160 PP_CONCAT_MASK(TOK_FLOAT
), /* head */
4161 PP_CONCAT_MASK(TOK_ID
) |
4162 PP_CONCAT_MASK(TOK_NUMBER
) |
4163 PP_CONCAT_MASK(TOK_FLOAT
) |
4164 PP_CONCAT_MASK(TOK_OTHER
) /* tail */
4167 PP_CONCAT_MASK(TOK_NUMBER
), /* head */
4168 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4171 paste_tokens(&thead
, t
, ARRAY_SIZE(t
), false);
4178 * Expand all single-line macro calls made in the given line.
4179 * Return the expanded version of the line. The original is deemed
4180 * to be destroyed in the process. (In reality we'll just move
4181 * Tokens from input to output a lot of the time, rather than
4182 * actually bothering to destroy and replicate.)
4185 static Token
*expand_smacro(Token
* tline
)
4187 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
4188 SMacro
*head
= NULL
, *m
;
4191 unsigned int nparam
, sparam
;
4193 Token
*org_tline
= tline
;
4196 int deadman
= DEADMAN_LIMIT
;
4200 * Trick: we should avoid changing the start token pointer since it can
4201 * be contained in "next" field of other token. Because of this
4202 * we allocate a copy of first token and work with it; at the end of
4203 * routine we copy it back
4206 tline
= new_Token(org_tline
->next
, org_tline
->type
,
4207 org_tline
->text
, 0);
4208 tline
->a
.mac
= org_tline
->a
.mac
;
4209 nasm_free(org_tline
->text
);
4210 org_tline
->text
= NULL
;
4213 expanded
= true; /* Always expand %+ at least once */
4219 while (tline
) { /* main token loop */
4221 nasm_error(ERR_NONFATAL
, "interminable macro recursion");
4225 if ((mname
= tline
->text
)) {
4226 /* if this token is a local macro, look in local context */
4227 if (tline
->type
== TOK_ID
) {
4228 head
= (SMacro
*)hash_findix(&smacros
, mname
);
4229 } else if (tline
->type
== TOK_PREPROC_ID
) {
4230 ctx
= get_ctx(mname
, &mname
);
4231 head
= ctx
? (SMacro
*)hash_findix(&ctx
->localmac
, mname
) : NULL
;
4236 * We've hit an identifier. As in is_mmacro below, we first
4237 * check whether the identifier is a single-line macro at
4238 * all, then think about checking for parameters if
4241 list_for_each(m
, head
)
4242 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
4248 if (m
->nparam
== 0) {
4250 * Simple case: the macro is parameterless. Discard the
4251 * one token that the macro call took, and push the
4252 * expansion back on the to-do stack.
4254 if (!m
->expansion
) {
4255 if (!strcmp("__FILE__", m
->name
)) {
4256 const char *file
= src_get_fname();
4257 /* nasm_free(tline->text); here? */
4258 tline
->text
= nasm_quote(file
, strlen(file
));
4259 tline
->type
= TOK_STRING
;
4262 if (!strcmp("__LINE__", m
->name
)) {
4263 nasm_free(tline
->text
);
4264 make_tok_num(tline
, src_get_linnum());
4267 if (!strcmp("__BITS__", m
->name
)) {
4268 nasm_free(tline
->text
);
4269 make_tok_num(tline
, globalbits
);
4272 tline
= delete_Token(tline
);
4277 * Complicated case: at least one macro with this name
4278 * exists and takes parameters. We must find the
4279 * parameters in the call, count them, find the SMacro
4280 * that corresponds to that form of the macro call, and
4281 * substitute for the parameters when we expand. What a
4284 /*tline = tline->next;
4285 skip_white_(tline); */
4288 while (tok_type_(t
, TOK_SMAC_END
)) {
4289 t
->a
.mac
->in_progress
= false;
4291 t
= tline
->next
= delete_Token(t
);
4294 } while (tok_type_(tline
, TOK_WHITESPACE
));
4295 if (!tok_is_(tline
, "(")) {
4297 * This macro wasn't called with parameters: ignore
4298 * the call. (Behaviour borrowed from gnu cpp.)
4307 sparam
= PARAM_DELTA
;
4308 params
= nasm_malloc(sparam
* sizeof(Token
*));
4309 params
[0] = tline
->next
;
4310 paramsize
= nasm_malloc(sparam
* sizeof(int));
4312 while (true) { /* parameter loop */
4314 * For some unusual expansions
4315 * which concatenates function call
4318 while (tok_type_(t
, TOK_SMAC_END
)) {
4319 t
->a
.mac
->in_progress
= false;
4321 t
= tline
->next
= delete_Token(t
);
4326 nasm_error(ERR_NONFATAL
,
4327 "macro call expects terminating `)'");
4330 if (tline
->type
== TOK_WHITESPACE
4332 if (paramsize
[nparam
])
4335 params
[nparam
] = tline
->next
;
4336 continue; /* parameter loop */
4338 if (tline
->type
== TOK_OTHER
4339 && tline
->text
[1] == 0) {
4340 char ch
= tline
->text
[0];
4341 if (ch
== ',' && !paren
&& brackets
<= 0) {
4342 if (++nparam
>= sparam
) {
4343 sparam
+= PARAM_DELTA
;
4344 params
= nasm_realloc(params
,
4345 sparam
* sizeof(Token
*));
4346 paramsize
= nasm_realloc(paramsize
,
4347 sparam
* sizeof(int));
4349 params
[nparam
] = tline
->next
;
4350 paramsize
[nparam
] = 0;
4352 continue; /* parameter loop */
4355 (brackets
> 0 || (brackets
== 0 &&
4356 !paramsize
[nparam
])))
4358 if (!(brackets
++)) {
4359 params
[nparam
] = tline
->next
;
4360 continue; /* parameter loop */
4363 if (ch
== '}' && brackets
> 0)
4364 if (--brackets
== 0) {
4366 continue; /* parameter loop */
4368 if (ch
== '(' && !brackets
)
4370 if (ch
== ')' && brackets
<= 0)
4376 nasm_error(ERR_NONFATAL
, "braces do not "
4377 "enclose all of macro parameter");
4379 paramsize
[nparam
] += white
+ 1;
4381 } /* parameter loop */
4383 while (m
&& (m
->nparam
!= nparam
||
4384 mstrcmp(m
->name
, mname
,
4388 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4389 "macro `%s' exists, "
4390 "but not taking %d parameters",
4391 mstart
->text
, nparam
);
4394 if (m
&& m
->in_progress
)
4396 if (!m
) { /* in progess or didn't find '(' or wrong nparam */
4398 * Design question: should we handle !tline, which
4399 * indicates missing ')' here, or expand those
4400 * macros anyway, which requires the (t) test a few
4404 nasm_free(paramsize
);
4408 * Expand the macro: we are placed on the last token of the
4409 * call, so that we can easily split the call from the
4410 * following tokens. We also start by pushing an SMAC_END
4411 * token for the cycle removal.
4418 tt
= new_Token(tline
, TOK_SMAC_END
, NULL
, 0);
4420 m
->in_progress
= true;
4422 list_for_each(t
, m
->expansion
) {
4423 if (t
->type
>= TOK_SMAC_PARAM
) {
4424 Token
*pcopy
= tline
, **ptail
= &pcopy
;
4428 ttt
= params
[t
->type
- TOK_SMAC_PARAM
];
4429 i
= paramsize
[t
->type
- TOK_SMAC_PARAM
];
4431 pt
= *ptail
= new_Token(tline
, ttt
->type
,
4435 if (!ttt
&& i
> 0) {
4437 * FIXME: Need to handle more gracefully,
4438 * exiting early on agruments analysis.
4440 nasm_error(ERR_FATAL
,
4441 "macro `%s' expects %d args",
4443 (int)paramsize
[t
->type
- TOK_SMAC_PARAM
]);
4447 } else if (t
->type
== TOK_PREPROC_Q
) {
4448 tt
= new_Token(tline
, TOK_ID
, mname
, 0);
4450 } else if (t
->type
== TOK_PREPROC_QQ
) {
4451 tt
= new_Token(tline
, TOK_ID
, m
->name
, 0);
4454 tt
= new_Token(tline
, t
->type
, t
->text
, 0);
4460 * Having done that, get rid of the macro call, and clean
4461 * up the parameters.
4464 nasm_free(paramsize
);
4467 continue; /* main token loop */
4472 if (tline
->type
== TOK_SMAC_END
) {
4473 tline
->a
.mac
->in_progress
= false;
4474 tline
= delete_Token(tline
);
4477 tline
= tline
->next
;
4485 * Now scan the entire line and look for successive TOK_IDs that resulted
4486 * after expansion (they can't be produced by tokenize()). The successive
4487 * TOK_IDs should be concatenated.
4488 * Also we look for %+ tokens and concatenate the tokens before and after
4489 * them (without white spaces in between).
4492 const struct tokseq_match t
[] = {
4494 PP_CONCAT_MASK(TOK_ID
) |
4495 PP_CONCAT_MASK(TOK_PREPROC_ID
), /* head */
4496 PP_CONCAT_MASK(TOK_ID
) |
4497 PP_CONCAT_MASK(TOK_PREPROC_ID
) |
4498 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4501 if (paste_tokens(&thead
, t
, ARRAY_SIZE(t
), true)) {
4503 * If we concatenated something, *and* we had previously expanded
4504 * an actual macro, scan the lines again for macros...
4515 *org_tline
= *thead
;
4516 /* since we just gave text to org_line, don't free it */
4518 delete_Token(thead
);
4520 /* the expression expanded to empty line;
4521 we can't return NULL for some reasons
4522 we just set the line to a single WHITESPACE token. */
4523 memset(org_tline
, 0, sizeof(*org_tline
));
4524 org_tline
->text
= NULL
;
4525 org_tline
->type
= TOK_WHITESPACE
;
4534 * Similar to expand_smacro but used exclusively with macro identifiers
4535 * right before they are fetched in. The reason is that there can be
4536 * identifiers consisting of several subparts. We consider that if there
4537 * are more than one element forming the name, user wants a expansion,
4538 * otherwise it will be left as-is. Example:
4542 * the identifier %$abc will be left as-is so that the handler for %define
4543 * will suck it and define the corresponding value. Other case:
4545 * %define _%$abc cde
4547 * In this case user wants name to be expanded *before* %define starts
4548 * working, so we'll expand %$abc into something (if it has a value;
4549 * otherwise it will be left as-is) then concatenate all successive
4552 static Token
*expand_id(Token
* tline
)
4554 Token
*cur
, *oldnext
= NULL
;
4556 if (!tline
|| !tline
->next
)
4561 (cur
->next
->type
== TOK_ID
||
4562 cur
->next
->type
== TOK_PREPROC_ID
4563 || cur
->next
->type
== TOK_NUMBER
))
4566 /* If identifier consists of just one token, don't expand */
4571 oldnext
= cur
->next
; /* Detach the tail past identifier */
4572 cur
->next
= NULL
; /* so that expand_smacro stops here */
4575 tline
= expand_smacro(tline
);
4578 /* expand_smacro possibly changhed tline; re-scan for EOL */
4580 while (cur
&& cur
->next
)
4583 cur
->next
= oldnext
;
4590 * Determine whether the given line constitutes a multi-line macro
4591 * call, and return the MMacro structure called if so. Doesn't have
4592 * to check for an initial label - that's taken care of in
4593 * expand_mmacro - but must check numbers of parameters. Guaranteed
4594 * to be called with tline->type == TOK_ID, so the putative macro
4595 * name is easy to find.
4597 static MMacro
*is_mmacro(Token
* tline
, Token
*** params_array
)
4603 head
= (MMacro
*) hash_findix(&mmacros
, tline
->text
);
4606 * Efficiency: first we see if any macro exists with the given
4607 * name. If not, we can return NULL immediately. _Then_ we
4608 * count the parameters, and then we look further along the
4609 * list if necessary to find the proper MMacro.
4611 list_for_each(m
, head
)
4612 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
4618 * OK, we have a potential macro. Count and demarcate the
4621 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
4624 * So we know how many parameters we've got. Find the MMacro
4625 * structure that handles this number.
4628 if (m
->nparam_min
<= nparam
4629 && (m
->plus
|| nparam
<= m
->nparam_max
)) {
4631 * This one is right. Just check if cycle removal
4632 * prohibits us using it before we actually celebrate...
4634 if (m
->in_progress
> m
->max_depth
) {
4635 if (m
->max_depth
> 0) {
4636 nasm_error(ERR_WARNING
,
4637 "reached maximum recursion depth of %i",
4644 * It's right, and we can use it. Add its default
4645 * parameters to the end of our list if necessary.
4647 if (m
->defaults
&& nparam
< m
->nparam_min
+ m
->ndefs
) {
4649 nasm_realloc(params
,
4650 ((m
->nparam_min
+ m
->ndefs
+
4651 1) * sizeof(*params
)));
4652 while (nparam
< m
->nparam_min
+ m
->ndefs
) {
4653 params
[nparam
] = m
->defaults
[nparam
- m
->nparam_min
];
4658 * If we've gone over the maximum parameter count (and
4659 * we're in Plus mode), ignore parameters beyond
4662 if (m
->plus
&& nparam
> m
->nparam_max
)
4663 nparam
= m
->nparam_max
;
4665 * Then terminate the parameter list, and leave.
4667 if (!params
) { /* need this special case */
4668 params
= nasm_malloc(sizeof(*params
));
4671 params
[nparam
] = NULL
;
4672 *params_array
= params
;
4676 * This one wasn't right: look for the next one with the
4679 list_for_each(m
, m
->next
)
4680 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
4685 * After all that, we didn't find one with the right number of
4686 * parameters. Issue a warning, and fail to expand the macro.
4688 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4689 "macro `%s' exists, but not taking %d parameters",
4690 tline
->text
, nparam
);
4697 * Save MMacro invocation specific fields in
4698 * preparation for a recursive macro expansion
4700 static void push_mmacro(MMacro
*m
)
4702 MMacroInvocation
*i
;
4704 i
= nasm_malloc(sizeof(MMacroInvocation
));
4706 i
->params
= m
->params
;
4707 i
->iline
= m
->iline
;
4708 i
->nparam
= m
->nparam
;
4709 i
->rotate
= m
->rotate
;
4710 i
->paramlen
= m
->paramlen
;
4711 i
->unique
= m
->unique
;
4712 i
->condcnt
= m
->condcnt
;
4718 * Restore MMacro invocation specific fields that were
4719 * saved during a previous recursive macro expansion
4721 static void pop_mmacro(MMacro
*m
)
4723 MMacroInvocation
*i
;
4728 m
->params
= i
->params
;
4729 m
->iline
= i
->iline
;
4730 m
->nparam
= i
->nparam
;
4731 m
->rotate
= i
->rotate
;
4732 m
->paramlen
= i
->paramlen
;
4733 m
->unique
= i
->unique
;
4734 m
->condcnt
= i
->condcnt
;
4741 * Expand the multi-line macro call made by the given line, if
4742 * there is one to be expanded. If there is, push the expansion on
4743 * istk->expansion and return 1. Otherwise return 0.
4745 static int expand_mmacro(Token
* tline
)
4747 Token
*startline
= tline
;
4748 Token
*label
= NULL
;
4749 int dont_prepend
= 0;
4750 Token
**params
, *t
, *tt
;
4753 int i
, nparam
, *paramlen
;
4758 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4759 if (!tok_type_(t
, TOK_ID
) && !tok_type_(t
, TOK_PREPROC_ID
))
4761 m
= is_mmacro(t
, ¶ms
);
4767 * We have an id which isn't a macro call. We'll assume
4768 * it might be a label; we'll also check to see if a
4769 * colon follows it. Then, if there's another id after
4770 * that lot, we'll check it again for macro-hood.
4774 if (tok_type_(t
, TOK_WHITESPACE
))
4775 last
= t
, t
= t
->next
;
4776 if (tok_is_(t
, ":")) {
4778 last
= t
, t
= t
->next
;
4779 if (tok_type_(t
, TOK_WHITESPACE
))
4780 last
= t
, t
= t
->next
;
4782 if (!tok_type_(t
, TOK_ID
) || !(m
= is_mmacro(t
, ¶ms
)))
4790 * Fix up the parameters: this involves stripping leading and
4791 * trailing whitespace, then stripping braces if they are
4794 for (nparam
= 0; params
[nparam
]; nparam
++) ;
4795 paramlen
= nparam
? nasm_malloc(nparam
* sizeof(*paramlen
)) : NULL
;
4797 for (i
= 0; params
[i
]; i
++) {
4799 int comma
= (!m
->plus
|| i
< nparam
- 1);
4803 if (tok_is_(t
, "{"))
4804 t
= t
->next
, brace
++, comma
= false;
4808 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
4809 break; /* ... because we have hit a comma */
4810 if (comma
&& t
->type
== TOK_WHITESPACE
4811 && tok_is_(t
->next
, ","))
4812 break; /* ... or a space then a comma */
4813 if (brace
&& t
->type
== TOK_OTHER
) {
4814 if (t
->text
[0] == '{')
4815 brace
++; /* ... or a nested opening brace */
4816 else if (t
->text
[0] == '}')
4818 break; /* ... or a brace */
4824 nasm_error(ERR_NONFATAL
, "macro params should be enclosed in braces");
4828 * OK, we have a MMacro structure together with a set of
4829 * parameters. We must now go through the expansion and push
4830 * copies of each Line on to istk->expansion. Substitution of
4831 * parameter tokens and macro-local tokens doesn't get done
4832 * until the single-line macro substitution process; this is
4833 * because delaying them allows us to change the semantics
4834 * later through %rotate.
4836 * First, push an end marker on to istk->expansion, mark this
4837 * macro as in progress, and set up its invocation-specific
4840 ll
= nasm_malloc(sizeof(Line
));
4841 ll
->next
= istk
->expansion
;
4844 istk
->expansion
= ll
;
4847 * Save the previous MMacro expansion in the case of
4850 if (m
->max_depth
&& m
->in_progress
)
4858 m
->paramlen
= paramlen
;
4859 m
->unique
= unique
++;
4863 m
->next_active
= istk
->mstk
;
4866 list_for_each(l
, m
->expansion
) {
4869 ll
= nasm_malloc(sizeof(Line
));
4870 ll
->finishes
= NULL
;
4871 ll
->next
= istk
->expansion
;
4872 istk
->expansion
= ll
;
4875 list_for_each(t
, l
->first
) {
4879 tt
= *tail
= new_Token(NULL
, TOK_ID
, mname
, 0);
4881 case TOK_PREPROC_QQ
:
4882 tt
= *tail
= new_Token(NULL
, TOK_ID
, m
->name
, 0);
4884 case TOK_PREPROC_ID
:
4885 if (t
->text
[1] == '0' && t
->text
[2] == '0') {
4893 tt
= *tail
= new_Token(NULL
, x
->type
, x
->text
, 0);
4902 * If we had a label, push it on as the first line of
4903 * the macro expansion.
4906 if (dont_prepend
< 0)
4907 free_tlist(startline
);
4909 ll
= nasm_malloc(sizeof(Line
));
4910 ll
->finishes
= NULL
;
4911 ll
->next
= istk
->expansion
;
4912 istk
->expansion
= ll
;
4913 ll
->first
= startline
;
4914 if (!dont_prepend
) {
4916 label
= label
->next
;
4917 label
->next
= tt
= new_Token(NULL
, TOK_OTHER
, ":", 0);
4922 lfmt
->uplevel(m
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
4928 * This function adds macro names to error messages, and suppresses
4929 * them if necessary.
4931 static void pp_verror(int severity
, const char *fmt
, va_list arg
)
4934 MMacro
*mmac
= NULL
;
4938 * If we're in a dead branch of IF or something like it, ignore the error.
4939 * However, because %else etc are evaluated in the state context
4940 * of the previous branch, errors might get lost:
4941 * %if 0 ... %else trailing garbage ... %endif
4942 * So %else etc should set the ERR_PP_PRECOND flag.
4944 if ((severity
& ERR_MASK
) < ERR_FATAL
&&
4945 istk
&& istk
->conds
&&
4946 ((severity
& ERR_PP_PRECOND
) ?
4947 istk
->conds
->state
== COND_NEVER
:
4948 !emitting(istk
->conds
->state
)))
4951 /* get %macro name */
4952 if (!(severity
& ERR_NOFILE
) && istk
&& istk
->mstk
) {
4954 /* but %rep blocks should be skipped */
4955 while (mmac
&& !mmac
->name
)
4956 mmac
= mmac
->next_active
, delta
++;
4960 vsnprintf(buff
, sizeof(buff
), fmt
, arg
);
4962 nasm_set_verror(real_verror
);
4963 nasm_error(severity
, "(%s:%d) %s",
4964 mmac
->name
, mmac
->lineno
- delta
, buff
);
4965 nasm_set_verror(pp_verror
);
4967 real_verror(severity
, fmt
, arg
);
4972 pp_reset(char *file
, int apass
, StrList
**deplist
)
4977 istk
= nasm_malloc(sizeof(Include
));
4980 istk
->expansion
= NULL
;
4982 istk
->fp
= nasm_open_read(file
, NF_TEXT
);
4987 nasm_fatal(ERR_NOFILE
, "unable to open input file `%s'", file
);
4989 nested_mac_count
= 0;
4990 nested_rep_count
= 0;
4994 if (tasm_compatible_mode
)
4995 pp_add_stdmac(nasm_stdmac_tasm
);
4997 pp_add_stdmac(nasm_stdmac_nasm
);
4998 pp_add_stdmac(nasm_stdmac_version
);
5001 pp_add_stdmac(extrastdmac
);
5003 stdmacpos
= stdmacros
[0];
5004 stdmacnext
= &stdmacros
[1];
5009 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
5010 * The caller, however, will also pass in 3 for preprocess-only so
5011 * we can set __PASS__ accordingly.
5013 pass
= apass
> 2 ? 2 : apass
;
5016 nasm_add_string_to_strlist(dephead
, file
);
5019 * Define the __PASS__ macro. This is defined here unlike
5020 * all the other builtins, because it is special -- it varies between
5023 t
= nasm_malloc(sizeof(*t
));
5025 make_tok_num(t
, apass
);
5027 define_smacro(NULL
, "__PASS__", true, 0, t
);
5030 static void pp_init(void)
5032 hash_init(&FileHash
, HASH_MEDIUM
);
5035 static char *pp_getline(void)
5040 real_verror
= nasm_set_verror(pp_verror
);
5044 * Fetch a tokenized line, either from the macro-expansion
5045 * buffer or from the input file.
5048 while (istk
->expansion
&& istk
->expansion
->finishes
) {
5049 Line
*l
= istk
->expansion
;
5050 if (!l
->finishes
->name
&& l
->finishes
->in_progress
> 1) {
5054 * This is a macro-end marker for a macro with no
5055 * name, which means it's not really a macro at all
5056 * but a %rep block, and the `in_progress' field is
5057 * more than 1, meaning that we still need to
5058 * repeat. (1 means the natural last repetition; 0
5059 * means termination by %exitrep.) We have
5060 * therefore expanded up to the %endrep, and must
5061 * push the whole block on to the expansion buffer
5062 * again. We don't bother to remove the macro-end
5063 * marker: we'd only have to generate another one
5066 l
->finishes
->in_progress
--;
5067 list_for_each(l
, l
->finishes
->expansion
) {
5068 Token
*t
, *tt
, **tail
;
5070 ll
= nasm_malloc(sizeof(Line
));
5071 ll
->next
= istk
->expansion
;
5072 ll
->finishes
= NULL
;
5076 list_for_each(t
, l
->first
) {
5077 if (t
->text
|| t
->type
== TOK_WHITESPACE
) {
5078 tt
= *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
5083 istk
->expansion
= ll
;
5087 * Check whether a `%rep' was started and not ended
5088 * within this macro expansion. This can happen and
5089 * should be detected. It's a fatal error because
5090 * I'm too confused to work out how to recover
5095 nasm_panic(0, "defining with name in expansion");
5096 else if (istk
->mstk
->name
)
5097 nasm_fatal(0, "`%%rep' without `%%endrep' within"
5098 " expansion of macro `%s'",
5103 * FIXME: investigate the relationship at this point between
5104 * istk->mstk and l->finishes
5107 MMacro
*m
= istk
->mstk
;
5108 istk
->mstk
= m
->next_active
;
5111 * This was a real macro call, not a %rep, and
5112 * therefore the parameter information needs to
5117 l
->finishes
->in_progress
--;
5119 nasm_free(m
->params
);
5120 free_tlist(m
->iline
);
5121 nasm_free(m
->paramlen
);
5122 l
->finishes
->in_progress
= 0;
5127 * FIXME It is incorrect to always free_mmacro here.
5128 * It leads to usage-after-free.
5130 * https://bugzilla.nasm.us/show_bug.cgi?id=3392414
5137 istk
->expansion
= l
->next
;
5139 lfmt
->downlevel(LIST_MACRO
);
5142 while (1) { /* until we get a line we can use */
5144 if (istk
->expansion
) { /* from a macro expansion */
5146 Line
*l
= istk
->expansion
;
5148 istk
->mstk
->lineno
++;
5150 istk
->expansion
= l
->next
;
5152 p
= detoken(tline
, false);
5153 lfmt
->line(LIST_MACRO
, p
);
5158 if (line
) { /* from the current input file */
5159 line
= prepreproc(line
);
5160 tline
= tokenize(line
);
5165 * The current file has ended; work down the istk
5171 /* nasm_error can't be conditionally suppressed */
5173 "expected `%%endif' before end of file");
5175 /* only set line and file name if there's a next node */
5177 src_set(i
->lineno
, i
->fname
);
5179 lfmt
->downlevel(LIST_INCLUDE
);
5185 if (istk
->expansion
&& istk
->expansion
->finishes
)
5191 * We must expand MMacro parameters and MMacro-local labels
5192 * _before_ we plunge into directive processing, to cope
5193 * with things like `%define something %1' such as STRUC
5194 * uses. Unless we're _defining_ a MMacro, in which case
5195 * those tokens should be left alone to go into the
5196 * definition; and unless we're in a non-emitting
5197 * condition, in which case we don't want to meddle with
5200 if (!defining
&& !(istk
->conds
&& !emitting(istk
->conds
->state
))
5201 && !(istk
->mstk
&& !istk
->mstk
->in_progress
)) {
5202 tline
= expand_mmac_params(tline
);
5206 * Check the line to see if it's a preprocessor directive.
5208 if (do_directive(tline
, &line
) == DIRECTIVE_FOUND
) {
5210 break; /* Directive generated output */
5213 } else if (defining
) {
5215 * We're defining a multi-line macro. We emit nothing
5217 * shove the tokenized line on to the macro definition.
5219 Line
*l
= nasm_malloc(sizeof(Line
));
5220 l
->next
= defining
->expansion
;
5223 defining
->expansion
= l
;
5225 } else if (istk
->conds
&& !emitting(istk
->conds
->state
)) {
5227 * We're in a non-emitting branch of a condition block.
5228 * Emit nothing at all, not even a blank line: when we
5229 * emerge from the condition we'll give a line-number
5230 * directive so we keep our place correctly.
5234 } else if (istk
->mstk
&& !istk
->mstk
->in_progress
) {
5236 * We're in a %rep block which has been terminated, so
5237 * we're walking through to the %endrep without
5238 * emitting anything. Emit nothing at all, not even a
5239 * blank line: when we emerge from the %rep block we'll
5240 * give a line-number directive so we keep our place
5246 tline
= expand_smacro(tline
);
5247 if (!expand_mmacro(tline
)) {
5249 * De-tokenize the line again, and emit it.
5251 line
= detoken(tline
, true);
5255 continue; /* expand_mmacro calls free_tlist */
5261 nasm_set_verror(real_verror
);
5265 static void pp_cleanup(int pass
)
5267 real_verror
= nasm_set_verror(pp_verror
);
5270 if (defining
->name
) {
5271 nasm_error(ERR_NONFATAL
,
5272 "end of file while still defining macro `%s'",
5275 nasm_error(ERR_NONFATAL
, "end of file while still in %%rep");
5278 free_mmacro(defining
);
5282 nasm_set_verror(real_verror
);
5295 src_set_fname(NULL
);
5302 while ((i
= ipath
)) {
5311 static void pp_include_path(char *path
)
5315 i
= nasm_malloc(sizeof(IncPath
));
5316 i
->path
= path
? nasm_strdup(path
) : NULL
;
5329 static void pp_pre_include(char *fname
)
5331 Token
*inc
, *space
, *name
;
5334 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
5335 space
= new_Token(name
, TOK_WHITESPACE
, NULL
, 0);
5336 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
5338 l
= nasm_malloc(sizeof(Line
));
5345 static void pp_pre_define(char *definition
)
5351 real_verror
= nasm_set_verror(pp_verror
);
5353 equals
= strchr(definition
, '=');
5354 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5355 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
5358 space
->next
= tokenize(definition
);
5362 if (space
->next
->type
!= TOK_PREPROC_ID
&&
5363 space
->next
->type
!= TOK_ID
)
5364 nasm_error(ERR_WARNING
, "pre-defining non ID `%s\'\n", definition
);
5366 l
= nasm_malloc(sizeof(Line
));
5372 nasm_set_verror(real_verror
);
5375 static void pp_pre_undefine(char *definition
)
5380 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5381 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
5382 space
->next
= tokenize(definition
);
5384 l
= nasm_malloc(sizeof(Line
));
5391 static void pp_add_stdmac(macros_t
*macros
)
5395 /* Find the end of the list and avoid duplicates */
5396 for (mp
= stdmacros
; *mp
; mp
++) {
5398 return; /* Nothing to do */
5401 nasm_assert(mp
< &stdmacros
[ARRAY_SIZE(stdmacros
)-1]);
5406 static void pp_extra_stdmac(macros_t
*macros
)
5408 extrastdmac
= macros
;
5411 static void make_tok_num(Token
* tok
, int64_t val
)
5414 snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
5415 tok
->text
= nasm_strdup(numbuf
);
5416 tok
->type
= TOK_NUMBER
;
5419 static void pp_list_one_macro(MMacro
*m
, int severity
)
5424 /* We need to print the next_active list in reverse order */
5425 pp_list_one_macro(m
->next_active
, severity
);
5427 if (m
->name
&& !m
->nolist
) {
5428 src_set(m
->xline
+ m
->lineno
, m
->fname
);
5429 nasm_error(severity
, "... from macro `%s' defined here", m
->name
);
5433 static void pp_error_list_macros(int severity
)
5436 const char *saved_fname
= NULL
;
5438 severity
|= ERR_PP_LISTMACRO
| ERR_NO_SEVERITY
;
5439 src_get(&saved_line
, &saved_fname
);
5442 pp_list_one_macro(istk
->mstk
, severity
);
5444 src_set(saved_line
, saved_fname
);
5447 const struct preproc_ops nasmpp
= {
5457 pp_error_list_macros
,