1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2016 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
84 typedef struct SMacro SMacro
;
85 typedef struct MMacro MMacro
;
86 typedef struct MMacroInvocation MMacroInvocation
;
87 typedef struct Context Context
;
88 typedef struct Token Token
;
89 typedef struct Blocks Blocks
;
90 typedef struct Line Line
;
91 typedef struct Include Include
;
92 typedef struct Cond Cond
;
93 typedef struct IncPath IncPath
;
96 * Note on the storage of both SMacro and MMacros: the hash table
97 * indexes them case-insensitively, and we then have to go through a
98 * linked list of potential case aliases (and, for MMacros, parameter
99 * ranges); this is to preserve the matching semantics of the earlier
100 * code. If the number of case aliases for a specific macro is a
101 * performance issue, you may want to reconsider your coding style.
105 * Store the definition of a single-line macro.
117 * Store the definition of a multi-line macro. This is also used to
118 * store the interiors of `%rep...%endrep' blocks, which are
119 * effectively self-re-invoking multi-line macros which simply
120 * don't have a name or bother to appear in the hash tables. %rep
121 * blocks are signified by having a NULL `name' field.
123 * In a MMacro describing a `%rep' block, the `in_progress' field
124 * isn't merely boolean, but gives the number of repeats left to
127 * The `next' field is used for storing MMacros in hash tables; the
128 * `next_active' field is for stacking them on istk entries.
130 * When a MMacro is being expanded, `params', `iline', `nparam',
131 * `paramlen', `rotate' and `unique' are local to the invocation.
135 MMacroInvocation
*prev
; /* previous invocation */
137 int nparam_min
, nparam_max
;
139 bool plus
; /* is the last parameter greedy? */
140 bool nolist
; /* is this macro listing-inhibited? */
141 int64_t in_progress
; /* is this macro currently being expanded? */
142 int32_t max_depth
; /* maximum number of recursive expansions allowed */
143 Token
*dlist
; /* All defaults as one list */
144 Token
**defaults
; /* Parameter default pointers */
145 int ndefs
; /* number of default parameters */
149 MMacro
*rep_nest
; /* used for nesting %rep */
150 Token
**params
; /* actual parameters */
151 Token
*iline
; /* invocation line */
152 unsigned int nparam
, rotate
;
155 int lineno
; /* Current line number on expansion */
156 uint64_t condcnt
; /* number of if blocks... */
158 const char *fname
; /* File where defined */
159 int32_t xline
; /* First line in macro */
163 /* Store the definition of a multi-line macro, as defined in a
164 * previous recursive macro expansion.
166 struct MMacroInvocation
{
167 MMacroInvocation
*prev
; /* previous invocation */
168 Token
**params
; /* actual parameters */
169 Token
*iline
; /* invocation line */
170 unsigned int nparam
, rotate
;
178 * The context stack is composed of a linked list of these.
183 struct hash_table localmac
;
188 * This is the internal form which we break input lines up into.
189 * Typically stored in linked lists.
191 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
192 * necessarily used as-is, but is intended to denote the number of
193 * the substituted parameter. So in the definition
195 * %define a(x,y) ( (x) & ~(y) )
197 * the token representing `x' will have its type changed to
198 * TOK_SMAC_PARAM, but the one representing `y' will be
201 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
202 * which doesn't need quotes around it. Used in the pre-include
203 * mechanism as an alternative to trying to find a sensible type of
204 * quote to use on the filename we were passed.
207 TOK_NONE
= 0, TOK_WHITESPACE
, TOK_COMMENT
, TOK_ID
,
208 TOK_PREPROC_ID
, TOK_STRING
,
209 TOK_NUMBER
, TOK_FLOAT
, TOK_SMAC_END
, TOK_OTHER
,
211 TOK_PREPROC_Q
, TOK_PREPROC_QQ
,
213 TOK_INDIRECT
, /* %[...] */
214 TOK_SMAC_PARAM
, /* MUST BE LAST IN THE LIST!!! */
215 TOK_MAX
= INT_MAX
/* Keep compiler from reducing the range */
218 #define PP_CONCAT_MASK(x) (1 << (x))
219 #define PP_CONCAT_MATCH(t, mask) (PP_CONCAT_MASK((t)->type) & mask)
221 struct tokseq_match
{
230 SMacro
*mac
; /* associated macro for TOK_SMAC_END */
231 size_t len
; /* scratch length field */
232 } a
; /* Auxiliary data */
233 enum pp_token_type type
;
237 * Multi-line macro definitions are stored as a linked list of
238 * these, which is essentially a container to allow several linked
241 * Note that in this module, linked lists are treated as stacks
242 * wherever possible. For this reason, Lines are _pushed_ on to the
243 * `expansion' field in MMacro structures, so that the linked list,
244 * if walked, would give the macro lines in reverse order; this
245 * means that we can walk the list when expanding a macro, and thus
246 * push the lines on to the `expansion' field in _istk_ in reverse
247 * order (so that when popped back off they are in the right
248 * order). It may seem cockeyed, and it relies on my design having
249 * an even number of steps in, but it works...
251 * Some of these structures, rather than being actual lines, are
252 * markers delimiting the end of the expansion of a given macro.
253 * This is for use in the cycle-tracking and %rep-handling code.
254 * Such structures have `finishes' non-NULL, and `first' NULL. All
255 * others have `finishes' NULL, but `first' may still be NULL if
265 * To handle an arbitrary level of file inclusion, we maintain a
266 * stack (ie linked list) of these things.
275 MMacro
*mstk
; /* stack of active macros/reps */
279 * Include search path. This is simply a list of strings which get
280 * prepended, in turn, to the name of an include file, in an
281 * attempt to find the file if it's not in the current directory.
289 * File real name hash, so we don't have to re-search the include
290 * path for every pass (and potentially more than that if a file
291 * is used more than once.)
293 struct hash_table FileHash
;
296 * Conditional assembly: we maintain a separate stack of these for
297 * each level of file inclusion. (The only reason we keep the
298 * stacks separate is to ensure that a stray `%endif' in a file
299 * included from within the true branch of a `%if' won't terminate
300 * it and cause confusion: instead, rightly, it'll cause an error.)
308 * These states are for use just after %if or %elif: IF_TRUE
309 * means the condition has evaluated to truth so we are
310 * currently emitting, whereas IF_FALSE means we are not
311 * currently emitting but will start doing so if a %else comes
312 * up. In these states, all directives are admissible: %elif,
313 * %else and %endif. (And of course %if.)
315 COND_IF_TRUE
, COND_IF_FALSE
,
317 * These states come up after a %else: ELSE_TRUE means we're
318 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
319 * any %elif or %else will cause an error.
321 COND_ELSE_TRUE
, COND_ELSE_FALSE
,
323 * These states mean that we're not emitting now, and also that
324 * nothing until %endif will be emitted at all. COND_DONE is
325 * used when we've had our moment of emission
326 * and have now started seeing %elifs. COND_NEVER is used when
327 * the condition construct in question is contained within a
328 * non-emitting branch of a larger condition construct,
329 * or if there is an error.
331 COND_DONE
, COND_NEVER
333 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
336 * These defines are used as the possible return values for do_directive
338 #define NO_DIRECTIVE_FOUND 0
339 #define DIRECTIVE_FOUND 1
342 * This define sets the upper limit for smacro and recursive mmacro
345 #define DEADMAN_LIMIT (1 << 20)
348 #define REP_LIMIT ((INT64_C(1) << 62))
351 * Condition codes. Note that we use c_ prefix not C_ because C_ is
352 * used in nasm.h for the "real" condition codes. At _this_ level,
353 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
354 * ones, so we need a different enum...
356 static const char * const conditions
[] = {
357 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
358 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
359 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
362 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
363 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
364 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_RCXZ
, c_S
, c_Z
,
367 static const enum pp_conds inverse_ccs
[] = {
368 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
369 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
,
370 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, -1, c_NS
, c_NZ
376 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
377 static int is_condition(enum preproc_token arg
)
379 return PP_IS_COND(arg
) || (arg
== PP_ELSE
) || (arg
== PP_ENDIF
);
382 /* For TASM compatibility we need to be able to recognise TASM compatible
383 * conditional compilation directives. Using the NASM pre-processor does
384 * not work, so we look for them specifically from the following list and
385 * then jam in the equivalent NASM directive into the input stream.
389 TM_ARG
, TM_ELIF
, TM_ELSE
, TM_ENDIF
, TM_IF
, TM_IFDEF
, TM_IFDIFI
,
390 TM_IFNDEF
, TM_INCLUDE
, TM_LOCAL
393 static const char * const tasm_directives
[] = {
394 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
395 "ifndef", "include", "local"
398 static int StackSize
= 4;
399 static const char *StackPointer
= "ebp";
400 static int ArgOffset
= 8;
401 static int LocalOffset
= 0;
403 static Context
*cstk
;
404 static Include
*istk
;
405 static IncPath
*ipath
= NULL
;
407 static int pass
; /* HACK: pass 0 = generate dependencies only */
408 static StrList
**dephead
;
410 static uint64_t unique
; /* unique identifier numbers */
412 static Line
*predef
= NULL
;
413 static bool do_predef
;
416 * The current set of multi-line macros we have defined.
418 static struct hash_table mmacros
;
421 * The current set of single-line macros we have defined.
423 static struct hash_table smacros
;
426 * The multi-line macro we are currently defining, or the %rep
427 * block we are currently reading, if any.
429 static MMacro
*defining
;
431 static uint64_t nested_mac_count
;
432 static uint64_t nested_rep_count
;
435 * The number of macro parameters to allocate space for at a time.
437 #define PARAM_DELTA 16
440 * The standard macro set: defined in macros.c in a set of arrays.
441 * This gives our position in any macro set, while we are processing it.
442 * The stdmacset is an array of such macro sets.
444 static macros_t
*stdmacpos
;
445 static macros_t
**stdmacnext
;
446 static macros_t
*stdmacros
[8];
449 * Tokens are allocated in blocks to improve speed
451 #define TOKEN_BLOCKSIZE 4096
452 static Token
*freeTokens
= NULL
;
458 static Blocks blocks
= { NULL
, NULL
};
461 * Forward declarations.
463 static void pp_add_stdmac(macros_t
*macros
);
464 static Token
*expand_mmac_params(Token
* tline
);
465 static Token
*expand_smacro(Token
* tline
);
466 static Token
*expand_id(Token
* tline
);
467 static Context
*get_ctx(const char *name
, const char **namep
);
468 static void make_tok_num(Token
* tok
, int64_t val
);
469 static void pp_verror(int severity
, const char *fmt
, va_list ap
);
470 static vefunc real_verror
;
471 static void *new_Block(size_t size
);
472 static void delete_Blocks(void);
473 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
474 const char *text
, int txtlen
);
475 static Token
*delete_Token(Token
* t
);
478 * Macros for safe checking of token pointers, avoid *(NULL)
480 #define tok_type_(x,t) ((x) && (x)->type == (t))
481 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
482 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
483 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
486 * nasm_unquote with error if the string contains NUL characters.
487 * If the string contains NUL characters, issue an error and return
488 * the C len, i.e. truncate at the NUL.
490 static size_t nasm_unquote_cstr(char *qstr
, enum preproc_token directive
)
492 size_t len
= nasm_unquote(qstr
, NULL
);
493 size_t clen
= strlen(qstr
);
496 nasm_error(ERR_NONFATAL
, "NUL character in `%s' directive",
497 pp_directives
[directive
]);
503 * In-place reverse a list of tokens.
505 static Token
*reverse_tokens(Token
*t
)
521 * Handle TASM specific directives, which do not contain a % in
522 * front of them. We do it here because I could not find any other
523 * place to do it for the moment, and it is a hack (ideally it would
524 * be nice to be able to use the NASM pre-processor to do it).
526 static char *check_tasm_directive(char *line
)
528 int32_t i
, j
, k
, m
, len
;
529 char *p
, *q
, *oldline
, oldchar
;
531 p
= nasm_skip_spaces(line
);
533 /* Binary search for the directive name */
535 j
= ARRAY_SIZE(tasm_directives
);
536 q
= nasm_skip_word(p
);
543 m
= nasm_stricmp(p
, tasm_directives
[k
]);
545 /* We have found a directive, so jam a % in front of it
546 * so that NASM will then recognise it as one if it's own.
551 line
= nasm_malloc(len
+ 2);
553 if (k
== TM_IFDIFI
) {
555 * NASM does not recognise IFDIFI, so we convert
556 * it to %if 0. This is not used in NASM
557 * compatible code, but does need to parse for the
558 * TASM macro package.
560 strcpy(line
+ 1, "if 0");
562 memcpy(line
+ 1, p
, len
+ 1);
577 * The pre-preprocessing stage... This function translates line
578 * number indications as they emerge from GNU cpp (`# lineno "file"
579 * flags') into NASM preprocessor line number indications (`%line
582 static char *prepreproc(char *line
)
585 char *fname
, *oldline
;
587 if (line
[0] == '#' && line
[1] == ' ') {
590 lineno
= atoi(fname
);
591 fname
+= strspn(fname
, "0123456789 ");
594 fnlen
= strcspn(fname
, "\"");
595 line
= nasm_malloc(20 + fnlen
);
596 snprintf(line
, 20 + fnlen
, "%%line %d %.*s", lineno
, fnlen
, fname
);
599 if (tasm_compatible_mode
)
600 return check_tasm_directive(line
);
605 * Free a linked list of tokens.
607 static void free_tlist(Token
* list
)
610 list
= delete_Token(list
);
614 * Free a linked list of lines.
616 static void free_llist(Line
* list
)
619 list_for_each_safe(l
, tmp
, list
) {
620 free_tlist(l
->first
);
628 static void free_mmacro(MMacro
* m
)
631 free_tlist(m
->dlist
);
632 nasm_free(m
->defaults
);
633 free_llist(m
->expansion
);
638 * Free all currently defined macros, and free the hash tables
640 static void free_smacro_table(struct hash_table
*smt
)
644 struct hash_tbl_node
*it
= NULL
;
646 while ((s
= hash_iterate(smt
, &it
, &key
)) != NULL
) {
647 nasm_free((void *)key
);
648 list_for_each_safe(s
, tmp
, s
) {
650 free_tlist(s
->expansion
);
657 static void free_mmacro_table(struct hash_table
*mmt
)
661 struct hash_tbl_node
*it
= NULL
;
664 while ((m
= hash_iterate(mmt
, &it
, &key
)) != NULL
) {
665 nasm_free((void *)key
);
666 list_for_each_safe(m
,tmp
, m
)
672 static void free_macros(void)
674 free_smacro_table(&smacros
);
675 free_mmacro_table(&mmacros
);
679 * Initialize the hash tables
681 static void init_macros(void)
683 hash_init(&smacros
, HASH_LARGE
);
684 hash_init(&mmacros
, HASH_LARGE
);
688 * Pop the context stack.
690 static void ctx_pop(void)
695 free_smacro_table(&c
->localmac
);
701 * Search for a key in the hash index; adding it if necessary
702 * (in which case we initialize the data pointer to NULL.)
705 hash_findi_add(struct hash_table
*hash
, const char *str
)
707 struct hash_insert hi
;
711 r
= hash_findi(hash
, str
, &hi
);
715 strx
= nasm_strdup(str
); /* Use a more efficient allocator here? */
716 return hash_add(&hi
, strx
, NULL
);
720 * Like hash_findi, but returns the data element rather than a pointer
721 * to it. Used only when not adding a new element, hence no third
725 hash_findix(struct hash_table
*hash
, const char *str
)
729 p
= hash_findi(hash
, str
, NULL
);
730 return p
? *p
: NULL
;
734 * read line from standart macros set,
735 * if there no more left -- return NULL
737 static char *line_from_stdmac(void)
740 const unsigned char *p
= stdmacpos
;
749 len
+= pp_directives_len
[c
- 0x80] + 1;
754 line
= nasm_malloc(len
+ 1);
756 while ((c
= *stdmacpos
++)) {
758 memcpy(q
, pp_directives
[c
- 0x80], pp_directives_len
[c
- 0x80]);
759 q
+= pp_directives_len
[c
- 0x80];
769 /* This was the last of this particular macro set */
772 stdmacpos
= *stdmacnext
++;
773 } else if (do_predef
) {
775 Token
*head
, **tail
, *t
;
778 * Nasty hack: here we push the contents of
779 * `predef' on to the top-level expansion stack,
780 * since this is the most convenient way to
781 * implement the pre-include and pre-define
784 list_for_each(pd
, predef
) {
787 list_for_each(t
, pd
->first
) {
788 *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
789 tail
= &(*tail
)->next
;
792 l
= nasm_malloc(sizeof(Line
));
793 l
->next
= istk
->expansion
;
806 static char *read_line(void)
808 unsigned int size
, c
, next
;
809 const unsigned int delta
= 512;
810 const unsigned int pad
= 8;
811 unsigned int nr_cont
= 0;
815 /* Standart macros set (predefined) goes first */
816 p
= line_from_stdmac();
821 p
= buffer
= nasm_malloc(size
);
825 if ((int)(c
) == EOF
) {
832 next
= fgetc(istk
->fp
);
834 ungetc(next
, istk
->fp
);
849 next
= fgetc(istk
->fp
);
850 ungetc(next
, istk
->fp
);
851 if (next
== '\r' || next
== '\n') {
859 if (c
== '\r' || c
== '\n') {
864 if (p
>= (buffer
+ size
- pad
)) {
865 buffer
= nasm_realloc(buffer
, size
+ delta
);
866 p
= buffer
+ size
- pad
;
870 *p
++ = (unsigned char)c
;
878 src_set_linnum(src_get_linnum() + istk
->lineinc
+
879 (nr_cont
* istk
->lineinc
));
882 * Handle spurious ^Z, which may be inserted into source files
883 * by some file transfer utilities.
885 buffer
[strcspn(buffer
, "\032")] = '\0';
887 lfmt
->line(LIST_READ
, buffer
);
893 * Tokenize a line of text. This is a very simple process since we
894 * don't need to parse the value out of e.g. numeric tokens: we
895 * simply split one string into many.
897 static Token
*tokenize(char *line
)
900 enum pp_token_type type
;
902 Token
*t
, **tail
= &list
;
908 if (*p
== '+' && !nasm_isdigit(p
[1])) {
911 } else if (nasm_isdigit(*p
) ||
912 ((*p
== '-' || *p
== '+') && nasm_isdigit(p
[1]))) {
916 while (nasm_isdigit(*p
));
917 type
= TOK_PREPROC_ID
;
918 } else if (*p
== '{') {
927 nasm_error(ERR_WARNING
| ERR_PASS1
,
928 "unterminated %%{ construct");
932 type
= TOK_PREPROC_ID
;
933 } else if (*p
== '[') {
935 line
+= 2; /* Skip the leading %[ */
937 while (lvl
&& (c
= *p
++)) {
949 p
= nasm_skip_string(p
- 1) + 1;
959 nasm_error(ERR_NONFATAL
|ERR_PASS1
,
960 "unterminated %%[ construct");
962 } else if (*p
== '?') {
963 type
= TOK_PREPROC_Q
; /* %? */
966 type
= TOK_PREPROC_QQ
; /* %?? */
969 } else if (*p
== '!') {
970 type
= TOK_PREPROC_ID
;
976 while (isidchar(*p
));
977 } else if (*p
== '\'' || *p
== '\"' || *p
== '`') {
978 p
= nasm_skip_string(p
);
982 nasm_error(ERR_NONFATAL
|ERR_PASS1
,
983 "unterminated %%! string");
985 /* %! without string or identifier */
986 type
= TOK_OTHER
; /* Legacy behavior... */
988 } else if (isidchar(*p
) ||
989 ((*p
== '!' || *p
== '%' || *p
== '$') &&
994 while (isidchar(*p
));
995 type
= TOK_PREPROC_ID
;
1001 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
1004 while (*p
&& isidchar(*p
))
1006 } else if (*p
== '\'' || *p
== '"' || *p
== '`') {
1011 p
= nasm_skip_string(p
);
1016 nasm_error(ERR_WARNING
|ERR_PASS1
, "unterminated string");
1017 /* Handling unterminated strings by UNV */
1020 } else if (p
[0] == '$' && p
[1] == '$') {
1021 type
= TOK_OTHER
; /* TOKEN_BASE */
1023 } else if (isnumstart(*p
)) {
1024 bool is_hex
= false;
1025 bool is_float
= false;
1041 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
1043 if (*p
== '+' || *p
== '-') {
1045 * e can only be followed by +/- if it is either a
1046 * prefixed hex number or a floating-point number
1051 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
1053 } else if (c
== 'P' || c
== 'p') {
1055 if (*p
== '+' || *p
== '-')
1057 } else if (isnumchar(c
))
1058 ; /* just advance */
1059 else if (c
== '.') {
1061 * we need to deal with consequences of the legacy
1062 * parser, like "1.nolist" being two tokens
1063 * (TOK_NUMBER, TOK_ID) here; at least give it
1064 * a shot for now. In the future, we probably need
1065 * a flex-based scanner with proper pattern matching
1066 * to do it as well as it can be done. Nothing in
1067 * the world is going to help the person who wants
1068 * 0x123.p16 interpreted as two tokens, though.
1074 if (nasm_isdigit(*r
) || (is_hex
&& nasm_isxdigit(*r
)) ||
1075 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
1076 (*r
== 'p' || *r
== 'P')) {
1080 break; /* Terminate the token */
1084 p
--; /* Point to first character beyond number */
1086 if (p
== line
+1 && *line
== '$') {
1087 type
= TOK_OTHER
; /* TOKEN_HERE */
1089 if (has_e
&& !is_hex
) {
1090 /* 1e13 is floating-point, but 1e13h is not */
1094 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
1096 } else if (nasm_isspace(*p
)) {
1097 type
= TOK_WHITESPACE
;
1098 p
= nasm_skip_spaces(p
);
1100 * Whitespace just before end-of-line is discarded by
1101 * pretending it's a comment; whitespace just before a
1102 * comment gets lumped into the comment.
1104 if (!*p
|| *p
== ';') {
1109 } else if (*p
== ';') {
1115 * Anything else is an operator of some kind. We check
1116 * for all the double-character operators (>>, <<, //,
1117 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1118 * else is a single-character operator.
1121 if ((p
[0] == '>' && p
[1] == '>') ||
1122 (p
[0] == '<' && p
[1] == '<') ||
1123 (p
[0] == '/' && p
[1] == '/') ||
1124 (p
[0] == '<' && p
[1] == '=') ||
1125 (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] == '^')) {
1137 /* Handling unterminated string by UNV */
1140 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1141 t->text[p-line] = *line;
1145 if (type
!= TOK_COMMENT
) {
1146 *tail
= t
= new_Token(NULL
, type
, line
, p
- line
);
1155 * this function allocates a new managed block of memory and
1156 * returns a pointer to the block. The managed blocks are
1157 * deleted only all at once by the delete_Blocks function.
1159 static void *new_Block(size_t size
)
1161 Blocks
*b
= &blocks
;
1163 /* first, get to the end of the linked list */
1166 /* now allocate the requested chunk */
1167 b
->chunk
= nasm_malloc(size
);
1169 /* now allocate a new block for the next request */
1170 b
->next
= nasm_zalloc(sizeof(Blocks
));
1175 * this function deletes all managed blocks of memory
1177 static void delete_Blocks(void)
1179 Blocks
*a
, *b
= &blocks
;
1182 * keep in mind that the first block, pointed to by blocks
1183 * is a static and not dynamically allocated, so we don't
1188 nasm_free(b
->chunk
);
1194 memset(&blocks
, 0, sizeof(blocks
));
1198 * this function creates a new Token and passes a pointer to it
1199 * back to the caller. It sets the type and text elements, and
1200 * also the a.mac and next elements to NULL.
1202 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
1203 const char *text
, int txtlen
)
1209 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1210 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1211 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1212 freeTokens
[i
].next
= NULL
;
1215 freeTokens
= t
->next
;
1219 if (type
== TOK_WHITESPACE
|| !text
) {
1223 txtlen
= strlen(text
);
1224 t
->text
= nasm_malloc(txtlen
+1);
1225 memcpy(t
->text
, text
, txtlen
);
1226 t
->text
[txtlen
] = '\0';
1231 static Token
*delete_Token(Token
* t
)
1233 Token
*next
= t
->next
;
1235 t
->next
= freeTokens
;
1241 * Convert a line of tokens back into text.
1242 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1243 * will be transformed into ..@ctxnum.xxx
1245 static char *detoken(Token
* tlist
, bool expand_locals
)
1252 list_for_each(t
, tlist
) {
1253 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
1258 if (*v
== '\'' || *v
== '\"' || *v
== '`') {
1259 size_t len
= nasm_unquote(v
, NULL
);
1260 size_t clen
= strlen(v
);
1263 nasm_error(ERR_NONFATAL
| ERR_PASS1
,
1264 "NUL character in %%! string");
1270 char *p
= getenv(v
);
1272 nasm_error(ERR_NONFATAL
| ERR_PASS1
,
1273 "nonexistent environment variable `%s'", v
);
1275 * FIXME We better should investigate if accessing
1276 * ->text[1] without ->text[0] is safe enough.
1278 t
->text
= nasm_zalloc(2);
1280 t
->text
= nasm_strdup(p
);
1285 /* Expand local macros here and not during preprocessing */
1286 if (expand_locals
&&
1287 t
->type
== TOK_PREPROC_ID
&& t
->text
&&
1288 t
->text
[0] == '%' && t
->text
[1] == '$') {
1291 Context
*ctx
= get_ctx(t
->text
, &q
);
1294 snprintf(buffer
, sizeof(buffer
), "..@%"PRIu32
".", ctx
->number
);
1295 p
= nasm_strcat(buffer
, q
);
1300 if (t
->type
== TOK_WHITESPACE
)
1303 len
+= strlen(t
->text
);
1306 p
= line
= nasm_malloc(len
+ 1);
1308 list_for_each(t
, tlist
) {
1309 if (t
->type
== TOK_WHITESPACE
) {
1311 } else if (t
->text
) {
1323 * A scanner, suitable for use by the expression evaluator, which
1324 * operates on a line of Tokens. Expects a pointer to a pointer to
1325 * the first token in the line to be passed in as its private_data
1328 * FIX: This really needs to be unified with stdscan.
1330 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1332 Token
**tlineptr
= private_data
;
1334 char ourcopy
[MAX_KEYWORD
+1], *p
, *r
, *s
;
1338 *tlineptr
= tline
? tline
->next
: NULL
;
1339 } while (tline
&& (tline
->type
== TOK_WHITESPACE
||
1340 tline
->type
== TOK_COMMENT
));
1343 return tokval
->t_type
= TOKEN_EOS
;
1345 tokval
->t_charptr
= tline
->text
;
1347 if (tline
->text
[0] == '$' && !tline
->text
[1])
1348 return tokval
->t_type
= TOKEN_HERE
;
1349 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[2])
1350 return tokval
->t_type
= TOKEN_BASE
;
1352 if (tline
->type
== TOK_ID
) {
1353 p
= tokval
->t_charptr
= tline
->text
;
1355 tokval
->t_charptr
++;
1356 return tokval
->t_type
= TOKEN_ID
;
1359 for (r
= p
, s
= ourcopy
; *r
; r
++) {
1360 if (r
>= p
+MAX_KEYWORD
)
1361 return tokval
->t_type
= TOKEN_ID
; /* Not a keyword */
1362 *s
++ = nasm_tolower(*r
);
1365 /* right, so we have an identifier sitting in temp storage. now,
1366 * is it actually a register or instruction name, or what? */
1367 return nasm_token_hash(ourcopy
, tokval
);
1370 if (tline
->type
== TOK_NUMBER
) {
1372 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
1373 tokval
->t_charptr
= tline
->text
;
1375 return tokval
->t_type
= TOKEN_ERRNUM
;
1377 return tokval
->t_type
= TOKEN_NUM
;
1380 if (tline
->type
== TOK_FLOAT
) {
1381 return tokval
->t_type
= TOKEN_FLOAT
;
1384 if (tline
->type
== TOK_STRING
) {
1387 bq
= tline
->text
[0];
1388 tokval
->t_charptr
= tline
->text
;
1389 tokval
->t_inttwo
= nasm_unquote(tline
->text
, &ep
);
1391 if (ep
[0] != bq
|| ep
[1] != '\0')
1392 return tokval
->t_type
= TOKEN_ERRSTR
;
1394 return tokval
->t_type
= TOKEN_STR
;
1397 if (tline
->type
== TOK_OTHER
) {
1398 if (!strcmp(tline
->text
, "<<"))
1399 return tokval
->t_type
= TOKEN_SHL
;
1400 if (!strcmp(tline
->text
, ">>"))
1401 return tokval
->t_type
= TOKEN_SHR
;
1402 if (!strcmp(tline
->text
, "//"))
1403 return tokval
->t_type
= TOKEN_SDIV
;
1404 if (!strcmp(tline
->text
, "%%"))
1405 return tokval
->t_type
= TOKEN_SMOD
;
1406 if (!strcmp(tline
->text
, "=="))
1407 return tokval
->t_type
= TOKEN_EQ
;
1408 if (!strcmp(tline
->text
, "<>"))
1409 return tokval
->t_type
= TOKEN_NE
;
1410 if (!strcmp(tline
->text
, "!="))
1411 return tokval
->t_type
= TOKEN_NE
;
1412 if (!strcmp(tline
->text
, "<="))
1413 return tokval
->t_type
= TOKEN_LE
;
1414 if (!strcmp(tline
->text
, ">="))
1415 return tokval
->t_type
= TOKEN_GE
;
1416 if (!strcmp(tline
->text
, "&&"))
1417 return tokval
->t_type
= TOKEN_DBL_AND
;
1418 if (!strcmp(tline
->text
, "^^"))
1419 return tokval
->t_type
= TOKEN_DBL_XOR
;
1420 if (!strcmp(tline
->text
, "||"))
1421 return tokval
->t_type
= TOKEN_DBL_OR
;
1425 * We have no other options: just return the first character of
1428 return tokval
->t_type
= tline
->text
[0];
1432 * Compare a string to the name of an existing macro; this is a
1433 * simple wrapper which calls either strcmp or nasm_stricmp
1434 * depending on the value of the `casesense' parameter.
1436 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
1438 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
1442 * Compare a string to the name of an existing macro; this is a
1443 * simple wrapper which calls either strcmp or nasm_stricmp
1444 * depending on the value of the `casesense' parameter.
1446 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
1448 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
1452 * Return the Context structure associated with a %$ token. Return
1453 * NULL, having _already_ reported an error condition, if the
1454 * context stack isn't deep enough for the supplied number of $
1457 * If "namep" is non-NULL, set it to the pointer to the macro name
1458 * tail, i.e. the part beyond %$...
1460 static Context
*get_ctx(const char *name
, const char **namep
)
1468 if (!name
|| name
[0] != '%' || name
[1] != '$')
1472 nasm_error(ERR_NONFATAL
, "`%s': context stack is empty", name
);
1479 while (ctx
&& *name
== '$') {
1485 nasm_error(ERR_NONFATAL
, "`%s': context stack is only"
1486 " %d level%s deep", name
, i
, (i
== 1 ? "" : "s"));
1497 * Open an include file. This routine must always return a valid
1498 * file pointer if it returns - it's responsible for throwing an
1499 * ERR_FATAL and bombing out completely if not. It should also try
1500 * the include path one by one until it finds the file or reaches
1501 * the end of the path.
1503 * Note: for INC_PROBE the function returns NULL at all times;
1504 * instead look for the
1507 INC_NEEDED
, /* File must exist */
1508 INC_OPTIONAL
, /* Missing is OK */
1509 INC_PROBE
/* Only an existence probe */
1512 /* This is conducts a full pathname search */
1513 static FILE *inc_fopen_search(const char *file
, StrList
**slpath
,
1514 enum incopen_mode omode
, enum file_flags fmode
)
1518 const IncPath
*ip
= ipath
;
1519 int len
= strlen(file
);
1520 size_t prefix_len
= 0;
1526 path_len
= prefix_len
+ len
+ 1;
1528 sl
= nasm_malloc(path_len
+ sizeof sl
->next
);
1529 memcpy(sl
->str
, prefix
, prefix_len
);
1530 memcpy(sl
->str
+prefix_len
, file
, len
+1);
1533 if (omode
== INC_PROBE
) {
1535 found
= nasm_file_exists(sl
->str
);
1537 fp
= nasm_open_read(sl
->str
, fmode
);
1538 found
= (fp
!= NULL
);
1551 prefix_len
= strlen(prefix
);
1557 * Open a file, or test for the presence of one (depending on omode),
1558 * considering the include path.
1560 static FILE *inc_fopen(const char *file
,
1562 const char **found_path
,
1563 enum incopen_mode omode
,
1564 enum file_flags fmode
)
1567 struct hash_insert hi
;
1572 hp
= hash_find(&FileHash
, file
, &hi
);
1576 /* Need to do the actual path search */
1580 fp
= inc_fopen_search(file
, &sl
, omode
, fmode
);
1582 file_len
= strlen(file
);
1585 /* Store negative result for this file */
1586 sl
= nasm_malloc(file_len
+ 1 + sizeof sl
->next
);
1587 memcpy(sl
->str
, file
, file_len
+1);
1593 file
= strchr(path
, '\0') - file_len
;
1596 hash_add(&hi
, file
, path
); /* Positive or negative result */
1599 * Add file to dependency path. The in_list() is needed
1600 * in case the file was already added with %depend.
1602 if (path
|| omode
!= INC_NEEDED
)
1603 nasm_add_to_strlist(dhead
, sl
);
1607 if (omode
== INC_NEEDED
)
1608 nasm_fatal(0, "unable to open include file `%s'", file
);
1616 if (!fp
&& omode
!= INC_PROBE
)
1617 fp
= nasm_open_read(file
, fmode
);
1626 * Opens an include or input file. Public version, for use by modules
1627 * that get a file:lineno pair and need to look at the file again
1628 * (e.g. the CodeView debug backend). Returns NULL on failure.
1630 FILE *pp_input_fopen(const char *filename
, enum file_flags mode
)
1632 return inc_fopen(filename
, NULL
, NULL
, INC_OPTIONAL
, mode
);
1636 * Determine if we should warn on defining a single-line macro of
1637 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1638 * return true if _any_ single-line macro of that name is defined.
1639 * Otherwise, will return true if a single-line macro with either
1640 * `nparam' or no parameters is defined.
1642 * If a macro with precisely the right number of parameters is
1643 * defined, or nparam is -1, the address of the definition structure
1644 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1645 * is NULL, no action will be taken regarding its contents, and no
1648 * Note that this is also called with nparam zero to resolve
1651 * If you already know which context macro belongs to, you can pass
1652 * the context pointer as first parameter; if you won't but name begins
1653 * with %$ the context will be automatically computed. If all_contexts
1654 * is true, macro will be searched in outer contexts as well.
1657 smacro_defined(Context
* ctx
, const char *name
, int nparam
, SMacro
** defn
,
1660 struct hash_table
*smtbl
;
1664 smtbl
= &ctx
->localmac
;
1665 } else if (name
[0] == '%' && name
[1] == '$') {
1667 ctx
= get_ctx(name
, &name
);
1669 return false; /* got to return _something_ */
1670 smtbl
= &ctx
->localmac
;
1674 m
= (SMacro
*) hash_findix(smtbl
, name
);
1677 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
1678 (nparam
<= 0 || m
->nparam
== 0 || nparam
== (int) m
->nparam
)) {
1680 if (nparam
== (int) m
->nparam
|| nparam
== -1)
1694 * Count and mark off the parameters in a multi-line macro call.
1695 * This is called both from within the multi-line macro expansion
1696 * code, and also to mark off the default parameters when provided
1697 * in a %macro definition line.
1699 static void count_mmac_params(Token
* t
, int *nparam
, Token
*** params
)
1701 int paramsize
, brace
;
1703 *nparam
= paramsize
= 0;
1706 /* +1: we need space for the final NULL */
1707 if (*nparam
+1 >= paramsize
) {
1708 paramsize
+= PARAM_DELTA
;
1709 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
1713 if (tok_is_(t
, "{"))
1715 (*params
)[(*nparam
)++] = t
;
1717 while (brace
&& (t
= t
->next
) != NULL
) {
1718 if (tok_is_(t
, "{"))
1720 else if (tok_is_(t
, "}"))
1726 * Now we've found the closing brace, look further
1731 if (tok_isnt_(t
, ",")) {
1732 nasm_error(ERR_NONFATAL
,
1733 "braces do not enclose all of macro parameter");
1734 while (tok_isnt_(t
, ","))
1739 while (tok_isnt_(t
, ","))
1742 if (t
) { /* got a comma/brace */
1743 t
= t
->next
; /* eat the comma */
1749 * Determine whether one of the various `if' conditions is true or
1752 * We must free the tline we get passed.
1754 static bool if_condition(Token
* tline
, enum preproc_token ct
)
1756 enum pp_conditional i
= PP_COND(ct
);
1758 Token
*t
, *tt
, **tptr
, *origline
;
1759 struct tokenval tokval
;
1761 enum pp_token_type needtype
;
1768 j
= false; /* have we matched yet? */
1773 if (tline
->type
!= TOK_ID
) {
1774 nasm_error(ERR_NONFATAL
,
1775 "`%s' expects context identifiers", pp_directives
[ct
]);
1776 free_tlist(origline
);
1779 if (cstk
&& cstk
->name
&& !nasm_stricmp(tline
->text
, cstk
->name
))
1781 tline
= tline
->next
;
1786 j
= false; /* have we matched yet? */
1789 if (!tline
|| (tline
->type
!= TOK_ID
&&
1790 (tline
->type
!= TOK_PREPROC_ID
||
1791 tline
->text
[1] != '$'))) {
1792 nasm_error(ERR_NONFATAL
,
1793 "`%s' expects macro identifiers", pp_directives
[ct
]);
1796 if (smacro_defined(NULL
, tline
->text
, 0, NULL
, true))
1798 tline
= tline
->next
;
1803 tline
= expand_smacro(tline
);
1804 j
= false; /* have we matched yet? */
1807 if (!tline
|| (tline
->type
!= TOK_ID
&&
1808 tline
->type
!= TOK_STRING
&&
1809 (tline
->type
!= TOK_PREPROC_ID
||
1810 tline
->text
[1] != '!'))) {
1811 nasm_error(ERR_NONFATAL
,
1812 "`%s' expects environment variable names",
1817 if (tline
->type
== TOK_PREPROC_ID
)
1818 p
+= 2; /* Skip leading %! */
1819 if (*p
== '\'' || *p
== '\"' || *p
== '`')
1820 nasm_unquote_cstr(p
, ct
);
1823 tline
= tline
->next
;
1829 tline
= expand_smacro(tline
);
1831 while (tok_isnt_(tt
, ","))
1834 nasm_error(ERR_NONFATAL
,
1835 "`%s' expects two comma-separated arguments",
1840 j
= true; /* assume equality unless proved not */
1841 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1842 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1843 nasm_error(ERR_NONFATAL
, "`%s': more than one comma on line",
1847 if (t
->type
== TOK_WHITESPACE
) {
1851 if (tt
->type
== TOK_WHITESPACE
) {
1855 if (tt
->type
!= t
->type
) {
1856 j
= false; /* found mismatching tokens */
1859 /* When comparing strings, need to unquote them first */
1860 if (t
->type
== TOK_STRING
) {
1861 size_t l1
= nasm_unquote(t
->text
, NULL
);
1862 size_t l2
= nasm_unquote(tt
->text
, NULL
);
1868 if (mmemcmp(t
->text
, tt
->text
, l1
, i
== PPC_IFIDN
)) {
1872 } else if (mstrcmp(tt
->text
, t
->text
, i
== PPC_IFIDN
) != 0) {
1873 j
= false; /* found mismatching tokens */
1880 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
1881 j
= false; /* trailing gunk on one end or other */
1887 MMacro searching
, *mmac
;
1890 tline
= expand_id(tline
);
1891 if (!tok_type_(tline
, TOK_ID
)) {
1892 nasm_error(ERR_NONFATAL
,
1893 "`%s' expects a macro name", pp_directives
[ct
]);
1896 searching
.name
= nasm_strdup(tline
->text
);
1897 searching
.casesense
= true;
1898 searching
.plus
= false;
1899 searching
.nolist
= false;
1900 searching
.in_progress
= 0;
1901 searching
.max_depth
= 0;
1902 searching
.rep_nest
= NULL
;
1903 searching
.nparam_min
= 0;
1904 searching
.nparam_max
= INT_MAX
;
1905 tline
= expand_smacro(tline
->next
);
1908 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
1909 nasm_error(ERR_NONFATAL
,
1910 "`%s' expects a parameter count or nothing",
1913 searching
.nparam_min
= searching
.nparam_max
=
1914 readnum(tline
->text
, &j
);
1916 nasm_error(ERR_NONFATAL
,
1917 "unable to parse parameter count `%s'",
1920 if (tline
&& tok_is_(tline
->next
, "-")) {
1921 tline
= tline
->next
->next
;
1922 if (tok_is_(tline
, "*"))
1923 searching
.nparam_max
= INT_MAX
;
1924 else if (!tok_type_(tline
, TOK_NUMBER
))
1925 nasm_error(ERR_NONFATAL
,
1926 "`%s' expects a parameter count after `-'",
1929 searching
.nparam_max
= readnum(tline
->text
, &j
);
1931 nasm_error(ERR_NONFATAL
,
1932 "unable to parse parameter count `%s'",
1934 if (searching
.nparam_min
> searching
.nparam_max
)
1935 nasm_error(ERR_NONFATAL
,
1936 "minimum parameter count exceeds maximum");
1939 if (tline
&& tok_is_(tline
->next
, "+")) {
1940 tline
= tline
->next
;
1941 searching
.plus
= true;
1943 mmac
= (MMacro
*) hash_findix(&mmacros
, searching
.name
);
1945 if (!strcmp(mmac
->name
, searching
.name
) &&
1946 (mmac
->nparam_min
<= searching
.nparam_max
1948 && (searching
.nparam_min
<= mmac
->nparam_max
1955 if (tline
&& tline
->next
)
1956 nasm_error(ERR_WARNING
|ERR_PASS1
,
1957 "trailing garbage after %%ifmacro ignored");
1958 nasm_free(searching
.name
);
1967 needtype
= TOK_NUMBER
;
1970 needtype
= TOK_STRING
;
1974 t
= tline
= expand_smacro(tline
);
1976 while (tok_type_(t
, TOK_WHITESPACE
) ||
1977 (needtype
== TOK_NUMBER
&&
1978 tok_type_(t
, TOK_OTHER
) &&
1979 (t
->text
[0] == '-' || t
->text
[0] == '+') &&
1983 j
= tok_type_(t
, needtype
);
1987 t
= tline
= expand_smacro(tline
);
1988 while (tok_type_(t
, TOK_WHITESPACE
))
1993 t
= t
->next
; /* Skip the actual token */
1994 while (tok_type_(t
, TOK_WHITESPACE
))
1996 j
= !t
; /* Should be nothing left */
2001 t
= tline
= expand_smacro(tline
);
2002 while (tok_type_(t
, TOK_WHITESPACE
))
2005 j
= !t
; /* Should be empty */
2009 t
= tline
= expand_smacro(tline
);
2011 tokval
.t_type
= TOKEN_INVALID
;
2012 evalresult
= evaluate(ppscan
, tptr
, &tokval
,
2013 NULL
, pass
| CRITICAL
, NULL
);
2017 nasm_error(ERR_WARNING
|ERR_PASS1
,
2018 "trailing garbage after expression ignored");
2019 if (!is_simple(evalresult
)) {
2020 nasm_error(ERR_NONFATAL
,
2021 "non-constant value given to `%s'", pp_directives
[ct
]);
2024 j
= reloc_value(evalresult
) != 0;
2028 nasm_error(ERR_FATAL
,
2029 "preprocessor directive `%s' not yet implemented",
2034 free_tlist(origline
);
2035 return j
^ PP_NEGATIVE(ct
);
2038 free_tlist(origline
);
2043 * Common code for defining an smacro
2045 static bool define_smacro(Context
*ctx
, const char *mname
, bool casesense
,
2046 int nparam
, Token
*expansion
)
2048 SMacro
*smac
, **smhead
;
2049 struct hash_table
*smtbl
;
2051 if (smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
)) {
2053 nasm_error(ERR_WARNING
|ERR_PASS1
,
2054 "single-line macro `%s' defined both with and"
2055 " without parameters", mname
);
2057 * Some instances of the old code considered this a failure,
2058 * some others didn't. What is the right thing to do here?
2060 free_tlist(expansion
);
2061 return false; /* Failure */
2064 * We're redefining, so we have to take over an
2065 * existing SMacro structure. This means freeing
2066 * what was already in it.
2068 nasm_free(smac
->name
);
2069 free_tlist(smac
->expansion
);
2072 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2073 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
2074 smac
= nasm_malloc(sizeof(SMacro
));
2075 smac
->next
= *smhead
;
2078 smac
->name
= nasm_strdup(mname
);
2079 smac
->casesense
= casesense
;
2080 smac
->nparam
= nparam
;
2081 smac
->expansion
= expansion
;
2082 smac
->in_progress
= false;
2083 return true; /* Success */
2087 * Undefine an smacro
2089 static void undef_smacro(Context
*ctx
, const char *mname
)
2091 SMacro
**smhead
, *s
, **sp
;
2092 struct hash_table
*smtbl
;
2094 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2095 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
2099 * We now have a macro name... go hunt for it.
2102 while ((s
= *sp
) != NULL
) {
2103 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
2106 free_tlist(s
->expansion
);
2116 * Parse a mmacro specification.
2118 static bool parse_mmacro_spec(Token
*tline
, MMacro
*def
, const char *directive
)
2122 tline
= tline
->next
;
2124 tline
= expand_id(tline
);
2125 if (!tok_type_(tline
, TOK_ID
)) {
2126 nasm_error(ERR_NONFATAL
, "`%s' expects a macro name", directive
);
2131 def
->name
= nasm_strdup(tline
->text
);
2133 def
->nolist
= false;
2134 def
->in_progress
= 0;
2135 def
->rep_nest
= NULL
;
2136 def
->nparam_min
= 0;
2137 def
->nparam_max
= 0;
2139 tline
= expand_smacro(tline
->next
);
2141 if (!tok_type_(tline
, TOK_NUMBER
)) {
2142 nasm_error(ERR_NONFATAL
, "`%s' expects a parameter count", directive
);
2144 def
->nparam_min
= def
->nparam_max
=
2145 readnum(tline
->text
, &err
);
2147 nasm_error(ERR_NONFATAL
,
2148 "unable to parse parameter count `%s'", tline
->text
);
2150 if (tline
&& tok_is_(tline
->next
, "-")) {
2151 tline
= tline
->next
->next
;
2152 if (tok_is_(tline
, "*")) {
2153 def
->nparam_max
= INT_MAX
;
2154 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2155 nasm_error(ERR_NONFATAL
,
2156 "`%s' expects a parameter count after `-'", directive
);
2158 def
->nparam_max
= readnum(tline
->text
, &err
);
2160 nasm_error(ERR_NONFATAL
, "unable to parse parameter count `%s'",
2163 if (def
->nparam_min
> def
->nparam_max
) {
2164 nasm_error(ERR_NONFATAL
, "minimum parameter count exceeds maximum");
2168 if (tline
&& tok_is_(tline
->next
, "+")) {
2169 tline
= tline
->next
;
2172 if (tline
&& tok_type_(tline
->next
, TOK_ID
) &&
2173 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
2174 tline
= tline
->next
;
2179 * Handle default parameters.
2181 if (tline
&& tline
->next
) {
2182 def
->dlist
= tline
->next
;
2184 count_mmac_params(def
->dlist
, &def
->ndefs
, &def
->defaults
);
2187 def
->defaults
= NULL
;
2189 def
->expansion
= NULL
;
2191 if (def
->defaults
&& def
->ndefs
> def
->nparam_max
- def
->nparam_min
&&
2193 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MDP
,
2194 "too many default macro parameters");
2201 * Decode a size directive
2203 static int parse_size(const char *str
) {
2204 static const char *size_names
[] =
2205 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2206 static const int sizes
[] =
2207 { 0, 1, 4, 16, 8, 10, 2, 32 };
2209 return sizes
[bsii(str
, size_names
, ARRAY_SIZE(size_names
))+1];
2213 * Process a preprocessor %pragma directive. Currently there are none.
2214 * Gets passed the token list starting with the "preproc" token from
2215 * "%pragma preproc".
2217 static void do_pragma_preproc(Token
*tline
)
2219 /* Skip to the real stuff */
2220 tline
= tline
->next
;
2225 (void)tline
; /* Nothing else to do at present */
2229 * find and process preprocessor directive in passed line
2230 * Find out if a line contains a preprocessor directive, and deal
2233 * If a directive _is_ found, it is the responsibility of this routine
2234 * (and not the caller) to free_tlist() the line.
2236 * @param tline a pointer to the current tokeninzed line linked list
2237 * @param output if this directive generated output
2238 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2241 static int do_directive(Token
*tline
, char **output
)
2243 enum preproc_token i
;
2252 const char *found_path
;
2257 MMacro
*mmac
, **mmhead
;
2258 Token
*t
= NULL
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
2260 struct tokenval tokval
;
2262 MMacro
*tmp_defining
; /* Used when manipulating rep_nest */
2267 *output
= NULL
; /* No output generated */
2271 if (!tline
|| !tok_type_(tline
, TOK_PREPROC_ID
) ||
2272 (tline
->text
[1] == '%' || tline
->text
[1] == '$'
2273 || tline
->text
[1] == '!'))
2274 return NO_DIRECTIVE_FOUND
;
2276 i
= pp_token_hash(tline
->text
);
2279 * FIXME: We zap execution of PP_RMACRO, PP_IRMACRO, PP_EXITMACRO
2280 * since they are known to be buggy at moment, we need to fix them
2281 * in future release (2.09-2.10)
2283 if (i
== PP_RMACRO
|| i
== PP_IRMACRO
|| i
== PP_EXITMACRO
) {
2284 nasm_error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2286 return NO_DIRECTIVE_FOUND
;
2290 * If we're in a non-emitting branch of a condition construct,
2291 * or walking to the end of an already terminated %rep block,
2292 * we should ignore all directives except for condition
2295 if (((istk
->conds
&& !emitting(istk
->conds
->state
)) ||
2296 (istk
->mstk
&& !istk
->mstk
->in_progress
)) && !is_condition(i
)) {
2297 return NO_DIRECTIVE_FOUND
;
2301 * If we're defining a macro or reading a %rep block, we should
2302 * ignore all directives except for %macro/%imacro (which nest),
2303 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2304 * If we're in a %rep block, another %rep nests, so should be let through.
2306 if (defining
&& i
!= PP_MACRO
&& i
!= PP_IMACRO
&&
2307 i
!= PP_RMACRO
&& i
!= PP_IRMACRO
&&
2308 i
!= PP_ENDMACRO
&& i
!= PP_ENDM
&&
2309 (defining
->name
|| (i
!= PP_ENDREP
&& i
!= PP_REP
))) {
2310 return NO_DIRECTIVE_FOUND
;
2314 if (i
== PP_MACRO
|| i
== PP_IMACRO
||
2315 i
== PP_RMACRO
|| i
== PP_IRMACRO
) {
2317 return NO_DIRECTIVE_FOUND
;
2318 } else if (nested_mac_count
> 0) {
2319 if (i
== PP_ENDMACRO
) {
2321 return NO_DIRECTIVE_FOUND
;
2324 if (!defining
->name
) {
2327 return NO_DIRECTIVE_FOUND
;
2328 } else if (nested_rep_count
> 0) {
2329 if (i
== PP_ENDREP
) {
2331 return NO_DIRECTIVE_FOUND
;
2339 nasm_error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2341 return NO_DIRECTIVE_FOUND
; /* didn't get it */
2345 * %pragma namespace options...
2347 * The namespace "preproc" is reserved for the preprocessor;
2348 * all other namespaces generate a [pragma] assembly directive.
2350 * Invalid %pragmas are ignored and may have different
2351 * meaning in future versions of NASM.
2353 tline
= tline
->next
;
2355 tline
= expand_smacro(tline
);
2356 if (tok_type_(tline
, TOK_ID
)) {
2357 if (!nasm_stricmp(tline
->text
, "preproc")) {
2358 /* Preprocessor pragma */
2359 do_pragma_preproc(tline
);
2361 /* Build the assembler directive */
2362 t
= new_Token(NULL
, TOK_OTHER
, "[", 1);
2363 t
->next
= new_Token(NULL
, TOK_ID
, "pragma", 6);
2364 t
->next
->next
= new_Token(tline
, TOK_WHITESPACE
, NULL
, 0);
2366 for (t
= tline
; t
->next
; t
= t
->next
)
2368 t
->next
= new_Token(NULL
, TOK_OTHER
, "]", 1);
2369 /* true here can be revisited in the future */
2370 *output
= detoken(tline
, true);
2373 free_tlist(origline
);
2374 return DIRECTIVE_FOUND
;
2377 /* Directive to tell NASM what the default stack size is. The
2378 * default is for a 16-bit stack, and this can be overriden with
2381 tline
= tline
->next
;
2382 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2383 tline
= tline
->next
;
2384 if (!tline
|| tline
->type
!= TOK_ID
) {
2385 nasm_error(ERR_NONFATAL
, "`%%stacksize' missing size parameter");
2386 free_tlist(origline
);
2387 return DIRECTIVE_FOUND
;
2389 if (nasm_stricmp(tline
->text
, "flat") == 0) {
2390 /* All subsequent ARG directives are for a 32-bit stack */
2392 StackPointer
= "ebp";
2395 } else if (nasm_stricmp(tline
->text
, "flat64") == 0) {
2396 /* All subsequent ARG directives are for a 64-bit stack */
2398 StackPointer
= "rbp";
2401 } else if (nasm_stricmp(tline
->text
, "large") == 0) {
2402 /* All subsequent ARG directives are for a 16-bit stack,
2403 * far function call.
2406 StackPointer
= "bp";
2409 } else if (nasm_stricmp(tline
->text
, "small") == 0) {
2410 /* All subsequent ARG directives are for a 16-bit stack,
2411 * far function call. We don't support near functions.
2414 StackPointer
= "bp";
2418 nasm_error(ERR_NONFATAL
, "`%%stacksize' invalid size type");
2419 free_tlist(origline
);
2420 return DIRECTIVE_FOUND
;
2422 free_tlist(origline
);
2423 return DIRECTIVE_FOUND
;
2426 /* TASM like ARG directive to define arguments to functions, in
2427 * the following form:
2429 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2433 char *arg
, directive
[256];
2434 int size
= StackSize
;
2436 /* Find the argument name */
2437 tline
= tline
->next
;
2438 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2439 tline
= tline
->next
;
2440 if (!tline
|| tline
->type
!= TOK_ID
) {
2441 nasm_error(ERR_NONFATAL
, "`%%arg' missing argument parameter");
2442 free_tlist(origline
);
2443 return DIRECTIVE_FOUND
;
2447 /* Find the argument size type */
2448 tline
= tline
->next
;
2449 if (!tline
|| tline
->type
!= TOK_OTHER
2450 || tline
->text
[0] != ':') {
2451 nasm_error(ERR_NONFATAL
,
2452 "Syntax error processing `%%arg' directive");
2453 free_tlist(origline
);
2454 return DIRECTIVE_FOUND
;
2456 tline
= tline
->next
;
2457 if (!tline
|| tline
->type
!= TOK_ID
) {
2458 nasm_error(ERR_NONFATAL
, "`%%arg' missing size type parameter");
2459 free_tlist(origline
);
2460 return DIRECTIVE_FOUND
;
2463 /* Allow macro expansion of type parameter */
2464 tt
= tokenize(tline
->text
);
2465 tt
= expand_smacro(tt
);
2466 size
= parse_size(tt
->text
);
2468 nasm_error(ERR_NONFATAL
,
2469 "Invalid size type for `%%arg' missing directive");
2471 free_tlist(origline
);
2472 return DIRECTIVE_FOUND
;
2476 /* Round up to even stack slots */
2477 size
= ALIGN(size
, StackSize
);
2479 /* Now define the macro for the argument */
2480 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
2481 arg
, StackPointer
, offset
);
2482 do_directive(tokenize(directive
), output
);
2485 /* Move to the next argument in the list */
2486 tline
= tline
->next
;
2487 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2488 tline
= tline
->next
;
2489 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2491 free_tlist(origline
);
2492 return DIRECTIVE_FOUND
;
2495 /* TASM like LOCAL directive to define local variables for a
2496 * function, in the following form:
2498 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2500 * The '= LocalSize' at the end is ignored by NASM, but is
2501 * required by TASM to define the local parameter size (and used
2502 * by the TASM macro package).
2504 offset
= LocalOffset
;
2506 char *local
, directive
[256];
2507 int size
= StackSize
;
2509 /* Find the argument name */
2510 tline
= tline
->next
;
2511 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2512 tline
= tline
->next
;
2513 if (!tline
|| tline
->type
!= TOK_ID
) {
2514 nasm_error(ERR_NONFATAL
,
2515 "`%%local' missing argument parameter");
2516 free_tlist(origline
);
2517 return DIRECTIVE_FOUND
;
2519 local
= tline
->text
;
2521 /* Find the argument size type */
2522 tline
= tline
->next
;
2523 if (!tline
|| tline
->type
!= TOK_OTHER
2524 || tline
->text
[0] != ':') {
2525 nasm_error(ERR_NONFATAL
,
2526 "Syntax error processing `%%local' directive");
2527 free_tlist(origline
);
2528 return DIRECTIVE_FOUND
;
2530 tline
= tline
->next
;
2531 if (!tline
|| tline
->type
!= TOK_ID
) {
2532 nasm_error(ERR_NONFATAL
,
2533 "`%%local' missing size type parameter");
2534 free_tlist(origline
);
2535 return DIRECTIVE_FOUND
;
2538 /* Allow macro expansion of type parameter */
2539 tt
= tokenize(tline
->text
);
2540 tt
= expand_smacro(tt
);
2541 size
= parse_size(tt
->text
);
2543 nasm_error(ERR_NONFATAL
,
2544 "Invalid size type for `%%local' missing directive");
2546 free_tlist(origline
);
2547 return DIRECTIVE_FOUND
;
2551 /* Round up to even stack slots */
2552 size
= ALIGN(size
, StackSize
);
2554 offset
+= size
; /* Negative offset, increment before */
2556 /* Now define the macro for the argument */
2557 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
2558 local
, StackPointer
, offset
);
2559 do_directive(tokenize(directive
), output
);
2561 /* Now define the assign to setup the enter_c macro correctly */
2562 snprintf(directive
, sizeof(directive
),
2563 "%%assign %%$localsize %%$localsize+%d", size
);
2564 do_directive(tokenize(directive
), output
);
2566 /* Move to the next argument in the list */
2567 tline
= tline
->next
;
2568 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2569 tline
= tline
->next
;
2570 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2571 LocalOffset
= offset
;
2572 free_tlist(origline
);
2573 return DIRECTIVE_FOUND
;
2577 nasm_error(ERR_WARNING
|ERR_PASS1
,
2578 "trailing garbage after `%%clear' ignored");
2581 free_tlist(origline
);
2582 return DIRECTIVE_FOUND
;
2585 t
= tline
->next
= expand_smacro(tline
->next
);
2587 if (!t
|| (t
->type
!= TOK_STRING
&&
2588 t
->type
!= TOK_INTERNAL_STRING
)) {
2589 nasm_error(ERR_NONFATAL
, "`%%depend' expects a file name");
2590 free_tlist(origline
);
2591 return DIRECTIVE_FOUND
; /* but we did _something_ */
2594 nasm_error(ERR_WARNING
|ERR_PASS1
,
2595 "trailing garbage after `%%depend' ignored");
2597 if (t
->type
!= TOK_INTERNAL_STRING
)
2598 nasm_unquote_cstr(p
, i
);
2599 nasm_add_string_to_strlist(dephead
, p
);
2600 free_tlist(origline
);
2601 return DIRECTIVE_FOUND
;
2604 t
= tline
->next
= expand_smacro(tline
->next
);
2607 if (!t
|| (t
->type
!= TOK_STRING
&&
2608 t
->type
!= TOK_INTERNAL_STRING
)) {
2609 nasm_error(ERR_NONFATAL
, "`%%include' expects a file name");
2610 free_tlist(origline
);
2611 return DIRECTIVE_FOUND
; /* but we did _something_ */
2614 nasm_error(ERR_WARNING
|ERR_PASS1
,
2615 "trailing garbage after `%%include' ignored");
2617 if (t
->type
!= TOK_INTERNAL_STRING
)
2618 nasm_unquote_cstr(p
, i
);
2619 inc
= nasm_malloc(sizeof(Include
));
2623 inc
->fp
= inc_fopen(p
, dephead
, &found_path
,
2624 pass
== 0 ? INC_OPTIONAL
: INC_NEEDED
, NF_TEXT
);
2626 /* -MG given but file not found */
2629 inc
->fname
= src_set_fname(found_path
? found_path
: p
);
2630 inc
->lineno
= src_set_linnum(0);
2632 inc
->expansion
= NULL
;
2635 lfmt
->uplevel(LIST_INCLUDE
);
2637 free_tlist(origline
);
2638 return DIRECTIVE_FOUND
;
2642 static macros_t
*use_pkg
;
2643 const char *pkg_macro
= NULL
;
2645 tline
= tline
->next
;
2647 tline
= expand_id(tline
);
2649 if (!tline
|| (tline
->type
!= TOK_STRING
&&
2650 tline
->type
!= TOK_INTERNAL_STRING
&&
2651 tline
->type
!= TOK_ID
)) {
2652 nasm_error(ERR_NONFATAL
, "`%%use' expects a package name");
2653 free_tlist(origline
);
2654 return DIRECTIVE_FOUND
; /* but we did _something_ */
2657 nasm_error(ERR_WARNING
|ERR_PASS1
,
2658 "trailing garbage after `%%use' ignored");
2659 if (tline
->type
== TOK_STRING
)
2660 nasm_unquote_cstr(tline
->text
, i
);
2661 use_pkg
= nasm_stdmac_find_package(tline
->text
);
2663 nasm_error(ERR_NONFATAL
, "unknown `%%use' package: %s", tline
->text
);
2665 pkg_macro
= (char *)use_pkg
+ 1; /* The first string will be <%define>__USE_*__ */
2666 if (use_pkg
&& ! smacro_defined(NULL
, pkg_macro
, 0, NULL
, true)) {
2667 /* Not already included, go ahead and include it */
2668 stdmacpos
= use_pkg
;
2670 free_tlist(origline
);
2671 return DIRECTIVE_FOUND
;
2676 tline
= tline
->next
;
2678 tline
= expand_id(tline
);
2680 if (!tok_type_(tline
, TOK_ID
)) {
2681 nasm_error(ERR_NONFATAL
, "`%s' expects a context identifier",
2683 free_tlist(origline
);
2684 return DIRECTIVE_FOUND
; /* but we did _something_ */
2687 nasm_error(ERR_WARNING
|ERR_PASS1
,
2688 "trailing garbage after `%s' ignored",
2690 p
= nasm_strdup(tline
->text
);
2692 p
= NULL
; /* Anonymous */
2696 ctx
= nasm_malloc(sizeof(Context
));
2698 hash_init(&ctx
->localmac
, HASH_SMALL
);
2700 ctx
->number
= unique
++;
2705 nasm_error(ERR_NONFATAL
, "`%s': context stack is empty",
2707 } else if (i
== PP_POP
) {
2708 if (p
&& (!cstk
->name
|| nasm_stricmp(p
, cstk
->name
)))
2709 nasm_error(ERR_NONFATAL
, "`%%pop' in wrong context: %s, "
2711 cstk
->name
? cstk
->name
: "anonymous", p
);
2716 nasm_free(cstk
->name
);
2722 free_tlist(origline
);
2723 return DIRECTIVE_FOUND
;
2725 severity
= ERR_FATAL
;
2728 severity
= ERR_NONFATAL
;
2731 severity
= ERR_WARNING
|ERR_WARN_USER
;
2736 /* Only error out if this is the final pass */
2737 if (pass
!= 2 && i
!= PP_FATAL
)
2738 return DIRECTIVE_FOUND
;
2740 tline
->next
= expand_smacro(tline
->next
);
2741 tline
= tline
->next
;
2743 t
= tline
? tline
->next
: NULL
;
2745 if (tok_type_(tline
, TOK_STRING
) && !t
) {
2746 /* The line contains only a quoted string */
2748 nasm_unquote(p
, NULL
); /* Ignore NUL character truncation */
2749 nasm_error(severity
, "%s", p
);
2751 /* Not a quoted string, or more than a quoted string */
2752 p
= detoken(tline
, false);
2753 nasm_error(severity
, "%s", p
);
2756 free_tlist(origline
);
2757 return DIRECTIVE_FOUND
;
2761 if (istk
->conds
&& !emitting(istk
->conds
->state
))
2764 j
= if_condition(tline
->next
, i
);
2765 tline
->next
= NULL
; /* it got freed */
2766 j
= j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2768 cond
= nasm_malloc(sizeof(Cond
));
2769 cond
->next
= istk
->conds
;
2773 istk
->mstk
->condcnt
++;
2774 free_tlist(origline
);
2775 return DIRECTIVE_FOUND
;
2779 nasm_error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2780 switch(istk
->conds
->state
) {
2782 istk
->conds
->state
= COND_DONE
;
2789 case COND_ELSE_TRUE
:
2790 case COND_ELSE_FALSE
:
2791 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_PP_PRECOND
,
2792 "`%%elif' after `%%else' ignored");
2793 istk
->conds
->state
= COND_NEVER
;
2798 * IMPORTANT: In the case of %if, we will already have
2799 * called expand_mmac_params(); however, if we're
2800 * processing an %elif we must have been in a
2801 * non-emitting mode, which would have inhibited
2802 * the normal invocation of expand_mmac_params().
2803 * Therefore, we have to do it explicitly here.
2805 j
= if_condition(expand_mmac_params(tline
->next
), i
);
2806 tline
->next
= NULL
; /* it got freed */
2807 istk
->conds
->state
=
2808 j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2811 free_tlist(origline
);
2812 return DIRECTIVE_FOUND
;
2816 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_PP_PRECOND
,
2817 "trailing garbage after `%%else' ignored");
2819 nasm_fatal(0, "`%%else: no matching `%%if'");
2820 switch(istk
->conds
->state
) {
2823 istk
->conds
->state
= COND_ELSE_FALSE
;
2830 istk
->conds
->state
= COND_ELSE_TRUE
;
2833 case COND_ELSE_TRUE
:
2834 case COND_ELSE_FALSE
:
2835 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_PP_PRECOND
,
2836 "`%%else' after `%%else' ignored.");
2837 istk
->conds
->state
= COND_NEVER
;
2840 free_tlist(origline
);
2841 return DIRECTIVE_FOUND
;
2845 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_PP_PRECOND
,
2846 "trailing garbage after `%%endif' ignored");
2848 nasm_error(ERR_FATAL
, "`%%endif': no matching `%%if'");
2850 istk
->conds
= cond
->next
;
2853 istk
->mstk
->condcnt
--;
2854 free_tlist(origline
);
2855 return DIRECTIVE_FOUND
;
2862 nasm_error(ERR_FATAL
, "`%s': already defining a macro",
2864 return DIRECTIVE_FOUND
;
2866 defining
= nasm_zalloc(sizeof(MMacro
));
2867 defining
->max_depth
=
2868 (i
== PP_RMACRO
) || (i
== PP_IRMACRO
) ? DEADMAN_LIMIT
: 0;
2869 defining
->casesense
= (i
== PP_MACRO
) || (i
== PP_RMACRO
);
2870 if (!parse_mmacro_spec(tline
, defining
, pp_directives
[i
])) {
2871 nasm_free(defining
);
2873 return DIRECTIVE_FOUND
;
2876 src_get(&defining
->xline
, &defining
->fname
);
2878 mmac
= (MMacro
*) hash_findix(&mmacros
, defining
->name
);
2880 if (!strcmp(mmac
->name
, defining
->name
) &&
2881 (mmac
->nparam_min
<= defining
->nparam_max
2883 && (defining
->nparam_min
<= mmac
->nparam_max
2885 nasm_error(ERR_WARNING
|ERR_PASS1
,
2886 "redefining multi-line macro `%s'", defining
->name
);
2887 return DIRECTIVE_FOUND
;
2891 free_tlist(origline
);
2892 return DIRECTIVE_FOUND
;
2896 if (! (defining
&& defining
->name
)) {
2897 nasm_error(ERR_NONFATAL
, "`%s': not defining a macro", tline
->text
);
2898 return DIRECTIVE_FOUND
;
2900 mmhead
= (MMacro
**) hash_findi_add(&mmacros
, defining
->name
);
2901 defining
->next
= *mmhead
;
2904 free_tlist(origline
);
2905 return DIRECTIVE_FOUND
;
2909 * We must search along istk->expansion until we hit a
2910 * macro-end marker for a macro with a name. Then we
2911 * bypass all lines between exitmacro and endmacro.
2913 list_for_each(l
, istk
->expansion
)
2914 if (l
->finishes
&& l
->finishes
->name
)
2919 * Remove all conditional entries relative to this
2920 * macro invocation. (safe to do in this context)
2922 for ( ; l
->finishes
->condcnt
> 0; l
->finishes
->condcnt
--) {
2924 istk
->conds
= cond
->next
;
2927 istk
->expansion
= l
;
2929 nasm_error(ERR_NONFATAL
, "`%%exitmacro' not within `%%macro' block");
2931 free_tlist(origline
);
2932 return DIRECTIVE_FOUND
;
2940 spec
.casesense
= (i
== PP_UNMACRO
);
2941 if (!parse_mmacro_spec(tline
, &spec
, pp_directives
[i
])) {
2942 return DIRECTIVE_FOUND
;
2944 mmac_p
= (MMacro
**) hash_findi(&mmacros
, spec
.name
, NULL
);
2945 while (mmac_p
&& *mmac_p
) {
2947 if (mmac
->casesense
== spec
.casesense
&&
2948 !mstrcmp(mmac
->name
, spec
.name
, spec
.casesense
) &&
2949 mmac
->nparam_min
== spec
.nparam_min
&&
2950 mmac
->nparam_max
== spec
.nparam_max
&&
2951 mmac
->plus
== spec
.plus
) {
2952 *mmac_p
= mmac
->next
;
2955 mmac_p
= &mmac
->next
;
2958 free_tlist(origline
);
2959 free_tlist(spec
.dlist
);
2960 return DIRECTIVE_FOUND
;
2964 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
2965 tline
= tline
->next
;
2967 free_tlist(origline
);
2968 nasm_error(ERR_NONFATAL
, "`%%rotate' missing rotate count");
2969 return DIRECTIVE_FOUND
;
2971 t
= expand_smacro(tline
->next
);
2973 free_tlist(origline
);
2976 tokval
.t_type
= TOKEN_INVALID
;
2978 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, NULL
);
2981 return DIRECTIVE_FOUND
;
2983 nasm_error(ERR_WARNING
|ERR_PASS1
,
2984 "trailing garbage after expression ignored");
2985 if (!is_simple(evalresult
)) {
2986 nasm_error(ERR_NONFATAL
, "non-constant value given to `%%rotate'");
2987 return DIRECTIVE_FOUND
;
2990 while (mmac
&& !mmac
->name
) /* avoid mistaking %reps for macros */
2991 mmac
= mmac
->next_active
;
2993 nasm_error(ERR_NONFATAL
, "`%%rotate' invoked outside a macro call");
2994 } else if (mmac
->nparam
== 0) {
2995 nasm_error(ERR_NONFATAL
,
2996 "`%%rotate' invoked within macro without parameters");
2998 int rotate
= mmac
->rotate
+ reloc_value(evalresult
);
3000 rotate
%= (int)mmac
->nparam
;
3002 rotate
+= mmac
->nparam
;
3004 mmac
->rotate
= rotate
;
3006 return DIRECTIVE_FOUND
;
3011 tline
= tline
->next
;
3012 } while (tok_type_(tline
, TOK_WHITESPACE
));
3014 if (tok_type_(tline
, TOK_ID
) &&
3015 nasm_stricmp(tline
->text
, ".nolist") == 0) {
3018 tline
= tline
->next
;
3019 } while (tok_type_(tline
, TOK_WHITESPACE
));
3023 t
= expand_smacro(tline
);
3025 tokval
.t_type
= TOKEN_INVALID
;
3027 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, NULL
);
3029 free_tlist(origline
);
3030 return DIRECTIVE_FOUND
;
3033 nasm_error(ERR_WARNING
|ERR_PASS1
,
3034 "trailing garbage after expression ignored");
3035 if (!is_simple(evalresult
)) {
3036 nasm_error(ERR_NONFATAL
, "non-constant value given to `%%rep'");
3037 return DIRECTIVE_FOUND
;
3039 count
= reloc_value(evalresult
);
3040 if (count
>= REP_LIMIT
) {
3041 nasm_error(ERR_NONFATAL
, "`%%rep' value exceeds limit");
3046 nasm_error(ERR_NONFATAL
, "`%%rep' expects a repeat count");
3049 free_tlist(origline
);
3051 tmp_defining
= defining
;
3052 defining
= nasm_malloc(sizeof(MMacro
));
3053 defining
->prev
= NULL
;
3054 defining
->name
= NULL
; /* flags this macro as a %rep block */
3055 defining
->casesense
= false;
3056 defining
->plus
= false;
3057 defining
->nolist
= nolist
;
3058 defining
->in_progress
= count
;
3059 defining
->max_depth
= 0;
3060 defining
->nparam_min
= defining
->nparam_max
= 0;
3061 defining
->defaults
= NULL
;
3062 defining
->dlist
= NULL
;
3063 defining
->expansion
= NULL
;
3064 defining
->next_active
= istk
->mstk
;
3065 defining
->rep_nest
= tmp_defining
;
3066 return DIRECTIVE_FOUND
;
3069 if (!defining
|| defining
->name
) {
3070 nasm_error(ERR_NONFATAL
, "`%%endrep': no matching `%%rep'");
3071 return DIRECTIVE_FOUND
;
3075 * Now we have a "macro" defined - although it has no name
3076 * and we won't be entering it in the hash tables - we must
3077 * push a macro-end marker for it on to istk->expansion.
3078 * After that, it will take care of propagating itself (a
3079 * macro-end marker line for a macro which is really a %rep
3080 * block will cause the macro to be re-expanded, complete
3081 * with another macro-end marker to ensure the process
3082 * continues) until the whole expansion is forcibly removed
3083 * from istk->expansion by a %exitrep.
3085 l
= nasm_malloc(sizeof(Line
));
3086 l
->next
= istk
->expansion
;
3087 l
->finishes
= defining
;
3089 istk
->expansion
= l
;
3091 istk
->mstk
= defining
;
3093 lfmt
->uplevel(defining
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
3094 tmp_defining
= defining
;
3095 defining
= defining
->rep_nest
;
3096 free_tlist(origline
);
3097 return DIRECTIVE_FOUND
;
3101 * We must search along istk->expansion until we hit a
3102 * macro-end marker for a macro with no name. Then we set
3103 * its `in_progress' flag to 0.
3105 list_for_each(l
, istk
->expansion
)
3106 if (l
->finishes
&& !l
->finishes
->name
)
3110 l
->finishes
->in_progress
= 1;
3112 nasm_error(ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
3113 free_tlist(origline
);
3114 return DIRECTIVE_FOUND
;
3120 casesense
= (i
== PP_DEFINE
|| i
== PP_XDEFINE
);
3122 tline
= tline
->next
;
3124 tline
= expand_id(tline
);
3125 if (!tline
|| (tline
->type
!= TOK_ID
&&
3126 (tline
->type
!= TOK_PREPROC_ID
||
3127 tline
->text
[1] != '$'))) {
3128 nasm_error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3130 free_tlist(origline
);
3131 return DIRECTIVE_FOUND
;
3134 ctx
= get_ctx(tline
->text
, &mname
);
3136 param_start
= tline
= tline
->next
;
3139 /* Expand the macro definition now for %xdefine and %ixdefine */
3140 if ((i
== PP_XDEFINE
) || (i
== PP_IXDEFINE
))
3141 tline
= expand_smacro(tline
);
3143 if (tok_is_(tline
, "(")) {
3145 * This macro has parameters.
3148 tline
= tline
->next
;
3152 nasm_error(ERR_NONFATAL
, "parameter identifier expected");
3153 free_tlist(origline
);
3154 return DIRECTIVE_FOUND
;
3156 if (tline
->type
!= TOK_ID
) {
3157 nasm_error(ERR_NONFATAL
,
3158 "`%s': parameter identifier expected",
3160 free_tlist(origline
);
3161 return DIRECTIVE_FOUND
;
3163 tline
->type
= TOK_SMAC_PARAM
+ nparam
++;
3164 tline
= tline
->next
;
3166 if (tok_is_(tline
, ",")) {
3167 tline
= tline
->next
;
3169 if (!tok_is_(tline
, ")")) {
3170 nasm_error(ERR_NONFATAL
,
3171 "`)' expected to terminate macro template");
3172 free_tlist(origline
);
3173 return DIRECTIVE_FOUND
;
3179 tline
= tline
->next
;
3181 if (tok_type_(tline
, TOK_WHITESPACE
))
3182 last
= tline
, tline
= tline
->next
;
3187 if (t
->type
== TOK_ID
) {
3188 list_for_each(tt
, param_start
)
3189 if (tt
->type
>= TOK_SMAC_PARAM
&&
3190 !strcmp(tt
->text
, t
->text
))
3194 t
->next
= macro_start
;
3199 * Good. We now have a macro name, a parameter count, and a
3200 * token list (in reverse order) for an expansion. We ought
3201 * to be OK just to create an SMacro, store it, and let
3202 * free_tlist have the rest of the line (which we have
3203 * carefully re-terminated after chopping off the expansion
3206 define_smacro(ctx
, mname
, casesense
, nparam
, macro_start
);
3207 free_tlist(origline
);
3208 return DIRECTIVE_FOUND
;
3211 tline
= tline
->next
;
3213 tline
= expand_id(tline
);
3214 if (!tline
|| (tline
->type
!= TOK_ID
&&
3215 (tline
->type
!= TOK_PREPROC_ID
||
3216 tline
->text
[1] != '$'))) {
3217 nasm_error(ERR_NONFATAL
, "`%%undef' expects a macro identifier");
3218 free_tlist(origline
);
3219 return DIRECTIVE_FOUND
;
3222 nasm_error(ERR_WARNING
|ERR_PASS1
,
3223 "trailing garbage after macro name ignored");
3226 /* Find the context that symbol belongs to */
3227 ctx
= get_ctx(tline
->text
, &mname
);
3228 undef_smacro(ctx
, mname
);
3229 free_tlist(origline
);
3230 return DIRECTIVE_FOUND
;
3234 casesense
= (i
== PP_DEFSTR
);
3236 tline
= tline
->next
;
3238 tline
= expand_id(tline
);
3239 if (!tline
|| (tline
->type
!= TOK_ID
&&
3240 (tline
->type
!= TOK_PREPROC_ID
||
3241 tline
->text
[1] != '$'))) {
3242 nasm_error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3244 free_tlist(origline
);
3245 return DIRECTIVE_FOUND
;
3248 ctx
= get_ctx(tline
->text
, &mname
);
3250 tline
= expand_smacro(tline
->next
);
3253 while (tok_type_(tline
, TOK_WHITESPACE
))
3254 tline
= delete_Token(tline
);
3256 p
= detoken(tline
, false);
3257 macro_start
= nasm_malloc(sizeof(*macro_start
));
3258 macro_start
->next
= NULL
;
3259 macro_start
->text
= nasm_quote(p
, strlen(p
));
3260 macro_start
->type
= TOK_STRING
;
3261 macro_start
->a
.mac
= NULL
;
3265 * We now have a macro name, an implicit parameter count of
3266 * zero, and a string token to use as an expansion. Create
3267 * and store an SMacro.
3269 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3270 free_tlist(origline
);
3271 return DIRECTIVE_FOUND
;
3275 casesense
= (i
== PP_DEFTOK
);
3277 tline
= tline
->next
;
3279 tline
= expand_id(tline
);
3280 if (!tline
|| (tline
->type
!= TOK_ID
&&
3281 (tline
->type
!= TOK_PREPROC_ID
||
3282 tline
->text
[1] != '$'))) {
3283 nasm_error(ERR_NONFATAL
,
3284 "`%s' expects a macro identifier as first parameter",
3286 free_tlist(origline
);
3287 return DIRECTIVE_FOUND
;
3289 ctx
= get_ctx(tline
->text
, &mname
);
3291 tline
= expand_smacro(tline
->next
);
3295 while (tok_type_(t
, TOK_WHITESPACE
))
3297 /* t should now point to the string */
3298 if (!tok_type_(t
, TOK_STRING
)) {
3299 nasm_error(ERR_NONFATAL
,
3300 "`%s` requires string as second parameter",
3303 free_tlist(origline
);
3304 return DIRECTIVE_FOUND
;
3308 * Convert the string to a token stream. Note that smacros
3309 * are stored with the token stream reversed, so we have to
3310 * reverse the output of tokenize().
3312 nasm_unquote_cstr(t
->text
, i
);
3313 macro_start
= reverse_tokens(tokenize(t
->text
));
3316 * We now have a macro name, an implicit parameter count of
3317 * zero, and a numeric token to use as an expansion. Create
3318 * and store an SMacro.
3320 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3322 free_tlist(origline
);
3323 return DIRECTIVE_FOUND
;
3327 const char *found_path
;
3331 tline
= tline
->next
;
3333 tline
= expand_id(tline
);
3334 if (!tline
|| (tline
->type
!= TOK_ID
&&
3335 (tline
->type
!= TOK_PREPROC_ID
||
3336 tline
->text
[1] != '$'))) {
3337 nasm_error(ERR_NONFATAL
,
3338 "`%%pathsearch' expects a macro identifier as first parameter");
3339 free_tlist(origline
);
3340 return DIRECTIVE_FOUND
;
3342 ctx
= get_ctx(tline
->text
, &mname
);
3344 tline
= expand_smacro(tline
->next
);
3348 while (tok_type_(t
, TOK_WHITESPACE
))
3351 if (!t
|| (t
->type
!= TOK_STRING
&&
3352 t
->type
!= TOK_INTERNAL_STRING
)) {
3353 nasm_error(ERR_NONFATAL
, "`%%pathsearch' expects a file name");
3355 free_tlist(origline
);
3356 return DIRECTIVE_FOUND
; /* but we did _something_ */
3359 nasm_error(ERR_WARNING
|ERR_PASS1
,
3360 "trailing garbage after `%%pathsearch' ignored");
3362 if (t
->type
!= TOK_INTERNAL_STRING
)
3363 nasm_unquote(p
, NULL
);
3365 inc_fopen(p
, NULL
, &found_path
, INC_PROBE
, NF_BINARY
);
3368 macro_start
= nasm_malloc(sizeof(*macro_start
));
3369 macro_start
->next
= NULL
;
3370 macro_start
->text
= nasm_quote(found_path
, strlen(found_path
));
3371 macro_start
->type
= TOK_STRING
;
3372 macro_start
->a
.mac
= NULL
;
3375 * We now have a macro name, an implicit parameter count of
3376 * zero, and a string token to use as an expansion. Create
3377 * and store an SMacro.
3379 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3381 free_tlist(origline
);
3382 return DIRECTIVE_FOUND
;
3388 tline
= tline
->next
;
3390 tline
= expand_id(tline
);
3391 if (!tline
|| (tline
->type
!= TOK_ID
&&
3392 (tline
->type
!= TOK_PREPROC_ID
||
3393 tline
->text
[1] != '$'))) {
3394 nasm_error(ERR_NONFATAL
,
3395 "`%%strlen' expects a macro identifier as first parameter");
3396 free_tlist(origline
);
3397 return DIRECTIVE_FOUND
;
3399 ctx
= get_ctx(tline
->text
, &mname
);
3401 tline
= expand_smacro(tline
->next
);
3405 while (tok_type_(t
, TOK_WHITESPACE
))
3407 /* t should now point to the string */
3408 if (!tok_type_(t
, TOK_STRING
)) {
3409 nasm_error(ERR_NONFATAL
,
3410 "`%%strlen` requires string as second parameter");
3412 free_tlist(origline
);
3413 return DIRECTIVE_FOUND
;
3416 macro_start
= nasm_malloc(sizeof(*macro_start
));
3417 macro_start
->next
= NULL
;
3418 make_tok_num(macro_start
, nasm_unquote(t
->text
, NULL
));
3419 macro_start
->a
.mac
= NULL
;
3422 * We now have a macro name, an implicit parameter count of
3423 * zero, and a numeric token to use as an expansion. Create
3424 * and store an SMacro.
3426 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3428 free_tlist(origline
);
3429 return DIRECTIVE_FOUND
;
3434 tline
= tline
->next
;
3436 tline
= expand_id(tline
);
3437 if (!tline
|| (tline
->type
!= TOK_ID
&&
3438 (tline
->type
!= TOK_PREPROC_ID
||
3439 tline
->text
[1] != '$'))) {
3440 nasm_error(ERR_NONFATAL
,
3441 "`%%strcat' expects a macro identifier as first parameter");
3442 free_tlist(origline
);
3443 return DIRECTIVE_FOUND
;
3445 ctx
= get_ctx(tline
->text
, &mname
);
3447 tline
= expand_smacro(tline
->next
);
3451 list_for_each(t
, tline
) {
3453 case TOK_WHITESPACE
:
3456 len
+= t
->a
.len
= nasm_unquote(t
->text
, NULL
);
3459 if (!strcmp(t
->text
, ",")) /* permit comma separators */
3461 /* else fall through */
3463 nasm_error(ERR_NONFATAL
,
3464 "non-string passed to `%%strcat' (%d)", t
->type
);
3466 free_tlist(origline
);
3467 return DIRECTIVE_FOUND
;
3471 p
= pp
= nasm_malloc(len
);
3472 list_for_each(t
, tline
) {
3473 if (t
->type
== TOK_STRING
) {
3474 memcpy(p
, t
->text
, t
->a
.len
);
3480 * We now have a macro name, an implicit parameter count of
3481 * zero, and a numeric token to use as an expansion. Create
3482 * and store an SMacro.
3484 macro_start
= new_Token(NULL
, TOK_STRING
, NULL
, 0);
3485 macro_start
->text
= nasm_quote(pp
, len
);
3487 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3489 free_tlist(origline
);
3490 return DIRECTIVE_FOUND
;
3494 int64_t start
, count
;
3499 tline
= tline
->next
;
3501 tline
= expand_id(tline
);
3502 if (!tline
|| (tline
->type
!= TOK_ID
&&
3503 (tline
->type
!= TOK_PREPROC_ID
||
3504 tline
->text
[1] != '$'))) {
3505 nasm_error(ERR_NONFATAL
,
3506 "`%%substr' expects a macro identifier as first parameter");
3507 free_tlist(origline
);
3508 return DIRECTIVE_FOUND
;
3510 ctx
= get_ctx(tline
->text
, &mname
);
3512 tline
= expand_smacro(tline
->next
);
3515 if (tline
) /* skip expanded id */
3517 while (tok_type_(t
, TOK_WHITESPACE
))
3520 /* t should now point to the string */
3521 if (!tok_type_(t
, TOK_STRING
)) {
3522 nasm_error(ERR_NONFATAL
,
3523 "`%%substr` requires string as second parameter");
3525 free_tlist(origline
);
3526 return DIRECTIVE_FOUND
;
3531 tokval
.t_type
= TOKEN_INVALID
;
3532 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, NULL
);
3535 free_tlist(origline
);
3536 return DIRECTIVE_FOUND
;
3537 } else if (!is_simple(evalresult
)) {
3538 nasm_error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3540 free_tlist(origline
);
3541 return DIRECTIVE_FOUND
;
3543 start
= evalresult
->value
- 1;
3545 while (tok_type_(tt
, TOK_WHITESPACE
))
3548 count
= 1; /* Backwards compatibility: one character */
3550 tokval
.t_type
= TOKEN_INVALID
;
3551 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, NULL
);
3554 free_tlist(origline
);
3555 return DIRECTIVE_FOUND
;
3556 } else if (!is_simple(evalresult
)) {
3557 nasm_error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3559 free_tlist(origline
);
3560 return DIRECTIVE_FOUND
;
3562 count
= evalresult
->value
;
3565 len
= nasm_unquote(t
->text
, NULL
);
3567 /* make start and count being in range */
3571 count
= len
+ count
+ 1 - start
;
3572 if (start
+ count
> (int64_t)len
)
3573 count
= len
- start
;
3574 if (!len
|| count
< 0 || start
>=(int64_t)len
)
3575 start
= -1, count
= 0; /* empty string */
3577 macro_start
= nasm_malloc(sizeof(*macro_start
));
3578 macro_start
->next
= NULL
;
3579 macro_start
->text
= nasm_quote((start
< 0) ? "" : t
->text
+ start
, count
);
3580 macro_start
->type
= TOK_STRING
;
3581 macro_start
->a
.mac
= NULL
;
3584 * We now have a macro name, an implicit parameter count of
3585 * zero, and a numeric token to use as an expansion. Create
3586 * and store an SMacro.
3588 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3590 free_tlist(origline
);
3591 return DIRECTIVE_FOUND
;
3596 casesense
= (i
== PP_ASSIGN
);
3598 tline
= tline
->next
;
3600 tline
= expand_id(tline
);
3601 if (!tline
|| (tline
->type
!= TOK_ID
&&
3602 (tline
->type
!= TOK_PREPROC_ID
||
3603 tline
->text
[1] != '$'))) {
3604 nasm_error(ERR_NONFATAL
,
3605 "`%%%sassign' expects a macro identifier",
3606 (i
== PP_IASSIGN
? "i" : ""));
3607 free_tlist(origline
);
3608 return DIRECTIVE_FOUND
;
3610 ctx
= get_ctx(tline
->text
, &mname
);
3612 tline
= expand_smacro(tline
->next
);
3617 tokval
.t_type
= TOKEN_INVALID
;
3618 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, NULL
);
3621 free_tlist(origline
);
3622 return DIRECTIVE_FOUND
;
3626 nasm_error(ERR_WARNING
|ERR_PASS1
,
3627 "trailing garbage after expression ignored");
3629 if (!is_simple(evalresult
)) {
3630 nasm_error(ERR_NONFATAL
,
3631 "non-constant value given to `%%%sassign'",
3632 (i
== PP_IASSIGN
? "i" : ""));
3633 free_tlist(origline
);
3634 return DIRECTIVE_FOUND
;
3637 macro_start
= nasm_malloc(sizeof(*macro_start
));
3638 macro_start
->next
= NULL
;
3639 make_tok_num(macro_start
, reloc_value(evalresult
));
3640 macro_start
->a
.mac
= NULL
;
3643 * We now have a macro name, an implicit parameter count of
3644 * zero, and a numeric token to use as an expansion. Create
3645 * and store an SMacro.
3647 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3648 free_tlist(origline
);
3649 return DIRECTIVE_FOUND
;
3653 * Syntax is `%line nnn[+mmm] [filename]'
3655 tline
= tline
->next
;
3657 if (!tok_type_(tline
, TOK_NUMBER
)) {
3658 nasm_error(ERR_NONFATAL
, "`%%line' expects line number");
3659 free_tlist(origline
);
3660 return DIRECTIVE_FOUND
;
3662 k
= readnum(tline
->text
, &err
);
3664 tline
= tline
->next
;
3665 if (tok_is_(tline
, "+")) {
3666 tline
= tline
->next
;
3667 if (!tok_type_(tline
, TOK_NUMBER
)) {
3668 nasm_error(ERR_NONFATAL
, "`%%line' expects line increment");
3669 free_tlist(origline
);
3670 return DIRECTIVE_FOUND
;
3672 m
= readnum(tline
->text
, &err
);
3673 tline
= tline
->next
;
3679 char *fname
= detoken(tline
, false);
3680 src_set_fname(fname
);
3683 free_tlist(origline
);
3684 return DIRECTIVE_FOUND
;
3687 nasm_error(ERR_FATAL
,
3688 "preprocessor directive `%s' not yet implemented",
3690 return DIRECTIVE_FOUND
;
3695 * Ensure that a macro parameter contains a condition code and
3696 * nothing else. Return the condition code index if so, or -1
3699 static int find_cc(Token
* t
)
3704 return -1; /* Probably a %+ without a space */
3707 if (t
->type
!= TOK_ID
)
3711 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
3714 return bsii(t
->text
, (const char **)conditions
, ARRAY_SIZE(conditions
));
3718 * This routines walks over tokens strem and hadnles tokens
3719 * pasting, if @handle_explicit passed then explicit pasting
3720 * term is handled, otherwise -- implicit pastings only.
3722 static bool paste_tokens(Token
**head
, const struct tokseq_match
*m
,
3723 size_t mnum
, bool handle_explicit
)
3725 Token
*tok
, *next
, **prev_next
, **prev_nonspace
;
3726 bool pasted
= false;
3731 * The last token before pasting. We need it
3732 * to be able to connect new handled tokens.
3733 * In other words if there were a tokens stream
3737 * and we've joined tokens B and C, the resulting
3745 if (!tok_type_(tok
, TOK_WHITESPACE
) && !tok_type_(tok
, TOK_PASTE
))
3746 prev_nonspace
= head
;
3748 prev_nonspace
= NULL
;
3750 while (tok
&& (next
= tok
->next
)) {
3752 switch (tok
->type
) {
3753 case TOK_WHITESPACE
:
3754 /* Zap redundant whitespaces */
3755 while (tok_type_(next
, TOK_WHITESPACE
))
3756 next
= delete_Token(next
);
3761 /* Explicit pasting */
3762 if (!handle_explicit
)
3764 next
= delete_Token(tok
);
3766 while (tok_type_(next
, TOK_WHITESPACE
))
3767 next
= delete_Token(next
);
3772 /* Left pasting token is start of line */
3774 nasm_error(ERR_FATAL
, "No lvalue found on pasting");
3777 * No ending token, this might happen in two
3780 * 1) There indeed no right token at all
3781 * 2) There is a bare "%define ID" statement,
3782 * and @ID does expand to whitespace.
3784 * So technically we need to do a grammar analysis
3785 * in another stage of parsing, but for now lets don't
3786 * change the behaviour people used to. Simply allow
3787 * whitespace after paste token.
3791 * Zap ending space tokens and that's all.
3793 tok
= (*prev_nonspace
)->next
;
3794 while (tok_type_(tok
, TOK_WHITESPACE
))
3795 tok
= delete_Token(tok
);
3796 tok
= *prev_nonspace
;
3801 tok
= *prev_nonspace
;
3802 while (tok_type_(tok
, TOK_WHITESPACE
))
3803 tok
= delete_Token(tok
);
3804 len
= strlen(tok
->text
);
3805 len
+= strlen(next
->text
);
3807 p
= buf
= nasm_malloc(len
+ 1);
3808 strcpy(p
, tok
->text
);
3809 p
= strchr(p
, '\0');
3810 strcpy(p
, next
->text
);
3814 tok
= tokenize(buf
);
3817 *prev_nonspace
= tok
;
3818 while (tok
&& tok
->next
)
3821 tok
->next
= delete_Token(next
);
3823 /* Restart from pasted tokens head */
3824 tok
= *prev_nonspace
;
3828 /* implicit pasting */
3829 for (i
= 0; i
< mnum
; i
++) {
3830 if (!(PP_CONCAT_MATCH(tok
, m
[i
].mask_head
)))
3834 while (next
&& PP_CONCAT_MATCH(next
, m
[i
].mask_tail
)) {
3835 len
+= strlen(next
->text
);
3843 len
+= strlen(tok
->text
);
3844 p
= buf
= nasm_malloc(len
+ 1);
3846 while (tok
!= next
) {
3847 strcpy(p
, tok
->text
);
3848 p
= strchr(p
, '\0');
3849 tok
= delete_Token(tok
);
3852 tok
= tokenize(buf
);
3861 * Connect pasted into original stream,
3862 * ie A -> new-tokens -> B
3864 while (tok
&& tok
->next
)
3871 /* Restart from pasted tokens head */
3872 tok
= prev_next
? *prev_next
: *head
;
3878 prev_next
= &tok
->next
;
3881 !tok_type_(tok
->next
, TOK_WHITESPACE
) &&
3882 !tok_type_(tok
->next
, TOK_PASTE
))
3883 prev_nonspace
= prev_next
;
3892 * expands to a list of tokens from %{x:y}
3894 static Token
*expand_mmac_params_range(MMacro
*mac
, Token
*tline
, Token
***last
)
3896 Token
*t
= tline
, **tt
, *tm
, *head
;
3900 pos
= strchr(tline
->text
, ':');
3903 lst
= atoi(pos
+ 1);
3904 fst
= atoi(tline
->text
+ 1);
3907 * only macros params are accounted so
3908 * if someone passes %0 -- we reject such
3911 if (lst
== 0 || fst
== 0)
3914 /* the values should be sane */
3915 if ((fst
> (int)mac
->nparam
|| fst
< (-(int)mac
->nparam
)) ||
3916 (lst
> (int)mac
->nparam
|| lst
< (-(int)mac
->nparam
)))
3919 fst
= fst
< 0 ? fst
+ (int)mac
->nparam
+ 1: fst
;
3920 lst
= lst
< 0 ? lst
+ (int)mac
->nparam
+ 1: lst
;
3922 /* counted from zero */
3926 * It will be at least one token. Note we
3927 * need to scan params until separator, otherwise
3928 * only first token will be passed.
3930 tm
= mac
->params
[(fst
+ mac
->rotate
) % mac
->nparam
];
3931 head
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3932 tt
= &head
->next
, tm
= tm
->next
;
3933 while (tok_isnt_(tm
, ",")) {
3934 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3935 *tt
= t
, tt
= &t
->next
, tm
= tm
->next
;
3939 for (i
= fst
+ 1; i
<= lst
; i
++) {
3940 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
3941 *tt
= t
, tt
= &t
->next
;
3942 j
= (i
+ mac
->rotate
) % mac
->nparam
;
3943 tm
= mac
->params
[j
];
3944 while (tok_isnt_(tm
, ",")) {
3945 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3946 *tt
= t
, tt
= &t
->next
, tm
= tm
->next
;
3950 for (i
= fst
- 1; i
>= lst
; i
--) {
3951 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
3952 *tt
= t
, tt
= &t
->next
;
3953 j
= (i
+ mac
->rotate
) % mac
->nparam
;
3954 tm
= mac
->params
[j
];
3955 while (tok_isnt_(tm
, ",")) {
3956 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3957 *tt
= t
, tt
= &t
->next
, tm
= tm
->next
;
3966 nasm_error(ERR_NONFATAL
, "`%%{%s}': macro parameters out of range",
3972 * Expand MMacro-local things: parameter references (%0, %n, %+n,
3973 * %-n) and MMacro-local identifiers (%%foo) as well as
3974 * macro indirection (%[...]) and range (%{..:..}).
3976 static Token
*expand_mmac_params(Token
* tline
)
3978 Token
*t
, *tt
, **tail
, *thead
;
3979 bool changed
= false;
3986 if (tline
->type
== TOK_PREPROC_ID
&&
3987 (((tline
->text
[1] == '+' || tline
->text
[1] == '-') && tline
->text
[2]) ||
3988 (tline
->text
[1] >= '0' && tline
->text
[1] <= '9') ||
3989 tline
->text
[1] == '%')) {
3991 int type
= 0, cc
; /* type = 0 to placate optimisers */
3998 tline
= tline
->next
;
4001 while (mac
&& !mac
->name
) /* avoid mistaking %reps for macros */
4002 mac
= mac
->next_active
;
4004 nasm_error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
4006 pos
= strchr(t
->text
, ':');
4008 switch (t
->text
[1]) {
4010 * We have to make a substitution of one of the
4011 * forms %1, %-1, %+1, %%foo, %0.
4015 snprintf(tmpbuf
, sizeof(tmpbuf
), "%d", mac
->nparam
);
4016 text
= nasm_strdup(tmpbuf
);
4020 snprintf(tmpbuf
, sizeof(tmpbuf
), "..@%"PRIu64
".",
4022 text
= nasm_strcat(tmpbuf
, t
->text
+ 2);
4025 n
= atoi(t
->text
+ 2) - 1;
4026 if (n
>= mac
->nparam
)
4029 if (mac
->nparam
> 1)
4030 n
= (n
+ mac
->rotate
) % mac
->nparam
;
4031 tt
= mac
->params
[n
];
4035 nasm_error(ERR_NONFATAL
,
4036 "macro parameter %d is not a condition code",
4041 if (inverse_ccs
[cc
] == -1) {
4042 nasm_error(ERR_NONFATAL
,
4043 "condition code `%s' is not invertible",
4047 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
4051 n
= atoi(t
->text
+ 2) - 1;
4052 if (n
>= mac
->nparam
)
4055 if (mac
->nparam
> 1)
4056 n
= (n
+ mac
->rotate
) % mac
->nparam
;
4057 tt
= mac
->params
[n
];
4061 nasm_error(ERR_NONFATAL
,
4062 "macro parameter %d is not a condition code",
4067 text
= nasm_strdup(conditions
[cc
]);
4071 n
= atoi(t
->text
+ 1) - 1;
4072 if (n
>= mac
->nparam
)
4075 if (mac
->nparam
> 1)
4076 n
= (n
+ mac
->rotate
) % mac
->nparam
;
4077 tt
= mac
->params
[n
];
4080 for (i
= 0; i
< mac
->paramlen
[n
]; i
++) {
4081 *tail
= new_Token(NULL
, tt
->type
, tt
->text
, 0);
4082 tail
= &(*tail
)->next
;
4086 text
= NULL
; /* we've done it here */
4091 * seems we have a parameters range here
4093 Token
*head
, **last
;
4094 head
= expand_mmac_params_range(mac
, t
, &last
);
4115 } else if (tline
->type
== TOK_INDIRECT
) {
4117 tline
= tline
->next
;
4118 tt
= tokenize(t
->text
);
4119 tt
= expand_mmac_params(tt
);
4120 tt
= expand_smacro(tt
);
4123 tt
->a
.mac
= NULL
; /* Necessary? */
4131 tline
= tline
->next
;
4139 const struct tokseq_match t
[] = {
4141 PP_CONCAT_MASK(TOK_ID
) |
4142 PP_CONCAT_MASK(TOK_FLOAT
), /* head */
4143 PP_CONCAT_MASK(TOK_ID
) |
4144 PP_CONCAT_MASK(TOK_NUMBER
) |
4145 PP_CONCAT_MASK(TOK_FLOAT
) |
4146 PP_CONCAT_MASK(TOK_OTHER
) /* tail */
4149 PP_CONCAT_MASK(TOK_NUMBER
), /* head */
4150 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4153 paste_tokens(&thead
, t
, ARRAY_SIZE(t
), false);
4160 * Expand all single-line macro calls made in the given line.
4161 * Return the expanded version of the line. The original is deemed
4162 * to be destroyed in the process. (In reality we'll just move
4163 * Tokens from input to output a lot of the time, rather than
4164 * actually bothering to destroy and replicate.)
4167 static Token
*expand_smacro(Token
* tline
)
4169 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
4170 SMacro
*head
= NULL
, *m
;
4173 unsigned int nparam
, sparam
;
4175 Token
*org_tline
= tline
;
4178 int deadman
= DEADMAN_LIMIT
;
4182 * Trick: we should avoid changing the start token pointer since it can
4183 * be contained in "next" field of other token. Because of this
4184 * we allocate a copy of first token and work with it; at the end of
4185 * routine we copy it back
4188 tline
= new_Token(org_tline
->next
, org_tline
->type
,
4189 org_tline
->text
, 0);
4190 tline
->a
.mac
= org_tline
->a
.mac
;
4191 nasm_free(org_tline
->text
);
4192 org_tline
->text
= NULL
;
4195 expanded
= true; /* Always expand %+ at least once */
4201 while (tline
) { /* main token loop */
4203 nasm_error(ERR_NONFATAL
, "interminable macro recursion");
4207 if ((mname
= tline
->text
)) {
4208 /* if this token is a local macro, look in local context */
4209 if (tline
->type
== TOK_ID
) {
4210 head
= (SMacro
*)hash_findix(&smacros
, mname
);
4211 } else if (tline
->type
== TOK_PREPROC_ID
) {
4212 ctx
= get_ctx(mname
, &mname
);
4213 head
= ctx
? (SMacro
*)hash_findix(&ctx
->localmac
, mname
) : NULL
;
4218 * We've hit an identifier. As in is_mmacro below, we first
4219 * check whether the identifier is a single-line macro at
4220 * all, then think about checking for parameters if
4223 list_for_each(m
, head
)
4224 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
4230 if (m
->nparam
== 0) {
4232 * Simple case: the macro is parameterless. Discard the
4233 * one token that the macro call took, and push the
4234 * expansion back on the to-do stack.
4236 if (!m
->expansion
) {
4237 if (!strcmp("__FILE__", m
->name
)) {
4238 const char *file
= src_get_fname();
4239 /* nasm_free(tline->text); here? */
4240 tline
->text
= nasm_quote(file
, strlen(file
));
4241 tline
->type
= TOK_STRING
;
4244 if (!strcmp("__LINE__", m
->name
)) {
4245 nasm_free(tline
->text
);
4246 make_tok_num(tline
, src_get_linnum());
4249 if (!strcmp("__BITS__", m
->name
)) {
4250 nasm_free(tline
->text
);
4251 make_tok_num(tline
, globalbits
);
4254 tline
= delete_Token(tline
);
4259 * Complicated case: at least one macro with this name
4260 * exists and takes parameters. We must find the
4261 * parameters in the call, count them, find the SMacro
4262 * that corresponds to that form of the macro call, and
4263 * substitute for the parameters when we expand. What a
4266 /*tline = tline->next;
4267 skip_white_(tline); */
4270 while (tok_type_(t
, TOK_SMAC_END
)) {
4271 t
->a
.mac
->in_progress
= false;
4273 t
= tline
->next
= delete_Token(t
);
4276 } while (tok_type_(tline
, TOK_WHITESPACE
));
4277 if (!tok_is_(tline
, "(")) {
4279 * This macro wasn't called with parameters: ignore
4280 * the call. (Behaviour borrowed from gnu cpp.)
4289 sparam
= PARAM_DELTA
;
4290 params
= nasm_malloc(sparam
* sizeof(Token
*));
4291 params
[0] = tline
->next
;
4292 paramsize
= nasm_malloc(sparam
* sizeof(int));
4294 while (true) { /* parameter loop */
4296 * For some unusual expansions
4297 * which concatenates function call
4300 while (tok_type_(t
, TOK_SMAC_END
)) {
4301 t
->a
.mac
->in_progress
= false;
4303 t
= tline
->next
= delete_Token(t
);
4308 nasm_error(ERR_NONFATAL
,
4309 "macro call expects terminating `)'");
4312 if (tline
->type
== TOK_WHITESPACE
4314 if (paramsize
[nparam
])
4317 params
[nparam
] = tline
->next
;
4318 continue; /* parameter loop */
4320 if (tline
->type
== TOK_OTHER
4321 && tline
->text
[1] == 0) {
4322 char ch
= tline
->text
[0];
4323 if (ch
== ',' && !paren
&& brackets
<= 0) {
4324 if (++nparam
>= sparam
) {
4325 sparam
+= PARAM_DELTA
;
4326 params
= nasm_realloc(params
,
4327 sparam
* sizeof(Token
*));
4328 paramsize
= nasm_realloc(paramsize
,
4329 sparam
* sizeof(int));
4331 params
[nparam
] = tline
->next
;
4332 paramsize
[nparam
] = 0;
4334 continue; /* parameter loop */
4337 (brackets
> 0 || (brackets
== 0 &&
4338 !paramsize
[nparam
])))
4340 if (!(brackets
++)) {
4341 params
[nparam
] = tline
->next
;
4342 continue; /* parameter loop */
4345 if (ch
== '}' && brackets
> 0)
4346 if (--brackets
== 0) {
4348 continue; /* parameter loop */
4350 if (ch
== '(' && !brackets
)
4352 if (ch
== ')' && brackets
<= 0)
4358 nasm_error(ERR_NONFATAL
, "braces do not "
4359 "enclose all of macro parameter");
4361 paramsize
[nparam
] += white
+ 1;
4363 } /* parameter loop */
4365 while (m
&& (m
->nparam
!= nparam
||
4366 mstrcmp(m
->name
, mname
,
4370 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4371 "macro `%s' exists, "
4372 "but not taking %d parameters",
4373 mstart
->text
, nparam
);
4376 if (m
&& m
->in_progress
)
4378 if (!m
) { /* in progess or didn't find '(' or wrong nparam */
4380 * Design question: should we handle !tline, which
4381 * indicates missing ')' here, or expand those
4382 * macros anyway, which requires the (t) test a few
4386 nasm_free(paramsize
);
4390 * Expand the macro: we are placed on the last token of the
4391 * call, so that we can easily split the call from the
4392 * following tokens. We also start by pushing an SMAC_END
4393 * token for the cycle removal.
4400 tt
= new_Token(tline
, TOK_SMAC_END
, NULL
, 0);
4402 m
->in_progress
= true;
4404 list_for_each(t
, m
->expansion
) {
4405 if (t
->type
>= TOK_SMAC_PARAM
) {
4406 Token
*pcopy
= tline
, **ptail
= &pcopy
;
4410 ttt
= params
[t
->type
- TOK_SMAC_PARAM
];
4411 i
= paramsize
[t
->type
- TOK_SMAC_PARAM
];
4413 pt
= *ptail
= new_Token(tline
, ttt
->type
,
4419 } else if (t
->type
== TOK_PREPROC_Q
) {
4420 tt
= new_Token(tline
, TOK_ID
, mname
, 0);
4422 } else if (t
->type
== TOK_PREPROC_QQ
) {
4423 tt
= new_Token(tline
, TOK_ID
, m
->name
, 0);
4426 tt
= new_Token(tline
, t
->type
, t
->text
, 0);
4432 * Having done that, get rid of the macro call, and clean
4433 * up the parameters.
4436 nasm_free(paramsize
);
4439 continue; /* main token loop */
4444 if (tline
->type
== TOK_SMAC_END
) {
4445 tline
->a
.mac
->in_progress
= false;
4446 tline
= delete_Token(tline
);
4449 tline
= tline
->next
;
4457 * Now scan the entire line and look for successive TOK_IDs that resulted
4458 * after expansion (they can't be produced by tokenize()). The successive
4459 * TOK_IDs should be concatenated.
4460 * Also we look for %+ tokens and concatenate the tokens before and after
4461 * them (without white spaces in between).
4464 const struct tokseq_match t
[] = {
4466 PP_CONCAT_MASK(TOK_ID
) |
4467 PP_CONCAT_MASK(TOK_PREPROC_ID
), /* head */
4468 PP_CONCAT_MASK(TOK_ID
) |
4469 PP_CONCAT_MASK(TOK_PREPROC_ID
) |
4470 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4473 if (paste_tokens(&thead
, t
, ARRAY_SIZE(t
), true)) {
4475 * If we concatenated something, *and* we had previously expanded
4476 * an actual macro, scan the lines again for macros...
4487 *org_tline
= *thead
;
4488 /* since we just gave text to org_line, don't free it */
4490 delete_Token(thead
);
4492 /* the expression expanded to empty line;
4493 we can't return NULL for some reasons
4494 we just set the line to a single WHITESPACE token. */
4495 memset(org_tline
, 0, sizeof(*org_tline
));
4496 org_tline
->text
= NULL
;
4497 org_tline
->type
= TOK_WHITESPACE
;
4506 * Similar to expand_smacro but used exclusively with macro identifiers
4507 * right before they are fetched in. The reason is that there can be
4508 * identifiers consisting of several subparts. We consider that if there
4509 * are more than one element forming the name, user wants a expansion,
4510 * otherwise it will be left as-is. Example:
4514 * the identifier %$abc will be left as-is so that the handler for %define
4515 * will suck it and define the corresponding value. Other case:
4517 * %define _%$abc cde
4519 * In this case user wants name to be expanded *before* %define starts
4520 * working, so we'll expand %$abc into something (if it has a value;
4521 * otherwise it will be left as-is) then concatenate all successive
4524 static Token
*expand_id(Token
* tline
)
4526 Token
*cur
, *oldnext
= NULL
;
4528 if (!tline
|| !tline
->next
)
4533 (cur
->next
->type
== TOK_ID
||
4534 cur
->next
->type
== TOK_PREPROC_ID
4535 || cur
->next
->type
== TOK_NUMBER
))
4538 /* If identifier consists of just one token, don't expand */
4543 oldnext
= cur
->next
; /* Detach the tail past identifier */
4544 cur
->next
= NULL
; /* so that expand_smacro stops here */
4547 tline
= expand_smacro(tline
);
4550 /* expand_smacro possibly changhed tline; re-scan for EOL */
4552 while (cur
&& cur
->next
)
4555 cur
->next
= oldnext
;
4562 * Determine whether the given line constitutes a multi-line macro
4563 * call, and return the MMacro structure called if so. Doesn't have
4564 * to check for an initial label - that's taken care of in
4565 * expand_mmacro - but must check numbers of parameters. Guaranteed
4566 * to be called with tline->type == TOK_ID, so the putative macro
4567 * name is easy to find.
4569 static MMacro
*is_mmacro(Token
* tline
, Token
*** params_array
)
4575 head
= (MMacro
*) hash_findix(&mmacros
, tline
->text
);
4578 * Efficiency: first we see if any macro exists with the given
4579 * name. If not, we can return NULL immediately. _Then_ we
4580 * count the parameters, and then we look further along the
4581 * list if necessary to find the proper MMacro.
4583 list_for_each(m
, head
)
4584 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
4590 * OK, we have a potential macro. Count and demarcate the
4593 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
4596 * So we know how many parameters we've got. Find the MMacro
4597 * structure that handles this number.
4600 if (m
->nparam_min
<= nparam
4601 && (m
->plus
|| nparam
<= m
->nparam_max
)) {
4603 * This one is right. Just check if cycle removal
4604 * prohibits us using it before we actually celebrate...
4606 if (m
->in_progress
> m
->max_depth
) {
4607 if (m
->max_depth
> 0) {
4608 nasm_error(ERR_WARNING
,
4609 "reached maximum recursion depth of %i",
4616 * It's right, and we can use it. Add its default
4617 * parameters to the end of our list if necessary.
4619 if (m
->defaults
&& nparam
< m
->nparam_min
+ m
->ndefs
) {
4621 nasm_realloc(params
,
4622 ((m
->nparam_min
+ m
->ndefs
+
4623 1) * sizeof(*params
)));
4624 while (nparam
< m
->nparam_min
+ m
->ndefs
) {
4625 params
[nparam
] = m
->defaults
[nparam
- m
->nparam_min
];
4630 * If we've gone over the maximum parameter count (and
4631 * we're in Plus mode), ignore parameters beyond
4634 if (m
->plus
&& nparam
> m
->nparam_max
)
4635 nparam
= m
->nparam_max
;
4637 * Then terminate the parameter list, and leave.
4639 if (!params
) { /* need this special case */
4640 params
= nasm_malloc(sizeof(*params
));
4643 params
[nparam
] = NULL
;
4644 *params_array
= params
;
4648 * This one wasn't right: look for the next one with the
4651 list_for_each(m
, m
->next
)
4652 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
4657 * After all that, we didn't find one with the right number of
4658 * parameters. Issue a warning, and fail to expand the macro.
4660 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4661 "macro `%s' exists, but not taking %d parameters",
4662 tline
->text
, nparam
);
4669 * Save MMacro invocation specific fields in
4670 * preparation for a recursive macro expansion
4672 static void push_mmacro(MMacro
*m
)
4674 MMacroInvocation
*i
;
4676 i
= nasm_malloc(sizeof(MMacroInvocation
));
4678 i
->params
= m
->params
;
4679 i
->iline
= m
->iline
;
4680 i
->nparam
= m
->nparam
;
4681 i
->rotate
= m
->rotate
;
4682 i
->paramlen
= m
->paramlen
;
4683 i
->unique
= m
->unique
;
4684 i
->condcnt
= m
->condcnt
;
4690 * Restore MMacro invocation specific fields that were
4691 * saved during a previous recursive macro expansion
4693 static void pop_mmacro(MMacro
*m
)
4695 MMacroInvocation
*i
;
4700 m
->params
= i
->params
;
4701 m
->iline
= i
->iline
;
4702 m
->nparam
= i
->nparam
;
4703 m
->rotate
= i
->rotate
;
4704 m
->paramlen
= i
->paramlen
;
4705 m
->unique
= i
->unique
;
4706 m
->condcnt
= i
->condcnt
;
4713 * Expand the multi-line macro call made by the given line, if
4714 * there is one to be expanded. If there is, push the expansion on
4715 * istk->expansion and return 1. Otherwise return 0.
4717 static int expand_mmacro(Token
* tline
)
4719 Token
*startline
= tline
;
4720 Token
*label
= NULL
;
4721 int dont_prepend
= 0;
4722 Token
**params
, *t
, *tt
;
4725 int i
, nparam
, *paramlen
;
4730 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4731 if (!tok_type_(t
, TOK_ID
) && !tok_type_(t
, TOK_PREPROC_ID
))
4733 m
= is_mmacro(t
, ¶ms
);
4739 * We have an id which isn't a macro call. We'll assume
4740 * it might be a label; we'll also check to see if a
4741 * colon follows it. Then, if there's another id after
4742 * that lot, we'll check it again for macro-hood.
4746 if (tok_type_(t
, TOK_WHITESPACE
))
4747 last
= t
, t
= t
->next
;
4748 if (tok_is_(t
, ":")) {
4750 last
= t
, t
= t
->next
;
4751 if (tok_type_(t
, TOK_WHITESPACE
))
4752 last
= t
, t
= t
->next
;
4754 if (!tok_type_(t
, TOK_ID
) || !(m
= is_mmacro(t
, ¶ms
)))
4762 * Fix up the parameters: this involves stripping leading and
4763 * trailing whitespace, then stripping braces if they are
4766 for (nparam
= 0; params
[nparam
]; nparam
++) ;
4767 paramlen
= nparam
? nasm_malloc(nparam
* sizeof(*paramlen
)) : NULL
;
4769 for (i
= 0; params
[i
]; i
++) {
4771 int comma
= (!m
->plus
|| i
< nparam
- 1);
4775 if (tok_is_(t
, "{"))
4776 t
= t
->next
, brace
++, comma
= false;
4780 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
4781 break; /* ... because we have hit a comma */
4782 if (comma
&& t
->type
== TOK_WHITESPACE
4783 && tok_is_(t
->next
, ","))
4784 break; /* ... or a space then a comma */
4785 if (brace
&& t
->type
== TOK_OTHER
) {
4786 if (t
->text
[0] == '{')
4787 brace
++; /* ... or a nested opening brace */
4788 else if (t
->text
[0] == '}')
4790 break; /* ... or a brace */
4796 nasm_error(ERR_NONFATAL
, "macro params should be enclosed in braces");
4800 * OK, we have a MMacro structure together with a set of
4801 * parameters. We must now go through the expansion and push
4802 * copies of each Line on to istk->expansion. Substitution of
4803 * parameter tokens and macro-local tokens doesn't get done
4804 * until the single-line macro substitution process; this is
4805 * because delaying them allows us to change the semantics
4806 * later through %rotate.
4808 * First, push an end marker on to istk->expansion, mark this
4809 * macro as in progress, and set up its invocation-specific
4812 ll
= nasm_malloc(sizeof(Line
));
4813 ll
->next
= istk
->expansion
;
4816 istk
->expansion
= ll
;
4819 * Save the previous MMacro expansion in the case of
4822 if (m
->max_depth
&& m
->in_progress
)
4830 m
->paramlen
= paramlen
;
4831 m
->unique
= unique
++;
4835 m
->next_active
= istk
->mstk
;
4838 list_for_each(l
, m
->expansion
) {
4841 ll
= nasm_malloc(sizeof(Line
));
4842 ll
->finishes
= NULL
;
4843 ll
->next
= istk
->expansion
;
4844 istk
->expansion
= ll
;
4847 list_for_each(t
, l
->first
) {
4851 tt
= *tail
= new_Token(NULL
, TOK_ID
, mname
, 0);
4853 case TOK_PREPROC_QQ
:
4854 tt
= *tail
= new_Token(NULL
, TOK_ID
, m
->name
, 0);
4856 case TOK_PREPROC_ID
:
4857 if (t
->text
[1] == '0' && t
->text
[2] == '0') {
4865 tt
= *tail
= new_Token(NULL
, x
->type
, x
->text
, 0);
4874 * If we had a label, push it on as the first line of
4875 * the macro expansion.
4878 if (dont_prepend
< 0)
4879 free_tlist(startline
);
4881 ll
= nasm_malloc(sizeof(Line
));
4882 ll
->finishes
= NULL
;
4883 ll
->next
= istk
->expansion
;
4884 istk
->expansion
= ll
;
4885 ll
->first
= startline
;
4886 if (!dont_prepend
) {
4888 label
= label
->next
;
4889 label
->next
= tt
= new_Token(NULL
, TOK_OTHER
, ":", 0);
4894 lfmt
->uplevel(m
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
4900 * This function adds macro names to error messages, and suppresses
4901 * them if necessary.
4903 static void pp_verror(int severity
, const char *fmt
, va_list arg
)
4906 MMacro
*mmac
= NULL
;
4910 * If we're in a dead branch of IF or something like it, ignore the error.
4911 * However, because %else etc are evaluated in the state context
4912 * of the previous branch, errors might get lost:
4913 * %if 0 ... %else trailing garbage ... %endif
4914 * So %else etc should set the ERR_PP_PRECOND flag.
4916 if ((severity
& ERR_MASK
) < ERR_FATAL
&&
4917 istk
&& istk
->conds
&&
4918 ((severity
& ERR_PP_PRECOND
) ?
4919 istk
->conds
->state
== COND_NEVER
:
4920 !emitting(istk
->conds
->state
)))
4923 /* get %macro name */
4924 if (!(severity
& ERR_NOFILE
) && istk
&& istk
->mstk
) {
4926 /* but %rep blocks should be skipped */
4927 while (mmac
&& !mmac
->name
)
4928 mmac
= mmac
->next_active
, delta
++;
4932 vsnprintf(buff
, sizeof(buff
), fmt
, arg
);
4934 nasm_set_verror(real_verror
);
4935 nasm_error(severity
, "(%s:%d) %s",
4936 mmac
->name
, mmac
->lineno
- delta
, buff
);
4937 nasm_set_verror(pp_verror
);
4939 real_verror(severity
, fmt
, arg
);
4944 pp_reset(char *file
, int apass
, StrList
**deplist
)
4949 istk
= nasm_malloc(sizeof(Include
));
4952 istk
->expansion
= NULL
;
4954 istk
->fp
= nasm_open_read(file
, NF_TEXT
);
4959 nasm_fatal(ERR_NOFILE
, "unable to open input file `%s'", file
);
4961 nested_mac_count
= 0;
4962 nested_rep_count
= 0;
4966 if (tasm_compatible_mode
)
4967 pp_add_stdmac(nasm_stdmac_tasm
);
4969 pp_add_stdmac(nasm_stdmac_nasm
);
4970 pp_add_stdmac(nasm_stdmac_version
);
4972 stdmacpos
= stdmacros
[0];
4973 stdmacnext
= &stdmacros
[1];
4978 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
4979 * The caller, however, will also pass in 3 for preprocess-only so
4980 * we can set __PASS__ accordingly.
4982 pass
= apass
> 2 ? 2 : apass
;
4985 nasm_add_string_to_strlist(dephead
, file
);
4988 * Define the __PASS__ macro. This is defined here unlike
4989 * all the other builtins, because it is special -- it varies between
4992 t
= nasm_malloc(sizeof(*t
));
4994 make_tok_num(t
, apass
);
4996 define_smacro(NULL
, "__PASS__", true, 0, t
);
4999 static void pp_init(void)
5001 hash_init(&FileHash
, HASH_MEDIUM
);
5004 static char *pp_getline(void)
5009 real_verror
= nasm_set_verror(pp_verror
);
5013 * Fetch a tokenized line, either from the macro-expansion
5014 * buffer or from the input file.
5017 while (istk
->expansion
&& istk
->expansion
->finishes
) {
5018 Line
*l
= istk
->expansion
;
5019 if (!l
->finishes
->name
&& l
->finishes
->in_progress
> 1) {
5023 * This is a macro-end marker for a macro with no
5024 * name, which means it's not really a macro at all
5025 * but a %rep block, and the `in_progress' field is
5026 * more than 1, meaning that we still need to
5027 * repeat. (1 means the natural last repetition; 0
5028 * means termination by %exitrep.) We have
5029 * therefore expanded up to the %endrep, and must
5030 * push the whole block on to the expansion buffer
5031 * again. We don't bother to remove the macro-end
5032 * marker: we'd only have to generate another one
5035 l
->finishes
->in_progress
--;
5036 list_for_each(l
, l
->finishes
->expansion
) {
5037 Token
*t
, *tt
, **tail
;
5039 ll
= nasm_malloc(sizeof(Line
));
5040 ll
->next
= istk
->expansion
;
5041 ll
->finishes
= NULL
;
5045 list_for_each(t
, l
->first
) {
5046 if (t
->text
|| t
->type
== TOK_WHITESPACE
) {
5047 tt
= *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
5052 istk
->expansion
= ll
;
5056 * Check whether a `%rep' was started and not ended
5057 * within this macro expansion. This can happen and
5058 * should be detected. It's a fatal error because
5059 * I'm too confused to work out how to recover
5064 nasm_panic(0, "defining with name in expansion");
5065 else if (istk
->mstk
->name
)
5066 nasm_fatal(0, "`%%rep' without `%%endrep' within"
5067 " expansion of macro `%s'",
5072 * FIXME: investigate the relationship at this point between
5073 * istk->mstk and l->finishes
5076 MMacro
*m
= istk
->mstk
;
5077 istk
->mstk
= m
->next_active
;
5080 * This was a real macro call, not a %rep, and
5081 * therefore the parameter information needs to
5086 l
->finishes
->in_progress
--;
5088 nasm_free(m
->params
);
5089 free_tlist(m
->iline
);
5090 nasm_free(m
->paramlen
);
5091 l
->finishes
->in_progress
= 0;
5096 istk
->expansion
= l
->next
;
5098 lfmt
->downlevel(LIST_MACRO
);
5101 while (1) { /* until we get a line we can use */
5103 if (istk
->expansion
) { /* from a macro expansion */
5105 Line
*l
= istk
->expansion
;
5107 istk
->mstk
->lineno
++;
5109 istk
->expansion
= l
->next
;
5111 p
= detoken(tline
, false);
5112 lfmt
->line(LIST_MACRO
, p
);
5117 if (line
) { /* from the current input file */
5118 line
= prepreproc(line
);
5119 tline
= tokenize(line
);
5124 * The current file has ended; work down the istk
5130 /* nasm_error can't be conditionally suppressed */
5132 "expected `%%endif' before end of file");
5134 /* only set line and file name if there's a next node */
5136 src_set(i
->lineno
, i
->fname
);
5138 lfmt
->downlevel(LIST_INCLUDE
);
5144 if (istk
->expansion
&& istk
->expansion
->finishes
)
5150 * We must expand MMacro parameters and MMacro-local labels
5151 * _before_ we plunge into directive processing, to cope
5152 * with things like `%define something %1' such as STRUC
5153 * uses. Unless we're _defining_ a MMacro, in which case
5154 * those tokens should be left alone to go into the
5155 * definition; and unless we're in a non-emitting
5156 * condition, in which case we don't want to meddle with
5159 if (!defining
&& !(istk
->conds
&& !emitting(istk
->conds
->state
))
5160 && !(istk
->mstk
&& !istk
->mstk
->in_progress
)) {
5161 tline
= expand_mmac_params(tline
);
5165 * Check the line to see if it's a preprocessor directive.
5167 if (do_directive(tline
, &line
) == DIRECTIVE_FOUND
) {
5169 break; /* Directive generated output */
5172 } else if (defining
) {
5174 * We're defining a multi-line macro. We emit nothing
5176 * shove the tokenized line on to the macro definition.
5178 Line
*l
= nasm_malloc(sizeof(Line
));
5179 l
->next
= defining
->expansion
;
5182 defining
->expansion
= l
;
5184 } else if (istk
->conds
&& !emitting(istk
->conds
->state
)) {
5186 * We're in a non-emitting branch of a condition block.
5187 * Emit nothing at all, not even a blank line: when we
5188 * emerge from the condition we'll give a line-number
5189 * directive so we keep our place correctly.
5193 } else if (istk
->mstk
&& !istk
->mstk
->in_progress
) {
5195 * We're in a %rep block which has been terminated, so
5196 * we're walking through to the %endrep without
5197 * emitting anything. Emit nothing at all, not even a
5198 * blank line: when we emerge from the %rep block we'll
5199 * give a line-number directive so we keep our place
5205 tline
= expand_smacro(tline
);
5206 if (!expand_mmacro(tline
)) {
5208 * De-tokenize the line again, and emit it.
5210 line
= detoken(tline
, true);
5214 continue; /* expand_mmacro calls free_tlist */
5220 nasm_set_verror(real_verror
);
5224 static void pp_cleanup(int pass
)
5226 real_verror
= nasm_set_verror(pp_verror
);
5229 if (defining
->name
) {
5230 nasm_error(ERR_NONFATAL
,
5231 "end of file while still defining macro `%s'",
5234 nasm_error(ERR_NONFATAL
, "end of file while still in %%rep");
5237 free_mmacro(defining
);
5241 nasm_set_verror(real_verror
);
5254 src_set_fname(NULL
);
5261 while ((i
= ipath
)) {
5270 static void pp_include_path(char *path
)
5274 i
= nasm_malloc(sizeof(IncPath
));
5275 i
->path
= path
? nasm_strdup(path
) : NULL
;
5288 static void pp_pre_include(char *fname
)
5290 Token
*inc
, *space
, *name
;
5293 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
5294 space
= new_Token(name
, TOK_WHITESPACE
, NULL
, 0);
5295 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
5297 l
= nasm_malloc(sizeof(Line
));
5304 static void pp_pre_define(char *definition
)
5310 real_verror
= nasm_set_verror(pp_verror
);
5312 equals
= strchr(definition
, '=');
5313 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5314 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
5317 space
->next
= tokenize(definition
);
5321 if (space
->next
->type
!= TOK_PREPROC_ID
&&
5322 space
->next
->type
!= TOK_ID
)
5323 nasm_error(ERR_WARNING
, "pre-defining non ID `%s\'\n", definition
);
5325 l
= nasm_malloc(sizeof(Line
));
5331 nasm_set_verror(real_verror
);
5334 static void pp_pre_undefine(char *definition
)
5339 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5340 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
5341 space
->next
= tokenize(definition
);
5343 l
= nasm_malloc(sizeof(Line
));
5350 static void pp_add_stdmac(macros_t
*macros
)
5354 /* Find the end of the list and avoid duplicates */
5355 for (mp
= stdmacros
; *mp
; mp
++) {
5357 return; /* Nothing to do */
5360 nasm_assert(mp
< &stdmacros
[ARRAY_SIZE(stdmacros
)-1]);
5365 static void make_tok_num(Token
* tok
, int64_t val
)
5368 snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
5369 tok
->text
= nasm_strdup(numbuf
);
5370 tok
->type
= TOK_NUMBER
;
5373 static void pp_list_one_macro(MMacro
*m
, int severity
)
5378 /* We need to print the next_active list in reverse order */
5379 pp_list_one_macro(m
->next_active
, severity
);
5381 if (m
->name
&& !m
->nolist
) {
5382 src_set(m
->xline
+ m
->lineno
, m
->fname
);
5383 nasm_error(severity
, "... from macro `%s' defined here", m
->name
);
5387 static void pp_error_list_macros(int severity
)
5390 const char *saved_fname
= NULL
;
5392 severity
|= ERR_PP_LISTMACRO
| ERR_NO_SEVERITY
;
5393 src_get(&saved_line
, &saved_fname
);
5396 pp_list_one_macro(istk
->mstk
, severity
);
5398 src_set(saved_line
, saved_fname
);
5401 const struct preproc_ops nasmpp
= {
5411 pp_error_list_macros
,