1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2010 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
35 * preproc.c macro preprocessor for the Netwide Assembler
38 /* Typical flow of text through preproc
40 * pp_getline gets tokenized lines, either
42 * from a macro expansion
46 * read_line gets raw text from stdmacpos, or predef, or current input file
47 * tokenize converts to tokens
50 * expand_mmac_params is used to expand %1 etc., unless a macro is being
51 * defined or a false conditional is being processed
52 * (%0, %1, %+1, %-1, %%foo
54 * do_directive checks for directives
56 * expand_smacro is used to expand single line macros
58 * expand_mmacro is used to expand multi-line macros
60 * detoken is used to convert the line back to text
84 typedef struct SMacro SMacro
;
85 typedef struct MMacro MMacro
;
86 typedef struct MMacroInvocation MMacroInvocation
;
87 typedef struct Context Context
;
88 typedef struct Token Token
;
89 typedef struct Blocks Blocks
;
90 typedef struct Line Line
;
91 typedef struct Include Include
;
92 typedef struct Cond Cond
;
93 typedef struct IncPath IncPath
;
96 * Note on the storage of both SMacro and MMacros: the hash table
97 * indexes them case-insensitively, and we then have to go through a
98 * linked list of potential case aliases (and, for MMacros, parameter
99 * ranges); this is to preserve the matching semantics of the earlier
100 * code. If the number of case aliases for a specific macro is a
101 * performance issue, you may want to reconsider your coding style.
105 * Store the definition of a single-line macro.
117 * Store the definition of a multi-line macro. This is also used to
118 * store the interiors of `%rep...%endrep' blocks, which are
119 * effectively self-re-invoking multi-line macros which simply
120 * don't have a name or bother to appear in the hash tables. %rep
121 * blocks are signified by having a NULL `name' field.
123 * In a MMacro describing a `%rep' block, the `in_progress' field
124 * isn't merely boolean, but gives the number of repeats left to
127 * The `next' field is used for storing MMacros in hash tables; the
128 * `next_active' field is for stacking them on istk entries.
130 * When a MMacro is being expanded, `params', `iline', `nparam',
131 * `paramlen', `rotate' and `unique' are local to the invocation.
135 MMacroInvocation
*prev
; /* previous invocation */
137 int nparam_min
, nparam_max
;
139 bool plus
; /* is the last parameter greedy? */
140 bool nolist
; /* is this macro listing-inhibited? */
141 int64_t in_progress
; /* is this macro currently being expanded? */
142 int32_t max_depth
; /* maximum number of recursive expansions allowed */
143 Token
*dlist
; /* All defaults as one list */
144 Token
**defaults
; /* Parameter default pointers */
145 int ndefs
; /* number of default parameters */
149 MMacro
*rep_nest
; /* used for nesting %rep */
150 Token
**params
; /* actual parameters */
151 Token
*iline
; /* invocation line */
152 unsigned int nparam
, rotate
;
155 int lineno
; /* Current line number on expansion */
156 uint64_t condcnt
; /* number of if blocks... */
160 /* Store the definition of a multi-line macro, as defined in a
161 * previous recursive macro expansion.
163 struct MMacroInvocation
{
164 MMacroInvocation
*prev
; /* previous invocation */
165 Token
**params
; /* actual parameters */
166 Token
*iline
; /* invocation line */
167 unsigned int nparam
, rotate
;
175 * The context stack is composed of a linked list of these.
180 struct hash_table localmac
;
185 * This is the internal form which we break input lines up into.
186 * Typically stored in linked lists.
188 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
189 * necessarily used as-is, but is intended to denote the number of
190 * the substituted parameter. So in the definition
192 * %define a(x,y) ( (x) & ~(y) )
194 * the token representing `x' will have its type changed to
195 * TOK_SMAC_PARAM, but the one representing `y' will be
198 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
199 * which doesn't need quotes around it. Used in the pre-include
200 * mechanism as an alternative to trying to find a sensible type of
201 * quote to use on the filename we were passed.
204 TOK_NONE
= 0, TOK_WHITESPACE
, TOK_COMMENT
, TOK_ID
,
205 TOK_PREPROC_ID
, TOK_STRING
,
206 TOK_NUMBER
, TOK_FLOAT
, TOK_SMAC_END
, TOK_OTHER
,
208 TOK_PREPROC_Q
, TOK_PREPROC_QQ
,
210 TOK_INDIRECT
, /* %[...] */
211 TOK_SMAC_PARAM
, /* MUST BE LAST IN THE LIST!!! */
212 TOK_MAX
= INT_MAX
/* Keep compiler from reducing the range */
215 #define PP_CONCAT_MASK(x) (1 << (x))
217 struct tokseq_match
{
226 SMacro
*mac
; /* associated macro for TOK_SMAC_END */
227 size_t len
; /* scratch length field */
228 } a
; /* Auxiliary data */
229 enum pp_token_type type
;
233 * Multi-line macro definitions are stored as a linked list of
234 * these, which is essentially a container to allow several linked
237 * Note that in this module, linked lists are treated as stacks
238 * wherever possible. For this reason, Lines are _pushed_ on to the
239 * `expansion' field in MMacro structures, so that the linked list,
240 * if walked, would give the macro lines in reverse order; this
241 * means that we can walk the list when expanding a macro, and thus
242 * push the lines on to the `expansion' field in _istk_ in reverse
243 * order (so that when popped back off they are in the right
244 * order). It may seem cockeyed, and it relies on my design having
245 * an even number of steps in, but it works...
247 * Some of these structures, rather than being actual lines, are
248 * markers delimiting the end of the expansion of a given macro.
249 * This is for use in the cycle-tracking and %rep-handling code.
250 * Such structures have `finishes' non-NULL, and `first' NULL. All
251 * others have `finishes' NULL, but `first' may still be NULL if
261 * To handle an arbitrary level of file inclusion, we maintain a
262 * stack (ie linked list) of these things.
271 MMacro
*mstk
; /* stack of active macros/reps */
275 * Include search path. This is simply a list of strings which get
276 * prepended, in turn, to the name of an include file, in an
277 * attempt to find the file if it's not in the current directory.
285 * Conditional assembly: we maintain a separate stack of these for
286 * each level of file inclusion. (The only reason we keep the
287 * stacks separate is to ensure that a stray `%endif' in a file
288 * included from within the true branch of a `%if' won't terminate
289 * it and cause confusion: instead, rightly, it'll cause an error.)
297 * These states are for use just after %if or %elif: IF_TRUE
298 * means the condition has evaluated to truth so we are
299 * currently emitting, whereas IF_FALSE means we are not
300 * currently emitting but will start doing so if a %else comes
301 * up. In these states, all directives are admissible: %elif,
302 * %else and %endif. (And of course %if.)
304 COND_IF_TRUE
, COND_IF_FALSE
,
306 * These states come up after a %else: ELSE_TRUE means we're
307 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
308 * any %elif or %else will cause an error.
310 COND_ELSE_TRUE
, COND_ELSE_FALSE
,
312 * These states mean that we're not emitting now, and also that
313 * nothing until %endif will be emitted at all. COND_DONE is
314 * used when we've had our moment of emission
315 * and have now started seeing %elifs. COND_NEVER is used when
316 * the condition construct in question is contained within a
317 * non-emitting branch of a larger condition construct,
318 * or if there is an error.
320 COND_DONE
, COND_NEVER
322 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
325 * These defines are used as the possible return values for do_directive
327 #define NO_DIRECTIVE_FOUND 0
328 #define DIRECTIVE_FOUND 1
331 * This define sets the upper limit for smacro and recursive mmacro
334 #define DEADMAN_LIMIT (1 << 20)
337 #define REP_LIMIT ((INT64_C(1) << 62))
340 * Condition codes. Note that we use c_ prefix not C_ because C_ is
341 * used in nasm.h for the "real" condition codes. At _this_ level,
342 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
343 * ones, so we need a different enum...
345 static const char * const conditions
[] = {
346 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
347 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
348 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
351 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
352 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
353 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_RCXZ
, c_S
, c_Z
,
356 static const enum pp_conds inverse_ccs
[] = {
357 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
358 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
,
359 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, -1, c_NS
, c_NZ
365 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
366 static int is_condition(enum preproc_token arg
)
368 return PP_IS_COND(arg
) || (arg
== PP_ELSE
) || (arg
== PP_ENDIF
);
371 /* For TASM compatibility we need to be able to recognise TASM compatible
372 * conditional compilation directives. Using the NASM pre-processor does
373 * not work, so we look for them specifically from the following list and
374 * then jam in the equivalent NASM directive into the input stream.
378 TM_ARG
, TM_ELIF
, TM_ELSE
, TM_ENDIF
, TM_IF
, TM_IFDEF
, TM_IFDIFI
,
379 TM_IFNDEF
, TM_INCLUDE
, TM_LOCAL
382 static const char * const tasm_directives
[] = {
383 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
384 "ifndef", "include", "local"
387 static int StackSize
= 4;
388 static char *StackPointer
= "ebp";
389 static int ArgOffset
= 8;
390 static int LocalOffset
= 0;
392 static Context
*cstk
;
393 static Include
*istk
;
394 static IncPath
*ipath
= NULL
;
396 static int pass
; /* HACK: pass 0 = generate dependencies only */
397 static StrList
**dephead
, **deptail
; /* Dependency list */
399 static uint64_t unique
; /* unique identifier numbers */
401 static Line
*predef
= NULL
;
402 static bool do_predef
;
404 static ListGen
*list
;
407 * The current set of multi-line macros we have defined.
409 static struct hash_table mmacros
;
412 * The current set of single-line macros we have defined.
414 static struct hash_table smacros
;
417 * The multi-line macro we are currently defining, or the %rep
418 * block we are currently reading, if any.
420 static MMacro
*defining
;
422 static uint64_t nested_mac_count
;
423 static uint64_t nested_rep_count
;
426 * The number of macro parameters to allocate space for at a time.
428 #define PARAM_DELTA 16
431 * The standard macro set: defined in macros.c in the array nasm_stdmac.
432 * This gives our position in the macro set, when we're processing it.
434 static macros_t
*stdmacpos
;
437 * The extra standard macros that come from the object format, if
440 static macros_t
*extrastdmac
= NULL
;
441 static bool any_extrastdmac
;
444 * Tokens are allocated in blocks to improve speed
446 #define TOKEN_BLOCKSIZE 4096
447 static Token
*freeTokens
= NULL
;
453 static Blocks blocks
= { NULL
, NULL
};
456 * Forward declarations.
458 static Token
*expand_mmac_params(Token
* tline
);
459 static Token
*expand_smacro(Token
* tline
);
460 static Token
*expand_id(Token
* tline
);
461 static Context
*get_ctx(const char *name
, const char **namep
,
463 static void make_tok_num(Token
* tok
, int64_t val
);
464 static void error(int severity
, const char *fmt
, ...);
465 static void error_precond(int severity
, const char *fmt
, ...);
466 static void *new_Block(size_t size
);
467 static void delete_Blocks(void);
468 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
469 const char *text
, int txtlen
);
470 static Token
*delete_Token(Token
* t
);
473 * Macros for safe checking of token pointers, avoid *(NULL)
475 #define tok_type_(x,t) ((x) && (x)->type == (t))
476 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
477 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
478 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
481 * nasm_unquote with error if the string contains NUL characters.
482 * If the string contains NUL characters, issue an error and return
483 * the C len, i.e. truncate at the NUL.
485 static size_t nasm_unquote_cstr(char *qstr
, enum preproc_token directive
)
487 size_t len
= nasm_unquote(qstr
, NULL
);
488 size_t clen
= strlen(qstr
);
491 error(ERR_NONFATAL
, "NUL character in `%s' directive",
492 pp_directives
[directive
]);
498 * In-place reverse a list of tokens.
500 static Token
*reverse_tokens(Token
*t
)
516 * Handle TASM specific directives, which do not contain a % in
517 * front of them. We do it here because I could not find any other
518 * place to do it for the moment, and it is a hack (ideally it would
519 * be nice to be able to use the NASM pre-processor to do it).
521 static char *check_tasm_directive(char *line
)
523 int32_t i
, j
, k
, m
, len
;
524 char *p
, *q
, *oldline
, oldchar
;
526 p
= nasm_skip_spaces(line
);
528 /* Binary search for the directive name */
530 j
= ARRAY_SIZE(tasm_directives
);
531 q
= nasm_skip_word(p
);
538 m
= nasm_stricmp(p
, tasm_directives
[k
]);
540 /* We have found a directive, so jam a % in front of it
541 * so that NASM will then recognise it as one if it's own.
546 line
= nasm_malloc(len
+ 2);
548 if (k
== TM_IFDIFI
) {
550 * NASM does not recognise IFDIFI, so we convert
551 * it to %if 0. This is not used in NASM
552 * compatible code, but does need to parse for the
553 * TASM macro package.
555 strcpy(line
+ 1, "if 0");
557 memcpy(line
+ 1, p
, len
+ 1);
572 * The pre-preprocessing stage... This function translates line
573 * number indications as they emerge from GNU cpp (`# lineno "file"
574 * flags') into NASM preprocessor line number indications (`%line
577 static char *prepreproc(char *line
)
580 char *fname
, *oldline
;
582 if (line
[0] == '#' && line
[1] == ' ') {
585 lineno
= atoi(fname
);
586 fname
+= strspn(fname
, "0123456789 ");
589 fnlen
= strcspn(fname
, "\"");
590 line
= nasm_malloc(20 + fnlen
);
591 snprintf(line
, 20 + fnlen
, "%%line %d %.*s", lineno
, fnlen
, fname
);
594 if (tasm_compatible_mode
)
595 return check_tasm_directive(line
);
600 * Free a linked list of tokens.
602 static void free_tlist(Token
* list
)
605 list
= delete_Token(list
);
609 * Free a linked list of lines.
611 static void free_llist(Line
* list
)
614 list_for_each_safe(l
, tmp
, list
) {
615 free_tlist(l
->first
);
623 static void free_mmacro(MMacro
* m
)
626 free_tlist(m
->dlist
);
627 nasm_free(m
->defaults
);
628 free_llist(m
->expansion
);
633 * Free all currently defined macros, and free the hash tables
635 static void free_smacro_table(struct hash_table
*smt
)
639 struct hash_tbl_node
*it
= NULL
;
641 while ((s
= hash_iterate(smt
, &it
, &key
)) != NULL
) {
642 nasm_free((void *)key
);
643 list_for_each_safe(s
, tmp
, s
) {
645 free_tlist(s
->expansion
);
652 static void free_mmacro_table(struct hash_table
*mmt
)
656 struct hash_tbl_node
*it
= NULL
;
659 while ((m
= hash_iterate(mmt
, &it
, &key
)) != NULL
) {
660 nasm_free((void *)key
);
661 list_for_each_safe(m
,tmp
, m
)
667 static void free_macros(void)
669 free_smacro_table(&smacros
);
670 free_mmacro_table(&mmacros
);
674 * Initialize the hash tables
676 static void init_macros(void)
678 hash_init(&smacros
, HASH_LARGE
);
679 hash_init(&mmacros
, HASH_LARGE
);
683 * Pop the context stack.
685 static void ctx_pop(void)
690 free_smacro_table(&c
->localmac
);
696 * Search for a key in the hash index; adding it if necessary
697 * (in which case we initialize the data pointer to NULL.)
700 hash_findi_add(struct hash_table
*hash
, const char *str
)
702 struct hash_insert hi
;
706 r
= hash_findi(hash
, str
, &hi
);
710 strx
= nasm_strdup(str
); /* Use a more efficient allocator here? */
711 return hash_add(&hi
, strx
, NULL
);
715 * Like hash_findi, but returns the data element rather than a pointer
716 * to it. Used only when not adding a new element, hence no third
720 hash_findix(struct hash_table
*hash
, const char *str
)
724 p
= hash_findi(hash
, str
, NULL
);
725 return p
? *p
: NULL
;
729 * read line from standart macros set,
730 * if there no more left -- return NULL
732 static char *line_from_stdmac(void)
735 const unsigned char *p
= stdmacpos
;
744 len
+= pp_directives_len
[c
- 0x80] + 1;
749 line
= nasm_malloc(len
+ 1);
751 while ((c
= *stdmacpos
++)) {
753 memcpy(q
, pp_directives
[c
- 0x80], pp_directives_len
[c
- 0x80]);
754 q
+= pp_directives_len
[c
- 0x80];
764 /* This was the last of the standard macro chain... */
766 if (any_extrastdmac
) {
767 stdmacpos
= extrastdmac
;
768 any_extrastdmac
= false;
769 } else if (do_predef
) {
771 Token
*head
, **tail
, *t
;
774 * Nasty hack: here we push the contents of
775 * `predef' on to the top-level expansion stack,
776 * since this is the most convenient way to
777 * implement the pre-include and pre-define
780 list_for_each(pd
, predef
) {
783 list_for_each(t
, pd
->first
) {
784 *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
785 tail
= &(*tail
)->next
;
788 l
= nasm_malloc(sizeof(Line
));
789 l
->next
= istk
->expansion
;
802 #define BUF_DELTA 512
804 * Read a line from the top file in istk, handling multiple CR/LFs
805 * at the end of the line read, and handling spurious ^Zs. Will
806 * return lines from the standard macro set if this has not already
809 static char *read_line(void)
811 char *buffer
, *p
, *q
;
812 int bufsize
, continued_count
;
815 * standart macros set (predefined) goes first
817 p
= line_from_stdmac();
822 * regular read from a file
825 buffer
= nasm_malloc(BUF_DELTA
);
829 q
= fgets(p
, bufsize
- (p
- buffer
), istk
->fp
);
833 if (p
> buffer
&& p
[-1] == '\n') {
835 * Convert backslash-CRLF line continuation sequences into
836 * nothing at all (for DOS and Windows)
838 if (((p
- 2) > buffer
) && (p
[-3] == '\\') && (p
[-2] == '\r')) {
844 * Also convert backslash-LF line continuation sequences into
845 * nothing at all (for Unix)
847 else if (((p
- 1) > buffer
) && (p
[-2] == '\\')) {
855 if (p
- buffer
> bufsize
- 10) {
856 int32_t offset
= p
- buffer
;
857 bufsize
+= BUF_DELTA
;
858 buffer
= nasm_realloc(buffer
, bufsize
);
859 p
= buffer
+ offset
; /* prevent stale-pointer problems */
863 if (!q
&& p
== buffer
) {
868 src_set_linnum(src_get_linnum() + istk
->lineinc
+
869 (continued_count
* istk
->lineinc
));
872 * Play safe: remove CRs as well as LFs, if any of either are
873 * present at the end of the line.
875 while (--p
>= buffer
&& (*p
== '\n' || *p
== '\r'))
879 * Handle spurious ^Z, which may be inserted into source files
880 * by some file transfer utilities.
882 buffer
[strcspn(buffer
, "\032")] = '\0';
884 list
->line(LIST_READ
, buffer
);
890 * Tokenize a line of text. This is a very simple process since we
891 * don't need to parse the value out of e.g. numeric tokens: we
892 * simply split one string into many.
894 static Token
*tokenize(char *line
)
897 enum pp_token_type type
;
899 Token
*t
, **tail
= &list
;
905 if (*p
== '+' && !nasm_isdigit(p
[1])) {
908 } else if (nasm_isdigit(*p
) ||
909 ((*p
== '-' || *p
== '+') && nasm_isdigit(p
[1]))) {
913 while (nasm_isdigit(*p
));
914 type
= TOK_PREPROC_ID
;
915 } else if (*p
== '{') {
924 error(ERR_WARNING
| ERR_PASS1
, "unterminated %{ construct");
928 type
= TOK_PREPROC_ID
;
929 } else if (*p
== '[') {
931 line
+= 2; /* Skip the leading %[ */
933 while (lvl
&& (c
= *p
++)) {
945 p
= nasm_skip_string(p
- 1) + 1;
955 error(ERR_NONFATAL
, "unterminated %[ construct");
957 } else if (*p
== '?') {
958 type
= TOK_PREPROC_Q
; /* %? */
961 type
= TOK_PREPROC_QQ
; /* %?? */
964 } else if (*p
== '!') {
965 type
= TOK_PREPROC_ID
;
970 } while (isidchar(*p
));
971 } else if (*p
== '\'' || *p
== '\"' || *p
== '`') {
972 p
= nasm_skip_string(p
);
976 error(ERR_NONFATAL
|ERR_PASS1
, "unterminated %! string");
978 /* %! without string or identifier */
979 type
= TOK_OTHER
; /* Legacy behavior... */
981 } else if (isidchar(*p
) ||
982 ((*p
== '!' || *p
== '%' || *p
== '$') &&
987 while (isidchar(*p
));
988 type
= TOK_PREPROC_ID
;
994 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
997 while (*p
&& isidchar(*p
))
999 } else if (*p
== '\'' || *p
== '"' || *p
== '`') {
1004 p
= nasm_skip_string(p
);
1009 error(ERR_WARNING
|ERR_PASS1
, "unterminated string");
1010 /* Handling unterminated strings by UNV */
1013 } else if (p
[0] == '$' && p
[1] == '$') {
1014 type
= TOK_OTHER
; /* TOKEN_BASE */
1016 } else if (isnumstart(*p
)) {
1017 bool is_hex
= false;
1018 bool is_float
= false;
1034 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
1036 if (*p
== '+' || *p
== '-') {
1038 * e can only be followed by +/- if it is either a
1039 * prefixed hex number or a floating-point number
1044 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
1046 } else if (c
== 'P' || c
== 'p') {
1048 if (*p
== '+' || *p
== '-')
1050 } else if (isnumchar(c
) || c
== '_')
1051 ; /* just advance */
1052 else if (c
== '.') {
1054 * we need to deal with consequences of the legacy
1055 * parser, like "1.nolist" being two tokens
1056 * (TOK_NUMBER, TOK_ID) here; at least give it
1057 * a shot for now. In the future, we probably need
1058 * a flex-based scanner with proper pattern matching
1059 * to do it as well as it can be done. Nothing in
1060 * the world is going to help the person who wants
1061 * 0x123.p16 interpreted as two tokens, though.
1067 if (nasm_isdigit(*r
) || (is_hex
&& nasm_isxdigit(*r
)) ||
1068 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
1069 (*r
== 'p' || *r
== 'P')) {
1073 break; /* Terminate the token */
1077 p
--; /* Point to first character beyond number */
1079 if (p
== line
+1 && *line
== '$') {
1080 type
= TOK_OTHER
; /* TOKEN_HERE */
1082 if (has_e
&& !is_hex
) {
1083 /* 1e13 is floating-point, but 1e13h is not */
1087 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
1089 } else if (nasm_isspace(*p
)) {
1090 type
= TOK_WHITESPACE
;
1091 p
= nasm_skip_spaces(p
);
1093 * Whitespace just before end-of-line is discarded by
1094 * pretending it's a comment; whitespace just before a
1095 * comment gets lumped into the comment.
1097 if (!*p
|| *p
== ';') {
1102 } else if (*p
== ';') {
1108 * Anything else is an operator of some kind. We check
1109 * for all the double-character operators (>>, <<, //,
1110 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1111 * else is a single-character operator.
1114 if ((p
[0] == '>' && p
[1] == '>') ||
1115 (p
[0] == '<' && p
[1] == '<') ||
1116 (p
[0] == '/' && p
[1] == '/') ||
1117 (p
[0] == '<' && p
[1] == '=') ||
1118 (p
[0] == '>' && p
[1] == '=') ||
1119 (p
[0] == '=' && p
[1] == '=') ||
1120 (p
[0] == '!' && p
[1] == '=') ||
1121 (p
[0] == '<' && p
[1] == '>') ||
1122 (p
[0] == '&' && p
[1] == '&') ||
1123 (p
[0] == '|' && p
[1] == '|') ||
1124 (p
[0] == '^' && p
[1] == '^')) {
1130 /* Handling unterminated string by UNV */
1133 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1134 t->text[p-line] = *line;
1138 if (type
!= TOK_COMMENT
) {
1139 *tail
= t
= new_Token(NULL
, type
, line
, p
- line
);
1148 * this function allocates a new managed block of memory and
1149 * returns a pointer to the block. The managed blocks are
1150 * deleted only all at once by the delete_Blocks function.
1152 static void *new_Block(size_t size
)
1154 Blocks
*b
= &blocks
;
1156 /* first, get to the end of the linked list */
1159 /* now allocate the requested chunk */
1160 b
->chunk
= nasm_malloc(size
);
1162 /* now allocate a new block for the next request */
1163 b
->next
= nasm_malloc(sizeof(Blocks
));
1164 /* and initialize the contents of the new block */
1165 b
->next
->next
= NULL
;
1166 b
->next
->chunk
= NULL
;
1171 * this function deletes all managed blocks of memory
1173 static void delete_Blocks(void)
1175 Blocks
*a
, *b
= &blocks
;
1178 * keep in mind that the first block, pointed to by blocks
1179 * is a static and not dynamically allocated, so we don't
1184 nasm_free(b
->chunk
);
1193 * this function creates a new Token and passes a pointer to it
1194 * back to the caller. It sets the type and text elements, and
1195 * also the a.mac and next elements to NULL.
1197 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
1198 const char *text
, int txtlen
)
1204 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1205 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1206 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1207 freeTokens
[i
].next
= NULL
;
1210 freeTokens
= t
->next
;
1214 if (type
== TOK_WHITESPACE
|| !text
) {
1218 txtlen
= strlen(text
);
1219 t
->text
= nasm_malloc(txtlen
+1);
1220 memcpy(t
->text
, text
, txtlen
);
1221 t
->text
[txtlen
] = '\0';
1226 static Token
*delete_Token(Token
* t
)
1228 Token
*next
= t
->next
;
1230 t
->next
= freeTokens
;
1236 * Convert a line of tokens back into text.
1237 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1238 * will be transformed into ..@ctxnum.xxx
1240 static char *detoken(Token
* tlist
, bool expand_locals
)
1247 list_for_each(t
, tlist
) {
1248 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
1253 if (*v
== '\'' || *v
== '\"' || *v
== '`') {
1254 size_t len
= nasm_unquote(v
, NULL
);
1255 size_t clen
= strlen(v
);
1258 error(ERR_NONFATAL
| ERR_PASS1
,
1259 "NUL character in %! string");
1265 char *p
= getenv(v
);
1267 error(ERR_NONFATAL
| ERR_PASS1
,
1268 "nonexistent environment variable `%s'", v
);
1271 t
->text
= nasm_strdup(p
);
1276 /* Expand local macros here and not during preprocessing */
1277 if (expand_locals
&&
1278 t
->type
== TOK_PREPROC_ID
&& t
->text
&&
1279 t
->text
[0] == '%' && t
->text
[1] == '$') {
1282 Context
*ctx
= get_ctx(t
->text
, &q
, false);
1285 snprintf(buffer
, sizeof(buffer
), "..@%"PRIu32
".", ctx
->number
);
1286 p
= nasm_strcat(buffer
, q
);
1291 if (t
->type
== TOK_WHITESPACE
)
1294 len
+= strlen(t
->text
);
1297 p
= line
= nasm_malloc(len
+ 1);
1299 list_for_each(t
, tlist
) {
1300 if (t
->type
== TOK_WHITESPACE
) {
1302 } else if (t
->text
) {
1314 * A scanner, suitable for use by the expression evaluator, which
1315 * operates on a line of Tokens. Expects a pointer to a pointer to
1316 * the first token in the line to be passed in as its private_data
1319 * FIX: This really needs to be unified with stdscan.
1321 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1323 Token
**tlineptr
= private_data
;
1325 char ourcopy
[MAX_KEYWORD
+1], *p
, *r
, *s
;
1329 *tlineptr
= tline
? tline
->next
: NULL
;
1330 } while (tline
&& (tline
->type
== TOK_WHITESPACE
||
1331 tline
->type
== TOK_COMMENT
));
1334 return tokval
->t_type
= TOKEN_EOS
;
1336 tokval
->t_charptr
= tline
->text
;
1338 if (tline
->text
[0] == '$' && !tline
->text
[1])
1339 return tokval
->t_type
= TOKEN_HERE
;
1340 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[2])
1341 return tokval
->t_type
= TOKEN_BASE
;
1343 if (tline
->type
== TOK_ID
) {
1344 p
= tokval
->t_charptr
= tline
->text
;
1346 tokval
->t_charptr
++;
1347 return tokval
->t_type
= TOKEN_ID
;
1350 for (r
= p
, s
= ourcopy
; *r
; r
++) {
1351 if (r
>= p
+MAX_KEYWORD
)
1352 return tokval
->t_type
= TOKEN_ID
; /* Not a keyword */
1353 *s
++ = nasm_tolower(*r
);
1356 /* right, so we have an identifier sitting in temp storage. now,
1357 * is it actually a register or instruction name, or what? */
1358 return nasm_token_hash(ourcopy
, tokval
);
1361 if (tline
->type
== TOK_NUMBER
) {
1363 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
1364 tokval
->t_charptr
= tline
->text
;
1366 return tokval
->t_type
= TOKEN_ERRNUM
;
1368 return tokval
->t_type
= TOKEN_NUM
;
1371 if (tline
->type
== TOK_FLOAT
) {
1372 return tokval
->t_type
= TOKEN_FLOAT
;
1375 if (tline
->type
== TOK_STRING
) {
1378 bq
= tline
->text
[0];
1379 tokval
->t_charptr
= tline
->text
;
1380 tokval
->t_inttwo
= nasm_unquote(tline
->text
, &ep
);
1382 if (ep
[0] != bq
|| ep
[1] != '\0')
1383 return tokval
->t_type
= TOKEN_ERRSTR
;
1385 return tokval
->t_type
= TOKEN_STR
;
1388 if (tline
->type
== TOK_OTHER
) {
1389 if (!strcmp(tline
->text
, "<<"))
1390 return tokval
->t_type
= TOKEN_SHL
;
1391 if (!strcmp(tline
->text
, ">>"))
1392 return tokval
->t_type
= TOKEN_SHR
;
1393 if (!strcmp(tline
->text
, "//"))
1394 return tokval
->t_type
= TOKEN_SDIV
;
1395 if (!strcmp(tline
->text
, "%%"))
1396 return tokval
->t_type
= TOKEN_SMOD
;
1397 if (!strcmp(tline
->text
, "=="))
1398 return tokval
->t_type
= TOKEN_EQ
;
1399 if (!strcmp(tline
->text
, "<>"))
1400 return tokval
->t_type
= TOKEN_NE
;
1401 if (!strcmp(tline
->text
, "!="))
1402 return tokval
->t_type
= TOKEN_NE
;
1403 if (!strcmp(tline
->text
, "<="))
1404 return tokval
->t_type
= TOKEN_LE
;
1405 if (!strcmp(tline
->text
, ">="))
1406 return tokval
->t_type
= TOKEN_GE
;
1407 if (!strcmp(tline
->text
, "&&"))
1408 return tokval
->t_type
= TOKEN_DBL_AND
;
1409 if (!strcmp(tline
->text
, "^^"))
1410 return tokval
->t_type
= TOKEN_DBL_XOR
;
1411 if (!strcmp(tline
->text
, "||"))
1412 return tokval
->t_type
= TOKEN_DBL_OR
;
1416 * We have no other options: just return the first character of
1419 return tokval
->t_type
= tline
->text
[0];
1423 * Compare a string to the name of an existing macro; this is a
1424 * simple wrapper which calls either strcmp or nasm_stricmp
1425 * depending on the value of the `casesense' parameter.
1427 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
1429 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
1433 * Compare a string to the name of an existing macro; this is a
1434 * simple wrapper which calls either strcmp or nasm_stricmp
1435 * depending on the value of the `casesense' parameter.
1437 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
1439 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
1443 * Return the Context structure associated with a %$ token. Return
1444 * NULL, having _already_ reported an error condition, if the
1445 * context stack isn't deep enough for the supplied number of $
1447 * If all_contexts == true, contexts that enclose current are
1448 * also scanned for such smacro, until it is found; if not -
1449 * only the context that directly results from the number of $'s
1450 * in variable's name.
1452 * If "namep" is non-NULL, set it to the pointer to the macro name
1453 * tail, i.e. the part beyond %$...
1455 static Context
*get_ctx(const char *name
, const char **namep
,
1465 if (!name
|| name
[0] != '%' || name
[1] != '$')
1469 error(ERR_NONFATAL
, "`%s': context stack is empty", name
);
1476 while (ctx
&& *name
== '$') {
1482 error(ERR_NONFATAL
, "`%s': context stack is only"
1483 " %d level%s deep", name
, i
, (i
== 1 ? "" : "s"));
1494 * NOTE: In 2.10 we will not need lookup in extarnal
1495 * contexts, so this is a gentle way to inform users
1496 * about their source code need to be updated
1499 /* first round -- check the current context */
1500 m
= hash_findix(&ctx
->localmac
, name
);
1502 if (!mstrcmp(m
->name
, name
, m
->casesense
))
1507 /* second round - external contexts */
1508 while ((ctx
= ctx
->next
)) {
1509 /* Search for this smacro in found context */
1510 m
= hash_findix(&ctx
->localmac
, name
);
1512 if (!mstrcmp(m
->name
, name
, m
->casesense
)) {
1513 /* NOTE: deprecated as of 2.10 */
1514 static int once
= 0;
1516 error(ERR_WARNING
, "context-local macro expansion"
1517 " fall-through (automatic searching of outer"
1518 " contexts) will be deprecated starting in"
1519 " NASM 2.10, please see the NASM Manual for"
1520 " more information");
1523 error(ERR_WARNING
, "`%s': context-local macro expansion fall-through", name
);
1534 * Check to see if a file is already in a string list
1536 static bool in_list(const StrList
*list
, const char *str
)
1539 if (!strcmp(list
->str
, str
))
1547 * Open an include file. This routine must always return a valid
1548 * file pointer if it returns - it's responsible for throwing an
1549 * ERR_FATAL and bombing out completely if not. It should also try
1550 * the include path one by one until it finds the file or reaches
1551 * the end of the path.
1553 static FILE *inc_fopen(const char *file
, StrList
**dhead
, StrList
***dtail
,
1558 IncPath
*ip
= ipath
;
1559 int len
= strlen(file
);
1560 size_t prefix_len
= 0;
1564 sl
= nasm_malloc(prefix_len
+len
+1+sizeof sl
->next
);
1565 memcpy(sl
->str
, prefix
, prefix_len
);
1566 memcpy(sl
->str
+prefix_len
, file
, len
+1);
1567 fp
= fopen(sl
->str
, "r");
1568 if (fp
&& dhead
&& !in_list(*dhead
, sl
->str
)) {
1586 prefix_len
= strlen(prefix
);
1588 /* -MG given and file not found */
1589 if (dhead
&& !in_list(*dhead
, file
)) {
1590 sl
= nasm_malloc(len
+1+sizeof sl
->next
);
1592 strcpy(sl
->str
, file
);
1600 error(ERR_FATAL
, "unable to open include file `%s'", file
);
1605 * Determine if we should warn on defining a single-line macro of
1606 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1607 * return true if _any_ single-line macro of that name is defined.
1608 * Otherwise, will return true if a single-line macro with either
1609 * `nparam' or no parameters is defined.
1611 * If a macro with precisely the right number of parameters is
1612 * defined, or nparam is -1, the address of the definition structure
1613 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1614 * is NULL, no action will be taken regarding its contents, and no
1617 * Note that this is also called with nparam zero to resolve
1620 * If you already know which context macro belongs to, you can pass
1621 * the context pointer as first parameter; if you won't but name begins
1622 * with %$ the context will be automatically computed. If all_contexts
1623 * is true, macro will be searched in outer contexts as well.
1626 smacro_defined(Context
* ctx
, const char *name
, int nparam
, SMacro
** defn
,
1629 struct hash_table
*smtbl
;
1633 smtbl
= &ctx
->localmac
;
1634 } else if (name
[0] == '%' && name
[1] == '$') {
1636 ctx
= get_ctx(name
, &name
, false);
1638 return false; /* got to return _something_ */
1639 smtbl
= &ctx
->localmac
;
1643 m
= (SMacro
*) hash_findix(smtbl
, name
);
1646 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
1647 (nparam
<= 0 || m
->nparam
== 0 || nparam
== (int) m
->nparam
)) {
1649 if (nparam
== (int) m
->nparam
|| nparam
== -1)
1663 * Count and mark off the parameters in a multi-line macro call.
1664 * This is called both from within the multi-line macro expansion
1665 * code, and also to mark off the default parameters when provided
1666 * in a %macro definition line.
1668 static void count_mmac_params(Token
* t
, int *nparam
, Token
*** params
)
1670 int paramsize
, brace
;
1672 *nparam
= paramsize
= 0;
1675 /* +1: we need space for the final NULL */
1676 if (*nparam
+1 >= paramsize
) {
1677 paramsize
+= PARAM_DELTA
;
1678 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
1682 if (tok_is_(t
, "{"))
1684 (*params
)[(*nparam
)++] = t
;
1685 while (tok_isnt_(t
, brace
? "}" : ","))
1687 if (t
) { /* got a comma/brace */
1691 * Now we've found the closing brace, look further
1695 if (tok_isnt_(t
, ",")) {
1697 "braces do not enclose all of macro parameter");
1698 while (tok_isnt_(t
, ","))
1702 t
= t
->next
; /* eat the comma */
1709 * Determine whether one of the various `if' conditions is true or
1712 * We must free the tline we get passed.
1714 static bool if_condition(Token
* tline
, enum preproc_token ct
)
1716 enum pp_conditional i
= PP_COND(ct
);
1718 Token
*t
, *tt
, **tptr
, *origline
;
1719 struct tokenval tokval
;
1721 enum pp_token_type needtype
;
1728 j
= false; /* have we matched yet? */
1733 if (tline
->type
!= TOK_ID
) {
1735 "`%s' expects context identifiers", pp_directives
[ct
]);
1736 free_tlist(origline
);
1739 if (cstk
&& cstk
->name
&& !nasm_stricmp(tline
->text
, cstk
->name
))
1741 tline
= tline
->next
;
1746 j
= false; /* have we matched yet? */
1749 if (!tline
|| (tline
->type
!= TOK_ID
&&
1750 (tline
->type
!= TOK_PREPROC_ID
||
1751 tline
->text
[1] != '$'))) {
1753 "`%s' expects macro identifiers", pp_directives
[ct
]);
1756 if (smacro_defined(NULL
, tline
->text
, 0, NULL
, true))
1758 tline
= tline
->next
;
1763 tline
= expand_smacro(tline
);
1764 j
= false; /* have we matched yet? */
1767 if (!tline
|| (tline
->type
!= TOK_ID
&&
1768 tline
->type
!= TOK_STRING
&&
1769 (tline
->type
!= TOK_PREPROC_ID
||
1770 tline
->text
[1] != '!'))) {
1772 "`%s' expects environment variable names",
1777 if (tline
->type
== TOK_PREPROC_ID
)
1778 p
+= 2; /* Skip leading %! */
1779 if (*p
== '\'' || *p
== '\"' || *p
== '`')
1780 nasm_unquote_cstr(p
, ct
);
1783 tline
= tline
->next
;
1789 tline
= expand_smacro(tline
);
1791 while (tok_isnt_(tt
, ","))
1795 "`%s' expects two comma-separated arguments",
1800 j
= true; /* assume equality unless proved not */
1801 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1802 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1803 error(ERR_NONFATAL
, "`%s': more than one comma on line",
1807 if (t
->type
== TOK_WHITESPACE
) {
1811 if (tt
->type
== TOK_WHITESPACE
) {
1815 if (tt
->type
!= t
->type
) {
1816 j
= false; /* found mismatching tokens */
1819 /* When comparing strings, need to unquote them first */
1820 if (t
->type
== TOK_STRING
) {
1821 size_t l1
= nasm_unquote(t
->text
, NULL
);
1822 size_t l2
= nasm_unquote(tt
->text
, NULL
);
1828 if (mmemcmp(t
->text
, tt
->text
, l1
, i
== PPC_IFIDN
)) {
1832 } else if (mstrcmp(tt
->text
, t
->text
, i
== PPC_IFIDN
) != 0) {
1833 j
= false; /* found mismatching tokens */
1840 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
1841 j
= false; /* trailing gunk on one end or other */
1847 MMacro searching
, *mmac
;
1850 tline
= expand_id(tline
);
1851 if (!tok_type_(tline
, TOK_ID
)) {
1853 "`%s' expects a macro name", pp_directives
[ct
]);
1856 searching
.name
= nasm_strdup(tline
->text
);
1857 searching
.casesense
= true;
1858 searching
.plus
= false;
1859 searching
.nolist
= false;
1860 searching
.in_progress
= 0;
1861 searching
.max_depth
= 0;
1862 searching
.rep_nest
= NULL
;
1863 searching
.nparam_min
= 0;
1864 searching
.nparam_max
= INT_MAX
;
1865 tline
= expand_smacro(tline
->next
);
1868 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
1870 "`%s' expects a parameter count or nothing",
1873 searching
.nparam_min
= searching
.nparam_max
=
1874 readnum(tline
->text
, &j
);
1877 "unable to parse parameter count `%s'",
1880 if (tline
&& tok_is_(tline
->next
, "-")) {
1881 tline
= tline
->next
->next
;
1882 if (tok_is_(tline
, "*"))
1883 searching
.nparam_max
= INT_MAX
;
1884 else if (!tok_type_(tline
, TOK_NUMBER
))
1886 "`%s' expects a parameter count after `-'",
1889 searching
.nparam_max
= readnum(tline
->text
, &j
);
1892 "unable to parse parameter count `%s'",
1894 if (searching
.nparam_min
> searching
.nparam_max
)
1896 "minimum parameter count exceeds maximum");
1899 if (tline
&& tok_is_(tline
->next
, "+")) {
1900 tline
= tline
->next
;
1901 searching
.plus
= true;
1903 mmac
= (MMacro
*) hash_findix(&mmacros
, searching
.name
);
1905 if (!strcmp(mmac
->name
, searching
.name
) &&
1906 (mmac
->nparam_min
<= searching
.nparam_max
1908 && (searching
.nparam_min
<= mmac
->nparam_max
1915 if (tline
&& tline
->next
)
1916 error(ERR_WARNING
|ERR_PASS1
,
1917 "trailing garbage after %%ifmacro ignored");
1918 nasm_free(searching
.name
);
1927 needtype
= TOK_NUMBER
;
1930 needtype
= TOK_STRING
;
1934 t
= tline
= expand_smacro(tline
);
1936 while (tok_type_(t
, TOK_WHITESPACE
) ||
1937 (needtype
== TOK_NUMBER
&&
1938 tok_type_(t
, TOK_OTHER
) &&
1939 (t
->text
[0] == '-' || t
->text
[0] == '+') &&
1943 j
= tok_type_(t
, needtype
);
1947 t
= tline
= expand_smacro(tline
);
1948 while (tok_type_(t
, TOK_WHITESPACE
))
1953 t
= t
->next
; /* Skip the actual token */
1954 while (tok_type_(t
, TOK_WHITESPACE
))
1956 j
= !t
; /* Should be nothing left */
1961 t
= tline
= expand_smacro(tline
);
1962 while (tok_type_(t
, TOK_WHITESPACE
))
1965 j
= !t
; /* Should be empty */
1969 t
= tline
= expand_smacro(tline
);
1971 tokval
.t_type
= TOKEN_INVALID
;
1972 evalresult
= evaluate(ppscan
, tptr
, &tokval
,
1973 NULL
, pass
| CRITICAL
, error
, NULL
);
1977 error(ERR_WARNING
|ERR_PASS1
,
1978 "trailing garbage after expression ignored");
1979 if (!is_simple(evalresult
)) {
1981 "non-constant value given to `%s'", pp_directives
[ct
]);
1984 j
= reloc_value(evalresult
) != 0;
1989 "preprocessor directive `%s' not yet implemented",
1994 free_tlist(origline
);
1995 return j
^ PP_NEGATIVE(ct
);
1998 free_tlist(origline
);
2003 * Common code for defining an smacro
2005 static bool define_smacro(Context
*ctx
, const char *mname
, bool casesense
,
2006 int nparam
, Token
*expansion
)
2008 SMacro
*smac
, **smhead
;
2009 struct hash_table
*smtbl
;
2011 if (smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
)) {
2013 error(ERR_WARNING
|ERR_PASS1
,
2014 "single-line macro `%s' defined both with and"
2015 " without parameters", mname
);
2017 * Some instances of the old code considered this a failure,
2018 * some others didn't. What is the right thing to do here?
2020 free_tlist(expansion
);
2021 return false; /* Failure */
2024 * We're redefining, so we have to take over an
2025 * existing SMacro structure. This means freeing
2026 * what was already in it.
2028 nasm_free(smac
->name
);
2029 free_tlist(smac
->expansion
);
2032 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2033 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
2034 smac
= nasm_malloc(sizeof(SMacro
));
2035 smac
->next
= *smhead
;
2038 smac
->name
= nasm_strdup(mname
);
2039 smac
->casesense
= casesense
;
2040 smac
->nparam
= nparam
;
2041 smac
->expansion
= expansion
;
2042 smac
->in_progress
= false;
2043 return true; /* Success */
2047 * Undefine an smacro
2049 static void undef_smacro(Context
*ctx
, const char *mname
)
2051 SMacro
**smhead
, *s
, **sp
;
2052 struct hash_table
*smtbl
;
2054 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2055 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
2059 * We now have a macro name... go hunt for it.
2062 while ((s
= *sp
) != NULL
) {
2063 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
2066 free_tlist(s
->expansion
);
2076 * Parse a mmacro specification.
2078 static bool parse_mmacro_spec(Token
*tline
, MMacro
*def
, const char *directive
)
2082 tline
= tline
->next
;
2084 tline
= expand_id(tline
);
2085 if (!tok_type_(tline
, TOK_ID
)) {
2086 error(ERR_NONFATAL
, "`%s' expects a macro name", directive
);
2091 def
->name
= nasm_strdup(tline
->text
);
2093 def
->nolist
= false;
2094 def
->in_progress
= 0;
2095 def
->rep_nest
= NULL
;
2096 def
->nparam_min
= 0;
2097 def
->nparam_max
= 0;
2099 tline
= expand_smacro(tline
->next
);
2101 if (!tok_type_(tline
, TOK_NUMBER
)) {
2102 error(ERR_NONFATAL
, "`%s' expects a parameter count", directive
);
2104 def
->nparam_min
= def
->nparam_max
=
2105 readnum(tline
->text
, &err
);
2108 "unable to parse parameter count `%s'", tline
->text
);
2110 if (tline
&& tok_is_(tline
->next
, "-")) {
2111 tline
= tline
->next
->next
;
2112 if (tok_is_(tline
, "*")) {
2113 def
->nparam_max
= INT_MAX
;
2114 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2116 "`%s' expects a parameter count after `-'", directive
);
2118 def
->nparam_max
= readnum(tline
->text
, &err
);
2120 error(ERR_NONFATAL
, "unable to parse parameter count `%s'",
2123 if (def
->nparam_min
> def
->nparam_max
) {
2124 error(ERR_NONFATAL
, "minimum parameter count exceeds maximum");
2128 if (tline
&& tok_is_(tline
->next
, "+")) {
2129 tline
= tline
->next
;
2132 if (tline
&& tok_type_(tline
->next
, TOK_ID
) &&
2133 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
2134 tline
= tline
->next
;
2139 * Handle default parameters.
2141 if (tline
&& tline
->next
) {
2142 def
->dlist
= tline
->next
;
2144 count_mmac_params(def
->dlist
, &def
->ndefs
, &def
->defaults
);
2147 def
->defaults
= NULL
;
2149 def
->expansion
= NULL
;
2151 if (def
->defaults
&& def
->ndefs
> def
->nparam_max
- def
->nparam_min
&&
2153 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MDP
,
2154 "too many default macro parameters");
2161 * Decode a size directive
2163 static int parse_size(const char *str
) {
2164 static const char *size_names
[] =
2165 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2166 static const int sizes
[] =
2167 { 0, 1, 4, 16, 8, 10, 2, 32 };
2169 return sizes
[bsii(str
, size_names
, ARRAY_SIZE(size_names
))+1];
2173 * find and process preprocessor directive in passed line
2174 * Find out if a line contains a preprocessor directive, and deal
2177 * If a directive _is_ found, it is the responsibility of this routine
2178 * (and not the caller) to free_tlist() the line.
2180 * @param tline a pointer to the current tokeninzed line linked list
2181 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2184 static int do_directive(Token
* tline
)
2186 enum preproc_token i
;
2199 MMacro
*mmac
, **mmhead
;
2200 Token
*t
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
2202 struct tokenval tokval
;
2204 MMacro
*tmp_defining
; /* Used when manipulating rep_nest */
2212 if (!tline
|| !tok_type_(tline
, TOK_PREPROC_ID
) ||
2213 (tline
->text
[1] == '%' || tline
->text
[1] == '$'
2214 || tline
->text
[1] == '!'))
2215 return NO_DIRECTIVE_FOUND
;
2217 i
= pp_token_hash(tline
->text
);
2220 * FIXME: We zap execution of PP_RMACRO, PP_IRMACRO, PP_EXITMACRO
2221 * since they are known to be buggy at moment, we need to fix them
2222 * in future release (2.09-2.10)
2224 if (i
== PP_RMACRO
|| i
== PP_RMACRO
|| i
== PP_EXITMACRO
) {
2225 error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2227 return NO_DIRECTIVE_FOUND
;
2231 * If we're in a non-emitting branch of a condition construct,
2232 * or walking to the end of an already terminated %rep block,
2233 * we should ignore all directives except for condition
2236 if (((istk
->conds
&& !emitting(istk
->conds
->state
)) ||
2237 (istk
->mstk
&& !istk
->mstk
->in_progress
)) && !is_condition(i
)) {
2238 return NO_DIRECTIVE_FOUND
;
2242 * If we're defining a macro or reading a %rep block, we should
2243 * ignore all directives except for %macro/%imacro (which nest),
2244 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2245 * If we're in a %rep block, another %rep nests, so should be let through.
2247 if (defining
&& i
!= PP_MACRO
&& i
!= PP_IMACRO
&&
2248 i
!= PP_RMACRO
&& i
!= PP_IRMACRO
&&
2249 i
!= PP_ENDMACRO
&& i
!= PP_ENDM
&&
2250 (defining
->name
|| (i
!= PP_ENDREP
&& i
!= PP_REP
))) {
2251 return NO_DIRECTIVE_FOUND
;
2255 if (i
== PP_MACRO
|| i
== PP_IMACRO
||
2256 i
== PP_RMACRO
|| i
== PP_IRMACRO
) {
2258 return NO_DIRECTIVE_FOUND
;
2259 } else if (nested_mac_count
> 0) {
2260 if (i
== PP_ENDMACRO
) {
2262 return NO_DIRECTIVE_FOUND
;
2265 if (!defining
->name
) {
2268 return NO_DIRECTIVE_FOUND
;
2269 } else if (nested_rep_count
> 0) {
2270 if (i
== PP_ENDREP
) {
2272 return NO_DIRECTIVE_FOUND
;
2280 error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2282 return NO_DIRECTIVE_FOUND
; /* didn't get it */
2285 /* Directive to tell NASM what the default stack size is. The
2286 * default is for a 16-bit stack, and this can be overriden with
2289 tline
= tline
->next
;
2290 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2291 tline
= tline
->next
;
2292 if (!tline
|| tline
->type
!= TOK_ID
) {
2293 error(ERR_NONFATAL
, "`%%stacksize' missing size parameter");
2294 free_tlist(origline
);
2295 return DIRECTIVE_FOUND
;
2297 if (nasm_stricmp(tline
->text
, "flat") == 0) {
2298 /* All subsequent ARG directives are for a 32-bit stack */
2300 StackPointer
= "ebp";
2303 } else if (nasm_stricmp(tline
->text
, "flat64") == 0) {
2304 /* All subsequent ARG directives are for a 64-bit stack */
2306 StackPointer
= "rbp";
2309 } else if (nasm_stricmp(tline
->text
, "large") == 0) {
2310 /* All subsequent ARG directives are for a 16-bit stack,
2311 * far function call.
2314 StackPointer
= "bp";
2317 } else if (nasm_stricmp(tline
->text
, "small") == 0) {
2318 /* All subsequent ARG directives are for a 16-bit stack,
2319 * far function call. We don't support near functions.
2322 StackPointer
= "bp";
2326 error(ERR_NONFATAL
, "`%%stacksize' invalid size type");
2327 free_tlist(origline
);
2328 return DIRECTIVE_FOUND
;
2330 free_tlist(origline
);
2331 return DIRECTIVE_FOUND
;
2334 /* TASM like ARG directive to define arguments to functions, in
2335 * the following form:
2337 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2341 char *arg
, directive
[256];
2342 int size
= StackSize
;
2344 /* Find the argument name */
2345 tline
= tline
->next
;
2346 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2347 tline
= tline
->next
;
2348 if (!tline
|| tline
->type
!= TOK_ID
) {
2349 error(ERR_NONFATAL
, "`%%arg' missing argument parameter");
2350 free_tlist(origline
);
2351 return DIRECTIVE_FOUND
;
2355 /* Find the argument size type */
2356 tline
= tline
->next
;
2357 if (!tline
|| tline
->type
!= TOK_OTHER
2358 || tline
->text
[0] != ':') {
2360 "Syntax error processing `%%arg' directive");
2361 free_tlist(origline
);
2362 return DIRECTIVE_FOUND
;
2364 tline
= tline
->next
;
2365 if (!tline
|| tline
->type
!= TOK_ID
) {
2366 error(ERR_NONFATAL
, "`%%arg' missing size type parameter");
2367 free_tlist(origline
);
2368 return DIRECTIVE_FOUND
;
2371 /* Allow macro expansion of type parameter */
2372 tt
= tokenize(tline
->text
);
2373 tt
= expand_smacro(tt
);
2374 size
= parse_size(tt
->text
);
2377 "Invalid size type for `%%arg' missing directive");
2379 free_tlist(origline
);
2380 return DIRECTIVE_FOUND
;
2384 /* Round up to even stack slots */
2385 size
= ALIGN(size
, StackSize
);
2387 /* Now define the macro for the argument */
2388 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
2389 arg
, StackPointer
, offset
);
2390 do_directive(tokenize(directive
));
2393 /* Move to the next argument in the list */
2394 tline
= tline
->next
;
2395 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2396 tline
= tline
->next
;
2397 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2399 free_tlist(origline
);
2400 return DIRECTIVE_FOUND
;
2403 /* TASM like LOCAL directive to define local variables for a
2404 * function, in the following form:
2406 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2408 * The '= LocalSize' at the end is ignored by NASM, but is
2409 * required by TASM to define the local parameter size (and used
2410 * by the TASM macro package).
2412 offset
= LocalOffset
;
2414 char *local
, directive
[256];
2415 int size
= StackSize
;
2417 /* Find the argument name */
2418 tline
= tline
->next
;
2419 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2420 tline
= tline
->next
;
2421 if (!tline
|| tline
->type
!= TOK_ID
) {
2423 "`%%local' missing argument parameter");
2424 free_tlist(origline
);
2425 return DIRECTIVE_FOUND
;
2427 local
= tline
->text
;
2429 /* Find the argument size type */
2430 tline
= tline
->next
;
2431 if (!tline
|| tline
->type
!= TOK_OTHER
2432 || tline
->text
[0] != ':') {
2434 "Syntax error processing `%%local' directive");
2435 free_tlist(origline
);
2436 return DIRECTIVE_FOUND
;
2438 tline
= tline
->next
;
2439 if (!tline
|| tline
->type
!= TOK_ID
) {
2441 "`%%local' missing size type parameter");
2442 free_tlist(origline
);
2443 return DIRECTIVE_FOUND
;
2446 /* Allow macro expansion of type parameter */
2447 tt
= tokenize(tline
->text
);
2448 tt
= expand_smacro(tt
);
2449 size
= parse_size(tt
->text
);
2452 "Invalid size type for `%%local' missing directive");
2454 free_tlist(origline
);
2455 return DIRECTIVE_FOUND
;
2459 /* Round up to even stack slots */
2460 size
= ALIGN(size
, StackSize
);
2462 offset
+= size
; /* Negative offset, increment before */
2464 /* Now define the macro for the argument */
2465 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
2466 local
, StackPointer
, offset
);
2467 do_directive(tokenize(directive
));
2469 /* Now define the assign to setup the enter_c macro correctly */
2470 snprintf(directive
, sizeof(directive
),
2471 "%%assign %%$localsize %%$localsize+%d", size
);
2472 do_directive(tokenize(directive
));
2474 /* Move to the next argument in the list */
2475 tline
= tline
->next
;
2476 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2477 tline
= tline
->next
;
2478 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2479 LocalOffset
= offset
;
2480 free_tlist(origline
);
2481 return DIRECTIVE_FOUND
;
2485 error(ERR_WARNING
|ERR_PASS1
,
2486 "trailing garbage after `%%clear' ignored");
2489 free_tlist(origline
);
2490 return DIRECTIVE_FOUND
;
2493 t
= tline
->next
= expand_smacro(tline
->next
);
2495 if (!t
|| (t
->type
!= TOK_STRING
&&
2496 t
->type
!= TOK_INTERNAL_STRING
)) {
2497 error(ERR_NONFATAL
, "`%%depend' expects a file name");
2498 free_tlist(origline
);
2499 return DIRECTIVE_FOUND
; /* but we did _something_ */
2502 error(ERR_WARNING
|ERR_PASS1
,
2503 "trailing garbage after `%%depend' ignored");
2505 if (t
->type
!= TOK_INTERNAL_STRING
)
2506 nasm_unquote_cstr(p
, i
);
2507 if (dephead
&& !in_list(*dephead
, p
)) {
2508 StrList
*sl
= nasm_malloc(strlen(p
)+1+sizeof sl
->next
);
2512 deptail
= &sl
->next
;
2514 free_tlist(origline
);
2515 return DIRECTIVE_FOUND
;
2518 t
= tline
->next
= expand_smacro(tline
->next
);
2521 if (!t
|| (t
->type
!= TOK_STRING
&&
2522 t
->type
!= TOK_INTERNAL_STRING
)) {
2523 error(ERR_NONFATAL
, "`%%include' expects a file name");
2524 free_tlist(origline
);
2525 return DIRECTIVE_FOUND
; /* but we did _something_ */
2528 error(ERR_WARNING
|ERR_PASS1
,
2529 "trailing garbage after `%%include' ignored");
2531 if (t
->type
!= TOK_INTERNAL_STRING
)
2532 nasm_unquote_cstr(p
, i
);
2533 inc
= nasm_malloc(sizeof(Include
));
2536 inc
->fp
= inc_fopen(p
, dephead
, &deptail
, pass
== 0);
2538 /* -MG given but file not found */
2541 inc
->fname
= src_set_fname(nasm_strdup(p
));
2542 inc
->lineno
= src_set_linnum(0);
2544 inc
->expansion
= NULL
;
2547 list
->uplevel(LIST_INCLUDE
);
2549 free_tlist(origline
);
2550 return DIRECTIVE_FOUND
;
2554 static macros_t
*use_pkg
;
2555 const char *pkg_macro
= NULL
;
2557 tline
= tline
->next
;
2559 tline
= expand_id(tline
);
2561 if (!tline
|| (tline
->type
!= TOK_STRING
&&
2562 tline
->type
!= TOK_INTERNAL_STRING
&&
2563 tline
->type
!= TOK_ID
)) {
2564 error(ERR_NONFATAL
, "`%%use' expects a package name");
2565 free_tlist(origline
);
2566 return DIRECTIVE_FOUND
; /* but we did _something_ */
2569 error(ERR_WARNING
|ERR_PASS1
,
2570 "trailing garbage after `%%use' ignored");
2571 if (tline
->type
== TOK_STRING
)
2572 nasm_unquote_cstr(tline
->text
, i
);
2573 use_pkg
= nasm_stdmac_find_package(tline
->text
);
2575 error(ERR_NONFATAL
, "unknown `%%use' package: %s", tline
->text
);
2577 pkg_macro
= (char *)use_pkg
+ 1; /* The first string will be <%define>__USE_*__ */
2578 if (use_pkg
&& ! smacro_defined(NULL
, pkg_macro
, 0, NULL
, true)) {
2579 /* Not already included, go ahead and include it */
2580 stdmacpos
= use_pkg
;
2582 free_tlist(origline
);
2583 return DIRECTIVE_FOUND
;
2588 tline
= tline
->next
;
2590 tline
= expand_id(tline
);
2592 if (!tok_type_(tline
, TOK_ID
)) {
2593 error(ERR_NONFATAL
, "`%s' expects a context identifier",
2595 free_tlist(origline
);
2596 return DIRECTIVE_FOUND
; /* but we did _something_ */
2599 error(ERR_WARNING
|ERR_PASS1
,
2600 "trailing garbage after `%s' ignored",
2602 p
= nasm_strdup(tline
->text
);
2604 p
= NULL
; /* Anonymous */
2608 ctx
= nasm_malloc(sizeof(Context
));
2610 hash_init(&ctx
->localmac
, HASH_SMALL
);
2612 ctx
->number
= unique
++;
2617 error(ERR_NONFATAL
, "`%s': context stack is empty",
2619 } else if (i
== PP_POP
) {
2620 if (p
&& (!cstk
->name
|| nasm_stricmp(p
, cstk
->name
)))
2621 error(ERR_NONFATAL
, "`%%pop' in wrong context: %s, "
2623 cstk
->name
? cstk
->name
: "anonymous", p
);
2628 nasm_free(cstk
->name
);
2634 free_tlist(origline
);
2635 return DIRECTIVE_FOUND
;
2637 severity
= ERR_FATAL
;
2640 severity
= ERR_NONFATAL
;
2643 severity
= ERR_WARNING
|ERR_WARN_USER
;
2648 /* Only error out if this is the final pass */
2649 if (pass
!= 2 && i
!= PP_FATAL
)
2650 return DIRECTIVE_FOUND
;
2652 tline
->next
= expand_smacro(tline
->next
);
2653 tline
= tline
->next
;
2655 t
= tline
? tline
->next
: NULL
;
2657 if (tok_type_(tline
, TOK_STRING
) && !t
) {
2658 /* The line contains only a quoted string */
2660 nasm_unquote(p
, NULL
); /* Ignore NUL character truncation */
2661 error(severity
, "%s", p
);
2663 /* Not a quoted string, or more than a quoted string */
2664 p
= detoken(tline
, false);
2665 error(severity
, "%s", p
);
2668 free_tlist(origline
);
2669 return DIRECTIVE_FOUND
;
2673 if (istk
->conds
&& !emitting(istk
->conds
->state
))
2676 j
= if_condition(tline
->next
, i
);
2677 tline
->next
= NULL
; /* it got freed */
2678 j
= j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2680 cond
= nasm_malloc(sizeof(Cond
));
2681 cond
->next
= istk
->conds
;
2685 istk
->mstk
->condcnt
++;
2686 free_tlist(origline
);
2687 return DIRECTIVE_FOUND
;
2691 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2692 switch(istk
->conds
->state
) {
2694 istk
->conds
->state
= COND_DONE
;
2701 case COND_ELSE_TRUE
:
2702 case COND_ELSE_FALSE
:
2703 error_precond(ERR_WARNING
|ERR_PASS1
,
2704 "`%%elif' after `%%else' ignored");
2705 istk
->conds
->state
= COND_NEVER
;
2710 * IMPORTANT: In the case of %if, we will already have
2711 * called expand_mmac_params(); however, if we're
2712 * processing an %elif we must have been in a
2713 * non-emitting mode, which would have inhibited
2714 * the normal invocation of expand_mmac_params().
2715 * Therefore, we have to do it explicitly here.
2717 j
= if_condition(expand_mmac_params(tline
->next
), i
);
2718 tline
->next
= NULL
; /* it got freed */
2719 istk
->conds
->state
=
2720 j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2723 free_tlist(origline
);
2724 return DIRECTIVE_FOUND
;
2728 error_precond(ERR_WARNING
|ERR_PASS1
,
2729 "trailing garbage after `%%else' ignored");
2731 error(ERR_FATAL
, "`%%else': no matching `%%if'");
2732 switch(istk
->conds
->state
) {
2735 istk
->conds
->state
= COND_ELSE_FALSE
;
2742 istk
->conds
->state
= COND_ELSE_TRUE
;
2745 case COND_ELSE_TRUE
:
2746 case COND_ELSE_FALSE
:
2747 error_precond(ERR_WARNING
|ERR_PASS1
,
2748 "`%%else' after `%%else' ignored.");
2749 istk
->conds
->state
= COND_NEVER
;
2752 free_tlist(origline
);
2753 return DIRECTIVE_FOUND
;
2757 error_precond(ERR_WARNING
|ERR_PASS1
,
2758 "trailing garbage after `%%endif' ignored");
2760 error(ERR_FATAL
, "`%%endif': no matching `%%if'");
2762 istk
->conds
= cond
->next
;
2765 istk
->mstk
->condcnt
--;
2766 free_tlist(origline
);
2767 return DIRECTIVE_FOUND
;
2774 error(ERR_FATAL
, "`%s': already defining a macro",
2776 return DIRECTIVE_FOUND
;
2778 defining
= nasm_malloc(sizeof(MMacro
));
2779 defining
->max_depth
=
2780 (i
== PP_RMACRO
) || (i
== PP_IRMACRO
) ? DEADMAN_LIMIT
: 0;
2781 defining
->casesense
= (i
== PP_MACRO
) || (i
== PP_RMACRO
);
2782 if (!parse_mmacro_spec(tline
, defining
, pp_directives
[i
])) {
2783 nasm_free(defining
);
2785 return DIRECTIVE_FOUND
;
2788 mmac
= (MMacro
*) hash_findix(&mmacros
, defining
->name
);
2790 if (!strcmp(mmac
->name
, defining
->name
) &&
2791 (mmac
->nparam_min
<= defining
->nparam_max
2793 && (defining
->nparam_min
<= mmac
->nparam_max
2795 error(ERR_WARNING
|ERR_PASS1
,
2796 "redefining multi-line macro `%s'", defining
->name
);
2797 return DIRECTIVE_FOUND
;
2801 free_tlist(origline
);
2802 return DIRECTIVE_FOUND
;
2806 if (! (defining
&& defining
->name
)) {
2807 error(ERR_NONFATAL
, "`%s': not defining a macro", tline
->text
);
2808 return DIRECTIVE_FOUND
;
2810 mmhead
= (MMacro
**) hash_findi_add(&mmacros
, defining
->name
);
2811 defining
->next
= *mmhead
;
2814 free_tlist(origline
);
2815 return DIRECTIVE_FOUND
;
2819 * We must search along istk->expansion until we hit a
2820 * macro-end marker for a macro with a name. Then we
2821 * bypass all lines between exitmacro and endmacro.
2823 list_for_each(l
, istk
->expansion
)
2824 if (l
->finishes
&& l
->finishes
->name
)
2829 * Remove all conditional entries relative to this
2830 * macro invocation. (safe to do in this context)
2832 for ( ; l
->finishes
->condcnt
> 0; l
->finishes
->condcnt
--) {
2834 istk
->conds
= cond
->next
;
2837 istk
->expansion
= l
;
2839 error(ERR_NONFATAL
, "`%%exitmacro' not within `%%macro' block");
2841 free_tlist(origline
);
2842 return DIRECTIVE_FOUND
;
2850 spec
.casesense
= (i
== PP_UNMACRO
);
2851 if (!parse_mmacro_spec(tline
, &spec
, pp_directives
[i
])) {
2852 return DIRECTIVE_FOUND
;
2854 mmac_p
= (MMacro
**) hash_findi(&mmacros
, spec
.name
, NULL
);
2855 while (mmac_p
&& *mmac_p
) {
2857 if (mmac
->casesense
== spec
.casesense
&&
2858 !mstrcmp(mmac
->name
, spec
.name
, spec
.casesense
) &&
2859 mmac
->nparam_min
== spec
.nparam_min
&&
2860 mmac
->nparam_max
== spec
.nparam_max
&&
2861 mmac
->plus
== spec
.plus
) {
2862 *mmac_p
= mmac
->next
;
2865 mmac_p
= &mmac
->next
;
2868 free_tlist(origline
);
2869 free_tlist(spec
.dlist
);
2870 return DIRECTIVE_FOUND
;
2874 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
2875 tline
= tline
->next
;
2877 free_tlist(origline
);
2878 error(ERR_NONFATAL
, "`%%rotate' missing rotate count");
2879 return DIRECTIVE_FOUND
;
2881 t
= expand_smacro(tline
->next
);
2883 free_tlist(origline
);
2886 tokval
.t_type
= TOKEN_INVALID
;
2888 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
2891 return DIRECTIVE_FOUND
;
2893 error(ERR_WARNING
|ERR_PASS1
,
2894 "trailing garbage after expression ignored");
2895 if (!is_simple(evalresult
)) {
2896 error(ERR_NONFATAL
, "non-constant value given to `%%rotate'");
2897 return DIRECTIVE_FOUND
;
2900 while (mmac
&& !mmac
->name
) /* avoid mistaking %reps for macros */
2901 mmac
= mmac
->next_active
;
2903 error(ERR_NONFATAL
, "`%%rotate' invoked outside a macro call");
2904 } else if (mmac
->nparam
== 0) {
2906 "`%%rotate' invoked within macro without parameters");
2908 int rotate
= mmac
->rotate
+ reloc_value(evalresult
);
2910 rotate
%= (int)mmac
->nparam
;
2912 rotate
+= mmac
->nparam
;
2914 mmac
->rotate
= rotate
;
2916 return DIRECTIVE_FOUND
;
2921 tline
= tline
->next
;
2922 } while (tok_type_(tline
, TOK_WHITESPACE
));
2924 if (tok_type_(tline
, TOK_ID
) &&
2925 nasm_stricmp(tline
->text
, ".nolist") == 0) {
2928 tline
= tline
->next
;
2929 } while (tok_type_(tline
, TOK_WHITESPACE
));
2933 t
= expand_smacro(tline
);
2935 tokval
.t_type
= TOKEN_INVALID
;
2937 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
2939 free_tlist(origline
);
2940 return DIRECTIVE_FOUND
;
2943 error(ERR_WARNING
|ERR_PASS1
,
2944 "trailing garbage after expression ignored");
2945 if (!is_simple(evalresult
)) {
2946 error(ERR_NONFATAL
, "non-constant value given to `%%rep'");
2947 return DIRECTIVE_FOUND
;
2949 count
= reloc_value(evalresult
);
2950 if (count
>= REP_LIMIT
) {
2951 error(ERR_NONFATAL
, "`%%rep' value exceeds limit");
2956 error(ERR_NONFATAL
, "`%%rep' expects a repeat count");
2959 free_tlist(origline
);
2961 tmp_defining
= defining
;
2962 defining
= nasm_malloc(sizeof(MMacro
));
2963 defining
->prev
= NULL
;
2964 defining
->name
= NULL
; /* flags this macro as a %rep block */
2965 defining
->casesense
= false;
2966 defining
->plus
= false;
2967 defining
->nolist
= nolist
;
2968 defining
->in_progress
= count
;
2969 defining
->max_depth
= 0;
2970 defining
->nparam_min
= defining
->nparam_max
= 0;
2971 defining
->defaults
= NULL
;
2972 defining
->dlist
= NULL
;
2973 defining
->expansion
= NULL
;
2974 defining
->next_active
= istk
->mstk
;
2975 defining
->rep_nest
= tmp_defining
;
2976 return DIRECTIVE_FOUND
;
2979 if (!defining
|| defining
->name
) {
2980 error(ERR_NONFATAL
, "`%%endrep': no matching `%%rep'");
2981 return DIRECTIVE_FOUND
;
2985 * Now we have a "macro" defined - although it has no name
2986 * and we won't be entering it in the hash tables - we must
2987 * push a macro-end marker for it on to istk->expansion.
2988 * After that, it will take care of propagating itself (a
2989 * macro-end marker line for a macro which is really a %rep
2990 * block will cause the macro to be re-expanded, complete
2991 * with another macro-end marker to ensure the process
2992 * continues) until the whole expansion is forcibly removed
2993 * from istk->expansion by a %exitrep.
2995 l
= nasm_malloc(sizeof(Line
));
2996 l
->next
= istk
->expansion
;
2997 l
->finishes
= defining
;
2999 istk
->expansion
= l
;
3001 istk
->mstk
= defining
;
3003 list
->uplevel(defining
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
3004 tmp_defining
= defining
;
3005 defining
= defining
->rep_nest
;
3006 free_tlist(origline
);
3007 return DIRECTIVE_FOUND
;
3011 * We must search along istk->expansion until we hit a
3012 * macro-end marker for a macro with no name. Then we set
3013 * its `in_progress' flag to 0.
3015 list_for_each(l
, istk
->expansion
)
3016 if (l
->finishes
&& !l
->finishes
->name
)
3020 l
->finishes
->in_progress
= 1;
3022 error(ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
3023 free_tlist(origline
);
3024 return DIRECTIVE_FOUND
;
3030 casesense
= (i
== PP_DEFINE
|| i
== PP_XDEFINE
);
3032 tline
= tline
->next
;
3034 tline
= expand_id(tline
);
3035 if (!tline
|| (tline
->type
!= TOK_ID
&&
3036 (tline
->type
!= TOK_PREPROC_ID
||
3037 tline
->text
[1] != '$'))) {
3038 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3040 free_tlist(origline
);
3041 return DIRECTIVE_FOUND
;
3044 ctx
= get_ctx(tline
->text
, &mname
, false);
3046 param_start
= tline
= tline
->next
;
3049 /* Expand the macro definition now for %xdefine and %ixdefine */
3050 if ((i
== PP_XDEFINE
) || (i
== PP_IXDEFINE
))
3051 tline
= expand_smacro(tline
);
3053 if (tok_is_(tline
, "(")) {
3055 * This macro has parameters.
3058 tline
= tline
->next
;
3062 error(ERR_NONFATAL
, "parameter identifier expected");
3063 free_tlist(origline
);
3064 return DIRECTIVE_FOUND
;
3066 if (tline
->type
!= TOK_ID
) {
3068 "`%s': parameter identifier expected",
3070 free_tlist(origline
);
3071 return DIRECTIVE_FOUND
;
3073 tline
->type
= TOK_SMAC_PARAM
+ nparam
++;
3074 tline
= tline
->next
;
3076 if (tok_is_(tline
, ",")) {
3077 tline
= tline
->next
;
3079 if (!tok_is_(tline
, ")")) {
3081 "`)' expected to terminate macro template");
3082 free_tlist(origline
);
3083 return DIRECTIVE_FOUND
;
3089 tline
= tline
->next
;
3091 if (tok_type_(tline
, TOK_WHITESPACE
))
3092 last
= tline
, tline
= tline
->next
;
3097 if (t
->type
== TOK_ID
) {
3098 list_for_each(tt
, param_start
)
3099 if (tt
->type
>= TOK_SMAC_PARAM
&&
3100 !strcmp(tt
->text
, t
->text
))
3104 t
->next
= macro_start
;
3109 * Good. We now have a macro name, a parameter count, and a
3110 * token list (in reverse order) for an expansion. We ought
3111 * to be OK just to create an SMacro, store it, and let
3112 * free_tlist have the rest of the line (which we have
3113 * carefully re-terminated after chopping off the expansion
3116 define_smacro(ctx
, mname
, casesense
, nparam
, macro_start
);
3117 free_tlist(origline
);
3118 return DIRECTIVE_FOUND
;
3121 tline
= tline
->next
;
3123 tline
= expand_id(tline
);
3124 if (!tline
|| (tline
->type
!= TOK_ID
&&
3125 (tline
->type
!= TOK_PREPROC_ID
||
3126 tline
->text
[1] != '$'))) {
3127 error(ERR_NONFATAL
, "`%%undef' expects a macro identifier");
3128 free_tlist(origline
);
3129 return DIRECTIVE_FOUND
;
3132 error(ERR_WARNING
|ERR_PASS1
,
3133 "trailing garbage after macro name ignored");
3136 /* Find the context that symbol belongs to */
3137 ctx
= get_ctx(tline
->text
, &mname
, false);
3138 undef_smacro(ctx
, mname
);
3139 free_tlist(origline
);
3140 return DIRECTIVE_FOUND
;
3144 casesense
= (i
== PP_DEFSTR
);
3146 tline
= tline
->next
;
3148 tline
= expand_id(tline
);
3149 if (!tline
|| (tline
->type
!= TOK_ID
&&
3150 (tline
->type
!= TOK_PREPROC_ID
||
3151 tline
->text
[1] != '$'))) {
3152 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3154 free_tlist(origline
);
3155 return DIRECTIVE_FOUND
;
3158 ctx
= get_ctx(tline
->text
, &mname
, false);
3160 tline
= expand_smacro(tline
->next
);
3163 while (tok_type_(tline
, TOK_WHITESPACE
))
3164 tline
= delete_Token(tline
);
3166 p
= detoken(tline
, false);
3167 macro_start
= nasm_malloc(sizeof(*macro_start
));
3168 macro_start
->next
= NULL
;
3169 macro_start
->text
= nasm_quote(p
, strlen(p
));
3170 macro_start
->type
= TOK_STRING
;
3171 macro_start
->a
.mac
= NULL
;
3175 * We now have a macro name, an implicit parameter count of
3176 * zero, and a string token to use as an expansion. Create
3177 * and store an SMacro.
3179 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3180 free_tlist(origline
);
3181 return DIRECTIVE_FOUND
;
3185 casesense
= (i
== PP_DEFTOK
);
3187 tline
= tline
->next
;
3189 tline
= expand_id(tline
);
3190 if (!tline
|| (tline
->type
!= TOK_ID
&&
3191 (tline
->type
!= TOK_PREPROC_ID
||
3192 tline
->text
[1] != '$'))) {
3194 "`%s' expects a macro identifier as first parameter",
3196 free_tlist(origline
);
3197 return DIRECTIVE_FOUND
;
3199 ctx
= get_ctx(tline
->text
, &mname
, false);
3201 tline
= expand_smacro(tline
->next
);
3205 while (tok_type_(t
, TOK_WHITESPACE
))
3207 /* t should now point to the string */
3208 if (!tok_type_(t
, TOK_STRING
)) {
3210 "`%s` requires string as second parameter",
3213 free_tlist(origline
);
3214 return DIRECTIVE_FOUND
;
3218 * Convert the string to a token stream. Note that smacros
3219 * are stored with the token stream reversed, so we have to
3220 * reverse the output of tokenize().
3222 nasm_unquote_cstr(t
->text
, i
);
3223 macro_start
= reverse_tokens(tokenize(t
->text
));
3226 * We now have a macro name, an implicit parameter count of
3227 * zero, and a numeric token to use as an expansion. Create
3228 * and store an SMacro.
3230 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3232 free_tlist(origline
);
3233 return DIRECTIVE_FOUND
;
3238 StrList
*xsl
= NULL
;
3239 StrList
**xst
= &xsl
;
3243 tline
= tline
->next
;
3245 tline
= expand_id(tline
);
3246 if (!tline
|| (tline
->type
!= TOK_ID
&&
3247 (tline
->type
!= TOK_PREPROC_ID
||
3248 tline
->text
[1] != '$'))) {
3250 "`%%pathsearch' expects a macro identifier as first parameter");
3251 free_tlist(origline
);
3252 return DIRECTIVE_FOUND
;
3254 ctx
= get_ctx(tline
->text
, &mname
, false);
3256 tline
= expand_smacro(tline
->next
);
3260 while (tok_type_(t
, TOK_WHITESPACE
))
3263 if (!t
|| (t
->type
!= TOK_STRING
&&
3264 t
->type
!= TOK_INTERNAL_STRING
)) {
3265 error(ERR_NONFATAL
, "`%%pathsearch' expects a file name");
3267 free_tlist(origline
);
3268 return DIRECTIVE_FOUND
; /* but we did _something_ */
3271 error(ERR_WARNING
|ERR_PASS1
,
3272 "trailing garbage after `%%pathsearch' ignored");
3274 if (t
->type
!= TOK_INTERNAL_STRING
)
3275 nasm_unquote(p
, NULL
);
3277 fp
= inc_fopen(p
, &xsl
, &xst
, true);
3280 fclose(fp
); /* Don't actually care about the file */
3282 macro_start
= nasm_malloc(sizeof(*macro_start
));
3283 macro_start
->next
= NULL
;
3284 macro_start
->text
= nasm_quote(p
, strlen(p
));
3285 macro_start
->type
= TOK_STRING
;
3286 macro_start
->a
.mac
= NULL
;
3291 * We now have a macro name, an implicit parameter count of
3292 * zero, and a string token to use as an expansion. Create
3293 * and store an SMacro.
3295 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3297 free_tlist(origline
);
3298 return DIRECTIVE_FOUND
;
3304 tline
= tline
->next
;
3306 tline
= expand_id(tline
);
3307 if (!tline
|| (tline
->type
!= TOK_ID
&&
3308 (tline
->type
!= TOK_PREPROC_ID
||
3309 tline
->text
[1] != '$'))) {
3311 "`%%strlen' expects a macro identifier as first parameter");
3312 free_tlist(origline
);
3313 return DIRECTIVE_FOUND
;
3315 ctx
= get_ctx(tline
->text
, &mname
, false);
3317 tline
= expand_smacro(tline
->next
);
3321 while (tok_type_(t
, TOK_WHITESPACE
))
3323 /* t should now point to the string */
3324 if (!tok_type_(t
, TOK_STRING
)) {
3326 "`%%strlen` requires string as second parameter");
3328 free_tlist(origline
);
3329 return DIRECTIVE_FOUND
;
3332 macro_start
= nasm_malloc(sizeof(*macro_start
));
3333 macro_start
->next
= NULL
;
3334 make_tok_num(macro_start
, nasm_unquote(t
->text
, NULL
));
3335 macro_start
->a
.mac
= NULL
;
3338 * We now have a macro name, an implicit parameter count of
3339 * zero, and a numeric token to use as an expansion. Create
3340 * and store an SMacro.
3342 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3344 free_tlist(origline
);
3345 return DIRECTIVE_FOUND
;
3350 tline
= tline
->next
;
3352 tline
= expand_id(tline
);
3353 if (!tline
|| (tline
->type
!= TOK_ID
&&
3354 (tline
->type
!= TOK_PREPROC_ID
||
3355 tline
->text
[1] != '$'))) {
3357 "`%%strcat' expects a macro identifier as first parameter");
3358 free_tlist(origline
);
3359 return DIRECTIVE_FOUND
;
3361 ctx
= get_ctx(tline
->text
, &mname
, false);
3363 tline
= expand_smacro(tline
->next
);
3367 list_for_each(t
, tline
) {
3369 case TOK_WHITESPACE
:
3372 len
+= t
->a
.len
= nasm_unquote(t
->text
, NULL
);
3375 if (!strcmp(t
->text
, ",")) /* permit comma separators */
3377 /* else fall through */
3380 "non-string passed to `%%strcat' (%d)", t
->type
);
3382 free_tlist(origline
);
3383 return DIRECTIVE_FOUND
;
3387 p
= pp
= nasm_malloc(len
);
3388 list_for_each(t
, tline
) {
3389 if (t
->type
== TOK_STRING
) {
3390 memcpy(p
, t
->text
, t
->a
.len
);
3396 * We now have a macro name, an implicit parameter count of
3397 * zero, and a numeric token to use as an expansion. Create
3398 * and store an SMacro.
3400 macro_start
= new_Token(NULL
, TOK_STRING
, NULL
, 0);
3401 macro_start
->text
= nasm_quote(pp
, len
);
3403 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3405 free_tlist(origline
);
3406 return DIRECTIVE_FOUND
;
3410 int64_t start
, count
;
3415 tline
= tline
->next
;
3417 tline
= expand_id(tline
);
3418 if (!tline
|| (tline
->type
!= TOK_ID
&&
3419 (tline
->type
!= TOK_PREPROC_ID
||
3420 tline
->text
[1] != '$'))) {
3422 "`%%substr' expects a macro identifier as first parameter");
3423 free_tlist(origline
);
3424 return DIRECTIVE_FOUND
;
3426 ctx
= get_ctx(tline
->text
, &mname
, false);
3428 tline
= expand_smacro(tline
->next
);
3431 if (tline
) /* skip expanded id */
3433 while (tok_type_(t
, TOK_WHITESPACE
))
3436 /* t should now point to the string */
3437 if (!tok_type_(t
, TOK_STRING
)) {
3439 "`%%substr` requires string as second parameter");
3441 free_tlist(origline
);
3442 return DIRECTIVE_FOUND
;
3447 tokval
.t_type
= TOKEN_INVALID
;
3448 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3452 free_tlist(origline
);
3453 return DIRECTIVE_FOUND
;
3454 } else if (!is_simple(evalresult
)) {
3455 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3457 free_tlist(origline
);
3458 return DIRECTIVE_FOUND
;
3460 start
= evalresult
->value
- 1;
3462 while (tok_type_(tt
, TOK_WHITESPACE
))
3465 count
= 1; /* Backwards compatibility: one character */
3467 tokval
.t_type
= TOKEN_INVALID
;
3468 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3472 free_tlist(origline
);
3473 return DIRECTIVE_FOUND
;
3474 } else if (!is_simple(evalresult
)) {
3475 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3477 free_tlist(origline
);
3478 return DIRECTIVE_FOUND
;
3480 count
= evalresult
->value
;
3483 len
= nasm_unquote(t
->text
, NULL
);
3485 /* make start and count being in range */
3489 count
= len
+ count
+ 1 - start
;
3490 if (start
+ count
> (int64_t)len
)
3491 count
= len
- start
;
3492 if (!len
|| count
< 0 || start
>=(int64_t)len
)
3493 start
= -1, count
= 0; /* empty string */
3495 macro_start
= nasm_malloc(sizeof(*macro_start
));
3496 macro_start
->next
= NULL
;
3497 macro_start
->text
= nasm_quote((start
< 0) ? "" : t
->text
+ start
, count
);
3498 macro_start
->type
= TOK_STRING
;
3499 macro_start
->a
.mac
= NULL
;
3502 * We now have a macro name, an implicit parameter count of
3503 * zero, and a numeric token to use as an expansion. Create
3504 * and store an SMacro.
3506 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3508 free_tlist(origline
);
3509 return DIRECTIVE_FOUND
;
3514 casesense
= (i
== PP_ASSIGN
);
3516 tline
= tline
->next
;
3518 tline
= expand_id(tline
);
3519 if (!tline
|| (tline
->type
!= TOK_ID
&&
3520 (tline
->type
!= TOK_PREPROC_ID
||
3521 tline
->text
[1] != '$'))) {
3523 "`%%%sassign' expects a macro identifier",
3524 (i
== PP_IASSIGN
? "i" : ""));
3525 free_tlist(origline
);
3526 return DIRECTIVE_FOUND
;
3528 ctx
= get_ctx(tline
->text
, &mname
, false);
3530 tline
= expand_smacro(tline
->next
);
3535 tokval
.t_type
= TOKEN_INVALID
;
3537 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3540 free_tlist(origline
);
3541 return DIRECTIVE_FOUND
;
3545 error(ERR_WARNING
|ERR_PASS1
,
3546 "trailing garbage after expression ignored");
3548 if (!is_simple(evalresult
)) {
3550 "non-constant value given to `%%%sassign'",
3551 (i
== PP_IASSIGN
? "i" : ""));
3552 free_tlist(origline
);
3553 return DIRECTIVE_FOUND
;
3556 macro_start
= nasm_malloc(sizeof(*macro_start
));
3557 macro_start
->next
= NULL
;
3558 make_tok_num(macro_start
, reloc_value(evalresult
));
3559 macro_start
->a
.mac
= NULL
;
3562 * We now have a macro name, an implicit parameter count of
3563 * zero, and a numeric token to use as an expansion. Create
3564 * and store an SMacro.
3566 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3567 free_tlist(origline
);
3568 return DIRECTIVE_FOUND
;
3572 * Syntax is `%line nnn[+mmm] [filename]'
3574 tline
= tline
->next
;
3576 if (!tok_type_(tline
, TOK_NUMBER
)) {
3577 error(ERR_NONFATAL
, "`%%line' expects line number");
3578 free_tlist(origline
);
3579 return DIRECTIVE_FOUND
;
3581 k
= readnum(tline
->text
, &err
);
3583 tline
= tline
->next
;
3584 if (tok_is_(tline
, "+")) {
3585 tline
= tline
->next
;
3586 if (!tok_type_(tline
, TOK_NUMBER
)) {
3587 error(ERR_NONFATAL
, "`%%line' expects line increment");
3588 free_tlist(origline
);
3589 return DIRECTIVE_FOUND
;
3591 m
= readnum(tline
->text
, &err
);
3592 tline
= tline
->next
;
3598 nasm_free(src_set_fname(detoken(tline
, false)));
3600 free_tlist(origline
);
3601 return DIRECTIVE_FOUND
;
3605 "preprocessor directive `%s' not yet implemented",
3607 return DIRECTIVE_FOUND
;
3612 * Ensure that a macro parameter contains a condition code and
3613 * nothing else. Return the condition code index if so, or -1
3616 static int find_cc(Token
* t
)
3622 return -1; /* Probably a %+ without a space */
3625 if (t
->type
!= TOK_ID
)
3629 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
3633 j
= ARRAY_SIZE(conditions
);
3636 m
= nasm_stricmp(t
->text
, conditions
[k
]);
3651 static bool paste_tokens(Token
**head
, const struct tokseq_match
*m
,
3652 int mnum
, bool handle_paste_tokens
)
3654 Token
**tail
, *t
, *tt
;
3656 bool did_paste
= false;
3660 /* Now handle token pasting... */
3663 while ((t
= *tail
) && (tt
= t
->next
)) {
3665 case TOK_WHITESPACE
:
3666 if (tt
->type
== TOK_WHITESPACE
) {
3667 /* Zap adjacent whitespace tokens */
3668 t
->next
= delete_Token(tt
);
3670 /* Do not advance paste_head here */
3674 case TOK_PASTE
: /* %+ */
3675 if (handle_paste_tokens
) {
3676 /* Zap %+ and whitespace tokens to the right */
3677 while (t
&& (t
->type
== TOK_WHITESPACE
||
3678 t
->type
== TOK_PASTE
))
3679 t
= *tail
= delete_Token(t
);
3680 if (!paste_head
|| !t
)
3681 break; /* Nothing to paste with */
3685 while (tok_type_(tt
, TOK_WHITESPACE
))
3686 tt
= t
->next
= delete_Token(tt
);
3688 tmp
= nasm_strcat(t
->text
, tt
->text
);
3690 tt
= delete_Token(tt
);
3691 t
= *tail
= tokenize(tmp
);
3697 t
->next
= tt
; /* Attach the remaining token chain */
3704 /* else fall through */
3707 * Concatenation of tokens might look nontrivial
3708 * but in real it's pretty simple -- the caller
3709 * prepares the masks of token types to be concatenated
3710 * and we simply find matched sequences and slip
3713 for (i
= 0; i
< mnum
; i
++) {
3714 if (PP_CONCAT_MASK(t
->type
) & m
[i
].mask_head
) {
3718 while (tt
&& (PP_CONCAT_MASK(tt
->type
) & m
[i
].mask_tail
)) {
3719 len
+= strlen(tt
->text
);
3724 * Now tt points to the first token after
3725 * the potential paste area...
3727 if (tt
!= t
->next
) {
3728 /* We have at least two tokens... */
3729 len
+= strlen(t
->text
);
3730 p
= tmp
= nasm_malloc(len
+1);
3733 p
= strchr(p
, '\0');
3734 t
= delete_Token(t
);
3736 t
= *tail
= tokenize(tmp
);
3742 t
->next
= tt
; /* Attach the remaining token chain */
3750 if (i
>= mnum
) { /* no match */
3752 if (!tok_type_(t
->next
, TOK_WHITESPACE
))
3762 * expands to a list of tokens from %{x:y}
3764 static Token
*expand_mmac_params_range(MMacro
*mac
, Token
*tline
, Token
***last
)
3766 Token
*t
= tline
, **tt
, *tm
, *head
;
3770 pos
= strchr(tline
->text
, ':');
3773 lst
= atoi(pos
+ 1);
3774 fst
= atoi(tline
->text
+ 1);
3777 * only macros params are accounted so
3778 * if someone passes %0 -- we reject such
3781 if (lst
== 0 || fst
== 0)
3784 /* the values should be sane */
3785 if ((fst
> (int)mac
->nparam
|| fst
< (-(int)mac
->nparam
)) ||
3786 (lst
> (int)mac
->nparam
|| lst
< (-(int)mac
->nparam
)))
3789 fst
= fst
< 0 ? fst
+ (int)mac
->nparam
+ 1: fst
;
3790 lst
= lst
< 0 ? lst
+ (int)mac
->nparam
+ 1: lst
;
3792 /* counted from zero */
3796 * it will be at least one token
3798 tm
= mac
->params
[(fst
+ mac
->rotate
) % mac
->nparam
];
3799 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3800 head
= t
, tt
= &t
->next
;
3802 for (i
= fst
+ 1; i
<= lst
; i
++) {
3803 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
3804 *tt
= t
, tt
= &t
->next
;
3805 j
= (i
+ mac
->rotate
) % mac
->nparam
;
3806 tm
= mac
->params
[j
];
3807 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3808 *tt
= t
, tt
= &t
->next
;
3811 for (i
= fst
- 1; i
>= lst
; i
--) {
3812 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
3813 *tt
= t
, tt
= &t
->next
;
3814 j
= (i
+ mac
->rotate
) % mac
->nparam
;
3815 tm
= mac
->params
[j
];
3816 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3817 *tt
= t
, tt
= &t
->next
;
3825 error(ERR_NONFATAL
, "`%%{%s}': macro parameters out of range",
3831 * Expand MMacro-local things: parameter references (%0, %n, %+n,
3832 * %-n) and MMacro-local identifiers (%%foo) as well as
3833 * macro indirection (%[...]) and range (%{..:..}).
3835 static Token
*expand_mmac_params(Token
* tline
)
3837 Token
*t
, *tt
, **tail
, *thead
;
3838 bool changed
= false;
3845 if (tline
->type
== TOK_PREPROC_ID
&&
3846 (((tline
->text
[1] == '+' || tline
->text
[1] == '-') && tline
->text
[2]) ||
3847 (tline
->text
[1] >= '0' && tline
->text
[1] <= '9') ||
3848 tline
->text
[1] == '%')) {
3850 int type
= 0, cc
; /* type = 0 to placate optimisers */
3857 tline
= tline
->next
;
3860 while (mac
&& !mac
->name
) /* avoid mistaking %reps for macros */
3861 mac
= mac
->next_active
;
3863 error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
3865 pos
= strchr(t
->text
, ':');
3867 switch (t
->text
[1]) {
3869 * We have to make a substitution of one of the
3870 * forms %1, %-1, %+1, %%foo, %0.
3874 snprintf(tmpbuf
, sizeof(tmpbuf
), "%d", mac
->nparam
);
3875 text
= nasm_strdup(tmpbuf
);
3879 snprintf(tmpbuf
, sizeof(tmpbuf
), "..@%"PRIu64
".",
3881 text
= nasm_strcat(tmpbuf
, t
->text
+ 2);
3884 n
= atoi(t
->text
+ 2) - 1;
3885 if (n
>= mac
->nparam
)
3888 if (mac
->nparam
> 1)
3889 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3890 tt
= mac
->params
[n
];
3895 "macro parameter %d is not a condition code",
3900 if (inverse_ccs
[cc
] == -1) {
3902 "condition code `%s' is not invertible",
3906 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
3910 n
= atoi(t
->text
+ 2) - 1;
3911 if (n
>= mac
->nparam
)
3914 if (mac
->nparam
> 1)
3915 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3916 tt
= mac
->params
[n
];
3921 "macro parameter %d is not a condition code",
3926 text
= nasm_strdup(conditions
[cc
]);
3930 n
= atoi(t
->text
+ 1) - 1;
3931 if (n
>= mac
->nparam
)
3934 if (mac
->nparam
> 1)
3935 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3936 tt
= mac
->params
[n
];
3939 for (i
= 0; i
< mac
->paramlen
[n
]; i
++) {
3940 *tail
= new_Token(NULL
, tt
->type
, tt
->text
, 0);
3941 tail
= &(*tail
)->next
;
3945 text
= NULL
; /* we've done it here */
3950 * seems we have a parameters range here
3952 Token
*head
, **last
;
3953 head
= expand_mmac_params_range(mac
, t
, &last
);
3974 } else if (tline
->type
== TOK_INDIRECT
) {
3976 tline
= tline
->next
;
3977 tt
= tokenize(t
->text
);
3978 tt
= expand_mmac_params(tt
);
3979 tt
= expand_smacro(tt
);
3982 tt
->a
.mac
= NULL
; /* Necessary? */
3990 tline
= tline
->next
;
3998 const struct tokseq_match t
[] = {
4000 PP_CONCAT_MASK(TOK_ID
) |
4001 PP_CONCAT_MASK(TOK_FLOAT
), /* head */
4002 PP_CONCAT_MASK(TOK_ID
) |
4003 PP_CONCAT_MASK(TOK_NUMBER
) |
4004 PP_CONCAT_MASK(TOK_FLOAT
) |
4005 PP_CONCAT_MASK(TOK_OTHER
) /* tail */
4008 PP_CONCAT_MASK(TOK_NUMBER
), /* head */
4009 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4012 paste_tokens(&thead
, t
, ARRAY_SIZE(t
), false);
4019 * Expand all single-line macro calls made in the given line.
4020 * Return the expanded version of the line. The original is deemed
4021 * to be destroyed in the process. (In reality we'll just move
4022 * Tokens from input to output a lot of the time, rather than
4023 * actually bothering to destroy and replicate.)
4026 static Token
*expand_smacro(Token
* tline
)
4028 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
4029 SMacro
*head
= NULL
, *m
;
4032 unsigned int nparam
, sparam
;
4034 Token
*org_tline
= tline
;
4037 int deadman
= DEADMAN_LIMIT
;
4041 * Trick: we should avoid changing the start token pointer since it can
4042 * be contained in "next" field of other token. Because of this
4043 * we allocate a copy of first token and work with it; at the end of
4044 * routine we copy it back
4047 tline
= new_Token(org_tline
->next
, org_tline
->type
,
4048 org_tline
->text
, 0);
4049 tline
->a
.mac
= org_tline
->a
.mac
;
4050 nasm_free(org_tline
->text
);
4051 org_tline
->text
= NULL
;
4054 expanded
= true; /* Always expand %+ at least once */
4060 while (tline
) { /* main token loop */
4062 error(ERR_NONFATAL
, "interminable macro recursion");
4066 if ((mname
= tline
->text
)) {
4067 /* if this token is a local macro, look in local context */
4068 if (tline
->type
== TOK_ID
) {
4069 head
= (SMacro
*)hash_findix(&smacros
, mname
);
4070 } else if (tline
->type
== TOK_PREPROC_ID
) {
4071 ctx
= get_ctx(mname
, &mname
, true);
4072 head
= ctx
? (SMacro
*)hash_findix(&ctx
->localmac
, mname
) : NULL
;
4077 * We've hit an identifier. As in is_mmacro below, we first
4078 * check whether the identifier is a single-line macro at
4079 * all, then think about checking for parameters if
4082 list_for_each(m
, head
)
4083 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
4089 if (m
->nparam
== 0) {
4091 * Simple case: the macro is parameterless. Discard the
4092 * one token that the macro call took, and push the
4093 * expansion back on the to-do stack.
4095 if (!m
->expansion
) {
4096 if (!strcmp("__FILE__", m
->name
)) {
4099 src_get(&num
, &file
);
4100 tline
->text
= nasm_quote(file
, strlen(file
));
4101 tline
->type
= TOK_STRING
;
4105 if (!strcmp("__LINE__", m
->name
)) {
4106 nasm_free(tline
->text
);
4107 make_tok_num(tline
, src_get_linnum());
4110 if (!strcmp("__BITS__", m
->name
)) {
4111 nasm_free(tline
->text
);
4112 make_tok_num(tline
, globalbits
);
4115 tline
= delete_Token(tline
);
4120 * Complicated case: at least one macro with this name
4121 * exists and takes parameters. We must find the
4122 * parameters in the call, count them, find the SMacro
4123 * that corresponds to that form of the macro call, and
4124 * substitute for the parameters when we expand. What a
4127 /*tline = tline->next;
4128 skip_white_(tline); */
4131 while (tok_type_(t
, TOK_SMAC_END
)) {
4132 t
->a
.mac
->in_progress
= false;
4134 t
= tline
->next
= delete_Token(t
);
4137 } while (tok_type_(tline
, TOK_WHITESPACE
));
4138 if (!tok_is_(tline
, "(")) {
4140 * This macro wasn't called with parameters: ignore
4141 * the call. (Behaviour borrowed from gnu cpp.)
4150 sparam
= PARAM_DELTA
;
4151 params
= nasm_malloc(sparam
* sizeof(Token
*));
4152 params
[0] = tline
->next
;
4153 paramsize
= nasm_malloc(sparam
* sizeof(int));
4155 while (true) { /* parameter loop */
4157 * For some unusual expansions
4158 * which concatenates function call
4161 while (tok_type_(t
, TOK_SMAC_END
)) {
4162 t
->a
.mac
->in_progress
= false;
4164 t
= tline
->next
= delete_Token(t
);
4170 "macro call expects terminating `)'");
4173 if (tline
->type
== TOK_WHITESPACE
4175 if (paramsize
[nparam
])
4178 params
[nparam
] = tline
->next
;
4179 continue; /* parameter loop */
4181 if (tline
->type
== TOK_OTHER
4182 && tline
->text
[1] == 0) {
4183 char ch
= tline
->text
[0];
4184 if (ch
== ',' && !paren
&& brackets
<= 0) {
4185 if (++nparam
>= sparam
) {
4186 sparam
+= PARAM_DELTA
;
4187 params
= nasm_realloc(params
,
4188 sparam
* sizeof(Token
*));
4189 paramsize
= nasm_realloc(paramsize
,
4190 sparam
* sizeof(int));
4192 params
[nparam
] = tline
->next
;
4193 paramsize
[nparam
] = 0;
4195 continue; /* parameter loop */
4198 (brackets
> 0 || (brackets
== 0 &&
4199 !paramsize
[nparam
])))
4201 if (!(brackets
++)) {
4202 params
[nparam
] = tline
->next
;
4203 continue; /* parameter loop */
4206 if (ch
== '}' && brackets
> 0)
4207 if (--brackets
== 0) {
4209 continue; /* parameter loop */
4211 if (ch
== '(' && !brackets
)
4213 if (ch
== ')' && brackets
<= 0)
4219 error(ERR_NONFATAL
, "braces do not "
4220 "enclose all of macro parameter");
4222 paramsize
[nparam
] += white
+ 1;
4224 } /* parameter loop */
4226 while (m
&& (m
->nparam
!= nparam
||
4227 mstrcmp(m
->name
, mname
,
4231 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4232 "macro `%s' exists, "
4233 "but not taking %d parameters",
4234 mstart
->text
, nparam
);
4237 if (m
&& m
->in_progress
)
4239 if (!m
) { /* in progess or didn't find '(' or wrong nparam */
4241 * Design question: should we handle !tline, which
4242 * indicates missing ')' here, or expand those
4243 * macros anyway, which requires the (t) test a few
4247 nasm_free(paramsize
);
4251 * Expand the macro: we are placed on the last token of the
4252 * call, so that we can easily split the call from the
4253 * following tokens. We also start by pushing an SMAC_END
4254 * token for the cycle removal.
4261 tt
= new_Token(tline
, TOK_SMAC_END
, NULL
, 0);
4263 m
->in_progress
= true;
4265 list_for_each(t
, m
->expansion
) {
4266 if (t
->type
>= TOK_SMAC_PARAM
) {
4267 Token
*pcopy
= tline
, **ptail
= &pcopy
;
4271 ttt
= params
[t
->type
- TOK_SMAC_PARAM
];
4272 i
= paramsize
[t
->type
- TOK_SMAC_PARAM
];
4274 pt
= *ptail
= new_Token(tline
, ttt
->type
,
4280 } else if (t
->type
== TOK_PREPROC_Q
) {
4281 tt
= new_Token(tline
, TOK_ID
, mname
, 0);
4283 } else if (t
->type
== TOK_PREPROC_QQ
) {
4284 tt
= new_Token(tline
, TOK_ID
, m
->name
, 0);
4287 tt
= new_Token(tline
, t
->type
, t
->text
, 0);
4293 * Having done that, get rid of the macro call, and clean
4294 * up the parameters.
4297 nasm_free(paramsize
);
4300 continue; /* main token loop */
4305 if (tline
->type
== TOK_SMAC_END
) {
4306 tline
->a
.mac
->in_progress
= false;
4307 tline
= delete_Token(tline
);
4310 tline
= tline
->next
;
4318 * Now scan the entire line and look for successive TOK_IDs that resulted
4319 * after expansion (they can't be produced by tokenize()). The successive
4320 * TOK_IDs should be concatenated.
4321 * Also we look for %+ tokens and concatenate the tokens before and after
4322 * them (without white spaces in between).
4325 const struct tokseq_match t
[] = {
4327 PP_CONCAT_MASK(TOK_ID
) |
4328 PP_CONCAT_MASK(TOK_PREPROC_ID
), /* head */
4329 PP_CONCAT_MASK(TOK_ID
) |
4330 PP_CONCAT_MASK(TOK_PREPROC_ID
) |
4331 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4334 if (paste_tokens(&thead
, t
, ARRAY_SIZE(t
), true)) {
4336 * If we concatenated something, *and* we had previously expanded
4337 * an actual macro, scan the lines again for macros...
4348 *org_tline
= *thead
;
4349 /* since we just gave text to org_line, don't free it */
4351 delete_Token(thead
);
4353 /* the expression expanded to empty line;
4354 we can't return NULL for some reasons
4355 we just set the line to a single WHITESPACE token. */
4356 memset(org_tline
, 0, sizeof(*org_tline
));
4357 org_tline
->text
= NULL
;
4358 org_tline
->type
= TOK_WHITESPACE
;
4367 * Similar to expand_smacro but used exclusively with macro identifiers
4368 * right before they are fetched in. The reason is that there can be
4369 * identifiers consisting of several subparts. We consider that if there
4370 * are more than one element forming the name, user wants a expansion,
4371 * otherwise it will be left as-is. Example:
4375 * the identifier %$abc will be left as-is so that the handler for %define
4376 * will suck it and define the corresponding value. Other case:
4378 * %define _%$abc cde
4380 * In this case user wants name to be expanded *before* %define starts
4381 * working, so we'll expand %$abc into something (if it has a value;
4382 * otherwise it will be left as-is) then concatenate all successive
4385 static Token
*expand_id(Token
* tline
)
4387 Token
*cur
, *oldnext
= NULL
;
4389 if (!tline
|| !tline
->next
)
4394 (cur
->next
->type
== TOK_ID
||
4395 cur
->next
->type
== TOK_PREPROC_ID
4396 || cur
->next
->type
== TOK_NUMBER
))
4399 /* If identifier consists of just one token, don't expand */
4404 oldnext
= cur
->next
; /* Detach the tail past identifier */
4405 cur
->next
= NULL
; /* so that expand_smacro stops here */
4408 tline
= expand_smacro(tline
);
4411 /* expand_smacro possibly changhed tline; re-scan for EOL */
4413 while (cur
&& cur
->next
)
4416 cur
->next
= oldnext
;
4423 * Determine whether the given line constitutes a multi-line macro
4424 * call, and return the MMacro structure called if so. Doesn't have
4425 * to check for an initial label - that's taken care of in
4426 * expand_mmacro - but must check numbers of parameters. Guaranteed
4427 * to be called with tline->type == TOK_ID, so the putative macro
4428 * name is easy to find.
4430 static MMacro
*is_mmacro(Token
* tline
, Token
*** params_array
)
4436 head
= (MMacro
*) hash_findix(&mmacros
, tline
->text
);
4439 * Efficiency: first we see if any macro exists with the given
4440 * name. If not, we can return NULL immediately. _Then_ we
4441 * count the parameters, and then we look further along the
4442 * list if necessary to find the proper MMacro.
4444 list_for_each(m
, head
)
4445 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
4451 * OK, we have a potential macro. Count and demarcate the
4454 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
4457 * So we know how many parameters we've got. Find the MMacro
4458 * structure that handles this number.
4461 if (m
->nparam_min
<= nparam
4462 && (m
->plus
|| nparam
<= m
->nparam_max
)) {
4464 * This one is right. Just check if cycle removal
4465 * prohibits us using it before we actually celebrate...
4467 if (m
->in_progress
> m
->max_depth
) {
4468 if (m
->max_depth
> 0) {
4470 "reached maximum recursion depth of %i",
4477 * It's right, and we can use it. Add its default
4478 * parameters to the end of our list if necessary.
4480 if (m
->defaults
&& nparam
< m
->nparam_min
+ m
->ndefs
) {
4482 nasm_realloc(params
,
4483 ((m
->nparam_min
+ m
->ndefs
+
4484 1) * sizeof(*params
)));
4485 while (nparam
< m
->nparam_min
+ m
->ndefs
) {
4486 params
[nparam
] = m
->defaults
[nparam
- m
->nparam_min
];
4491 * If we've gone over the maximum parameter count (and
4492 * we're in Plus mode), ignore parameters beyond
4495 if (m
->plus
&& nparam
> m
->nparam_max
)
4496 nparam
= m
->nparam_max
;
4498 * Then terminate the parameter list, and leave.
4500 if (!params
) { /* need this special case */
4501 params
= nasm_malloc(sizeof(*params
));
4504 params
[nparam
] = NULL
;
4505 *params_array
= params
;
4509 * This one wasn't right: look for the next one with the
4512 list_for_each(m
, m
->next
)
4513 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
4518 * After all that, we didn't find one with the right number of
4519 * parameters. Issue a warning, and fail to expand the macro.
4521 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4522 "macro `%s' exists, but not taking %d parameters",
4523 tline
->text
, nparam
);
4530 * Save MMacro invocation specific fields in
4531 * preparation for a recursive macro expansion
4533 static void push_mmacro(MMacro
*m
)
4535 MMacroInvocation
*i
;
4537 i
= nasm_malloc(sizeof(MMacroInvocation
));
4539 i
->params
= m
->params
;
4540 i
->iline
= m
->iline
;
4541 i
->nparam
= m
->nparam
;
4542 i
->rotate
= m
->rotate
;
4543 i
->paramlen
= m
->paramlen
;
4544 i
->unique
= m
->unique
;
4545 i
->condcnt
= m
->condcnt
;
4551 * Restore MMacro invocation specific fields that were
4552 * saved during a previous recursive macro expansion
4554 static void pop_mmacro(MMacro
*m
)
4556 MMacroInvocation
*i
;
4561 m
->params
= i
->params
;
4562 m
->iline
= i
->iline
;
4563 m
->nparam
= i
->nparam
;
4564 m
->rotate
= i
->rotate
;
4565 m
->paramlen
= i
->paramlen
;
4566 m
->unique
= i
->unique
;
4567 m
->condcnt
= i
->condcnt
;
4574 * Expand the multi-line macro call made by the given line, if
4575 * there is one to be expanded. If there is, push the expansion on
4576 * istk->expansion and return 1. Otherwise return 0.
4578 static int expand_mmacro(Token
* tline
)
4580 Token
*startline
= tline
;
4581 Token
*label
= NULL
;
4582 int dont_prepend
= 0;
4583 Token
**params
, *t
, *mtok
, *tt
;
4586 int i
, nparam
, *paramlen
;
4591 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4592 if (!tok_type_(t
, TOK_ID
) && !tok_type_(t
, TOK_PREPROC_ID
))
4595 m
= is_mmacro(t
, ¶ms
);
4601 * We have an id which isn't a macro call. We'll assume
4602 * it might be a label; we'll also check to see if a
4603 * colon follows it. Then, if there's another id after
4604 * that lot, we'll check it again for macro-hood.
4608 if (tok_type_(t
, TOK_WHITESPACE
))
4609 last
= t
, t
= t
->next
;
4610 if (tok_is_(t
, ":")) {
4612 last
= t
, t
= t
->next
;
4613 if (tok_type_(t
, TOK_WHITESPACE
))
4614 last
= t
, t
= t
->next
;
4616 if (!tok_type_(t
, TOK_ID
) || !(m
= is_mmacro(t
, ¶ms
)))
4624 * Fix up the parameters: this involves stripping leading and
4625 * trailing whitespace, then stripping braces if they are
4628 for (nparam
= 0; params
[nparam
]; nparam
++) ;
4629 paramlen
= nparam
? nasm_malloc(nparam
* sizeof(*paramlen
)) : NULL
;
4631 for (i
= 0; params
[i
]; i
++) {
4633 int comma
= (!m
->plus
|| i
< nparam
- 1);
4637 if (tok_is_(t
, "{"))
4638 t
= t
->next
, brace
= true, comma
= false;
4642 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
4643 break; /* ... because we have hit a comma */
4644 if (comma
&& t
->type
== TOK_WHITESPACE
4645 && tok_is_(t
->next
, ","))
4646 break; /* ... or a space then a comma */
4647 if (brace
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "}"))
4648 break; /* ... or a brace */
4655 * OK, we have a MMacro structure together with a set of
4656 * parameters. We must now go through the expansion and push
4657 * copies of each Line on to istk->expansion. Substitution of
4658 * parameter tokens and macro-local tokens doesn't get done
4659 * until the single-line macro substitution process; this is
4660 * because delaying them allows us to change the semantics
4661 * later through %rotate.
4663 * First, push an end marker on to istk->expansion, mark this
4664 * macro as in progress, and set up its invocation-specific
4667 ll
= nasm_malloc(sizeof(Line
));
4668 ll
->next
= istk
->expansion
;
4671 istk
->expansion
= ll
;
4674 * Save the previous MMacro expansion in the case of
4677 if (m
->max_depth
&& m
->in_progress
)
4685 m
->paramlen
= paramlen
;
4686 m
->unique
= unique
++;
4690 m
->next_active
= istk
->mstk
;
4693 list_for_each(l
, m
->expansion
) {
4696 ll
= nasm_malloc(sizeof(Line
));
4697 ll
->finishes
= NULL
;
4698 ll
->next
= istk
->expansion
;
4699 istk
->expansion
= ll
;
4702 list_for_each(t
, l
->first
) {
4706 tt
= *tail
= new_Token(NULL
, TOK_ID
, mname
, 0);
4708 case TOK_PREPROC_QQ
:
4709 tt
= *tail
= new_Token(NULL
, TOK_ID
, m
->name
, 0);
4711 case TOK_PREPROC_ID
:
4712 if (t
->text
[1] == '0' && t
->text
[2] == '0') {
4720 tt
= *tail
= new_Token(NULL
, x
->type
, x
->text
, 0);
4729 * If we had a label, push it on as the first line of
4730 * the macro expansion.
4733 if (dont_prepend
< 0)
4734 free_tlist(startline
);
4736 ll
= nasm_malloc(sizeof(Line
));
4737 ll
->finishes
= NULL
;
4738 ll
->next
= istk
->expansion
;
4739 istk
->expansion
= ll
;
4740 ll
->first
= startline
;
4741 if (!dont_prepend
) {
4743 label
= label
->next
;
4744 label
->next
= tt
= new_Token(NULL
, TOK_OTHER
, ":", 0);
4749 list
->uplevel(m
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
4754 /* The function that actually does the error reporting */
4755 static void verror(int severity
, const char *fmt
, va_list arg
)
4758 MMacro
*mmac
= NULL
;
4761 vsnprintf(buff
, sizeof(buff
), fmt
, arg
);
4763 /* get %macro name */
4764 if (istk
&& istk
->mstk
) {
4766 /* but %rep blocks should be skipped */
4767 while (mmac
&& !mmac
->name
)
4768 mmac
= mmac
->next_active
, delta
++;
4772 nasm_error(severity
, "(%s:%d) %s",
4773 mmac
->name
, mmac
->lineno
- delta
, buff
);
4775 nasm_error(severity
, "%s", buff
);
4779 * Since preprocessor always operate only on the line that didn't
4780 * arrived yet, we should always use ERR_OFFBY1.
4782 static void error(int severity
, const char *fmt
, ...)
4786 /* If we're in a dead branch of IF or something like it, ignore the error */
4787 if (istk
&& istk
->conds
&& !emitting(istk
->conds
->state
))
4791 verror(severity
, fmt
, arg
);
4796 * Because %else etc are evaluated in the state context
4797 * of the previous branch, errors might get lost with error():
4798 * %if 0 ... %else trailing garbage ... %endif
4799 * So %else etc should report errors with this function.
4801 static void error_precond(int severity
, const char *fmt
, ...)
4805 /* Only ignore the error if it's really in a dead branch */
4806 if (istk
&& istk
->conds
&& istk
->conds
->state
== COND_NEVER
)
4810 verror(severity
, fmt
, arg
);
4815 pp_reset(char *file
, int apass
, ListGen
* listgen
, StrList
**deplist
)
4820 istk
= nasm_malloc(sizeof(Include
));
4823 istk
->expansion
= NULL
;
4825 istk
->fp
= fopen(file
, "r");
4827 src_set_fname(nasm_strdup(file
));
4831 error(ERR_FATAL
|ERR_NOFILE
, "unable to open input file `%s'",
4834 nested_mac_count
= 0;
4835 nested_rep_count
= 0;
4838 if (tasm_compatible_mode
) {
4839 stdmacpos
= nasm_stdmac
;
4841 stdmacpos
= nasm_stdmac_after_tasm
;
4843 any_extrastdmac
= extrastdmac
&& *extrastdmac
;
4848 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
4849 * The caller, however, will also pass in 3 for preprocess-only so
4850 * we can set __PASS__ accordingly.
4852 pass
= apass
> 2 ? 2 : apass
;
4854 dephead
= deptail
= deplist
;
4856 StrList
*sl
= nasm_malloc(strlen(file
)+1+sizeof sl
->next
);
4858 strcpy(sl
->str
, file
);
4860 deptail
= &sl
->next
;
4864 * Define the __PASS__ macro. This is defined here unlike
4865 * all the other builtins, because it is special -- it varies between
4868 t
= nasm_malloc(sizeof(*t
));
4870 make_tok_num(t
, apass
);
4872 define_smacro(NULL
, "__PASS__", true, 0, t
);
4875 static char *pp_getline(void)
4882 * Fetch a tokenized line, either from the macro-expansion
4883 * buffer or from the input file.
4886 while (istk
->expansion
&& istk
->expansion
->finishes
) {
4887 Line
*l
= istk
->expansion
;
4888 if (!l
->finishes
->name
&& l
->finishes
->in_progress
> 1) {
4892 * This is a macro-end marker for a macro with no
4893 * name, which means it's not really a macro at all
4894 * but a %rep block, and the `in_progress' field is
4895 * more than 1, meaning that we still need to
4896 * repeat. (1 means the natural last repetition; 0
4897 * means termination by %exitrep.) We have
4898 * therefore expanded up to the %endrep, and must
4899 * push the whole block on to the expansion buffer
4900 * again. We don't bother to remove the macro-end
4901 * marker: we'd only have to generate another one
4904 l
->finishes
->in_progress
--;
4905 list_for_each(l
, l
->finishes
->expansion
) {
4906 Token
*t
, *tt
, **tail
;
4908 ll
= nasm_malloc(sizeof(Line
));
4909 ll
->next
= istk
->expansion
;
4910 ll
->finishes
= NULL
;
4914 list_for_each(t
, l
->first
) {
4915 if (t
->text
|| t
->type
== TOK_WHITESPACE
) {
4916 tt
= *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
4921 istk
->expansion
= ll
;
4925 * Check whether a `%rep' was started and not ended
4926 * within this macro expansion. This can happen and
4927 * should be detected. It's a fatal error because
4928 * I'm too confused to work out how to recover
4934 "defining with name in expansion");
4935 else if (istk
->mstk
->name
)
4937 "`%%rep' without `%%endrep' within"
4938 " expansion of macro `%s'",
4943 * FIXME: investigate the relationship at this point between
4944 * istk->mstk and l->finishes
4947 MMacro
*m
= istk
->mstk
;
4948 istk
->mstk
= m
->next_active
;
4951 * This was a real macro call, not a %rep, and
4952 * therefore the parameter information needs to
4957 l
->finishes
->in_progress
--;
4959 nasm_free(m
->params
);
4960 free_tlist(m
->iline
);
4961 nasm_free(m
->paramlen
);
4962 l
->finishes
->in_progress
= 0;
4967 istk
->expansion
= l
->next
;
4969 list
->downlevel(LIST_MACRO
);
4972 while (1) { /* until we get a line we can use */
4974 if (istk
->expansion
) { /* from a macro expansion */
4976 Line
*l
= istk
->expansion
;
4978 istk
->mstk
->lineno
++;
4980 istk
->expansion
= l
->next
;
4982 p
= detoken(tline
, false);
4983 list
->line(LIST_MACRO
, p
);
4988 if (line
) { /* from the current input file */
4989 line
= prepreproc(line
);
4990 tline
= tokenize(line
);
4995 * The current file has ended; work down the istk
5001 /* nasm_error can't be conditionally suppressed */
5002 nasm_error(ERR_FATAL
,
5003 "expected `%%endif' before end of file");
5005 /* only set line and file name if there's a next node */
5007 src_set_linnum(i
->lineno
);
5008 nasm_free(src_set_fname(i
->fname
));
5011 list
->downlevel(LIST_INCLUDE
);
5015 if (istk
->expansion
&& istk
->expansion
->finishes
)
5021 * We must expand MMacro parameters and MMacro-local labels
5022 * _before_ we plunge into directive processing, to cope
5023 * with things like `%define something %1' such as STRUC
5024 * uses. Unless we're _defining_ a MMacro, in which case
5025 * those tokens should be left alone to go into the
5026 * definition; and unless we're in a non-emitting
5027 * condition, in which case we don't want to meddle with
5030 if (!defining
&& !(istk
->conds
&& !emitting(istk
->conds
->state
))
5031 && !(istk
->mstk
&& !istk
->mstk
->in_progress
)) {
5032 tline
= expand_mmac_params(tline
);
5036 * Check the line to see if it's a preprocessor directive.
5038 if (do_directive(tline
) == DIRECTIVE_FOUND
) {
5040 } else if (defining
) {
5042 * We're defining a multi-line macro. We emit nothing
5044 * shove the tokenized line on to the macro definition.
5046 Line
*l
= nasm_malloc(sizeof(Line
));
5047 l
->next
= defining
->expansion
;
5050 defining
->expansion
= l
;
5052 } else if (istk
->conds
&& !emitting(istk
->conds
->state
)) {
5054 * We're in a non-emitting branch of a condition block.
5055 * Emit nothing at all, not even a blank line: when we
5056 * emerge from the condition we'll give a line-number
5057 * directive so we keep our place correctly.
5061 } else if (istk
->mstk
&& !istk
->mstk
->in_progress
) {
5063 * We're in a %rep block which has been terminated, so
5064 * we're walking through to the %endrep without
5065 * emitting anything. Emit nothing at all, not even a
5066 * blank line: when we emerge from the %rep block we'll
5067 * give a line-number directive so we keep our place
5073 tline
= expand_smacro(tline
);
5074 if (!expand_mmacro(tline
)) {
5076 * De-tokenize the line again, and emit it.
5078 line
= detoken(tline
, true);
5082 continue; /* expand_mmacro calls free_tlist */
5090 static void pp_cleanup(int pass
)
5093 if (defining
->name
) {
5095 "end of file while still defining macro `%s'",
5098 error(ERR_NONFATAL
, "end of file while still in %%rep");
5101 free_mmacro(defining
);
5111 nasm_free(i
->fname
);
5116 nasm_free(src_set_fname(NULL
));
5121 while ((i
= ipath
)) {
5130 void pp_include_path(char *path
)
5134 i
= nasm_malloc(sizeof(IncPath
));
5135 i
->path
= path
? nasm_strdup(path
) : NULL
;
5148 void pp_pre_include(char *fname
)
5150 Token
*inc
, *space
, *name
;
5153 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
5154 space
= new_Token(name
, TOK_WHITESPACE
, NULL
, 0);
5155 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
5157 l
= nasm_malloc(sizeof(Line
));
5164 void pp_pre_define(char *definition
)
5170 equals
= strchr(definition
, '=');
5171 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5172 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
5175 space
->next
= tokenize(definition
);
5179 l
= nasm_malloc(sizeof(Line
));
5186 void pp_pre_undefine(char *definition
)
5191 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5192 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
5193 space
->next
= tokenize(definition
);
5195 l
= nasm_malloc(sizeof(Line
));
5203 * Added by Keith Kanios:
5205 * This function is used to assist with "runtime" preprocessor
5206 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
5208 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
5209 * PASS A VALID STRING TO THIS FUNCTION!!!!!
5212 void pp_runtime(char *definition
)
5216 def
= tokenize(definition
);
5217 if (do_directive(def
) == NO_DIRECTIVE_FOUND
)
5222 void pp_extra_stdmac(macros_t
*macros
)
5224 extrastdmac
= macros
;
5227 static void make_tok_num(Token
* tok
, int64_t val
)
5230 snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
5231 tok
->text
= nasm_strdup(numbuf
);
5232 tok
->type
= TOK_NUMBER
;