1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2017 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
35 * preproc.c macro preprocessor for the Netwide Assembler
38 /* Typical flow of text through preproc
40 * pp_getline gets tokenized lines, either
42 * from a macro expansion
46 * read_line gets raw text from stdmacpos, or predef, or current input file
47 * tokenize converts to tokens
50 * expand_mmac_params is used to expand %1 etc., unless a macro is being
51 * defined or a false conditional is being processed
52 * (%0, %1, %+1, %-1, %%foo
54 * do_directive checks for directives
56 * expand_smacro is used to expand single line macros
58 * expand_mmacro is used to expand multi-line macros
60 * detoken is used to convert the line back to text
85 typedef struct SMacro SMacro
;
86 typedef struct MMacro MMacro
;
87 typedef struct MMacroInvocation MMacroInvocation
;
88 typedef struct Context Context
;
89 typedef struct Token Token
;
90 typedef struct Blocks Blocks
;
91 typedef struct Line Line
;
92 typedef struct Include Include
;
93 typedef struct Cond Cond
;
94 typedef struct IncPath IncPath
;
97 * Note on the storage of both SMacro and MMacros: the hash table
98 * indexes them case-insensitively, and we then have to go through a
99 * linked list of potential case aliases (and, for MMacros, parameter
100 * ranges); this is to preserve the matching semantics of the earlier
101 * code. If the number of case aliases for a specific macro is a
102 * performance issue, you may want to reconsider your coding style.
106 * Store the definition of a single-line macro.
118 * Store the definition of a multi-line macro. This is also used to
119 * store the interiors of `%rep...%endrep' blocks, which are
120 * effectively self-re-invoking multi-line macros which simply
121 * don't have a name or bother to appear in the hash tables. %rep
122 * blocks are signified by having a NULL `name' field.
124 * In a MMacro describing a `%rep' block, the `in_progress' field
125 * isn't merely boolean, but gives the number of repeats left to
128 * The `next' field is used for storing MMacros in hash tables; the
129 * `next_active' field is for stacking them on istk entries.
131 * When a MMacro is being expanded, `params', `iline', `nparam',
132 * `paramlen', `rotate' and `unique' are local to the invocation.
136 MMacroInvocation
*prev
; /* previous invocation */
138 int nparam_min
, nparam_max
;
140 bool plus
; /* is the last parameter greedy? */
141 bool nolist
; /* is this macro listing-inhibited? */
142 int64_t in_progress
; /* is this macro currently being expanded? */
143 int32_t max_depth
; /* maximum number of recursive expansions allowed */
144 Token
*dlist
; /* All defaults as one list */
145 Token
**defaults
; /* Parameter default pointers */
146 int ndefs
; /* number of default parameters */
150 MMacro
*rep_nest
; /* used for nesting %rep */
151 Token
**params
; /* actual parameters */
152 Token
*iline
; /* invocation line */
153 unsigned int nparam
, rotate
;
156 int lineno
; /* Current line number on expansion */
157 uint64_t condcnt
; /* number of if blocks... */
159 const char *fname
; /* File where defined */
160 int32_t xline
; /* First line in macro */
164 /* Store the definition of a multi-line macro, as defined in a
165 * previous recursive macro expansion.
167 struct MMacroInvocation
{
168 MMacroInvocation
*prev
; /* previous invocation */
169 Token
**params
; /* actual parameters */
170 Token
*iline
; /* invocation line */
171 unsigned int nparam
, rotate
;
179 * The context stack is composed of a linked list of these.
184 struct hash_table localmac
;
189 * This is the internal form which we break input lines up into.
190 * Typically stored in linked lists.
192 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
193 * necessarily used as-is, but is intended to denote the number of
194 * the substituted parameter. So in the definition
196 * %define a(x,y) ( (x) & ~(y) )
198 * the token representing `x' will have its type changed to
199 * TOK_SMAC_PARAM, but the one representing `y' will be
202 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
203 * which doesn't need quotes around it. Used in the pre-include
204 * mechanism as an alternative to trying to find a sensible type of
205 * quote to use on the filename we were passed.
208 TOK_NONE
= 0, TOK_WHITESPACE
, TOK_COMMENT
, TOK_ID
,
209 TOK_PREPROC_ID
, TOK_STRING
,
210 TOK_NUMBER
, TOK_FLOAT
, TOK_SMAC_END
, TOK_OTHER
,
212 TOK_PREPROC_Q
, TOK_PREPROC_QQ
,
214 TOK_INDIRECT
, /* %[...] */
215 TOK_SMAC_PARAM
, /* MUST BE LAST IN THE LIST!!! */
216 TOK_MAX
= INT_MAX
/* Keep compiler from reducing the range */
219 #define PP_CONCAT_MASK(x) (1 << (x))
220 #define PP_CONCAT_MATCH(t, mask) (PP_CONCAT_MASK((t)->type) & mask)
222 struct tokseq_match
{
231 SMacro
*mac
; /* associated macro for TOK_SMAC_END */
232 size_t len
; /* scratch length field */
233 } a
; /* Auxiliary data */
234 enum pp_token_type type
;
238 * Multi-line macro definitions are stored as a linked list of
239 * these, which is essentially a container to allow several linked
242 * Note that in this module, linked lists are treated as stacks
243 * wherever possible. For this reason, Lines are _pushed_ on to the
244 * `expansion' field in MMacro structures, so that the linked list,
245 * if walked, would give the macro lines in reverse order; this
246 * means that we can walk the list when expanding a macro, and thus
247 * push the lines on to the `expansion' field in _istk_ in reverse
248 * order (so that when popped back off they are in the right
249 * order). It may seem cockeyed, and it relies on my design having
250 * an even number of steps in, but it works...
252 * Some of these structures, rather than being actual lines, are
253 * markers delimiting the end of the expansion of a given macro.
254 * This is for use in the cycle-tracking and %rep-handling code.
255 * Such structures have `finishes' non-NULL, and `first' NULL. All
256 * others have `finishes' NULL, but `first' may still be NULL if
266 * To handle an arbitrary level of file inclusion, we maintain a
267 * stack (ie linked list) of these things.
276 MMacro
*mstk
; /* stack of active macros/reps */
280 * Include search path. This is simply a list of strings which get
281 * prepended, in turn, to the name of an include file, in an
282 * attempt to find the file if it's not in the current directory.
290 * File real name hash, so we don't have to re-search the include
291 * path for every pass (and potentially more than that if a file
292 * is used more than once.)
294 struct hash_table FileHash
;
297 * Conditional assembly: we maintain a separate stack of these for
298 * each level of file inclusion. (The only reason we keep the
299 * stacks separate is to ensure that a stray `%endif' in a file
300 * included from within the true branch of a `%if' won't terminate
301 * it and cause confusion: instead, rightly, it'll cause an error.)
309 * These states are for use just after %if or %elif: IF_TRUE
310 * means the condition has evaluated to truth so we are
311 * currently emitting, whereas IF_FALSE means we are not
312 * currently emitting but will start doing so if a %else comes
313 * up. In these states, all directives are admissible: %elif,
314 * %else and %endif. (And of course %if.)
316 COND_IF_TRUE
, COND_IF_FALSE
,
318 * These states come up after a %else: ELSE_TRUE means we're
319 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
320 * any %elif or %else will cause an error.
322 COND_ELSE_TRUE
, COND_ELSE_FALSE
,
324 * These states mean that we're not emitting now, and also that
325 * nothing until %endif will be emitted at all. COND_DONE is
326 * used when we've had our moment of emission
327 * and have now started seeing %elifs. COND_NEVER is used when
328 * the condition construct in question is contained within a
329 * non-emitting branch of a larger condition construct,
330 * or if there is an error.
332 COND_DONE
, COND_NEVER
334 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
337 * These defines are used as the possible return values for do_directive
339 #define NO_DIRECTIVE_FOUND 0
340 #define DIRECTIVE_FOUND 1
343 * This define sets the upper limit for smacro and recursive mmacro
346 #define DEADMAN_LIMIT (1 << 20)
349 #define REP_LIMIT ((INT64_C(1) << 62))
352 * Condition codes. Note that we use c_ prefix not C_ because C_ is
353 * used in nasm.h for the "real" condition codes. At _this_ level,
354 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
355 * ones, so we need a different enum...
357 static const char * const conditions
[] = {
358 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
359 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
360 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
363 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
364 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
365 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_RCXZ
, c_S
, c_Z
,
368 static const enum pp_conds inverse_ccs
[] = {
369 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
370 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_E
, c_G
, c_GE
, c_L
, c_LE
, c_O
, c_P
, c_S
,
371 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, -1, c_NS
, c_NZ
377 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
378 static int is_condition(enum preproc_token arg
)
380 return PP_IS_COND(arg
) || (arg
== PP_ELSE
) || (arg
== PP_ENDIF
);
383 /* For TASM compatibility we need to be able to recognise TASM compatible
384 * conditional compilation directives. Using the NASM pre-processor does
385 * not work, so we look for them specifically from the following list and
386 * then jam in the equivalent NASM directive into the input stream.
390 TM_ARG
, TM_ELIF
, TM_ELSE
, TM_ENDIF
, TM_IF
, TM_IFDEF
, TM_IFDIFI
,
391 TM_IFNDEF
, TM_INCLUDE
, TM_LOCAL
394 static const char * const tasm_directives
[] = {
395 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
396 "ifndef", "include", "local"
399 static int StackSize
= 4;
400 static const char *StackPointer
= "ebp";
401 static int ArgOffset
= 8;
402 static int LocalOffset
= 0;
404 static Context
*cstk
;
405 static Include
*istk
;
406 static IncPath
*ipath
= NULL
;
408 static int pass
; /* HACK: pass 0 = generate dependencies only */
409 static StrList
**dephead
;
411 static uint64_t unique
; /* unique identifier numbers */
413 static Line
*predef
= NULL
;
414 static bool do_predef
;
417 * The current set of multi-line macros we have defined.
419 static struct hash_table mmacros
;
422 * The current set of single-line macros we have defined.
424 static struct hash_table smacros
;
427 * The multi-line macro we are currently defining, or the %rep
428 * block we are currently reading, if any.
430 static MMacro
*defining
;
432 static uint64_t nested_mac_count
;
433 static uint64_t nested_rep_count
;
436 * The number of macro parameters to allocate space for at a time.
438 #define PARAM_DELTA 16
441 * The standard macro set: defined in macros.c in a set of arrays.
442 * This gives our position in any macro set, while we are processing it.
443 * The stdmacset is an array of such macro sets.
445 static macros_t
*stdmacpos
;
446 static macros_t
**stdmacnext
;
447 static macros_t
*stdmacros
[8];
448 static macros_t
*extrastdmac
;
451 * Tokens are allocated in blocks to improve speed
453 #define TOKEN_BLOCKSIZE 4096
454 static Token
*freeTokens
= NULL
;
460 static Blocks blocks
= { NULL
, NULL
};
463 * Forward declarations.
465 static void pp_add_stdmac(macros_t
*macros
);
466 static Token
*expand_mmac_params(Token
* tline
);
467 static Token
*expand_smacro(Token
* tline
);
468 static Token
*expand_id(Token
* tline
);
469 static Context
*get_ctx(const char *name
, const char **namep
);
470 static void make_tok_num(Token
* tok
, int64_t val
);
471 static void pp_verror(int severity
, const char *fmt
, va_list ap
);
472 static vefunc real_verror
;
473 static void *new_Block(size_t size
);
474 static void delete_Blocks(void);
475 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
476 const char *text
, int txtlen
);
477 static Token
*delete_Token(Token
* t
);
480 * Macros for safe checking of token pointers, avoid *(NULL)
482 #define tok_type_(x,t) ((x) && (x)->type == (t))
483 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
484 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
485 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
488 * nasm_unquote with error if the string contains NUL characters.
489 * If the string contains NUL characters, issue an error and return
490 * the C len, i.e. truncate at the NUL.
492 static size_t nasm_unquote_cstr(char *qstr
, enum preproc_token directive
)
494 size_t len
= nasm_unquote(qstr
, NULL
);
495 size_t clen
= strlen(qstr
);
498 nasm_error(ERR_NONFATAL
, "NUL character in `%s' directive",
499 pp_directives
[directive
]);
505 * In-place reverse a list of tokens.
507 static Token
*reverse_tokens(Token
*t
)
523 * Handle TASM specific directives, which do not contain a % in
524 * front of them. We do it here because I could not find any other
525 * place to do it for the moment, and it is a hack (ideally it would
526 * be nice to be able to use the NASM pre-processor to do it).
528 static char *check_tasm_directive(char *line
)
530 int32_t i
, j
, k
, m
, len
;
531 char *p
, *q
, *oldline
, oldchar
;
533 p
= nasm_skip_spaces(line
);
535 /* Binary search for the directive name */
537 j
= ARRAY_SIZE(tasm_directives
);
538 q
= nasm_skip_word(p
);
545 m
= nasm_stricmp(p
, tasm_directives
[k
]);
547 /* We have found a directive, so jam a % in front of it
548 * so that NASM will then recognise it as one if it's own.
553 line
= nasm_malloc(len
+ 2);
555 if (k
== TM_IFDIFI
) {
557 * NASM does not recognise IFDIFI, so we convert
558 * it to %if 0. This is not used in NASM
559 * compatible code, but does need to parse for the
560 * TASM macro package.
562 strcpy(line
+ 1, "if 0");
564 memcpy(line
+ 1, p
, len
+ 1);
579 * The pre-preprocessing stage... This function translates line
580 * number indications as they emerge from GNU cpp (`# lineno "file"
581 * flags') into NASM preprocessor line number indications (`%line
584 static char *prepreproc(char *line
)
587 char *fname
, *oldline
;
589 if (line
[0] == '#' && line
[1] == ' ') {
592 lineno
= atoi(fname
);
593 fname
+= strspn(fname
, "0123456789 ");
596 fnlen
= strcspn(fname
, "\"");
597 line
= nasm_malloc(20 + fnlen
);
598 snprintf(line
, 20 + fnlen
, "%%line %d %.*s", lineno
, fnlen
, fname
);
601 if (tasm_compatible_mode
)
602 return check_tasm_directive(line
);
607 * Free a linked list of tokens.
609 static void free_tlist(Token
* list
)
612 list
= delete_Token(list
);
616 * Free a linked list of lines.
618 static void free_llist(Line
* list
)
621 list_for_each_safe(l
, tmp
, list
) {
622 free_tlist(l
->first
);
630 static void free_mmacro(MMacro
* m
)
633 free_tlist(m
->dlist
);
634 nasm_free(m
->defaults
);
635 free_llist(m
->expansion
);
640 * Free all currently defined macros, and free the hash tables
642 static void free_smacro_table(struct hash_table
*smt
)
646 struct hash_tbl_node
*it
= NULL
;
648 while ((s
= hash_iterate(smt
, &it
, &key
)) != NULL
) {
649 nasm_free((void *)key
);
650 list_for_each_safe(s
, tmp
, s
) {
652 free_tlist(s
->expansion
);
659 static void free_mmacro_table(struct hash_table
*mmt
)
663 struct hash_tbl_node
*it
= NULL
;
666 while ((m
= hash_iterate(mmt
, &it
, &key
)) != NULL
) {
667 nasm_free((void *)key
);
668 list_for_each_safe(m
,tmp
, m
)
674 static void free_macros(void)
676 free_smacro_table(&smacros
);
677 free_mmacro_table(&mmacros
);
681 * Initialize the hash tables
683 static void init_macros(void)
685 hash_init(&smacros
, HASH_LARGE
);
686 hash_init(&mmacros
, HASH_LARGE
);
690 * Pop the context stack.
692 static void ctx_pop(void)
697 free_smacro_table(&c
->localmac
);
703 * Search for a key in the hash index; adding it if necessary
704 * (in which case we initialize the data pointer to NULL.)
707 hash_findi_add(struct hash_table
*hash
, const char *str
)
709 struct hash_insert hi
;
713 r
= hash_findi(hash
, str
, &hi
);
717 strx
= nasm_strdup(str
); /* Use a more efficient allocator here? */
718 return hash_add(&hi
, strx
, NULL
);
722 * Like hash_findi, but returns the data element rather than a pointer
723 * to it. Used only when not adding a new element, hence no third
727 hash_findix(struct hash_table
*hash
, const char *str
)
731 p
= hash_findi(hash
, str
, NULL
);
732 return p
? *p
: NULL
;
736 * read line from standart macros set,
737 * if there no more left -- return NULL
739 static char *line_from_stdmac(void)
742 const unsigned char *p
= stdmacpos
;
751 len
+= pp_directives_len
[c
- 0x80] + 1;
756 line
= nasm_malloc(len
+ 1);
758 while ((c
= *stdmacpos
++)) {
760 memcpy(q
, pp_directives
[c
- 0x80], pp_directives_len
[c
- 0x80]);
761 q
+= pp_directives_len
[c
- 0x80];
771 /* This was the last of this particular macro set */
774 stdmacpos
= *stdmacnext
++;
775 } else if (do_predef
) {
777 Token
*head
, **tail
, *t
;
780 * Nasty hack: here we push the contents of
781 * `predef' on to the top-level expansion stack,
782 * since this is the most convenient way to
783 * implement the pre-include and pre-define
786 list_for_each(pd
, predef
) {
789 list_for_each(t
, pd
->first
) {
790 *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
791 tail
= &(*tail
)->next
;
794 l
= nasm_malloc(sizeof(Line
));
795 l
->next
= istk
->expansion
;
808 static char *read_line(void)
810 unsigned int size
, c
, next
;
811 const unsigned int delta
= 512;
812 const unsigned int pad
= 8;
813 unsigned int nr_cont
= 0;
817 /* Standart macros set (predefined) goes first */
818 p
= line_from_stdmac();
823 p
= buffer
= nasm_malloc(size
);
827 if ((int)(c
) == EOF
) {
834 next
= fgetc(istk
->fp
);
836 ungetc(next
, istk
->fp
);
851 next
= fgetc(istk
->fp
);
852 ungetc(next
, istk
->fp
);
853 if (next
== '\r' || next
== '\n') {
861 if (c
== '\r' || c
== '\n') {
866 if (p
>= (buffer
+ size
- pad
)) {
867 buffer
= nasm_realloc(buffer
, size
+ delta
);
868 p
= buffer
+ size
- pad
;
872 *p
++ = (unsigned char)c
;
880 src_set_linnum(src_get_linnum() + istk
->lineinc
+
881 (nr_cont
* istk
->lineinc
));
884 * Handle spurious ^Z, which may be inserted into source files
885 * by some file transfer utilities.
887 buffer
[strcspn(buffer
, "\032")] = '\0';
889 lfmt
->line(LIST_READ
, buffer
);
895 * Tokenize a line of text. This is a very simple process since we
896 * don't need to parse the value out of e.g. numeric tokens: we
897 * simply split one string into many.
899 static Token
*tokenize(char *line
)
902 enum pp_token_type type
;
904 Token
*t
, **tail
= &list
;
910 if (*p
== '+' && !nasm_isdigit(p
[1])) {
913 } else if (nasm_isdigit(*p
) ||
914 ((*p
== '-' || *p
== '+') && nasm_isdigit(p
[1]))) {
918 while (nasm_isdigit(*p
));
919 type
= TOK_PREPROC_ID
;
920 } else if (*p
== '{') {
929 nasm_error(ERR_WARNING
| ERR_PASS1
,
930 "unterminated %%{ construct");
934 type
= TOK_PREPROC_ID
;
935 } else if (*p
== '[') {
937 line
+= 2; /* Skip the leading %[ */
939 while (lvl
&& (c
= *p
++)) {
951 p
= nasm_skip_string(p
- 1) + 1;
961 nasm_error(ERR_NONFATAL
|ERR_PASS1
,
962 "unterminated %%[ construct");
964 } else if (*p
== '?') {
965 type
= TOK_PREPROC_Q
; /* %? */
968 type
= TOK_PREPROC_QQ
; /* %?? */
971 } else if (*p
== '!') {
972 type
= TOK_PREPROC_ID
;
978 while (isidchar(*p
));
979 } else if (*p
== '\'' || *p
== '\"' || *p
== '`') {
980 p
= nasm_skip_string(p
);
984 nasm_error(ERR_NONFATAL
|ERR_PASS1
,
985 "unterminated %%! string");
987 /* %! without string or identifier */
988 type
= TOK_OTHER
; /* Legacy behavior... */
990 } else if (isidchar(*p
) ||
991 ((*p
== '!' || *p
== '%' || *p
== '$') &&
996 while (isidchar(*p
));
997 type
= TOK_PREPROC_ID
;
1003 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
1006 while (*p
&& isidchar(*p
))
1008 } else if (*p
== '\'' || *p
== '"' || *p
== '`') {
1013 p
= nasm_skip_string(p
);
1018 nasm_error(ERR_WARNING
|ERR_PASS1
, "unterminated string");
1019 /* Handling unterminated strings by UNV */
1022 } else if (p
[0] == '$' && p
[1] == '$') {
1023 type
= TOK_OTHER
; /* TOKEN_BASE */
1025 } else if (isnumstart(*p
)) {
1026 bool is_hex
= false;
1027 bool is_float
= false;
1043 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
1045 if (*p
== '+' || *p
== '-') {
1047 * e can only be followed by +/- if it is either a
1048 * prefixed hex number or a floating-point number
1053 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
1055 } else if (c
== 'P' || c
== 'p') {
1057 if (*p
== '+' || *p
== '-')
1059 } else if (isnumchar(c
))
1060 ; /* just advance */
1061 else if (c
== '.') {
1063 * we need to deal with consequences of the legacy
1064 * parser, like "1.nolist" being two tokens
1065 * (TOK_NUMBER, TOK_ID) here; at least give it
1066 * a shot for now. In the future, we probably need
1067 * a flex-based scanner with proper pattern matching
1068 * to do it as well as it can be done. Nothing in
1069 * the world is going to help the person who wants
1070 * 0x123.p16 interpreted as two tokens, though.
1076 if (nasm_isdigit(*r
) || (is_hex
&& nasm_isxdigit(*r
)) ||
1077 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
1078 (*r
== 'p' || *r
== 'P')) {
1082 break; /* Terminate the token */
1086 p
--; /* Point to first character beyond number */
1088 if (p
== line
+1 && *line
== '$') {
1089 type
= TOK_OTHER
; /* TOKEN_HERE */
1091 if (has_e
&& !is_hex
) {
1092 /* 1e13 is floating-point, but 1e13h is not */
1096 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
1098 } else if (nasm_isspace(*p
)) {
1099 type
= TOK_WHITESPACE
;
1100 p
= nasm_skip_spaces(p
);
1102 * Whitespace just before end-of-line is discarded by
1103 * pretending it's a comment; whitespace just before a
1104 * comment gets lumped into the comment.
1106 if (!*p
|| *p
== ';') {
1111 } else if (*p
== ';') {
1117 * Anything else is an operator of some kind. We check
1118 * for all the double-character operators (>>, <<, //,
1119 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1120 * else is a single-character operator.
1123 if ((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] == '&') ||
1132 (p
[0] == '|' && p
[1] == '|') ||
1133 (p
[0] == '^' && p
[1] == '^')) {
1139 /* Handling unterminated string by UNV */
1142 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1143 t->text[p-line] = *line;
1147 if (type
!= TOK_COMMENT
) {
1148 *tail
= t
= new_Token(NULL
, type
, line
, p
- line
);
1157 * this function allocates a new managed block of memory and
1158 * returns a pointer to the block. The managed blocks are
1159 * deleted only all at once by the delete_Blocks function.
1161 static void *new_Block(size_t size
)
1163 Blocks
*b
= &blocks
;
1165 /* first, get to the end of the linked list */
1168 /* now allocate the requested chunk */
1169 b
->chunk
= nasm_malloc(size
);
1171 /* now allocate a new block for the next request */
1172 b
->next
= nasm_zalloc(sizeof(Blocks
));
1177 * this function deletes all managed blocks of memory
1179 static void delete_Blocks(void)
1181 Blocks
*a
, *b
= &blocks
;
1184 * keep in mind that the first block, pointed to by blocks
1185 * is a static and not dynamically allocated, so we don't
1190 nasm_free(b
->chunk
);
1196 memset(&blocks
, 0, sizeof(blocks
));
1200 * this function creates a new Token and passes a pointer to it
1201 * back to the caller. It sets the type and text elements, and
1202 * also the a.mac and next elements to NULL.
1204 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
1205 const char *text
, int txtlen
)
1211 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1212 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1213 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1214 freeTokens
[i
].next
= NULL
;
1217 freeTokens
= t
->next
;
1221 if (type
== TOK_WHITESPACE
|| !text
) {
1225 txtlen
= strlen(text
);
1226 t
->text
= nasm_malloc(txtlen
+1);
1227 memcpy(t
->text
, text
, txtlen
);
1228 t
->text
[txtlen
] = '\0';
1233 static Token
*delete_Token(Token
* t
)
1235 Token
*next
= t
->next
;
1237 t
->next
= freeTokens
;
1243 * Convert a line of tokens back into text.
1244 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1245 * will be transformed into ..@ctxnum.xxx
1247 static char *detoken(Token
* tlist
, bool expand_locals
)
1254 list_for_each(t
, tlist
) {
1255 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
1260 if (*v
== '\'' || *v
== '\"' || *v
== '`') {
1261 size_t len
= nasm_unquote(v
, NULL
);
1262 size_t clen
= strlen(v
);
1265 nasm_error(ERR_NONFATAL
| ERR_PASS1
,
1266 "NUL character in %%! string");
1272 char *p
= getenv(v
);
1274 nasm_error(ERR_NONFATAL
| ERR_PASS1
,
1275 "nonexistent environment variable `%s'", v
);
1277 * FIXME We better should investigate if accessing
1278 * ->text[1] without ->text[0] is safe enough.
1280 t
->text
= nasm_zalloc(2);
1282 t
->text
= nasm_strdup(p
);
1287 /* Expand local macros here and not during preprocessing */
1288 if (expand_locals
&&
1289 t
->type
== TOK_PREPROC_ID
&& t
->text
&&
1290 t
->text
[0] == '%' && t
->text
[1] == '$') {
1293 Context
*ctx
= get_ctx(t
->text
, &q
);
1296 snprintf(buffer
, sizeof(buffer
), "..@%"PRIu32
".", ctx
->number
);
1297 p
= nasm_strcat(buffer
, q
);
1302 if (t
->type
== TOK_WHITESPACE
)
1305 len
+= strlen(t
->text
);
1308 p
= line
= nasm_malloc(len
+ 1);
1310 list_for_each(t
, tlist
) {
1311 if (t
->type
== TOK_WHITESPACE
) {
1313 } else if (t
->text
) {
1325 * A scanner, suitable for use by the expression evaluator, which
1326 * operates on a line of Tokens. Expects a pointer to a pointer to
1327 * the first token in the line to be passed in as its private_data
1330 * FIX: This really needs to be unified with stdscan.
1332 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1334 Token
**tlineptr
= private_data
;
1336 char ourcopy
[MAX_KEYWORD
+1], *p
, *r
, *s
;
1340 *tlineptr
= tline
? tline
->next
: NULL
;
1341 } while (tline
&& (tline
->type
== TOK_WHITESPACE
||
1342 tline
->type
== TOK_COMMENT
));
1345 return tokval
->t_type
= TOKEN_EOS
;
1347 tokval
->t_charptr
= tline
->text
;
1349 if (tline
->text
[0] == '$' && !tline
->text
[1])
1350 return tokval
->t_type
= TOKEN_HERE
;
1351 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[2])
1352 return tokval
->t_type
= TOKEN_BASE
;
1354 if (tline
->type
== TOK_ID
) {
1355 p
= tokval
->t_charptr
= tline
->text
;
1357 tokval
->t_charptr
++;
1358 return tokval
->t_type
= TOKEN_ID
;
1361 for (r
= p
, s
= ourcopy
; *r
; r
++) {
1362 if (r
>= p
+MAX_KEYWORD
)
1363 return tokval
->t_type
= TOKEN_ID
; /* Not a keyword */
1364 *s
++ = nasm_tolower(*r
);
1367 /* right, so we have an identifier sitting in temp storage. now,
1368 * is it actually a register or instruction name, or what? */
1369 return nasm_token_hash(ourcopy
, tokval
);
1372 if (tline
->type
== TOK_NUMBER
) {
1374 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
1375 tokval
->t_charptr
= tline
->text
;
1377 return tokval
->t_type
= TOKEN_ERRNUM
;
1379 return tokval
->t_type
= TOKEN_NUM
;
1382 if (tline
->type
== TOK_FLOAT
) {
1383 return tokval
->t_type
= TOKEN_FLOAT
;
1386 if (tline
->type
== TOK_STRING
) {
1389 bq
= tline
->text
[0];
1390 tokval
->t_charptr
= tline
->text
;
1391 tokval
->t_inttwo
= nasm_unquote(tline
->text
, &ep
);
1393 if (ep
[0] != bq
|| ep
[1] != '\0')
1394 return tokval
->t_type
= TOKEN_ERRSTR
;
1396 return tokval
->t_type
= TOKEN_STR
;
1399 if (tline
->type
== TOK_OTHER
) {
1400 if (!strcmp(tline
->text
, "<<"))
1401 return tokval
->t_type
= TOKEN_SHL
;
1402 if (!strcmp(tline
->text
, ">>"))
1403 return tokval
->t_type
= TOKEN_SHR
;
1404 if (!strcmp(tline
->text
, "//"))
1405 return tokval
->t_type
= TOKEN_SDIV
;
1406 if (!strcmp(tline
->text
, "%%"))
1407 return tokval
->t_type
= TOKEN_SMOD
;
1408 if (!strcmp(tline
->text
, "=="))
1409 return tokval
->t_type
= TOKEN_EQ
;
1410 if (!strcmp(tline
->text
, "<>"))
1411 return tokval
->t_type
= TOKEN_NE
;
1412 if (!strcmp(tline
->text
, "!="))
1413 return tokval
->t_type
= TOKEN_NE
;
1414 if (!strcmp(tline
->text
, "<="))
1415 return tokval
->t_type
= TOKEN_LE
;
1416 if (!strcmp(tline
->text
, ">="))
1417 return tokval
->t_type
= TOKEN_GE
;
1418 if (!strcmp(tline
->text
, "&&"))
1419 return tokval
->t_type
= TOKEN_DBL_AND
;
1420 if (!strcmp(tline
->text
, "^^"))
1421 return tokval
->t_type
= TOKEN_DBL_XOR
;
1422 if (!strcmp(tline
->text
, "||"))
1423 return tokval
->t_type
= TOKEN_DBL_OR
;
1427 * We have no other options: just return the first character of
1430 return tokval
->t_type
= tline
->text
[0];
1434 * Compare a string to the name of an existing macro; this is a
1435 * simple wrapper which calls either strcmp or nasm_stricmp
1436 * depending on the value of the `casesense' parameter.
1438 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
1440 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
1444 * Compare a string to the name of an existing macro; this is a
1445 * simple wrapper which calls either strcmp or nasm_stricmp
1446 * depending on the value of the `casesense' parameter.
1448 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
1450 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
1454 * Return the Context structure associated with a %$ token. Return
1455 * NULL, having _already_ reported an error condition, if the
1456 * context stack isn't deep enough for the supplied number of $
1459 * If "namep" is non-NULL, set it to the pointer to the macro name
1460 * tail, i.e. the part beyond %$...
1462 static Context
*get_ctx(const char *name
, const char **namep
)
1470 if (!name
|| name
[0] != '%' || name
[1] != '$')
1474 nasm_error(ERR_NONFATAL
, "`%s': context stack is empty", name
);
1481 while (ctx
&& *name
== '$') {
1487 nasm_error(ERR_NONFATAL
, "`%s': context stack is only"
1488 " %d level%s deep", name
, i
, (i
== 1 ? "" : "s"));
1499 * Open an include file. This routine must always return a valid
1500 * file pointer if it returns - it's responsible for throwing an
1501 * ERR_FATAL and bombing out completely if not. It should also try
1502 * the include path one by one until it finds the file or reaches
1503 * the end of the path.
1505 * Note: for INC_PROBE the function returns NULL at all times;
1506 * instead look for the
1509 INC_NEEDED
, /* File must exist */
1510 INC_OPTIONAL
, /* Missing is OK */
1511 INC_PROBE
/* Only an existence probe */
1514 /* This is conducts a full pathname search */
1515 static FILE *inc_fopen_search(const char *file
, StrList
**slpath
,
1516 enum incopen_mode omode
, enum file_flags fmode
)
1520 const IncPath
*ip
= ipath
;
1521 int len
= strlen(file
);
1522 size_t prefix_len
= 0;
1528 path_len
= prefix_len
+ len
+ 1;
1530 sl
= nasm_malloc(path_len
+ sizeof sl
->next
);
1531 memcpy(sl
->str
, prefix
, prefix_len
);
1532 memcpy(sl
->str
+prefix_len
, file
, len
+1);
1535 if (omode
== INC_PROBE
) {
1537 found
= nasm_file_exists(sl
->str
);
1539 fp
= nasm_open_read(sl
->str
, fmode
);
1540 found
= (fp
!= NULL
);
1553 prefix_len
= strlen(prefix
);
1559 * Open a file, or test for the presence of one (depending on omode),
1560 * considering the include path.
1562 static FILE *inc_fopen(const char *file
,
1564 const char **found_path
,
1565 enum incopen_mode omode
,
1566 enum file_flags fmode
)
1569 struct hash_insert hi
;
1574 hp
= hash_find(&FileHash
, file
, &hi
);
1578 /* Need to do the actual path search */
1582 fp
= inc_fopen_search(file
, &sl
, omode
, fmode
);
1584 file_len
= strlen(file
);
1587 /* Store negative result for this file */
1588 sl
= nasm_malloc(file_len
+ 1 + sizeof sl
->next
);
1589 memcpy(sl
->str
, file
, file_len
+1);
1595 file
= strchr(path
, '\0') - file_len
;
1598 hash_add(&hi
, file
, path
); /* Positive or negative result */
1601 * Add file to dependency path. The in_list() is needed
1602 * in case the file was already added with %depend.
1604 if (path
|| omode
!= INC_NEEDED
)
1605 nasm_add_to_strlist(dhead
, sl
);
1609 if (omode
== INC_NEEDED
)
1610 nasm_fatal(0, "unable to open include file `%s'", file
);
1618 if (!fp
&& omode
!= INC_PROBE
)
1619 fp
= nasm_open_read(path
, fmode
);
1628 * Opens an include or input file. Public version, for use by modules
1629 * that get a file:lineno pair and need to look at the file again
1630 * (e.g. the CodeView debug backend). Returns NULL on failure.
1632 FILE *pp_input_fopen(const char *filename
, enum file_flags mode
)
1634 return inc_fopen(filename
, NULL
, NULL
, INC_OPTIONAL
, mode
);
1638 * Determine if we should warn on defining a single-line macro of
1639 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1640 * return true if _any_ single-line macro of that name is defined.
1641 * Otherwise, will return true if a single-line macro with either
1642 * `nparam' or no parameters is defined.
1644 * If a macro with precisely the right number of parameters is
1645 * defined, or nparam is -1, the address of the definition structure
1646 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1647 * is NULL, no action will be taken regarding its contents, and no
1650 * Note that this is also called with nparam zero to resolve
1653 * If you already know which context macro belongs to, you can pass
1654 * the context pointer as first parameter; if you won't but name begins
1655 * with %$ the context will be automatically computed. If all_contexts
1656 * is true, macro will be searched in outer contexts as well.
1659 smacro_defined(Context
* ctx
, const char *name
, int nparam
, SMacro
** defn
,
1662 struct hash_table
*smtbl
;
1666 smtbl
= &ctx
->localmac
;
1667 } else if (name
[0] == '%' && name
[1] == '$') {
1669 ctx
= get_ctx(name
, &name
);
1671 return false; /* got to return _something_ */
1672 smtbl
= &ctx
->localmac
;
1676 m
= (SMacro
*) hash_findix(smtbl
, name
);
1679 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
1680 (nparam
<= 0 || m
->nparam
== 0 || nparam
== (int) m
->nparam
)) {
1682 if (nparam
== (int) m
->nparam
|| nparam
== -1)
1696 * Count and mark off the parameters in a multi-line macro call.
1697 * This is called both from within the multi-line macro expansion
1698 * code, and also to mark off the default parameters when provided
1699 * in a %macro definition line.
1701 static void count_mmac_params(Token
* t
, int *nparam
, Token
*** params
)
1703 int paramsize
, brace
;
1705 *nparam
= paramsize
= 0;
1708 /* +1: we need space for the final NULL */
1709 if (*nparam
+1 >= paramsize
) {
1710 paramsize
+= PARAM_DELTA
;
1711 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
1715 if (tok_is_(t
, "{"))
1717 (*params
)[(*nparam
)++] = t
;
1719 while (brace
&& (t
= t
->next
) != NULL
) {
1720 if (tok_is_(t
, "{"))
1722 else if (tok_is_(t
, "}"))
1728 * Now we've found the closing brace, look further
1733 if (tok_isnt_(t
, ",")) {
1734 nasm_error(ERR_NONFATAL
,
1735 "braces do not enclose all of macro parameter");
1736 while (tok_isnt_(t
, ","))
1741 while (tok_isnt_(t
, ","))
1744 if (t
) { /* got a comma/brace */
1745 t
= t
->next
; /* eat the comma */
1751 * Determine whether one of the various `if' conditions is true or
1754 * We must free the tline we get passed.
1756 static bool if_condition(Token
* tline
, enum preproc_token ct
)
1758 enum pp_conditional i
= PP_COND(ct
);
1760 Token
*t
, *tt
, **tptr
, *origline
;
1761 struct tokenval tokval
;
1763 enum pp_token_type needtype
;
1770 j
= false; /* have we matched yet? */
1775 if (tline
->type
!= TOK_ID
) {
1776 nasm_error(ERR_NONFATAL
,
1777 "`%s' expects context identifiers", pp_directives
[ct
]);
1778 free_tlist(origline
);
1781 if (cstk
&& cstk
->name
&& !nasm_stricmp(tline
->text
, cstk
->name
))
1783 tline
= tline
->next
;
1788 j
= false; /* have we matched yet? */
1791 if (!tline
|| (tline
->type
!= TOK_ID
&&
1792 (tline
->type
!= TOK_PREPROC_ID
||
1793 tline
->text
[1] != '$'))) {
1794 nasm_error(ERR_NONFATAL
,
1795 "`%s' expects macro identifiers", pp_directives
[ct
]);
1798 if (smacro_defined(NULL
, tline
->text
, 0, NULL
, true))
1800 tline
= tline
->next
;
1805 tline
= expand_smacro(tline
);
1806 j
= false; /* have we matched yet? */
1809 if (!tline
|| (tline
->type
!= TOK_ID
&&
1810 tline
->type
!= TOK_STRING
&&
1811 (tline
->type
!= TOK_PREPROC_ID
||
1812 tline
->text
[1] != '!'))) {
1813 nasm_error(ERR_NONFATAL
,
1814 "`%s' expects environment variable names",
1819 if (tline
->type
== TOK_PREPROC_ID
)
1820 p
+= 2; /* Skip leading %! */
1821 if (*p
== '\'' || *p
== '\"' || *p
== '`')
1822 nasm_unquote_cstr(p
, ct
);
1825 tline
= tline
->next
;
1831 tline
= expand_smacro(tline
);
1833 while (tok_isnt_(tt
, ","))
1836 nasm_error(ERR_NONFATAL
,
1837 "`%s' expects two comma-separated arguments",
1842 j
= true; /* assume equality unless proved not */
1843 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1844 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1845 nasm_error(ERR_NONFATAL
, "`%s': more than one comma on line",
1849 if (t
->type
== TOK_WHITESPACE
) {
1853 if (tt
->type
== TOK_WHITESPACE
) {
1857 if (tt
->type
!= t
->type
) {
1858 j
= false; /* found mismatching tokens */
1861 /* When comparing strings, need to unquote them first */
1862 if (t
->type
== TOK_STRING
) {
1863 size_t l1
= nasm_unquote(t
->text
, NULL
);
1864 size_t l2
= nasm_unquote(tt
->text
, NULL
);
1870 if (mmemcmp(t
->text
, tt
->text
, l1
, i
== PPC_IFIDN
)) {
1874 } else if (mstrcmp(tt
->text
, t
->text
, i
== PPC_IFIDN
) != 0) {
1875 j
= false; /* found mismatching tokens */
1882 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
1883 j
= false; /* trailing gunk on one end or other */
1889 MMacro searching
, *mmac
;
1892 tline
= expand_id(tline
);
1893 if (!tok_type_(tline
, TOK_ID
)) {
1894 nasm_error(ERR_NONFATAL
,
1895 "`%s' expects a macro name", pp_directives
[ct
]);
1898 searching
.name
= nasm_strdup(tline
->text
);
1899 searching
.casesense
= true;
1900 searching
.plus
= false;
1901 searching
.nolist
= false;
1902 searching
.in_progress
= 0;
1903 searching
.max_depth
= 0;
1904 searching
.rep_nest
= NULL
;
1905 searching
.nparam_min
= 0;
1906 searching
.nparam_max
= INT_MAX
;
1907 tline
= expand_smacro(tline
->next
);
1910 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
1911 nasm_error(ERR_NONFATAL
,
1912 "`%s' expects a parameter count or nothing",
1915 searching
.nparam_min
= searching
.nparam_max
=
1916 readnum(tline
->text
, &j
);
1918 nasm_error(ERR_NONFATAL
,
1919 "unable to parse parameter count `%s'",
1922 if (tline
&& tok_is_(tline
->next
, "-")) {
1923 tline
= tline
->next
->next
;
1924 if (tok_is_(tline
, "*"))
1925 searching
.nparam_max
= INT_MAX
;
1926 else if (!tok_type_(tline
, TOK_NUMBER
))
1927 nasm_error(ERR_NONFATAL
,
1928 "`%s' expects a parameter count after `-'",
1931 searching
.nparam_max
= readnum(tline
->text
, &j
);
1933 nasm_error(ERR_NONFATAL
,
1934 "unable to parse parameter count `%s'",
1936 if (searching
.nparam_min
> searching
.nparam_max
)
1937 nasm_error(ERR_NONFATAL
,
1938 "minimum parameter count exceeds maximum");
1941 if (tline
&& tok_is_(tline
->next
, "+")) {
1942 tline
= tline
->next
;
1943 searching
.plus
= true;
1945 mmac
= (MMacro
*) hash_findix(&mmacros
, searching
.name
);
1947 if (!strcmp(mmac
->name
, searching
.name
) &&
1948 (mmac
->nparam_min
<= searching
.nparam_max
1950 && (searching
.nparam_min
<= mmac
->nparam_max
1957 if (tline
&& tline
->next
)
1958 nasm_error(ERR_WARNING
|ERR_PASS1
,
1959 "trailing garbage after %%ifmacro ignored");
1960 nasm_free(searching
.name
);
1969 needtype
= TOK_NUMBER
;
1972 needtype
= TOK_STRING
;
1976 t
= tline
= expand_smacro(tline
);
1978 while (tok_type_(t
, TOK_WHITESPACE
) ||
1979 (needtype
== TOK_NUMBER
&&
1980 tok_type_(t
, TOK_OTHER
) &&
1981 (t
->text
[0] == '-' || t
->text
[0] == '+') &&
1985 j
= tok_type_(t
, needtype
);
1989 t
= tline
= expand_smacro(tline
);
1990 while (tok_type_(t
, TOK_WHITESPACE
))
1995 t
= t
->next
; /* Skip the actual token */
1996 while (tok_type_(t
, TOK_WHITESPACE
))
1998 j
= !t
; /* Should be nothing left */
2003 t
= tline
= expand_smacro(tline
);
2004 while (tok_type_(t
, TOK_WHITESPACE
))
2007 j
= !t
; /* Should be empty */
2011 t
= tline
= expand_smacro(tline
);
2013 tokval
.t_type
= TOKEN_INVALID
;
2014 evalresult
= evaluate(ppscan
, tptr
, &tokval
,
2015 NULL
, pass
| CRITICAL
, NULL
);
2019 nasm_error(ERR_WARNING
|ERR_PASS1
,
2020 "trailing garbage after expression ignored");
2021 if (!is_simple(evalresult
)) {
2022 nasm_error(ERR_NONFATAL
,
2023 "non-constant value given to `%s'", pp_directives
[ct
]);
2026 j
= reloc_value(evalresult
) != 0;
2030 nasm_error(ERR_FATAL
,
2031 "preprocessor directive `%s' not yet implemented",
2036 free_tlist(origline
);
2037 return j
^ PP_NEGATIVE(ct
);
2040 free_tlist(origline
);
2045 * Common code for defining an smacro
2047 static bool define_smacro(Context
*ctx
, const char *mname
, bool casesense
,
2048 int nparam
, Token
*expansion
)
2050 SMacro
*smac
, **smhead
;
2051 struct hash_table
*smtbl
;
2053 if (smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
)) {
2055 nasm_error(ERR_WARNING
|ERR_PASS1
,
2056 "single-line macro `%s' defined both with and"
2057 " without parameters", mname
);
2059 * Some instances of the old code considered this a failure,
2060 * some others didn't. What is the right thing to do here?
2062 free_tlist(expansion
);
2063 return false; /* Failure */
2066 * We're redefining, so we have to take over an
2067 * existing SMacro structure. This means freeing
2068 * what was already in it.
2070 nasm_free(smac
->name
);
2071 free_tlist(smac
->expansion
);
2074 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2075 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
2076 smac
= nasm_malloc(sizeof(SMacro
));
2077 smac
->next
= *smhead
;
2080 smac
->name
= nasm_strdup(mname
);
2081 smac
->casesense
= casesense
;
2082 smac
->nparam
= nparam
;
2083 smac
->expansion
= expansion
;
2084 smac
->in_progress
= false;
2085 return true; /* Success */
2089 * Undefine an smacro
2091 static void undef_smacro(Context
*ctx
, const char *mname
)
2093 SMacro
**smhead
, *s
, **sp
;
2094 struct hash_table
*smtbl
;
2096 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2097 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
2101 * We now have a macro name... go hunt for it.
2104 while ((s
= *sp
) != NULL
) {
2105 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
2108 free_tlist(s
->expansion
);
2118 * Parse a mmacro specification.
2120 static bool parse_mmacro_spec(Token
*tline
, MMacro
*def
, const char *directive
)
2124 tline
= tline
->next
;
2126 tline
= expand_id(tline
);
2127 if (!tok_type_(tline
, TOK_ID
)) {
2128 nasm_error(ERR_NONFATAL
, "`%s' expects a macro name", directive
);
2133 def
->name
= nasm_strdup(tline
->text
);
2135 def
->nolist
= false;
2136 def
->in_progress
= 0;
2137 def
->rep_nest
= NULL
;
2138 def
->nparam_min
= 0;
2139 def
->nparam_max
= 0;
2141 tline
= expand_smacro(tline
->next
);
2143 if (!tok_type_(tline
, TOK_NUMBER
)) {
2144 nasm_error(ERR_NONFATAL
, "`%s' expects a parameter count", directive
);
2146 def
->nparam_min
= def
->nparam_max
=
2147 readnum(tline
->text
, &err
);
2149 nasm_error(ERR_NONFATAL
,
2150 "unable to parse parameter count `%s'", tline
->text
);
2152 if (tline
&& tok_is_(tline
->next
, "-")) {
2153 tline
= tline
->next
->next
;
2154 if (tok_is_(tline
, "*")) {
2155 def
->nparam_max
= INT_MAX
;
2156 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2157 nasm_error(ERR_NONFATAL
,
2158 "`%s' expects a parameter count after `-'", directive
);
2160 def
->nparam_max
= readnum(tline
->text
, &err
);
2162 nasm_error(ERR_NONFATAL
, "unable to parse parameter count `%s'",
2165 if (def
->nparam_min
> def
->nparam_max
) {
2166 nasm_error(ERR_NONFATAL
, "minimum parameter count exceeds maximum");
2170 if (tline
&& tok_is_(tline
->next
, "+")) {
2171 tline
= tline
->next
;
2174 if (tline
&& tok_type_(tline
->next
, TOK_ID
) &&
2175 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
2176 tline
= tline
->next
;
2181 * Handle default parameters.
2183 if (tline
&& tline
->next
) {
2184 def
->dlist
= tline
->next
;
2186 count_mmac_params(def
->dlist
, &def
->ndefs
, &def
->defaults
);
2189 def
->defaults
= NULL
;
2191 def
->expansion
= NULL
;
2193 if (def
->defaults
&& def
->ndefs
> def
->nparam_max
- def
->nparam_min
&&
2195 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MDP
,
2196 "too many default macro parameters");
2203 * Decode a size directive
2205 static int parse_size(const char *str
) {
2206 static const char *size_names
[] =
2207 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2208 static const int sizes
[] =
2209 { 0, 1, 4, 16, 8, 10, 2, 32 };
2211 return sizes
[bsii(str
, size_names
, ARRAY_SIZE(size_names
))+1];
2215 * Process a preprocessor %pragma directive. Currently there are none.
2216 * Gets passed the token list starting with the "preproc" token from
2217 * "%pragma preproc".
2219 static void do_pragma_preproc(Token
*tline
)
2221 /* Skip to the real stuff */
2222 tline
= tline
->next
;
2227 (void)tline
; /* Nothing else to do at present */
2231 * find and process preprocessor directive in passed line
2232 * Find out if a line contains a preprocessor directive, and deal
2235 * If a directive _is_ found, it is the responsibility of this routine
2236 * (and not the caller) to free_tlist() the line.
2238 * @param tline a pointer to the current tokeninzed line linked list
2239 * @param output if this directive generated output
2240 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2243 static int do_directive(Token
*tline
, char **output
)
2245 enum preproc_token i
;
2254 const char *found_path
;
2259 MMacro
*mmac
, **mmhead
;
2260 Token
*t
= NULL
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
2262 struct tokenval tokval
;
2264 MMacro
*tmp_defining
; /* Used when manipulating rep_nest */
2269 *output
= NULL
; /* No output generated */
2273 if (!tline
|| !tok_type_(tline
, TOK_PREPROC_ID
) ||
2274 (tline
->text
[1] == '%' || tline
->text
[1] == '$'
2275 || tline
->text
[1] == '!'))
2276 return NO_DIRECTIVE_FOUND
;
2278 i
= pp_token_hash(tline
->text
);
2281 * FIXME: We zap execution of PP_RMACRO, PP_IRMACRO, PP_EXITMACRO
2282 * since they are known to be buggy at moment, we need to fix them
2283 * in future release (2.09-2.10)
2285 if (i
== PP_RMACRO
|| i
== PP_IRMACRO
|| i
== PP_EXITMACRO
) {
2286 nasm_error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2288 return NO_DIRECTIVE_FOUND
;
2292 * If we're in a non-emitting branch of a condition construct,
2293 * or walking to the end of an already terminated %rep block,
2294 * we should ignore all directives except for condition
2297 if (((istk
->conds
&& !emitting(istk
->conds
->state
)) ||
2298 (istk
->mstk
&& !istk
->mstk
->in_progress
)) && !is_condition(i
)) {
2299 return NO_DIRECTIVE_FOUND
;
2303 * If we're defining a macro or reading a %rep block, we should
2304 * ignore all directives except for %macro/%imacro (which nest),
2305 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2306 * If we're in a %rep block, another %rep nests, so should be let through.
2308 if (defining
&& i
!= PP_MACRO
&& i
!= PP_IMACRO
&&
2309 i
!= PP_RMACRO
&& i
!= PP_IRMACRO
&&
2310 i
!= PP_ENDMACRO
&& i
!= PP_ENDM
&&
2311 (defining
->name
|| (i
!= PP_ENDREP
&& i
!= PP_REP
))) {
2312 return NO_DIRECTIVE_FOUND
;
2316 if (i
== PP_MACRO
|| i
== PP_IMACRO
||
2317 i
== PP_RMACRO
|| i
== PP_IRMACRO
) {
2319 return NO_DIRECTIVE_FOUND
;
2320 } else if (nested_mac_count
> 0) {
2321 if (i
== PP_ENDMACRO
) {
2323 return NO_DIRECTIVE_FOUND
;
2326 if (!defining
->name
) {
2329 return NO_DIRECTIVE_FOUND
;
2330 } else if (nested_rep_count
> 0) {
2331 if (i
== PP_ENDREP
) {
2333 return NO_DIRECTIVE_FOUND
;
2341 nasm_error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2343 return NO_DIRECTIVE_FOUND
; /* didn't get it */
2347 * %pragma namespace options...
2349 * The namespace "preproc" is reserved for the preprocessor;
2350 * all other namespaces generate a [pragma] assembly directive.
2352 * Invalid %pragmas are ignored and may have different
2353 * meaning in future versions of NASM.
2355 tline
= tline
->next
;
2357 tline
= expand_smacro(tline
);
2358 if (tok_type_(tline
, TOK_ID
)) {
2359 if (!nasm_stricmp(tline
->text
, "preproc")) {
2360 /* Preprocessor pragma */
2361 do_pragma_preproc(tline
);
2363 /* Build the assembler directive */
2364 t
= new_Token(NULL
, TOK_OTHER
, "[", 1);
2365 t
->next
= new_Token(NULL
, TOK_ID
, "pragma", 6);
2366 t
->next
->next
= new_Token(tline
, TOK_WHITESPACE
, NULL
, 0);
2368 for (t
= tline
; t
->next
; t
= t
->next
)
2370 t
->next
= new_Token(NULL
, TOK_OTHER
, "]", 1);
2371 /* true here can be revisited in the future */
2372 *output
= detoken(tline
, true);
2375 free_tlist(origline
);
2376 return DIRECTIVE_FOUND
;
2379 /* Directive to tell NASM what the default stack size is. The
2380 * default is for a 16-bit stack, and this can be overriden with
2383 tline
= tline
->next
;
2384 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2385 tline
= tline
->next
;
2386 if (!tline
|| tline
->type
!= TOK_ID
) {
2387 nasm_error(ERR_NONFATAL
, "`%%stacksize' missing size parameter");
2388 free_tlist(origline
);
2389 return DIRECTIVE_FOUND
;
2391 if (nasm_stricmp(tline
->text
, "flat") == 0) {
2392 /* All subsequent ARG directives are for a 32-bit stack */
2394 StackPointer
= "ebp";
2397 } else if (nasm_stricmp(tline
->text
, "flat64") == 0) {
2398 /* All subsequent ARG directives are for a 64-bit stack */
2400 StackPointer
= "rbp";
2403 } else if (nasm_stricmp(tline
->text
, "large") == 0) {
2404 /* All subsequent ARG directives are for a 16-bit stack,
2405 * far function call.
2408 StackPointer
= "bp";
2411 } else if (nasm_stricmp(tline
->text
, "small") == 0) {
2412 /* All subsequent ARG directives are for a 16-bit stack,
2413 * far function call. We don't support near functions.
2416 StackPointer
= "bp";
2420 nasm_error(ERR_NONFATAL
, "`%%stacksize' invalid size type");
2421 free_tlist(origline
);
2422 return DIRECTIVE_FOUND
;
2424 free_tlist(origline
);
2425 return DIRECTIVE_FOUND
;
2428 /* TASM like ARG directive to define arguments to functions, in
2429 * the following form:
2431 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2435 char *arg
, directive
[256];
2436 int size
= StackSize
;
2438 /* Find the argument name */
2439 tline
= tline
->next
;
2440 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2441 tline
= tline
->next
;
2442 if (!tline
|| tline
->type
!= TOK_ID
) {
2443 nasm_error(ERR_NONFATAL
, "`%%arg' missing argument parameter");
2444 free_tlist(origline
);
2445 return DIRECTIVE_FOUND
;
2449 /* Find the argument size type */
2450 tline
= tline
->next
;
2451 if (!tline
|| tline
->type
!= TOK_OTHER
2452 || tline
->text
[0] != ':') {
2453 nasm_error(ERR_NONFATAL
,
2454 "Syntax error processing `%%arg' directive");
2455 free_tlist(origline
);
2456 return DIRECTIVE_FOUND
;
2458 tline
= tline
->next
;
2459 if (!tline
|| tline
->type
!= TOK_ID
) {
2460 nasm_error(ERR_NONFATAL
, "`%%arg' missing size type parameter");
2461 free_tlist(origline
);
2462 return DIRECTIVE_FOUND
;
2465 /* Allow macro expansion of type parameter */
2466 tt
= tokenize(tline
->text
);
2467 tt
= expand_smacro(tt
);
2468 size
= parse_size(tt
->text
);
2470 nasm_error(ERR_NONFATAL
,
2471 "Invalid size type for `%%arg' missing directive");
2473 free_tlist(origline
);
2474 return DIRECTIVE_FOUND
;
2478 /* Round up to even stack slots */
2479 size
= ALIGN(size
, StackSize
);
2481 /* Now define the macro for the argument */
2482 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
2483 arg
, StackPointer
, offset
);
2484 do_directive(tokenize(directive
), output
);
2487 /* Move to the next argument in the list */
2488 tline
= tline
->next
;
2489 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2490 tline
= tline
->next
;
2491 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2493 free_tlist(origline
);
2494 return DIRECTIVE_FOUND
;
2497 /* TASM like LOCAL directive to define local variables for a
2498 * function, in the following form:
2500 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2502 * The '= LocalSize' at the end is ignored by NASM, but is
2503 * required by TASM to define the local parameter size (and used
2504 * by the TASM macro package).
2506 offset
= LocalOffset
;
2508 char *local
, directive
[256];
2509 int size
= StackSize
;
2511 /* Find the argument name */
2512 tline
= tline
->next
;
2513 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2514 tline
= tline
->next
;
2515 if (!tline
|| tline
->type
!= TOK_ID
) {
2516 nasm_error(ERR_NONFATAL
,
2517 "`%%local' missing argument parameter");
2518 free_tlist(origline
);
2519 return DIRECTIVE_FOUND
;
2521 local
= tline
->text
;
2523 /* Find the argument size type */
2524 tline
= tline
->next
;
2525 if (!tline
|| tline
->type
!= TOK_OTHER
2526 || tline
->text
[0] != ':') {
2527 nasm_error(ERR_NONFATAL
,
2528 "Syntax error processing `%%local' directive");
2529 free_tlist(origline
);
2530 return DIRECTIVE_FOUND
;
2532 tline
= tline
->next
;
2533 if (!tline
|| tline
->type
!= TOK_ID
) {
2534 nasm_error(ERR_NONFATAL
,
2535 "`%%local' missing size type parameter");
2536 free_tlist(origline
);
2537 return DIRECTIVE_FOUND
;
2540 /* Allow macro expansion of type parameter */
2541 tt
= tokenize(tline
->text
);
2542 tt
= expand_smacro(tt
);
2543 size
= parse_size(tt
->text
);
2545 nasm_error(ERR_NONFATAL
,
2546 "Invalid size type for `%%local' missing directive");
2548 free_tlist(origline
);
2549 return DIRECTIVE_FOUND
;
2553 /* Round up to even stack slots */
2554 size
= ALIGN(size
, StackSize
);
2556 offset
+= size
; /* Negative offset, increment before */
2558 /* Now define the macro for the argument */
2559 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
2560 local
, StackPointer
, offset
);
2561 do_directive(tokenize(directive
), output
);
2563 /* Now define the assign to setup the enter_c macro correctly */
2564 snprintf(directive
, sizeof(directive
),
2565 "%%assign %%$localsize %%$localsize+%d", size
);
2566 do_directive(tokenize(directive
), output
);
2568 /* Move to the next argument in the list */
2569 tline
= tline
->next
;
2570 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2571 tline
= tline
->next
;
2572 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2573 LocalOffset
= offset
;
2574 free_tlist(origline
);
2575 return DIRECTIVE_FOUND
;
2579 nasm_error(ERR_WARNING
|ERR_PASS1
,
2580 "trailing garbage after `%%clear' ignored");
2583 free_tlist(origline
);
2584 return DIRECTIVE_FOUND
;
2587 t
= tline
->next
= expand_smacro(tline
->next
);
2589 if (!t
|| (t
->type
!= TOK_STRING
&&
2590 t
->type
!= TOK_INTERNAL_STRING
)) {
2591 nasm_error(ERR_NONFATAL
, "`%%depend' expects a file name");
2592 free_tlist(origline
);
2593 return DIRECTIVE_FOUND
; /* but we did _something_ */
2596 nasm_error(ERR_WARNING
|ERR_PASS1
,
2597 "trailing garbage after `%%depend' ignored");
2599 if (t
->type
!= TOK_INTERNAL_STRING
)
2600 nasm_unquote_cstr(p
, i
);
2601 nasm_add_string_to_strlist(dephead
, p
);
2602 free_tlist(origline
);
2603 return DIRECTIVE_FOUND
;
2606 t
= tline
->next
= expand_smacro(tline
->next
);
2609 if (!t
|| (t
->type
!= TOK_STRING
&&
2610 t
->type
!= TOK_INTERNAL_STRING
)) {
2611 nasm_error(ERR_NONFATAL
, "`%%include' expects a file name");
2612 free_tlist(origline
);
2613 return DIRECTIVE_FOUND
; /* but we did _something_ */
2616 nasm_error(ERR_WARNING
|ERR_PASS1
,
2617 "trailing garbage after `%%include' ignored");
2619 if (t
->type
!= TOK_INTERNAL_STRING
)
2620 nasm_unquote_cstr(p
, i
);
2621 inc
= nasm_malloc(sizeof(Include
));
2625 inc
->fp
= inc_fopen(p
, dephead
, &found_path
,
2626 pass
== 0 ? INC_OPTIONAL
: INC_NEEDED
, NF_TEXT
);
2628 /* -MG given but file not found */
2631 inc
->fname
= src_set_fname(found_path
? found_path
: p
);
2632 inc
->lineno
= src_set_linnum(0);
2634 inc
->expansion
= NULL
;
2637 lfmt
->uplevel(LIST_INCLUDE
);
2639 free_tlist(origline
);
2640 return DIRECTIVE_FOUND
;
2644 static macros_t
*use_pkg
;
2645 const char *pkg_macro
= NULL
;
2647 tline
= tline
->next
;
2649 tline
= expand_id(tline
);
2651 if (!tline
|| (tline
->type
!= TOK_STRING
&&
2652 tline
->type
!= TOK_INTERNAL_STRING
&&
2653 tline
->type
!= TOK_ID
)) {
2654 nasm_error(ERR_NONFATAL
, "`%%use' expects a package name");
2655 free_tlist(origline
);
2656 return DIRECTIVE_FOUND
; /* but we did _something_ */
2659 nasm_error(ERR_WARNING
|ERR_PASS1
,
2660 "trailing garbage after `%%use' ignored");
2661 if (tline
->type
== TOK_STRING
)
2662 nasm_unquote_cstr(tline
->text
, i
);
2663 use_pkg
= nasm_stdmac_find_package(tline
->text
);
2665 nasm_error(ERR_NONFATAL
, "unknown `%%use' package: %s", tline
->text
);
2667 pkg_macro
= (char *)use_pkg
+ 1; /* The first string will be <%define>__USE_*__ */
2668 if (use_pkg
&& ! smacro_defined(NULL
, pkg_macro
, 0, NULL
, true)) {
2669 /* Not already included, go ahead and include it */
2670 stdmacpos
= use_pkg
;
2672 free_tlist(origline
);
2673 return DIRECTIVE_FOUND
;
2678 tline
= tline
->next
;
2680 tline
= expand_id(tline
);
2682 if (!tok_type_(tline
, TOK_ID
)) {
2683 nasm_error(ERR_NONFATAL
, "`%s' expects a context identifier",
2685 free_tlist(origline
);
2686 return DIRECTIVE_FOUND
; /* but we did _something_ */
2689 nasm_error(ERR_WARNING
|ERR_PASS1
,
2690 "trailing garbage after `%s' ignored",
2692 p
= nasm_strdup(tline
->text
);
2694 p
= NULL
; /* Anonymous */
2698 ctx
= nasm_malloc(sizeof(Context
));
2700 hash_init(&ctx
->localmac
, HASH_SMALL
);
2702 ctx
->number
= unique
++;
2707 nasm_error(ERR_NONFATAL
, "`%s': context stack is empty",
2709 } else if (i
== PP_POP
) {
2710 if (p
&& (!cstk
->name
|| nasm_stricmp(p
, cstk
->name
)))
2711 nasm_error(ERR_NONFATAL
, "`%%pop' in wrong context: %s, "
2713 cstk
->name
? cstk
->name
: "anonymous", p
);
2718 nasm_free(cstk
->name
);
2724 free_tlist(origline
);
2725 return DIRECTIVE_FOUND
;
2727 severity
= ERR_FATAL
;
2730 severity
= ERR_NONFATAL
;
2733 severity
= ERR_WARNING
|ERR_WARN_USER
;
2738 /* Only error out if this is the final pass */
2739 if (pass
!= 2 && i
!= PP_FATAL
)
2740 return DIRECTIVE_FOUND
;
2742 tline
->next
= expand_smacro(tline
->next
);
2743 tline
= tline
->next
;
2745 t
= tline
? tline
->next
: NULL
;
2747 if (tok_type_(tline
, TOK_STRING
) && !t
) {
2748 /* The line contains only a quoted string */
2750 nasm_unquote(p
, NULL
); /* Ignore NUL character truncation */
2751 nasm_error(severity
, "%s", p
);
2753 /* Not a quoted string, or more than a quoted string */
2754 p
= detoken(tline
, false);
2755 nasm_error(severity
, "%s", p
);
2758 free_tlist(origline
);
2759 return DIRECTIVE_FOUND
;
2763 if (istk
->conds
&& !emitting(istk
->conds
->state
))
2766 j
= if_condition(tline
->next
, i
);
2767 tline
->next
= NULL
; /* it got freed */
2768 j
= j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2770 cond
= nasm_malloc(sizeof(Cond
));
2771 cond
->next
= istk
->conds
;
2775 istk
->mstk
->condcnt
++;
2776 free_tlist(origline
);
2777 return DIRECTIVE_FOUND
;
2781 nasm_error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2782 switch(istk
->conds
->state
) {
2784 istk
->conds
->state
= COND_DONE
;
2791 case COND_ELSE_TRUE
:
2792 case COND_ELSE_FALSE
:
2793 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_PP_PRECOND
,
2794 "`%%elif' after `%%else' ignored");
2795 istk
->conds
->state
= COND_NEVER
;
2800 * IMPORTANT: In the case of %if, we will already have
2801 * called expand_mmac_params(); however, if we're
2802 * processing an %elif we must have been in a
2803 * non-emitting mode, which would have inhibited
2804 * the normal invocation of expand_mmac_params().
2805 * Therefore, we have to do it explicitly here.
2807 j
= if_condition(expand_mmac_params(tline
->next
), i
);
2808 tline
->next
= NULL
; /* it got freed */
2809 istk
->conds
->state
=
2810 j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2813 free_tlist(origline
);
2814 return DIRECTIVE_FOUND
;
2818 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_PP_PRECOND
,
2819 "trailing garbage after `%%else' ignored");
2821 nasm_fatal(0, "`%%else: no matching `%%if'");
2822 switch(istk
->conds
->state
) {
2825 istk
->conds
->state
= COND_ELSE_FALSE
;
2832 istk
->conds
->state
= COND_ELSE_TRUE
;
2835 case COND_ELSE_TRUE
:
2836 case COND_ELSE_FALSE
:
2837 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_PP_PRECOND
,
2838 "`%%else' after `%%else' ignored.");
2839 istk
->conds
->state
= COND_NEVER
;
2842 free_tlist(origline
);
2843 return DIRECTIVE_FOUND
;
2847 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_PP_PRECOND
,
2848 "trailing garbage after `%%endif' ignored");
2850 nasm_error(ERR_FATAL
, "`%%endif': no matching `%%if'");
2852 istk
->conds
= cond
->next
;
2855 istk
->mstk
->condcnt
--;
2856 free_tlist(origline
);
2857 return DIRECTIVE_FOUND
;
2864 nasm_error(ERR_FATAL
, "`%s': already defining a macro",
2866 return DIRECTIVE_FOUND
;
2868 defining
= nasm_zalloc(sizeof(MMacro
));
2869 defining
->max_depth
=
2870 (i
== PP_RMACRO
) || (i
== PP_IRMACRO
) ? DEADMAN_LIMIT
: 0;
2871 defining
->casesense
= (i
== PP_MACRO
) || (i
== PP_RMACRO
);
2872 if (!parse_mmacro_spec(tline
, defining
, pp_directives
[i
])) {
2873 nasm_free(defining
);
2875 return DIRECTIVE_FOUND
;
2878 src_get(&defining
->xline
, &defining
->fname
);
2880 mmac
= (MMacro
*) hash_findix(&mmacros
, defining
->name
);
2882 if (!strcmp(mmac
->name
, defining
->name
) &&
2883 (mmac
->nparam_min
<= defining
->nparam_max
2885 && (defining
->nparam_min
<= mmac
->nparam_max
2887 nasm_error(ERR_WARNING
|ERR_PASS1
,
2888 "redefining multi-line macro `%s'", defining
->name
);
2889 return DIRECTIVE_FOUND
;
2893 free_tlist(origline
);
2894 return DIRECTIVE_FOUND
;
2898 if (! (defining
&& defining
->name
)) {
2899 nasm_error(ERR_NONFATAL
, "`%s': not defining a macro", tline
->text
);
2900 return DIRECTIVE_FOUND
;
2902 mmhead
= (MMacro
**) hash_findi_add(&mmacros
, defining
->name
);
2903 defining
->next
= *mmhead
;
2906 free_tlist(origline
);
2907 return DIRECTIVE_FOUND
;
2911 * We must search along istk->expansion until we hit a
2912 * macro-end marker for a macro with a name. Then we
2913 * bypass all lines between exitmacro and endmacro.
2915 list_for_each(l
, istk
->expansion
)
2916 if (l
->finishes
&& l
->finishes
->name
)
2921 * Remove all conditional entries relative to this
2922 * macro invocation. (safe to do in this context)
2924 for ( ; l
->finishes
->condcnt
> 0; l
->finishes
->condcnt
--) {
2926 istk
->conds
= cond
->next
;
2929 istk
->expansion
= l
;
2931 nasm_error(ERR_NONFATAL
, "`%%exitmacro' not within `%%macro' block");
2933 free_tlist(origline
);
2934 return DIRECTIVE_FOUND
;
2942 spec
.casesense
= (i
== PP_UNMACRO
);
2943 if (!parse_mmacro_spec(tline
, &spec
, pp_directives
[i
])) {
2944 return DIRECTIVE_FOUND
;
2946 mmac_p
= (MMacro
**) hash_findi(&mmacros
, spec
.name
, NULL
);
2947 while (mmac_p
&& *mmac_p
) {
2949 if (mmac
->casesense
== spec
.casesense
&&
2950 !mstrcmp(mmac
->name
, spec
.name
, spec
.casesense
) &&
2951 mmac
->nparam_min
== spec
.nparam_min
&&
2952 mmac
->nparam_max
== spec
.nparam_max
&&
2953 mmac
->plus
== spec
.plus
) {
2954 *mmac_p
= mmac
->next
;
2957 mmac_p
= &mmac
->next
;
2960 free_tlist(origline
);
2961 free_tlist(spec
.dlist
);
2962 return DIRECTIVE_FOUND
;
2966 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
2967 tline
= tline
->next
;
2969 free_tlist(origline
);
2970 nasm_error(ERR_NONFATAL
, "`%%rotate' missing rotate count");
2971 return DIRECTIVE_FOUND
;
2973 t
= expand_smacro(tline
->next
);
2975 free_tlist(origline
);
2978 tokval
.t_type
= TOKEN_INVALID
;
2980 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, NULL
);
2983 return DIRECTIVE_FOUND
;
2985 nasm_error(ERR_WARNING
|ERR_PASS1
,
2986 "trailing garbage after expression ignored");
2987 if (!is_simple(evalresult
)) {
2988 nasm_error(ERR_NONFATAL
, "non-constant value given to `%%rotate'");
2989 return DIRECTIVE_FOUND
;
2992 while (mmac
&& !mmac
->name
) /* avoid mistaking %reps for macros */
2993 mmac
= mmac
->next_active
;
2995 nasm_error(ERR_NONFATAL
, "`%%rotate' invoked outside a macro call");
2996 } else if (mmac
->nparam
== 0) {
2997 nasm_error(ERR_NONFATAL
,
2998 "`%%rotate' invoked within macro without parameters");
3000 int rotate
= mmac
->rotate
+ reloc_value(evalresult
);
3002 rotate
%= (int)mmac
->nparam
;
3004 rotate
+= mmac
->nparam
;
3006 mmac
->rotate
= rotate
;
3008 return DIRECTIVE_FOUND
;
3013 tline
= tline
->next
;
3014 } while (tok_type_(tline
, TOK_WHITESPACE
));
3016 if (tok_type_(tline
, TOK_ID
) &&
3017 nasm_stricmp(tline
->text
, ".nolist") == 0) {
3020 tline
= tline
->next
;
3021 } while (tok_type_(tline
, TOK_WHITESPACE
));
3025 t
= expand_smacro(tline
);
3027 tokval
.t_type
= TOKEN_INVALID
;
3029 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, NULL
);
3031 free_tlist(origline
);
3032 return DIRECTIVE_FOUND
;
3035 nasm_error(ERR_WARNING
|ERR_PASS1
,
3036 "trailing garbage after expression ignored");
3037 if (!is_simple(evalresult
)) {
3038 nasm_error(ERR_NONFATAL
, "non-constant value given to `%%rep'");
3039 return DIRECTIVE_FOUND
;
3041 count
= reloc_value(evalresult
);
3042 if (count
>= REP_LIMIT
) {
3043 nasm_error(ERR_NONFATAL
, "`%%rep' value exceeds limit");
3048 nasm_error(ERR_NONFATAL
, "`%%rep' expects a repeat count");
3051 free_tlist(origline
);
3053 tmp_defining
= defining
;
3054 defining
= nasm_malloc(sizeof(MMacro
));
3055 defining
->prev
= NULL
;
3056 defining
->name
= NULL
; /* flags this macro as a %rep block */
3057 defining
->casesense
= false;
3058 defining
->plus
= false;
3059 defining
->nolist
= nolist
;
3060 defining
->in_progress
= count
;
3061 defining
->max_depth
= 0;
3062 defining
->nparam_min
= defining
->nparam_max
= 0;
3063 defining
->defaults
= NULL
;
3064 defining
->dlist
= NULL
;
3065 defining
->expansion
= NULL
;
3066 defining
->next_active
= istk
->mstk
;
3067 defining
->rep_nest
= tmp_defining
;
3068 return DIRECTIVE_FOUND
;
3071 if (!defining
|| defining
->name
) {
3072 nasm_error(ERR_NONFATAL
, "`%%endrep': no matching `%%rep'");
3073 return DIRECTIVE_FOUND
;
3077 * Now we have a "macro" defined - although it has no name
3078 * and we won't be entering it in the hash tables - we must
3079 * push a macro-end marker for it on to istk->expansion.
3080 * After that, it will take care of propagating itself (a
3081 * macro-end marker line for a macro which is really a %rep
3082 * block will cause the macro to be re-expanded, complete
3083 * with another macro-end marker to ensure the process
3084 * continues) until the whole expansion is forcibly removed
3085 * from istk->expansion by a %exitrep.
3087 l
= nasm_malloc(sizeof(Line
));
3088 l
->next
= istk
->expansion
;
3089 l
->finishes
= defining
;
3091 istk
->expansion
= l
;
3093 istk
->mstk
= defining
;
3095 lfmt
->uplevel(defining
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
3096 tmp_defining
= defining
;
3097 defining
= defining
->rep_nest
;
3098 free_tlist(origline
);
3099 return DIRECTIVE_FOUND
;
3103 * We must search along istk->expansion until we hit a
3104 * macro-end marker for a macro with no name. Then we set
3105 * its `in_progress' flag to 0.
3107 list_for_each(l
, istk
->expansion
)
3108 if (l
->finishes
&& !l
->finishes
->name
)
3112 l
->finishes
->in_progress
= 1;
3114 nasm_error(ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
3115 free_tlist(origline
);
3116 return DIRECTIVE_FOUND
;
3122 casesense
= (i
== PP_DEFINE
|| i
== PP_XDEFINE
);
3124 tline
= tline
->next
;
3126 tline
= expand_id(tline
);
3127 if (!tline
|| (tline
->type
!= TOK_ID
&&
3128 (tline
->type
!= TOK_PREPROC_ID
||
3129 tline
->text
[1] != '$'))) {
3130 nasm_error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3132 free_tlist(origline
);
3133 return DIRECTIVE_FOUND
;
3136 ctx
= get_ctx(tline
->text
, &mname
);
3138 param_start
= tline
= tline
->next
;
3141 /* Expand the macro definition now for %xdefine and %ixdefine */
3142 if ((i
== PP_XDEFINE
) || (i
== PP_IXDEFINE
))
3143 tline
= expand_smacro(tline
);
3145 if (tok_is_(tline
, "(")) {
3147 * This macro has parameters.
3150 tline
= tline
->next
;
3154 nasm_error(ERR_NONFATAL
, "parameter identifier expected");
3155 free_tlist(origline
);
3156 return DIRECTIVE_FOUND
;
3158 if (tline
->type
!= TOK_ID
) {
3159 nasm_error(ERR_NONFATAL
,
3160 "`%s': parameter identifier expected",
3162 free_tlist(origline
);
3163 return DIRECTIVE_FOUND
;
3165 tline
->type
= TOK_SMAC_PARAM
+ nparam
++;
3166 tline
= tline
->next
;
3168 if (tok_is_(tline
, ",")) {
3169 tline
= tline
->next
;
3171 if (!tok_is_(tline
, ")")) {
3172 nasm_error(ERR_NONFATAL
,
3173 "`)' expected to terminate macro template");
3174 free_tlist(origline
);
3175 return DIRECTIVE_FOUND
;
3181 tline
= tline
->next
;
3183 if (tok_type_(tline
, TOK_WHITESPACE
))
3184 last
= tline
, tline
= tline
->next
;
3189 if (t
->type
== TOK_ID
) {
3190 list_for_each(tt
, param_start
)
3191 if (tt
->type
>= TOK_SMAC_PARAM
&&
3192 !strcmp(tt
->text
, t
->text
))
3196 t
->next
= macro_start
;
3201 * Good. We now have a macro name, a parameter count, and a
3202 * token list (in reverse order) for an expansion. We ought
3203 * to be OK just to create an SMacro, store it, and let
3204 * free_tlist have the rest of the line (which we have
3205 * carefully re-terminated after chopping off the expansion
3208 define_smacro(ctx
, mname
, casesense
, nparam
, macro_start
);
3209 free_tlist(origline
);
3210 return DIRECTIVE_FOUND
;
3213 tline
= tline
->next
;
3215 tline
= expand_id(tline
);
3216 if (!tline
|| (tline
->type
!= TOK_ID
&&
3217 (tline
->type
!= TOK_PREPROC_ID
||
3218 tline
->text
[1] != '$'))) {
3219 nasm_error(ERR_NONFATAL
, "`%%undef' expects a macro identifier");
3220 free_tlist(origline
);
3221 return DIRECTIVE_FOUND
;
3224 nasm_error(ERR_WARNING
|ERR_PASS1
,
3225 "trailing garbage after macro name ignored");
3228 /* Find the context that symbol belongs to */
3229 ctx
= get_ctx(tline
->text
, &mname
);
3230 undef_smacro(ctx
, mname
);
3231 free_tlist(origline
);
3232 return DIRECTIVE_FOUND
;
3236 casesense
= (i
== PP_DEFSTR
);
3238 tline
= tline
->next
;
3240 tline
= expand_id(tline
);
3241 if (!tline
|| (tline
->type
!= TOK_ID
&&
3242 (tline
->type
!= TOK_PREPROC_ID
||
3243 tline
->text
[1] != '$'))) {
3244 nasm_error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3246 free_tlist(origline
);
3247 return DIRECTIVE_FOUND
;
3250 ctx
= get_ctx(tline
->text
, &mname
);
3252 tline
= expand_smacro(tline
->next
);
3255 while (tok_type_(tline
, TOK_WHITESPACE
))
3256 tline
= delete_Token(tline
);
3258 p
= detoken(tline
, false);
3259 macro_start
= nasm_malloc(sizeof(*macro_start
));
3260 macro_start
->next
= NULL
;
3261 macro_start
->text
= nasm_quote(p
, strlen(p
));
3262 macro_start
->type
= TOK_STRING
;
3263 macro_start
->a
.mac
= NULL
;
3267 * We now have a macro name, an implicit parameter count of
3268 * zero, and a string token to use as an expansion. Create
3269 * and store an SMacro.
3271 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3272 free_tlist(origline
);
3273 return DIRECTIVE_FOUND
;
3277 casesense
= (i
== PP_DEFTOK
);
3279 tline
= tline
->next
;
3281 tline
= expand_id(tline
);
3282 if (!tline
|| (tline
->type
!= TOK_ID
&&
3283 (tline
->type
!= TOK_PREPROC_ID
||
3284 tline
->text
[1] != '$'))) {
3285 nasm_error(ERR_NONFATAL
,
3286 "`%s' expects a macro identifier as first parameter",
3288 free_tlist(origline
);
3289 return DIRECTIVE_FOUND
;
3291 ctx
= get_ctx(tline
->text
, &mname
);
3293 tline
= expand_smacro(tline
->next
);
3297 while (tok_type_(t
, TOK_WHITESPACE
))
3299 /* t should now point to the string */
3300 if (!tok_type_(t
, TOK_STRING
)) {
3301 nasm_error(ERR_NONFATAL
,
3302 "`%s` requires string as second parameter",
3305 free_tlist(origline
);
3306 return DIRECTIVE_FOUND
;
3310 * Convert the string to a token stream. Note that smacros
3311 * are stored with the token stream reversed, so we have to
3312 * reverse the output of tokenize().
3314 nasm_unquote_cstr(t
->text
, i
);
3315 macro_start
= reverse_tokens(tokenize(t
->text
));
3318 * We now have a macro name, an implicit parameter count of
3319 * zero, and a numeric token to use as an expansion. Create
3320 * and store an SMacro.
3322 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3324 free_tlist(origline
);
3325 return DIRECTIVE_FOUND
;
3329 const char *found_path
;
3333 tline
= tline
->next
;
3335 tline
= expand_id(tline
);
3336 if (!tline
|| (tline
->type
!= TOK_ID
&&
3337 (tline
->type
!= TOK_PREPROC_ID
||
3338 tline
->text
[1] != '$'))) {
3339 nasm_error(ERR_NONFATAL
,
3340 "`%%pathsearch' expects a macro identifier as first parameter");
3341 free_tlist(origline
);
3342 return DIRECTIVE_FOUND
;
3344 ctx
= get_ctx(tline
->text
, &mname
);
3346 tline
= expand_smacro(tline
->next
);
3350 while (tok_type_(t
, TOK_WHITESPACE
))
3353 if (!t
|| (t
->type
!= TOK_STRING
&&
3354 t
->type
!= TOK_INTERNAL_STRING
)) {
3355 nasm_error(ERR_NONFATAL
, "`%%pathsearch' expects a file name");
3357 free_tlist(origline
);
3358 return DIRECTIVE_FOUND
; /* but we did _something_ */
3361 nasm_error(ERR_WARNING
|ERR_PASS1
,
3362 "trailing garbage after `%%pathsearch' ignored");
3364 if (t
->type
!= TOK_INTERNAL_STRING
)
3365 nasm_unquote(p
, NULL
);
3367 inc_fopen(p
, NULL
, &found_path
, INC_PROBE
, NF_BINARY
);
3370 macro_start
= nasm_malloc(sizeof(*macro_start
));
3371 macro_start
->next
= NULL
;
3372 macro_start
->text
= nasm_quote(found_path
, strlen(found_path
));
3373 macro_start
->type
= TOK_STRING
;
3374 macro_start
->a
.mac
= NULL
;
3377 * We now have a macro name, an implicit parameter count of
3378 * zero, and a string token to use as an expansion. Create
3379 * and store an SMacro.
3381 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3383 free_tlist(origline
);
3384 return DIRECTIVE_FOUND
;
3390 tline
= tline
->next
;
3392 tline
= expand_id(tline
);
3393 if (!tline
|| (tline
->type
!= TOK_ID
&&
3394 (tline
->type
!= TOK_PREPROC_ID
||
3395 tline
->text
[1] != '$'))) {
3396 nasm_error(ERR_NONFATAL
,
3397 "`%%strlen' expects a macro identifier as first parameter");
3398 free_tlist(origline
);
3399 return DIRECTIVE_FOUND
;
3401 ctx
= get_ctx(tline
->text
, &mname
);
3403 tline
= expand_smacro(tline
->next
);
3407 while (tok_type_(t
, TOK_WHITESPACE
))
3409 /* t should now point to the string */
3410 if (!tok_type_(t
, TOK_STRING
)) {
3411 nasm_error(ERR_NONFATAL
,
3412 "`%%strlen` requires string as second parameter");
3414 free_tlist(origline
);
3415 return DIRECTIVE_FOUND
;
3418 macro_start
= nasm_malloc(sizeof(*macro_start
));
3419 macro_start
->next
= NULL
;
3420 make_tok_num(macro_start
, nasm_unquote(t
->text
, NULL
));
3421 macro_start
->a
.mac
= NULL
;
3424 * We now have a macro name, an implicit parameter count of
3425 * zero, and a numeric token to use as an expansion. Create
3426 * and store an SMacro.
3428 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3430 free_tlist(origline
);
3431 return DIRECTIVE_FOUND
;
3436 tline
= tline
->next
;
3438 tline
= expand_id(tline
);
3439 if (!tline
|| (tline
->type
!= TOK_ID
&&
3440 (tline
->type
!= TOK_PREPROC_ID
||
3441 tline
->text
[1] != '$'))) {
3442 nasm_error(ERR_NONFATAL
,
3443 "`%%strcat' expects a macro identifier as first parameter");
3444 free_tlist(origline
);
3445 return DIRECTIVE_FOUND
;
3447 ctx
= get_ctx(tline
->text
, &mname
);
3449 tline
= expand_smacro(tline
->next
);
3453 list_for_each(t
, tline
) {
3455 case TOK_WHITESPACE
:
3458 len
+= t
->a
.len
= nasm_unquote(t
->text
, NULL
);
3461 if (!strcmp(t
->text
, ",")) /* permit comma separators */
3463 /* else fall through */
3465 nasm_error(ERR_NONFATAL
,
3466 "non-string passed to `%%strcat' (%d)", t
->type
);
3468 free_tlist(origline
);
3469 return DIRECTIVE_FOUND
;
3473 p
= pp
= nasm_malloc(len
);
3474 list_for_each(t
, tline
) {
3475 if (t
->type
== TOK_STRING
) {
3476 memcpy(p
, t
->text
, t
->a
.len
);
3482 * We now have a macro name, an implicit parameter count of
3483 * zero, and a numeric token to use as an expansion. Create
3484 * and store an SMacro.
3486 macro_start
= new_Token(NULL
, TOK_STRING
, NULL
, 0);
3487 macro_start
->text
= nasm_quote(pp
, len
);
3489 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3491 free_tlist(origline
);
3492 return DIRECTIVE_FOUND
;
3496 int64_t start
, count
;
3501 tline
= tline
->next
;
3503 tline
= expand_id(tline
);
3504 if (!tline
|| (tline
->type
!= TOK_ID
&&
3505 (tline
->type
!= TOK_PREPROC_ID
||
3506 tline
->text
[1] != '$'))) {
3507 nasm_error(ERR_NONFATAL
,
3508 "`%%substr' expects a macro identifier as first parameter");
3509 free_tlist(origline
);
3510 return DIRECTIVE_FOUND
;
3512 ctx
= get_ctx(tline
->text
, &mname
);
3514 tline
= expand_smacro(tline
->next
);
3517 if (tline
) /* skip expanded id */
3519 while (tok_type_(t
, TOK_WHITESPACE
))
3522 /* t should now point to the string */
3523 if (!tok_type_(t
, TOK_STRING
)) {
3524 nasm_error(ERR_NONFATAL
,
3525 "`%%substr` requires string as second parameter");
3527 free_tlist(origline
);
3528 return DIRECTIVE_FOUND
;
3533 tokval
.t_type
= TOKEN_INVALID
;
3534 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, NULL
);
3537 free_tlist(origline
);
3538 return DIRECTIVE_FOUND
;
3539 } else if (!is_simple(evalresult
)) {
3540 nasm_error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3542 free_tlist(origline
);
3543 return DIRECTIVE_FOUND
;
3545 start
= evalresult
->value
- 1;
3547 while (tok_type_(tt
, TOK_WHITESPACE
))
3550 count
= 1; /* Backwards compatibility: one character */
3552 tokval
.t_type
= TOKEN_INVALID
;
3553 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, NULL
);
3556 free_tlist(origline
);
3557 return DIRECTIVE_FOUND
;
3558 } else if (!is_simple(evalresult
)) {
3559 nasm_error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3561 free_tlist(origline
);
3562 return DIRECTIVE_FOUND
;
3564 count
= evalresult
->value
;
3567 len
= nasm_unquote(t
->text
, NULL
);
3569 /* make start and count being in range */
3573 count
= len
+ count
+ 1 - start
;
3574 if (start
+ count
> (int64_t)len
)
3575 count
= len
- start
;
3576 if (!len
|| count
< 0 || start
>=(int64_t)len
)
3577 start
= -1, count
= 0; /* empty string */
3579 macro_start
= nasm_malloc(sizeof(*macro_start
));
3580 macro_start
->next
= NULL
;
3581 macro_start
->text
= nasm_quote((start
< 0) ? "" : t
->text
+ start
, count
);
3582 macro_start
->type
= TOK_STRING
;
3583 macro_start
->a
.mac
= NULL
;
3586 * We now have a macro name, an implicit parameter count of
3587 * zero, and a numeric token to use as an expansion. Create
3588 * and store an SMacro.
3590 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3592 free_tlist(origline
);
3593 return DIRECTIVE_FOUND
;
3598 casesense
= (i
== PP_ASSIGN
);
3600 tline
= tline
->next
;
3602 tline
= expand_id(tline
);
3603 if (!tline
|| (tline
->type
!= TOK_ID
&&
3604 (tline
->type
!= TOK_PREPROC_ID
||
3605 tline
->text
[1] != '$'))) {
3606 nasm_error(ERR_NONFATAL
,
3607 "`%%%sassign' expects a macro identifier",
3608 (i
== PP_IASSIGN
? "i" : ""));
3609 free_tlist(origline
);
3610 return DIRECTIVE_FOUND
;
3612 ctx
= get_ctx(tline
->text
, &mname
);
3614 tline
= expand_smacro(tline
->next
);
3619 tokval
.t_type
= TOKEN_INVALID
;
3620 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, NULL
);
3623 free_tlist(origline
);
3624 return DIRECTIVE_FOUND
;
3628 nasm_error(ERR_WARNING
|ERR_PASS1
,
3629 "trailing garbage after expression ignored");
3631 if (!is_simple(evalresult
)) {
3632 nasm_error(ERR_NONFATAL
,
3633 "non-constant value given to `%%%sassign'",
3634 (i
== PP_IASSIGN
? "i" : ""));
3635 free_tlist(origline
);
3636 return DIRECTIVE_FOUND
;
3639 macro_start
= nasm_malloc(sizeof(*macro_start
));
3640 macro_start
->next
= NULL
;
3641 make_tok_num(macro_start
, reloc_value(evalresult
));
3642 macro_start
->a
.mac
= NULL
;
3645 * We now have a macro name, an implicit parameter count of
3646 * zero, and a numeric token to use as an expansion. Create
3647 * and store an SMacro.
3649 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3650 free_tlist(origline
);
3651 return DIRECTIVE_FOUND
;
3655 * Syntax is `%line nnn[+mmm] [filename]'
3657 tline
= tline
->next
;
3659 if (!tok_type_(tline
, TOK_NUMBER
)) {
3660 nasm_error(ERR_NONFATAL
, "`%%line' expects line number");
3661 free_tlist(origline
);
3662 return DIRECTIVE_FOUND
;
3664 k
= readnum(tline
->text
, &err
);
3666 tline
= tline
->next
;
3667 if (tok_is_(tline
, "+")) {
3668 tline
= tline
->next
;
3669 if (!tok_type_(tline
, TOK_NUMBER
)) {
3670 nasm_error(ERR_NONFATAL
, "`%%line' expects line increment");
3671 free_tlist(origline
);
3672 return DIRECTIVE_FOUND
;
3674 m
= readnum(tline
->text
, &err
);
3675 tline
= tline
->next
;
3681 char *fname
= detoken(tline
, false);
3682 src_set_fname(fname
);
3685 free_tlist(origline
);
3686 return DIRECTIVE_FOUND
;
3689 nasm_error(ERR_FATAL
,
3690 "preprocessor directive `%s' not yet implemented",
3692 return DIRECTIVE_FOUND
;
3697 * Ensure that a macro parameter contains a condition code and
3698 * nothing else. Return the condition code index if so, or -1
3701 static int find_cc(Token
* t
)
3706 return -1; /* Probably a %+ without a space */
3709 if (t
->type
!= TOK_ID
)
3713 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
3716 return bsii(t
->text
, (const char **)conditions
, ARRAY_SIZE(conditions
));
3720 * This routines walks over tokens strem and hadnles tokens
3721 * pasting, if @handle_explicit passed then explicit pasting
3722 * term is handled, otherwise -- implicit pastings only.
3724 static bool paste_tokens(Token
**head
, const struct tokseq_match
*m
,
3725 size_t mnum
, bool handle_explicit
)
3727 Token
*tok
, *next
, **prev_next
, **prev_nonspace
;
3728 bool pasted
= false;
3733 * The last token before pasting. We need it
3734 * to be able to connect new handled tokens.
3735 * In other words if there were a tokens stream
3739 * and we've joined tokens B and C, the resulting
3747 if (!tok_type_(tok
, TOK_WHITESPACE
) && !tok_type_(tok
, TOK_PASTE
))
3748 prev_nonspace
= head
;
3750 prev_nonspace
= NULL
;
3752 while (tok
&& (next
= tok
->next
)) {
3754 switch (tok
->type
) {
3755 case TOK_WHITESPACE
:
3756 /* Zap redundant whitespaces */
3757 while (tok_type_(next
, TOK_WHITESPACE
))
3758 next
= delete_Token(next
);
3763 /* Explicit pasting */
3764 if (!handle_explicit
)
3766 next
= delete_Token(tok
);
3768 while (tok_type_(next
, TOK_WHITESPACE
))
3769 next
= delete_Token(next
);
3774 /* Left pasting token is start of line */
3776 nasm_error(ERR_FATAL
, "No lvalue found on pasting");
3779 * No ending token, this might happen in two
3782 * 1) There indeed no right token at all
3783 * 2) There is a bare "%define ID" statement,
3784 * and @ID does expand to whitespace.
3786 * So technically we need to do a grammar analysis
3787 * in another stage of parsing, but for now lets don't
3788 * change the behaviour people used to. Simply allow
3789 * whitespace after paste token.
3793 * Zap ending space tokens and that's all.
3795 tok
= (*prev_nonspace
)->next
;
3796 while (tok_type_(tok
, TOK_WHITESPACE
))
3797 tok
= delete_Token(tok
);
3798 tok
= *prev_nonspace
;
3803 tok
= *prev_nonspace
;
3804 while (tok_type_(tok
, TOK_WHITESPACE
))
3805 tok
= delete_Token(tok
);
3806 len
= strlen(tok
->text
);
3807 len
+= strlen(next
->text
);
3809 p
= buf
= nasm_malloc(len
+ 1);
3810 strcpy(p
, tok
->text
);
3811 p
= strchr(p
, '\0');
3812 strcpy(p
, next
->text
);
3816 tok
= tokenize(buf
);
3819 *prev_nonspace
= tok
;
3820 while (tok
&& tok
->next
)
3823 tok
->next
= delete_Token(next
);
3825 /* Restart from pasted tokens head */
3826 tok
= *prev_nonspace
;
3830 /* implicit pasting */
3831 for (i
= 0; i
< mnum
; i
++) {
3832 if (!(PP_CONCAT_MATCH(tok
, m
[i
].mask_head
)))
3836 while (next
&& PP_CONCAT_MATCH(next
, m
[i
].mask_tail
)) {
3837 len
+= strlen(next
->text
);
3845 len
+= strlen(tok
->text
);
3846 p
= buf
= nasm_malloc(len
+ 1);
3848 while (tok
!= next
) {
3849 strcpy(p
, tok
->text
);
3850 p
= strchr(p
, '\0');
3851 tok
= delete_Token(tok
);
3854 tok
= tokenize(buf
);
3863 * Connect pasted into original stream,
3864 * ie A -> new-tokens -> B
3866 while (tok
&& tok
->next
)
3873 /* Restart from pasted tokens head */
3874 tok
= prev_next
? *prev_next
: *head
;
3880 prev_next
= &tok
->next
;
3883 !tok_type_(tok
->next
, TOK_WHITESPACE
) &&
3884 !tok_type_(tok
->next
, TOK_PASTE
))
3885 prev_nonspace
= prev_next
;
3894 * expands to a list of tokens from %{x:y}
3896 static Token
*expand_mmac_params_range(MMacro
*mac
, Token
*tline
, Token
***last
)
3898 Token
*t
= tline
, **tt
, *tm
, *head
;
3902 pos
= strchr(tline
->text
, ':');
3905 lst
= atoi(pos
+ 1);
3906 fst
= atoi(tline
->text
+ 1);
3909 * only macros params are accounted so
3910 * if someone passes %0 -- we reject such
3913 if (lst
== 0 || fst
== 0)
3916 /* the values should be sane */
3917 if ((fst
> (int)mac
->nparam
|| fst
< (-(int)mac
->nparam
)) ||
3918 (lst
> (int)mac
->nparam
|| lst
< (-(int)mac
->nparam
)))
3921 fst
= fst
< 0 ? fst
+ (int)mac
->nparam
+ 1: fst
;
3922 lst
= lst
< 0 ? lst
+ (int)mac
->nparam
+ 1: lst
;
3924 /* counted from zero */
3928 * It will be at least one token. Note we
3929 * need to scan params until separator, otherwise
3930 * only first token will be passed.
3932 tm
= mac
->params
[(fst
+ mac
->rotate
) % mac
->nparam
];
3933 head
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3934 tt
= &head
->next
, tm
= tm
->next
;
3935 while (tok_isnt_(tm
, ",")) {
3936 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3937 *tt
= t
, tt
= &t
->next
, tm
= tm
->next
;
3941 for (i
= fst
+ 1; i
<= lst
; i
++) {
3942 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
3943 *tt
= t
, tt
= &t
->next
;
3944 j
= (i
+ mac
->rotate
) % mac
->nparam
;
3945 tm
= mac
->params
[j
];
3946 while (tok_isnt_(tm
, ",")) {
3947 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3948 *tt
= t
, tt
= &t
->next
, tm
= tm
->next
;
3952 for (i
= fst
- 1; i
>= lst
; i
--) {
3953 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
3954 *tt
= t
, tt
= &t
->next
;
3955 j
= (i
+ mac
->rotate
) % mac
->nparam
;
3956 tm
= mac
->params
[j
];
3957 while (tok_isnt_(tm
, ",")) {
3958 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3959 *tt
= t
, tt
= &t
->next
, tm
= tm
->next
;
3968 nasm_error(ERR_NONFATAL
, "`%%{%s}': macro parameters out of range",
3974 * Expand MMacro-local things: parameter references (%0, %n, %+n,
3975 * %-n) and MMacro-local identifiers (%%foo) as well as
3976 * macro indirection (%[...]) and range (%{..:..}).
3978 static Token
*expand_mmac_params(Token
* tline
)
3980 Token
*t
, *tt
, **tail
, *thead
;
3981 bool changed
= false;
3988 if (tline
->type
== TOK_PREPROC_ID
&&
3989 (((tline
->text
[1] == '+' || tline
->text
[1] == '-') && tline
->text
[2]) ||
3990 (tline
->text
[1] >= '0' && tline
->text
[1] <= '9') ||
3991 tline
->text
[1] == '%')) {
3993 int type
= 0, cc
; /* type = 0 to placate optimisers */
4000 tline
= tline
->next
;
4003 while (mac
&& !mac
->name
) /* avoid mistaking %reps for macros */
4004 mac
= mac
->next_active
;
4006 nasm_error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
4008 pos
= strchr(t
->text
, ':');
4010 switch (t
->text
[1]) {
4012 * We have to make a substitution of one of the
4013 * forms %1, %-1, %+1, %%foo, %0.
4017 snprintf(tmpbuf
, sizeof(tmpbuf
), "%d", mac
->nparam
);
4018 text
= nasm_strdup(tmpbuf
);
4022 snprintf(tmpbuf
, sizeof(tmpbuf
), "..@%"PRIu64
".",
4024 text
= nasm_strcat(tmpbuf
, t
->text
+ 2);
4027 n
= atoi(t
->text
+ 2) - 1;
4028 if (n
>= mac
->nparam
)
4031 if (mac
->nparam
> 1)
4032 n
= (n
+ mac
->rotate
) % mac
->nparam
;
4033 tt
= mac
->params
[n
];
4037 nasm_error(ERR_NONFATAL
,
4038 "macro parameter %d is not a condition code",
4043 if (inverse_ccs
[cc
] == -1) {
4044 nasm_error(ERR_NONFATAL
,
4045 "condition code `%s' is not invertible",
4049 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
4053 n
= atoi(t
->text
+ 2) - 1;
4054 if (n
>= mac
->nparam
)
4057 if (mac
->nparam
> 1)
4058 n
= (n
+ mac
->rotate
) % mac
->nparam
;
4059 tt
= mac
->params
[n
];
4063 nasm_error(ERR_NONFATAL
,
4064 "macro parameter %d is not a condition code",
4069 text
= nasm_strdup(conditions
[cc
]);
4073 n
= atoi(t
->text
+ 1) - 1;
4074 if (n
>= mac
->nparam
)
4077 if (mac
->nparam
> 1)
4078 n
= (n
+ mac
->rotate
) % mac
->nparam
;
4079 tt
= mac
->params
[n
];
4082 for (i
= 0; i
< mac
->paramlen
[n
]; i
++) {
4083 *tail
= new_Token(NULL
, tt
->type
, tt
->text
, 0);
4084 tail
= &(*tail
)->next
;
4088 text
= NULL
; /* we've done it here */
4093 * seems we have a parameters range here
4095 Token
*head
, **last
;
4096 head
= expand_mmac_params_range(mac
, t
, &last
);
4117 } else if (tline
->type
== TOK_INDIRECT
) {
4119 tline
= tline
->next
;
4120 tt
= tokenize(t
->text
);
4121 tt
= expand_mmac_params(tt
);
4122 tt
= expand_smacro(tt
);
4125 tt
->a
.mac
= NULL
; /* Necessary? */
4133 tline
= tline
->next
;
4141 const struct tokseq_match t
[] = {
4143 PP_CONCAT_MASK(TOK_ID
) |
4144 PP_CONCAT_MASK(TOK_FLOAT
), /* head */
4145 PP_CONCAT_MASK(TOK_ID
) |
4146 PP_CONCAT_MASK(TOK_NUMBER
) |
4147 PP_CONCAT_MASK(TOK_FLOAT
) |
4148 PP_CONCAT_MASK(TOK_OTHER
) /* tail */
4151 PP_CONCAT_MASK(TOK_NUMBER
), /* head */
4152 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4155 paste_tokens(&thead
, t
, ARRAY_SIZE(t
), false);
4162 * Expand all single-line macro calls made in the given line.
4163 * Return the expanded version of the line. The original is deemed
4164 * to be destroyed in the process. (In reality we'll just move
4165 * Tokens from input to output a lot of the time, rather than
4166 * actually bothering to destroy and replicate.)
4169 static Token
*expand_smacro(Token
* tline
)
4171 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
4172 SMacro
*head
= NULL
, *m
;
4175 unsigned int nparam
, sparam
;
4177 Token
*org_tline
= tline
;
4180 int deadman
= DEADMAN_LIMIT
;
4184 * Trick: we should avoid changing the start token pointer since it can
4185 * be contained in "next" field of other token. Because of this
4186 * we allocate a copy of first token and work with it; at the end of
4187 * routine we copy it back
4190 tline
= new_Token(org_tline
->next
, org_tline
->type
,
4191 org_tline
->text
, 0);
4192 tline
->a
.mac
= org_tline
->a
.mac
;
4193 nasm_free(org_tline
->text
);
4194 org_tline
->text
= NULL
;
4197 expanded
= true; /* Always expand %+ at least once */
4203 while (tline
) { /* main token loop */
4205 nasm_error(ERR_NONFATAL
, "interminable macro recursion");
4209 if ((mname
= tline
->text
)) {
4210 /* if this token is a local macro, look in local context */
4211 if (tline
->type
== TOK_ID
) {
4212 head
= (SMacro
*)hash_findix(&smacros
, mname
);
4213 } else if (tline
->type
== TOK_PREPROC_ID
) {
4214 ctx
= get_ctx(mname
, &mname
);
4215 head
= ctx
? (SMacro
*)hash_findix(&ctx
->localmac
, mname
) : NULL
;
4220 * We've hit an identifier. As in is_mmacro below, we first
4221 * check whether the identifier is a single-line macro at
4222 * all, then think about checking for parameters if
4225 list_for_each(m
, head
)
4226 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
4232 if (m
->nparam
== 0) {
4234 * Simple case: the macro is parameterless. Discard the
4235 * one token that the macro call took, and push the
4236 * expansion back on the to-do stack.
4238 if (!m
->expansion
) {
4239 if (!strcmp("__FILE__", m
->name
)) {
4240 const char *file
= src_get_fname();
4241 /* nasm_free(tline->text); here? */
4242 tline
->text
= nasm_quote(file
, strlen(file
));
4243 tline
->type
= TOK_STRING
;
4246 if (!strcmp("__LINE__", m
->name
)) {
4247 nasm_free(tline
->text
);
4248 make_tok_num(tline
, src_get_linnum());
4251 if (!strcmp("__BITS__", m
->name
)) {
4252 nasm_free(tline
->text
);
4253 make_tok_num(tline
, globalbits
);
4256 tline
= delete_Token(tline
);
4261 * Complicated case: at least one macro with this name
4262 * exists and takes parameters. We must find the
4263 * parameters in the call, count them, find the SMacro
4264 * that corresponds to that form of the macro call, and
4265 * substitute for the parameters when we expand. What a
4268 /*tline = tline->next;
4269 skip_white_(tline); */
4272 while (tok_type_(t
, TOK_SMAC_END
)) {
4273 t
->a
.mac
->in_progress
= false;
4275 t
= tline
->next
= delete_Token(t
);
4278 } while (tok_type_(tline
, TOK_WHITESPACE
));
4279 if (!tok_is_(tline
, "(")) {
4281 * This macro wasn't called with parameters: ignore
4282 * the call. (Behaviour borrowed from gnu cpp.)
4291 sparam
= PARAM_DELTA
;
4292 params
= nasm_malloc(sparam
* sizeof(Token
*));
4293 params
[0] = tline
->next
;
4294 paramsize
= nasm_malloc(sparam
* sizeof(int));
4296 while (true) { /* parameter loop */
4298 * For some unusual expansions
4299 * which concatenates function call
4302 while (tok_type_(t
, TOK_SMAC_END
)) {
4303 t
->a
.mac
->in_progress
= false;
4305 t
= tline
->next
= delete_Token(t
);
4310 nasm_error(ERR_NONFATAL
,
4311 "macro call expects terminating `)'");
4314 if (tline
->type
== TOK_WHITESPACE
4316 if (paramsize
[nparam
])
4319 params
[nparam
] = tline
->next
;
4320 continue; /* parameter loop */
4322 if (tline
->type
== TOK_OTHER
4323 && tline
->text
[1] == 0) {
4324 char ch
= tline
->text
[0];
4325 if (ch
== ',' && !paren
&& brackets
<= 0) {
4326 if (++nparam
>= sparam
) {
4327 sparam
+= PARAM_DELTA
;
4328 params
= nasm_realloc(params
,
4329 sparam
* sizeof(Token
*));
4330 paramsize
= nasm_realloc(paramsize
,
4331 sparam
* sizeof(int));
4333 params
[nparam
] = tline
->next
;
4334 paramsize
[nparam
] = 0;
4336 continue; /* parameter loop */
4339 (brackets
> 0 || (brackets
== 0 &&
4340 !paramsize
[nparam
])))
4342 if (!(brackets
++)) {
4343 params
[nparam
] = tline
->next
;
4344 continue; /* parameter loop */
4347 if (ch
== '}' && brackets
> 0)
4348 if (--brackets
== 0) {
4350 continue; /* parameter loop */
4352 if (ch
== '(' && !brackets
)
4354 if (ch
== ')' && brackets
<= 0)
4360 nasm_error(ERR_NONFATAL
, "braces do not "
4361 "enclose all of macro parameter");
4363 paramsize
[nparam
] += white
+ 1;
4365 } /* parameter loop */
4367 while (m
&& (m
->nparam
!= nparam
||
4368 mstrcmp(m
->name
, mname
,
4372 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4373 "macro `%s' exists, "
4374 "but not taking %d parameters",
4375 mstart
->text
, nparam
);
4378 if (m
&& m
->in_progress
)
4380 if (!m
) { /* in progess or didn't find '(' or wrong nparam */
4382 * Design question: should we handle !tline, which
4383 * indicates missing ')' here, or expand those
4384 * macros anyway, which requires the (t) test a few
4388 nasm_free(paramsize
);
4392 * Expand the macro: we are placed on the last token of the
4393 * call, so that we can easily split the call from the
4394 * following tokens. We also start by pushing an SMAC_END
4395 * token for the cycle removal.
4402 tt
= new_Token(tline
, TOK_SMAC_END
, NULL
, 0);
4404 m
->in_progress
= true;
4406 list_for_each(t
, m
->expansion
) {
4407 if (t
->type
>= TOK_SMAC_PARAM
) {
4408 Token
*pcopy
= tline
, **ptail
= &pcopy
;
4412 ttt
= params
[t
->type
- TOK_SMAC_PARAM
];
4413 i
= paramsize
[t
->type
- TOK_SMAC_PARAM
];
4415 pt
= *ptail
= new_Token(tline
, ttt
->type
,
4421 } else if (t
->type
== TOK_PREPROC_Q
) {
4422 tt
= new_Token(tline
, TOK_ID
, mname
, 0);
4424 } else if (t
->type
== TOK_PREPROC_QQ
) {
4425 tt
= new_Token(tline
, TOK_ID
, m
->name
, 0);
4428 tt
= new_Token(tline
, t
->type
, t
->text
, 0);
4434 * Having done that, get rid of the macro call, and clean
4435 * up the parameters.
4438 nasm_free(paramsize
);
4441 continue; /* main token loop */
4446 if (tline
->type
== TOK_SMAC_END
) {
4447 tline
->a
.mac
->in_progress
= false;
4448 tline
= delete_Token(tline
);
4451 tline
= tline
->next
;
4459 * Now scan the entire line and look for successive TOK_IDs that resulted
4460 * after expansion (they can't be produced by tokenize()). The successive
4461 * TOK_IDs should be concatenated.
4462 * Also we look for %+ tokens and concatenate the tokens before and after
4463 * them (without white spaces in between).
4466 const struct tokseq_match t
[] = {
4468 PP_CONCAT_MASK(TOK_ID
) |
4469 PP_CONCAT_MASK(TOK_PREPROC_ID
), /* head */
4470 PP_CONCAT_MASK(TOK_ID
) |
4471 PP_CONCAT_MASK(TOK_PREPROC_ID
) |
4472 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4475 if (paste_tokens(&thead
, t
, ARRAY_SIZE(t
), true)) {
4477 * If we concatenated something, *and* we had previously expanded
4478 * an actual macro, scan the lines again for macros...
4489 *org_tline
= *thead
;
4490 /* since we just gave text to org_line, don't free it */
4492 delete_Token(thead
);
4494 /* the expression expanded to empty line;
4495 we can't return NULL for some reasons
4496 we just set the line to a single WHITESPACE token. */
4497 memset(org_tline
, 0, sizeof(*org_tline
));
4498 org_tline
->text
= NULL
;
4499 org_tline
->type
= TOK_WHITESPACE
;
4508 * Similar to expand_smacro but used exclusively with macro identifiers
4509 * right before they are fetched in. The reason is that there can be
4510 * identifiers consisting of several subparts. We consider that if there
4511 * are more than one element forming the name, user wants a expansion,
4512 * otherwise it will be left as-is. Example:
4516 * the identifier %$abc will be left as-is so that the handler for %define
4517 * will suck it and define the corresponding value. Other case:
4519 * %define _%$abc cde
4521 * In this case user wants name to be expanded *before* %define starts
4522 * working, so we'll expand %$abc into something (if it has a value;
4523 * otherwise it will be left as-is) then concatenate all successive
4526 static Token
*expand_id(Token
* tline
)
4528 Token
*cur
, *oldnext
= NULL
;
4530 if (!tline
|| !tline
->next
)
4535 (cur
->next
->type
== TOK_ID
||
4536 cur
->next
->type
== TOK_PREPROC_ID
4537 || cur
->next
->type
== TOK_NUMBER
))
4540 /* If identifier consists of just one token, don't expand */
4545 oldnext
= cur
->next
; /* Detach the tail past identifier */
4546 cur
->next
= NULL
; /* so that expand_smacro stops here */
4549 tline
= expand_smacro(tline
);
4552 /* expand_smacro possibly changhed tline; re-scan for EOL */
4554 while (cur
&& cur
->next
)
4557 cur
->next
= oldnext
;
4564 * Determine whether the given line constitutes a multi-line macro
4565 * call, and return the MMacro structure called if so. Doesn't have
4566 * to check for an initial label - that's taken care of in
4567 * expand_mmacro - but must check numbers of parameters. Guaranteed
4568 * to be called with tline->type == TOK_ID, so the putative macro
4569 * name is easy to find.
4571 static MMacro
*is_mmacro(Token
* tline
, Token
*** params_array
)
4577 head
= (MMacro
*) hash_findix(&mmacros
, tline
->text
);
4580 * Efficiency: first we see if any macro exists with the given
4581 * name. If not, we can return NULL immediately. _Then_ we
4582 * count the parameters, and then we look further along the
4583 * list if necessary to find the proper MMacro.
4585 list_for_each(m
, head
)
4586 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
4592 * OK, we have a potential macro. Count and demarcate the
4595 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
4598 * So we know how many parameters we've got. Find the MMacro
4599 * structure that handles this number.
4602 if (m
->nparam_min
<= nparam
4603 && (m
->plus
|| nparam
<= m
->nparam_max
)) {
4605 * This one is right. Just check if cycle removal
4606 * prohibits us using it before we actually celebrate...
4608 if (m
->in_progress
> m
->max_depth
) {
4609 if (m
->max_depth
> 0) {
4610 nasm_error(ERR_WARNING
,
4611 "reached maximum recursion depth of %i",
4618 * It's right, and we can use it. Add its default
4619 * parameters to the end of our list if necessary.
4621 if (m
->defaults
&& nparam
< m
->nparam_min
+ m
->ndefs
) {
4623 nasm_realloc(params
,
4624 ((m
->nparam_min
+ m
->ndefs
+
4625 1) * sizeof(*params
)));
4626 while (nparam
< m
->nparam_min
+ m
->ndefs
) {
4627 params
[nparam
] = m
->defaults
[nparam
- m
->nparam_min
];
4632 * If we've gone over the maximum parameter count (and
4633 * we're in Plus mode), ignore parameters beyond
4636 if (m
->plus
&& nparam
> m
->nparam_max
)
4637 nparam
= m
->nparam_max
;
4639 * Then terminate the parameter list, and leave.
4641 if (!params
) { /* need this special case */
4642 params
= nasm_malloc(sizeof(*params
));
4645 params
[nparam
] = NULL
;
4646 *params_array
= params
;
4650 * This one wasn't right: look for the next one with the
4653 list_for_each(m
, m
->next
)
4654 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
4659 * After all that, we didn't find one with the right number of
4660 * parameters. Issue a warning, and fail to expand the macro.
4662 nasm_error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4663 "macro `%s' exists, but not taking %d parameters",
4664 tline
->text
, nparam
);
4671 * Save MMacro invocation specific fields in
4672 * preparation for a recursive macro expansion
4674 static void push_mmacro(MMacro
*m
)
4676 MMacroInvocation
*i
;
4678 i
= nasm_malloc(sizeof(MMacroInvocation
));
4680 i
->params
= m
->params
;
4681 i
->iline
= m
->iline
;
4682 i
->nparam
= m
->nparam
;
4683 i
->rotate
= m
->rotate
;
4684 i
->paramlen
= m
->paramlen
;
4685 i
->unique
= m
->unique
;
4686 i
->condcnt
= m
->condcnt
;
4692 * Restore MMacro invocation specific fields that were
4693 * saved during a previous recursive macro expansion
4695 static void pop_mmacro(MMacro
*m
)
4697 MMacroInvocation
*i
;
4702 m
->params
= i
->params
;
4703 m
->iline
= i
->iline
;
4704 m
->nparam
= i
->nparam
;
4705 m
->rotate
= i
->rotate
;
4706 m
->paramlen
= i
->paramlen
;
4707 m
->unique
= i
->unique
;
4708 m
->condcnt
= i
->condcnt
;
4715 * Expand the multi-line macro call made by the given line, if
4716 * there is one to be expanded. If there is, push the expansion on
4717 * istk->expansion and return 1. Otherwise return 0.
4719 static int expand_mmacro(Token
* tline
)
4721 Token
*startline
= tline
;
4722 Token
*label
= NULL
;
4723 int dont_prepend
= 0;
4724 Token
**params
, *t
, *tt
;
4727 int i
, nparam
, *paramlen
;
4732 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4733 if (!tok_type_(t
, TOK_ID
) && !tok_type_(t
, TOK_PREPROC_ID
))
4735 m
= is_mmacro(t
, ¶ms
);
4741 * We have an id which isn't a macro call. We'll assume
4742 * it might be a label; we'll also check to see if a
4743 * colon follows it. Then, if there's another id after
4744 * that lot, we'll check it again for macro-hood.
4748 if (tok_type_(t
, TOK_WHITESPACE
))
4749 last
= t
, t
= t
->next
;
4750 if (tok_is_(t
, ":")) {
4752 last
= t
, t
= t
->next
;
4753 if (tok_type_(t
, TOK_WHITESPACE
))
4754 last
= t
, t
= t
->next
;
4756 if (!tok_type_(t
, TOK_ID
) || !(m
= is_mmacro(t
, ¶ms
)))
4764 * Fix up the parameters: this involves stripping leading and
4765 * trailing whitespace, then stripping braces if they are
4768 for (nparam
= 0; params
[nparam
]; nparam
++) ;
4769 paramlen
= nparam
? nasm_malloc(nparam
* sizeof(*paramlen
)) : NULL
;
4771 for (i
= 0; params
[i
]; i
++) {
4773 int comma
= (!m
->plus
|| i
< nparam
- 1);
4777 if (tok_is_(t
, "{"))
4778 t
= t
->next
, brace
++, comma
= false;
4782 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
4783 break; /* ... because we have hit a comma */
4784 if (comma
&& t
->type
== TOK_WHITESPACE
4785 && tok_is_(t
->next
, ","))
4786 break; /* ... or a space then a comma */
4787 if (brace
&& t
->type
== TOK_OTHER
) {
4788 if (t
->text
[0] == '{')
4789 brace
++; /* ... or a nested opening brace */
4790 else if (t
->text
[0] == '}')
4792 break; /* ... or a brace */
4798 nasm_error(ERR_NONFATAL
, "macro params should be enclosed in braces");
4802 * OK, we have a MMacro structure together with a set of
4803 * parameters. We must now go through the expansion and push
4804 * copies of each Line on to istk->expansion. Substitution of
4805 * parameter tokens and macro-local tokens doesn't get done
4806 * until the single-line macro substitution process; this is
4807 * because delaying them allows us to change the semantics
4808 * later through %rotate.
4810 * First, push an end marker on to istk->expansion, mark this
4811 * macro as in progress, and set up its invocation-specific
4814 ll
= nasm_malloc(sizeof(Line
));
4815 ll
->next
= istk
->expansion
;
4818 istk
->expansion
= ll
;
4821 * Save the previous MMacro expansion in the case of
4824 if (m
->max_depth
&& m
->in_progress
)
4832 m
->paramlen
= paramlen
;
4833 m
->unique
= unique
++;
4837 m
->next_active
= istk
->mstk
;
4840 list_for_each(l
, m
->expansion
) {
4843 ll
= nasm_malloc(sizeof(Line
));
4844 ll
->finishes
= NULL
;
4845 ll
->next
= istk
->expansion
;
4846 istk
->expansion
= ll
;
4849 list_for_each(t
, l
->first
) {
4853 tt
= *tail
= new_Token(NULL
, TOK_ID
, mname
, 0);
4855 case TOK_PREPROC_QQ
:
4856 tt
= *tail
= new_Token(NULL
, TOK_ID
, m
->name
, 0);
4858 case TOK_PREPROC_ID
:
4859 if (t
->text
[1] == '0' && t
->text
[2] == '0') {
4867 tt
= *tail
= new_Token(NULL
, x
->type
, x
->text
, 0);
4876 * If we had a label, push it on as the first line of
4877 * the macro expansion.
4880 if (dont_prepend
< 0)
4881 free_tlist(startline
);
4883 ll
= nasm_malloc(sizeof(Line
));
4884 ll
->finishes
= NULL
;
4885 ll
->next
= istk
->expansion
;
4886 istk
->expansion
= ll
;
4887 ll
->first
= startline
;
4888 if (!dont_prepend
) {
4890 label
= label
->next
;
4891 label
->next
= tt
= new_Token(NULL
, TOK_OTHER
, ":", 0);
4896 lfmt
->uplevel(m
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
4902 * This function adds macro names to error messages, and suppresses
4903 * them if necessary.
4905 static void pp_verror(int severity
, const char *fmt
, va_list arg
)
4908 MMacro
*mmac
= NULL
;
4912 * If we're in a dead branch of IF or something like it, ignore the error.
4913 * However, because %else etc are evaluated in the state context
4914 * of the previous branch, errors might get lost:
4915 * %if 0 ... %else trailing garbage ... %endif
4916 * So %else etc should set the ERR_PP_PRECOND flag.
4918 if ((severity
& ERR_MASK
) < ERR_FATAL
&&
4919 istk
&& istk
->conds
&&
4920 ((severity
& ERR_PP_PRECOND
) ?
4921 istk
->conds
->state
== COND_NEVER
:
4922 !emitting(istk
->conds
->state
)))
4925 /* get %macro name */
4926 if (!(severity
& ERR_NOFILE
) && istk
&& istk
->mstk
) {
4928 /* but %rep blocks should be skipped */
4929 while (mmac
&& !mmac
->name
)
4930 mmac
= mmac
->next_active
, delta
++;
4934 vsnprintf(buff
, sizeof(buff
), fmt
, arg
);
4936 nasm_set_verror(real_verror
);
4937 nasm_error(severity
, "(%s:%d) %s",
4938 mmac
->name
, mmac
->lineno
- delta
, buff
);
4939 nasm_set_verror(pp_verror
);
4941 real_verror(severity
, fmt
, arg
);
4946 pp_reset(char *file
, int apass
, StrList
**deplist
)
4951 istk
= nasm_malloc(sizeof(Include
));
4954 istk
->expansion
= NULL
;
4956 istk
->fp
= nasm_open_read(file
, NF_TEXT
);
4961 nasm_fatal(ERR_NOFILE
, "unable to open input file `%s'", file
);
4963 nested_mac_count
= 0;
4964 nested_rep_count
= 0;
4968 if (tasm_compatible_mode
)
4969 pp_add_stdmac(nasm_stdmac_tasm
);
4971 pp_add_stdmac(nasm_stdmac_nasm
);
4972 pp_add_stdmac(nasm_stdmac_version
);
4975 pp_add_stdmac(extrastdmac
);
4977 stdmacpos
= stdmacros
[0];
4978 stdmacnext
= &stdmacros
[1];
4983 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
4984 * The caller, however, will also pass in 3 for preprocess-only so
4985 * we can set __PASS__ accordingly.
4987 pass
= apass
> 2 ? 2 : apass
;
4990 nasm_add_string_to_strlist(dephead
, file
);
4993 * Define the __PASS__ macro. This is defined here unlike
4994 * all the other builtins, because it is special -- it varies between
4997 t
= nasm_malloc(sizeof(*t
));
4999 make_tok_num(t
, apass
);
5001 define_smacro(NULL
, "__PASS__", true, 0, t
);
5004 static void pp_init(void)
5006 hash_init(&FileHash
, HASH_MEDIUM
);
5009 static char *pp_getline(void)
5014 real_verror
= nasm_set_verror(pp_verror
);
5018 * Fetch a tokenized line, either from the macro-expansion
5019 * buffer or from the input file.
5022 while (istk
->expansion
&& istk
->expansion
->finishes
) {
5023 Line
*l
= istk
->expansion
;
5024 if (!l
->finishes
->name
&& l
->finishes
->in_progress
> 1) {
5028 * This is a macro-end marker for a macro with no
5029 * name, which means it's not really a macro at all
5030 * but a %rep block, and the `in_progress' field is
5031 * more than 1, meaning that we still need to
5032 * repeat. (1 means the natural last repetition; 0
5033 * means termination by %exitrep.) We have
5034 * therefore expanded up to the %endrep, and must
5035 * push the whole block on to the expansion buffer
5036 * again. We don't bother to remove the macro-end
5037 * marker: we'd only have to generate another one
5040 l
->finishes
->in_progress
--;
5041 list_for_each(l
, l
->finishes
->expansion
) {
5042 Token
*t
, *tt
, **tail
;
5044 ll
= nasm_malloc(sizeof(Line
));
5045 ll
->next
= istk
->expansion
;
5046 ll
->finishes
= NULL
;
5050 list_for_each(t
, l
->first
) {
5051 if (t
->text
|| t
->type
== TOK_WHITESPACE
) {
5052 tt
= *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
5057 istk
->expansion
= ll
;
5061 * Check whether a `%rep' was started and not ended
5062 * within this macro expansion. This can happen and
5063 * should be detected. It's a fatal error because
5064 * I'm too confused to work out how to recover
5069 nasm_panic(0, "defining with name in expansion");
5070 else if (istk
->mstk
->name
)
5071 nasm_fatal(0, "`%%rep' without `%%endrep' within"
5072 " expansion of macro `%s'",
5077 * FIXME: investigate the relationship at this point between
5078 * istk->mstk and l->finishes
5081 MMacro
*m
= istk
->mstk
;
5082 istk
->mstk
= m
->next_active
;
5085 * This was a real macro call, not a %rep, and
5086 * therefore the parameter information needs to
5091 l
->finishes
->in_progress
--;
5093 nasm_free(m
->params
);
5094 free_tlist(m
->iline
);
5095 nasm_free(m
->paramlen
);
5096 l
->finishes
->in_progress
= 0;
5101 istk
->expansion
= l
->next
;
5103 lfmt
->downlevel(LIST_MACRO
);
5106 while (1) { /* until we get a line we can use */
5108 if (istk
->expansion
) { /* from a macro expansion */
5110 Line
*l
= istk
->expansion
;
5112 istk
->mstk
->lineno
++;
5114 istk
->expansion
= l
->next
;
5116 p
= detoken(tline
, false);
5117 lfmt
->line(LIST_MACRO
, p
);
5122 if (line
) { /* from the current input file */
5123 line
= prepreproc(line
);
5124 tline
= tokenize(line
);
5129 * The current file has ended; work down the istk
5135 /* nasm_error can't be conditionally suppressed */
5137 "expected `%%endif' before end of file");
5139 /* only set line and file name if there's a next node */
5141 src_set(i
->lineno
, i
->fname
);
5143 lfmt
->downlevel(LIST_INCLUDE
);
5149 if (istk
->expansion
&& istk
->expansion
->finishes
)
5155 * We must expand MMacro parameters and MMacro-local labels
5156 * _before_ we plunge into directive processing, to cope
5157 * with things like `%define something %1' such as STRUC
5158 * uses. Unless we're _defining_ a MMacro, in which case
5159 * those tokens should be left alone to go into the
5160 * definition; and unless we're in a non-emitting
5161 * condition, in which case we don't want to meddle with
5164 if (!defining
&& !(istk
->conds
&& !emitting(istk
->conds
->state
))
5165 && !(istk
->mstk
&& !istk
->mstk
->in_progress
)) {
5166 tline
= expand_mmac_params(tline
);
5170 * Check the line to see if it's a preprocessor directive.
5172 if (do_directive(tline
, &line
) == DIRECTIVE_FOUND
) {
5174 break; /* Directive generated output */
5177 } else if (defining
) {
5179 * We're defining a multi-line macro. We emit nothing
5181 * shove the tokenized line on to the macro definition.
5183 Line
*l
= nasm_malloc(sizeof(Line
));
5184 l
->next
= defining
->expansion
;
5187 defining
->expansion
= l
;
5189 } else if (istk
->conds
&& !emitting(istk
->conds
->state
)) {
5191 * We're in a non-emitting branch of a condition block.
5192 * Emit nothing at all, not even a blank line: when we
5193 * emerge from the condition we'll give a line-number
5194 * directive so we keep our place correctly.
5198 } else if (istk
->mstk
&& !istk
->mstk
->in_progress
) {
5200 * We're in a %rep block which has been terminated, so
5201 * we're walking through to the %endrep without
5202 * emitting anything. Emit nothing at all, not even a
5203 * blank line: when we emerge from the %rep block we'll
5204 * give a line-number directive so we keep our place
5210 tline
= expand_smacro(tline
);
5211 if (!expand_mmacro(tline
)) {
5213 * De-tokenize the line again, and emit it.
5215 line
= detoken(tline
, true);
5219 continue; /* expand_mmacro calls free_tlist */
5225 nasm_set_verror(real_verror
);
5229 static void pp_cleanup(int pass
)
5231 real_verror
= nasm_set_verror(pp_verror
);
5234 if (defining
->name
) {
5235 nasm_error(ERR_NONFATAL
,
5236 "end of file while still defining macro `%s'",
5239 nasm_error(ERR_NONFATAL
, "end of file while still in %%rep");
5242 free_mmacro(defining
);
5246 nasm_set_verror(real_verror
);
5259 src_set_fname(NULL
);
5266 while ((i
= ipath
)) {
5275 static void pp_include_path(char *path
)
5279 i
= nasm_malloc(sizeof(IncPath
));
5280 i
->path
= path
? nasm_strdup(path
) : NULL
;
5293 static void pp_pre_include(char *fname
)
5295 Token
*inc
, *space
, *name
;
5298 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
5299 space
= new_Token(name
, TOK_WHITESPACE
, NULL
, 0);
5300 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
5302 l
= nasm_malloc(sizeof(Line
));
5309 static void pp_pre_define(char *definition
)
5315 real_verror
= nasm_set_verror(pp_verror
);
5317 equals
= strchr(definition
, '=');
5318 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5319 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
5322 space
->next
= tokenize(definition
);
5326 if (space
->next
->type
!= TOK_PREPROC_ID
&&
5327 space
->next
->type
!= TOK_ID
)
5328 nasm_error(ERR_WARNING
, "pre-defining non ID `%s\'\n", definition
);
5330 l
= nasm_malloc(sizeof(Line
));
5336 nasm_set_verror(real_verror
);
5339 static void pp_pre_undefine(char *definition
)
5344 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5345 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
5346 space
->next
= tokenize(definition
);
5348 l
= nasm_malloc(sizeof(Line
));
5355 static void pp_add_stdmac(macros_t
*macros
)
5359 /* Find the end of the list and avoid duplicates */
5360 for (mp
= stdmacros
; *mp
; mp
++) {
5362 return; /* Nothing to do */
5365 nasm_assert(mp
< &stdmacros
[ARRAY_SIZE(stdmacros
)-1]);
5370 static void pp_extra_stdmac(macros_t
*macros
)
5372 extrastdmac
= macros
;
5375 static void make_tok_num(Token
* tok
, int64_t val
)
5378 snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
5379 tok
->text
= nasm_strdup(numbuf
);
5380 tok
->type
= TOK_NUMBER
;
5383 static void pp_list_one_macro(MMacro
*m
, int severity
)
5388 /* We need to print the next_active list in reverse order */
5389 pp_list_one_macro(m
->next_active
, severity
);
5391 if (m
->name
&& !m
->nolist
) {
5392 src_set(m
->xline
+ m
->lineno
, m
->fname
);
5393 nasm_error(severity
, "... from macro `%s' defined here", m
->name
);
5397 static void pp_error_list_macros(int severity
)
5400 const char *saved_fname
= NULL
;
5402 severity
|= ERR_PP_LISTMACRO
| ERR_NO_SEVERITY
;
5403 src_get(&saved_line
, &saved_fname
);
5406 pp_list_one_macro(istk
->mstk
, severity
);
5408 src_set(saved_line
, saved_fname
);
5411 const struct preproc_ops nasmpp
= {
5421 pp_error_list_macros
,