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
== '{') {
917 while (*p
&& *p
!= '}') {
924 type
= TOK_PREPROC_ID
;
925 } else if (*p
== '[') {
927 line
+= 2; /* Skip the leading %[ */
929 while (lvl
&& (c
= *p
++)) {
941 p
= nasm_skip_string(p
- 1) + 1;
951 error(ERR_NONFATAL
, "unterminated %[ construct");
953 } else if (*p
== '?') {
954 type
= TOK_PREPROC_Q
; /* %? */
957 type
= TOK_PREPROC_QQ
; /* %?? */
960 } else if (*p
== '!') {
961 type
= TOK_PREPROC_ID
;
966 } while (isidchar(*p
));
967 } else if (*p
== '\'' || *p
== '\"' || *p
== '`') {
968 p
= nasm_skip_string(p
);
972 error(ERR_NONFATAL
|ERR_PASS1
, "unterminated %! string");
974 /* %! without string or identifier */
975 type
= TOK_OTHER
; /* Legacy behavior... */
977 } else if (isidchar(*p
) ||
978 ((*p
== '!' || *p
== '%' || *p
== '$') &&
983 while (isidchar(*p
));
984 type
= TOK_PREPROC_ID
;
990 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
993 while (*p
&& isidchar(*p
))
995 } else if (*p
== '\'' || *p
== '"' || *p
== '`') {
1000 p
= nasm_skip_string(p
);
1005 error(ERR_WARNING
|ERR_PASS1
, "unterminated string");
1006 /* Handling unterminated strings by UNV */
1009 } else if (p
[0] == '$' && p
[1] == '$') {
1010 type
= TOK_OTHER
; /* TOKEN_BASE */
1012 } else if (isnumstart(*p
)) {
1013 bool is_hex
= false;
1014 bool is_float
= false;
1030 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
1032 if (*p
== '+' || *p
== '-') {
1034 * e can only be followed by +/- if it is either a
1035 * prefixed hex number or a floating-point number
1040 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
1042 } else if (c
== 'P' || c
== 'p') {
1044 if (*p
== '+' || *p
== '-')
1046 } else if (isnumchar(c
) || c
== '_')
1047 ; /* just advance */
1048 else if (c
== '.') {
1050 * we need to deal with consequences of the legacy
1051 * parser, like "1.nolist" being two tokens
1052 * (TOK_NUMBER, TOK_ID) here; at least give it
1053 * a shot for now. In the future, we probably need
1054 * a flex-based scanner with proper pattern matching
1055 * to do it as well as it can be done. Nothing in
1056 * the world is going to help the person who wants
1057 * 0x123.p16 interpreted as two tokens, though.
1063 if (nasm_isdigit(*r
) || (is_hex
&& nasm_isxdigit(*r
)) ||
1064 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
1065 (*r
== 'p' || *r
== 'P')) {
1069 break; /* Terminate the token */
1073 p
--; /* Point to first character beyond number */
1075 if (p
== line
+1 && *line
== '$') {
1076 type
= TOK_OTHER
; /* TOKEN_HERE */
1078 if (has_e
&& !is_hex
) {
1079 /* 1e13 is floating-point, but 1e13h is not */
1083 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
1085 } else if (nasm_isspace(*p
)) {
1086 type
= TOK_WHITESPACE
;
1087 p
= nasm_skip_spaces(p
);
1089 * Whitespace just before end-of-line is discarded by
1090 * pretending it's a comment; whitespace just before a
1091 * comment gets lumped into the comment.
1093 if (!*p
|| *p
== ';') {
1098 } else if (*p
== ';') {
1104 * Anything else is an operator of some kind. We check
1105 * for all the double-character operators (>>, <<, //,
1106 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1107 * else is a single-character operator.
1110 if ((p
[0] == '>' && p
[1] == '>') ||
1111 (p
[0] == '<' && p
[1] == '<') ||
1112 (p
[0] == '/' && p
[1] == '/') ||
1113 (p
[0] == '<' && p
[1] == '=') ||
1114 (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] == '^')) {
1126 /* Handling unterminated string by UNV */
1129 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1130 t->text[p-line] = *line;
1134 if (type
!= TOK_COMMENT
) {
1135 *tail
= t
= new_Token(NULL
, type
, line
, p
- line
);
1144 * this function allocates a new managed block of memory and
1145 * returns a pointer to the block. The managed blocks are
1146 * deleted only all at once by the delete_Blocks function.
1148 static void *new_Block(size_t size
)
1150 Blocks
*b
= &blocks
;
1152 /* first, get to the end of the linked list */
1155 /* now allocate the requested chunk */
1156 b
->chunk
= nasm_malloc(size
);
1158 /* now allocate a new block for the next request */
1159 b
->next
= nasm_malloc(sizeof(Blocks
));
1160 /* and initialize the contents of the new block */
1161 b
->next
->next
= NULL
;
1162 b
->next
->chunk
= NULL
;
1167 * this function deletes all managed blocks of memory
1169 static void delete_Blocks(void)
1171 Blocks
*a
, *b
= &blocks
;
1174 * keep in mind that the first block, pointed to by blocks
1175 * is a static and not dynamically allocated, so we don't
1180 nasm_free(b
->chunk
);
1189 * this function creates a new Token and passes a pointer to it
1190 * back to the caller. It sets the type and text elements, and
1191 * also the a.mac and next elements to NULL.
1193 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
1194 const char *text
, int txtlen
)
1200 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1201 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1202 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1203 freeTokens
[i
].next
= NULL
;
1206 freeTokens
= t
->next
;
1210 if (type
== TOK_WHITESPACE
|| !text
) {
1214 txtlen
= strlen(text
);
1215 t
->text
= nasm_malloc(txtlen
+1);
1216 memcpy(t
->text
, text
, txtlen
);
1217 t
->text
[txtlen
] = '\0';
1222 static Token
*delete_Token(Token
* t
)
1224 Token
*next
= t
->next
;
1226 t
->next
= freeTokens
;
1232 * Convert a line of tokens back into text.
1233 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1234 * will be transformed into ..@ctxnum.xxx
1236 static char *detoken(Token
* tlist
, bool expand_locals
)
1243 list_for_each(t
, tlist
) {
1244 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
1249 if (*v
== '\'' || *v
== '\"' || *v
== '`') {
1250 size_t len
= nasm_unquote(v
, NULL
);
1251 size_t clen
= strlen(v
);
1254 error(ERR_NONFATAL
| ERR_PASS1
,
1255 "NUL character in %! string");
1261 char *p
= getenv(v
);
1263 error(ERR_NONFATAL
| ERR_PASS1
,
1264 "nonexistent environment variable `%s'", v
);
1267 t
->text
= nasm_strdup(p
);
1272 /* Expand local macros here and not during preprocessing */
1273 if (expand_locals
&&
1274 t
->type
== TOK_PREPROC_ID
&& t
->text
&&
1275 t
->text
[0] == '%' && t
->text
[1] == '$') {
1278 Context
*ctx
= get_ctx(t
->text
, &q
, false);
1281 snprintf(buffer
, sizeof(buffer
), "..@%"PRIu32
".", ctx
->number
);
1282 p
= nasm_strcat(buffer
, q
);
1287 if (t
->type
== TOK_WHITESPACE
)
1290 len
+= strlen(t
->text
);
1293 p
= line
= nasm_malloc(len
+ 1);
1295 list_for_each(t
, tlist
) {
1296 if (t
->type
== TOK_WHITESPACE
) {
1298 } else if (t
->text
) {
1310 * A scanner, suitable for use by the expression evaluator, which
1311 * operates on a line of Tokens. Expects a pointer to a pointer to
1312 * the first token in the line to be passed in as its private_data
1315 * FIX: This really needs to be unified with stdscan.
1317 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1319 Token
**tlineptr
= private_data
;
1321 char ourcopy
[MAX_KEYWORD
+1], *p
, *r
, *s
;
1325 *tlineptr
= tline
? tline
->next
: NULL
;
1326 } while (tline
&& (tline
->type
== TOK_WHITESPACE
||
1327 tline
->type
== TOK_COMMENT
));
1330 return tokval
->t_type
= TOKEN_EOS
;
1332 tokval
->t_charptr
= tline
->text
;
1334 if (tline
->text
[0] == '$' && !tline
->text
[1])
1335 return tokval
->t_type
= TOKEN_HERE
;
1336 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[2])
1337 return tokval
->t_type
= TOKEN_BASE
;
1339 if (tline
->type
== TOK_ID
) {
1340 p
= tokval
->t_charptr
= tline
->text
;
1342 tokval
->t_charptr
++;
1343 return tokval
->t_type
= TOKEN_ID
;
1346 for (r
= p
, s
= ourcopy
; *r
; r
++) {
1347 if (r
>= p
+MAX_KEYWORD
)
1348 return tokval
->t_type
= TOKEN_ID
; /* Not a keyword */
1349 *s
++ = nasm_tolower(*r
);
1352 /* right, so we have an identifier sitting in temp storage. now,
1353 * is it actually a register or instruction name, or what? */
1354 return nasm_token_hash(ourcopy
, tokval
);
1357 if (tline
->type
== TOK_NUMBER
) {
1359 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
1360 tokval
->t_charptr
= tline
->text
;
1362 return tokval
->t_type
= TOKEN_ERRNUM
;
1364 return tokval
->t_type
= TOKEN_NUM
;
1367 if (tline
->type
== TOK_FLOAT
) {
1368 return tokval
->t_type
= TOKEN_FLOAT
;
1371 if (tline
->type
== TOK_STRING
) {
1374 bq
= tline
->text
[0];
1375 tokval
->t_charptr
= tline
->text
;
1376 tokval
->t_inttwo
= nasm_unquote(tline
->text
, &ep
);
1378 if (ep
[0] != bq
|| ep
[1] != '\0')
1379 return tokval
->t_type
= TOKEN_ERRSTR
;
1381 return tokval
->t_type
= TOKEN_STR
;
1384 if (tline
->type
== TOK_OTHER
) {
1385 if (!strcmp(tline
->text
, "<<"))
1386 return tokval
->t_type
= TOKEN_SHL
;
1387 if (!strcmp(tline
->text
, ">>"))
1388 return tokval
->t_type
= TOKEN_SHR
;
1389 if (!strcmp(tline
->text
, "//"))
1390 return tokval
->t_type
= TOKEN_SDIV
;
1391 if (!strcmp(tline
->text
, "%%"))
1392 return tokval
->t_type
= TOKEN_SMOD
;
1393 if (!strcmp(tline
->text
, "=="))
1394 return tokval
->t_type
= TOKEN_EQ
;
1395 if (!strcmp(tline
->text
, "<>"))
1396 return tokval
->t_type
= TOKEN_NE
;
1397 if (!strcmp(tline
->text
, "!="))
1398 return tokval
->t_type
= TOKEN_NE
;
1399 if (!strcmp(tline
->text
, "<="))
1400 return tokval
->t_type
= TOKEN_LE
;
1401 if (!strcmp(tline
->text
, ">="))
1402 return tokval
->t_type
= TOKEN_GE
;
1403 if (!strcmp(tline
->text
, "&&"))
1404 return tokval
->t_type
= TOKEN_DBL_AND
;
1405 if (!strcmp(tline
->text
, "^^"))
1406 return tokval
->t_type
= TOKEN_DBL_XOR
;
1407 if (!strcmp(tline
->text
, "||"))
1408 return tokval
->t_type
= TOKEN_DBL_OR
;
1412 * We have no other options: just return the first character of
1415 return tokval
->t_type
= tline
->text
[0];
1419 * Compare a string to the name of an existing macro; this is a
1420 * simple wrapper which calls either strcmp or nasm_stricmp
1421 * depending on the value of the `casesense' parameter.
1423 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
1425 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
1429 * Compare a string to the name of an existing macro; this is a
1430 * simple wrapper which calls either strcmp or nasm_stricmp
1431 * depending on the value of the `casesense' parameter.
1433 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
1435 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
1439 * Return the Context structure associated with a %$ token. Return
1440 * NULL, having _already_ reported an error condition, if the
1441 * context stack isn't deep enough for the supplied number of $
1443 * If all_contexts == true, contexts that enclose current are
1444 * also scanned for such smacro, until it is found; if not -
1445 * only the context that directly results from the number of $'s
1446 * in variable's name.
1448 * If "namep" is non-NULL, set it to the pointer to the macro name
1449 * tail, i.e. the part beyond %$...
1451 static Context
*get_ctx(const char *name
, const char **namep
,
1461 if (!name
|| name
[0] != '%' || name
[1] != '$')
1465 error(ERR_NONFATAL
, "`%s': context stack is empty", name
);
1472 while (ctx
&& *name
== '$') {
1478 error(ERR_NONFATAL
, "`%s': context stack is only"
1479 " %d level%s deep", name
, i
, (i
== 1 ? "" : "s"));
1490 * NOTE: In 2.10 we will not need lookup in extarnal
1491 * contexts, so this is a gentle way to inform users
1492 * about their source code need to be updated
1495 /* first round -- check the current context */
1496 m
= hash_findix(&ctx
->localmac
, name
);
1498 if (!mstrcmp(m
->name
, name
, m
->casesense
))
1503 /* second round - external contexts */
1504 while ((ctx
= ctx
->next
)) {
1505 /* Search for this smacro in found context */
1506 m
= hash_findix(&ctx
->localmac
, name
);
1508 if (!mstrcmp(m
->name
, name
, m
->casesense
)) {
1509 /* NOTE: deprecated as of 2.10 */
1510 static int once
= 0;
1512 error(ERR_WARNING
, "context-local macro expansion"
1513 " fall-through (automatic searching of outer"
1514 " contexts) will be deprecated starting in"
1515 " NASM 2.10, please see the NASM Manual for"
1516 " more information");
1519 error(ERR_WARNING
, "`%s': context-local macro expansion fall-through", name
);
1530 * Check to see if a file is already in a string list
1532 static bool in_list(const StrList
*list
, const char *str
)
1535 if (!strcmp(list
->str
, str
))
1543 * Open an include file. This routine must always return a valid
1544 * file pointer if it returns - it's responsible for throwing an
1545 * ERR_FATAL and bombing out completely if not. It should also try
1546 * the include path one by one until it finds the file or reaches
1547 * the end of the path.
1549 static FILE *inc_fopen(const char *file
, StrList
**dhead
, StrList
***dtail
,
1554 IncPath
*ip
= ipath
;
1555 int len
= strlen(file
);
1556 size_t prefix_len
= 0;
1560 sl
= nasm_malloc(prefix_len
+len
+1+sizeof sl
->next
);
1561 memcpy(sl
->str
, prefix
, prefix_len
);
1562 memcpy(sl
->str
+prefix_len
, file
, len
+1);
1563 fp
= fopen(sl
->str
, "r");
1564 if (fp
&& dhead
&& !in_list(*dhead
, sl
->str
)) {
1582 prefix_len
= strlen(prefix
);
1584 /* -MG given and file not found */
1585 if (dhead
&& !in_list(*dhead
, file
)) {
1586 sl
= nasm_malloc(len
+1+sizeof sl
->next
);
1588 strcpy(sl
->str
, file
);
1596 error(ERR_FATAL
, "unable to open include file `%s'", file
);
1601 * Determine if we should warn on defining a single-line macro of
1602 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1603 * return true if _any_ single-line macro of that name is defined.
1604 * Otherwise, will return true if a single-line macro with either
1605 * `nparam' or no parameters is defined.
1607 * If a macro with precisely the right number of parameters is
1608 * defined, or nparam is -1, the address of the definition structure
1609 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1610 * is NULL, no action will be taken regarding its contents, and no
1613 * Note that this is also called with nparam zero to resolve
1616 * If you already know which context macro belongs to, you can pass
1617 * the context pointer as first parameter; if you won't but name begins
1618 * with %$ the context will be automatically computed. If all_contexts
1619 * is true, macro will be searched in outer contexts as well.
1622 smacro_defined(Context
* ctx
, const char *name
, int nparam
, SMacro
** defn
,
1625 struct hash_table
*smtbl
;
1629 smtbl
= &ctx
->localmac
;
1630 } else if (name
[0] == '%' && name
[1] == '$') {
1632 ctx
= get_ctx(name
, &name
, false);
1634 return false; /* got to return _something_ */
1635 smtbl
= &ctx
->localmac
;
1639 m
= (SMacro
*) hash_findix(smtbl
, name
);
1642 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
1643 (nparam
<= 0 || m
->nparam
== 0 || nparam
== (int) m
->nparam
)) {
1645 if (nparam
== (int) m
->nparam
|| nparam
== -1)
1659 * Count and mark off the parameters in a multi-line macro call.
1660 * This is called both from within the multi-line macro expansion
1661 * code, and also to mark off the default parameters when provided
1662 * in a %macro definition line.
1664 static void count_mmac_params(Token
* t
, int *nparam
, Token
*** params
)
1666 int paramsize
, brace
;
1668 *nparam
= paramsize
= 0;
1671 /* +1: we need space for the final NULL */
1672 if (*nparam
+1 >= paramsize
) {
1673 paramsize
+= PARAM_DELTA
;
1674 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
1678 if (tok_is_(t
, "{"))
1680 (*params
)[(*nparam
)++] = t
;
1681 while (tok_isnt_(t
, brace
? "}" : ","))
1683 if (t
) { /* got a comma/brace */
1687 * Now we've found the closing brace, look further
1691 if (tok_isnt_(t
, ",")) {
1693 "braces do not enclose all of macro parameter");
1694 while (tok_isnt_(t
, ","))
1698 t
= t
->next
; /* eat the comma */
1705 * Determine whether one of the various `if' conditions is true or
1708 * We must free the tline we get passed.
1710 static bool if_condition(Token
* tline
, enum preproc_token ct
)
1712 enum pp_conditional i
= PP_COND(ct
);
1714 Token
*t
, *tt
, **tptr
, *origline
;
1715 struct tokenval tokval
;
1717 enum pp_token_type needtype
;
1724 j
= false; /* have we matched yet? */
1729 if (tline
->type
!= TOK_ID
) {
1731 "`%s' expects context identifiers", pp_directives
[ct
]);
1732 free_tlist(origline
);
1735 if (cstk
&& cstk
->name
&& !nasm_stricmp(tline
->text
, cstk
->name
))
1737 tline
= tline
->next
;
1742 j
= false; /* have we matched yet? */
1745 if (!tline
|| (tline
->type
!= TOK_ID
&&
1746 (tline
->type
!= TOK_PREPROC_ID
||
1747 tline
->text
[1] != '$'))) {
1749 "`%s' expects macro identifiers", pp_directives
[ct
]);
1752 if (smacro_defined(NULL
, tline
->text
, 0, NULL
, true))
1754 tline
= tline
->next
;
1759 tline
= expand_smacro(tline
);
1760 j
= false; /* have we matched yet? */
1763 if (!tline
|| (tline
->type
!= TOK_ID
&&
1764 tline
->type
!= TOK_STRING
&&
1765 (tline
->type
!= TOK_PREPROC_ID
||
1766 tline
->text
[1] != '!'))) {
1768 "`%s' expects environment variable names",
1773 if (tline
->type
== TOK_PREPROC_ID
)
1774 p
+= 2; /* Skip leading %! */
1775 if (*p
== '\'' || *p
== '\"' || *p
== '`')
1776 nasm_unquote_cstr(p
, ct
);
1779 tline
= tline
->next
;
1785 tline
= expand_smacro(tline
);
1787 while (tok_isnt_(tt
, ","))
1791 "`%s' expects two comma-separated arguments",
1796 j
= true; /* assume equality unless proved not */
1797 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1798 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1799 error(ERR_NONFATAL
, "`%s': more than one comma on line",
1803 if (t
->type
== TOK_WHITESPACE
) {
1807 if (tt
->type
== TOK_WHITESPACE
) {
1811 if (tt
->type
!= t
->type
) {
1812 j
= false; /* found mismatching tokens */
1815 /* When comparing strings, need to unquote them first */
1816 if (t
->type
== TOK_STRING
) {
1817 size_t l1
= nasm_unquote(t
->text
, NULL
);
1818 size_t l2
= nasm_unquote(tt
->text
, NULL
);
1824 if (mmemcmp(t
->text
, tt
->text
, l1
, i
== PPC_IFIDN
)) {
1828 } else if (mstrcmp(tt
->text
, t
->text
, i
== PPC_IFIDN
) != 0) {
1829 j
= false; /* found mismatching tokens */
1836 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
1837 j
= false; /* trailing gunk on one end or other */
1843 MMacro searching
, *mmac
;
1846 tline
= expand_id(tline
);
1847 if (!tok_type_(tline
, TOK_ID
)) {
1849 "`%s' expects a macro name", pp_directives
[ct
]);
1852 searching
.name
= nasm_strdup(tline
->text
);
1853 searching
.casesense
= true;
1854 searching
.plus
= false;
1855 searching
.nolist
= false;
1856 searching
.in_progress
= 0;
1857 searching
.max_depth
= 0;
1858 searching
.rep_nest
= NULL
;
1859 searching
.nparam_min
= 0;
1860 searching
.nparam_max
= INT_MAX
;
1861 tline
= expand_smacro(tline
->next
);
1864 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
1866 "`%s' expects a parameter count or nothing",
1869 searching
.nparam_min
= searching
.nparam_max
=
1870 readnum(tline
->text
, &j
);
1873 "unable to parse parameter count `%s'",
1876 if (tline
&& tok_is_(tline
->next
, "-")) {
1877 tline
= tline
->next
->next
;
1878 if (tok_is_(tline
, "*"))
1879 searching
.nparam_max
= INT_MAX
;
1880 else if (!tok_type_(tline
, TOK_NUMBER
))
1882 "`%s' expects a parameter count after `-'",
1885 searching
.nparam_max
= readnum(tline
->text
, &j
);
1888 "unable to parse parameter count `%s'",
1890 if (searching
.nparam_min
> searching
.nparam_max
)
1892 "minimum parameter count exceeds maximum");
1895 if (tline
&& tok_is_(tline
->next
, "+")) {
1896 tline
= tline
->next
;
1897 searching
.plus
= true;
1899 mmac
= (MMacro
*) hash_findix(&mmacros
, searching
.name
);
1901 if (!strcmp(mmac
->name
, searching
.name
) &&
1902 (mmac
->nparam_min
<= searching
.nparam_max
1904 && (searching
.nparam_min
<= mmac
->nparam_max
1911 if (tline
&& tline
->next
)
1912 error(ERR_WARNING
|ERR_PASS1
,
1913 "trailing garbage after %%ifmacro ignored");
1914 nasm_free(searching
.name
);
1923 needtype
= TOK_NUMBER
;
1926 needtype
= TOK_STRING
;
1930 t
= tline
= expand_smacro(tline
);
1932 while (tok_type_(t
, TOK_WHITESPACE
) ||
1933 (needtype
== TOK_NUMBER
&&
1934 tok_type_(t
, TOK_OTHER
) &&
1935 (t
->text
[0] == '-' || t
->text
[0] == '+') &&
1939 j
= tok_type_(t
, needtype
);
1943 t
= tline
= expand_smacro(tline
);
1944 while (tok_type_(t
, TOK_WHITESPACE
))
1949 t
= t
->next
; /* Skip the actual token */
1950 while (tok_type_(t
, TOK_WHITESPACE
))
1952 j
= !t
; /* Should be nothing left */
1957 t
= tline
= expand_smacro(tline
);
1958 while (tok_type_(t
, TOK_WHITESPACE
))
1961 j
= !t
; /* Should be empty */
1965 t
= tline
= expand_smacro(tline
);
1967 tokval
.t_type
= TOKEN_INVALID
;
1968 evalresult
= evaluate(ppscan
, tptr
, &tokval
,
1969 NULL
, pass
| CRITICAL
, error
, NULL
);
1973 error(ERR_WARNING
|ERR_PASS1
,
1974 "trailing garbage after expression ignored");
1975 if (!is_simple(evalresult
)) {
1977 "non-constant value given to `%s'", pp_directives
[ct
]);
1980 j
= reloc_value(evalresult
) != 0;
1985 "preprocessor directive `%s' not yet implemented",
1990 free_tlist(origline
);
1991 return j
^ PP_NEGATIVE(ct
);
1994 free_tlist(origline
);
1999 * Common code for defining an smacro
2001 static bool define_smacro(Context
*ctx
, const char *mname
, bool casesense
,
2002 int nparam
, Token
*expansion
)
2004 SMacro
*smac
, **smhead
;
2005 struct hash_table
*smtbl
;
2007 if (smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
)) {
2009 error(ERR_WARNING
|ERR_PASS1
,
2010 "single-line macro `%s' defined both with and"
2011 " without parameters", mname
);
2013 * Some instances of the old code considered this a failure,
2014 * some others didn't. What is the right thing to do here?
2016 free_tlist(expansion
);
2017 return false; /* Failure */
2020 * We're redefining, so we have to take over an
2021 * existing SMacro structure. This means freeing
2022 * what was already in it.
2024 nasm_free(smac
->name
);
2025 free_tlist(smac
->expansion
);
2028 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2029 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
2030 smac
= nasm_malloc(sizeof(SMacro
));
2031 smac
->next
= *smhead
;
2034 smac
->name
= nasm_strdup(mname
);
2035 smac
->casesense
= casesense
;
2036 smac
->nparam
= nparam
;
2037 smac
->expansion
= expansion
;
2038 smac
->in_progress
= false;
2039 return true; /* Success */
2043 * Undefine an smacro
2045 static void undef_smacro(Context
*ctx
, const char *mname
)
2047 SMacro
**smhead
, *s
, **sp
;
2048 struct hash_table
*smtbl
;
2050 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2051 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
2055 * We now have a macro name... go hunt for it.
2058 while ((s
= *sp
) != NULL
) {
2059 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
2062 free_tlist(s
->expansion
);
2072 * Parse a mmacro specification.
2074 static bool parse_mmacro_spec(Token
*tline
, MMacro
*def
, const char *directive
)
2078 tline
= tline
->next
;
2080 tline
= expand_id(tline
);
2081 if (!tok_type_(tline
, TOK_ID
)) {
2082 error(ERR_NONFATAL
, "`%s' expects a macro name", directive
);
2087 def
->name
= nasm_strdup(tline
->text
);
2089 def
->nolist
= false;
2090 def
->in_progress
= 0;
2091 def
->rep_nest
= NULL
;
2092 def
->nparam_min
= 0;
2093 def
->nparam_max
= 0;
2095 tline
= expand_smacro(tline
->next
);
2097 if (!tok_type_(tline
, TOK_NUMBER
)) {
2098 error(ERR_NONFATAL
, "`%s' expects a parameter count", directive
);
2100 def
->nparam_min
= def
->nparam_max
=
2101 readnum(tline
->text
, &err
);
2104 "unable to parse parameter count `%s'", tline
->text
);
2106 if (tline
&& tok_is_(tline
->next
, "-")) {
2107 tline
= tline
->next
->next
;
2108 if (tok_is_(tline
, "*")) {
2109 def
->nparam_max
= INT_MAX
;
2110 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2112 "`%s' expects a parameter count after `-'", directive
);
2114 def
->nparam_max
= readnum(tline
->text
, &err
);
2116 error(ERR_NONFATAL
, "unable to parse parameter count `%s'",
2119 if (def
->nparam_min
> def
->nparam_max
) {
2120 error(ERR_NONFATAL
, "minimum parameter count exceeds maximum");
2124 if (tline
&& tok_is_(tline
->next
, "+")) {
2125 tline
= tline
->next
;
2128 if (tline
&& tok_type_(tline
->next
, TOK_ID
) &&
2129 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
2130 tline
= tline
->next
;
2135 * Handle default parameters.
2137 if (tline
&& tline
->next
) {
2138 def
->dlist
= tline
->next
;
2140 count_mmac_params(def
->dlist
, &def
->ndefs
, &def
->defaults
);
2143 def
->defaults
= NULL
;
2145 def
->expansion
= NULL
;
2147 if (def
->defaults
&& def
->ndefs
> def
->nparam_max
- def
->nparam_min
&&
2149 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MDP
,
2150 "too many default macro parameters");
2157 * Decode a size directive
2159 static int parse_size(const char *str
) {
2160 static const char *size_names
[] =
2161 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2162 static const int sizes
[] =
2163 { 0, 1, 4, 16, 8, 10, 2, 32 };
2165 return sizes
[bsii(str
, size_names
, ARRAY_SIZE(size_names
))+1];
2169 * find and process preprocessor directive in passed line
2170 * Find out if a line contains a preprocessor directive, and deal
2173 * If a directive _is_ found, it is the responsibility of this routine
2174 * (and not the caller) to free_tlist() the line.
2176 * @param tline a pointer to the current tokeninzed line linked list
2177 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2180 static int do_directive(Token
* tline
)
2182 enum preproc_token i
;
2195 MMacro
*mmac
, **mmhead
;
2196 Token
*t
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
2198 struct tokenval tokval
;
2200 MMacro
*tmp_defining
; /* Used when manipulating rep_nest */
2208 if (!tline
|| !tok_type_(tline
, TOK_PREPROC_ID
) ||
2209 (tline
->text
[1] == '%' || tline
->text
[1] == '$'
2210 || tline
->text
[1] == '!'))
2211 return NO_DIRECTIVE_FOUND
;
2213 i
= pp_token_hash(tline
->text
);
2216 * FIXME: We zap execution of PP_RMACRO, PP_IRMACRO, PP_EXITMACRO
2217 * since they are known to be buggy at moment, we need to fix them
2218 * in future release (2.09-2.10)
2220 if (i
== PP_RMACRO
|| i
== PP_RMACRO
|| i
== PP_EXITMACRO
) {
2221 error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2223 return NO_DIRECTIVE_FOUND
;
2227 * If we're in a non-emitting branch of a condition construct,
2228 * or walking to the end of an already terminated %rep block,
2229 * we should ignore all directives except for condition
2232 if (((istk
->conds
&& !emitting(istk
->conds
->state
)) ||
2233 (istk
->mstk
&& !istk
->mstk
->in_progress
)) && !is_condition(i
)) {
2234 return NO_DIRECTIVE_FOUND
;
2238 * If we're defining a macro or reading a %rep block, we should
2239 * ignore all directives except for %macro/%imacro (which nest),
2240 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2241 * If we're in a %rep block, another %rep nests, so should be let through.
2243 if (defining
&& i
!= PP_MACRO
&& i
!= PP_IMACRO
&&
2244 i
!= PP_RMACRO
&& i
!= PP_IRMACRO
&&
2245 i
!= PP_ENDMACRO
&& i
!= PP_ENDM
&&
2246 (defining
->name
|| (i
!= PP_ENDREP
&& i
!= PP_REP
))) {
2247 return NO_DIRECTIVE_FOUND
;
2251 if (i
== PP_MACRO
|| i
== PP_IMACRO
||
2252 i
== PP_RMACRO
|| i
== PP_IRMACRO
) {
2254 return NO_DIRECTIVE_FOUND
;
2255 } else if (nested_mac_count
> 0) {
2256 if (i
== PP_ENDMACRO
) {
2258 return NO_DIRECTIVE_FOUND
;
2261 if (!defining
->name
) {
2264 return NO_DIRECTIVE_FOUND
;
2265 } else if (nested_rep_count
> 0) {
2266 if (i
== PP_ENDREP
) {
2268 return NO_DIRECTIVE_FOUND
;
2276 error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2278 return NO_DIRECTIVE_FOUND
; /* didn't get it */
2281 /* Directive to tell NASM what the default stack size is. The
2282 * default is for a 16-bit stack, and this can be overriden with
2285 tline
= tline
->next
;
2286 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2287 tline
= tline
->next
;
2288 if (!tline
|| tline
->type
!= TOK_ID
) {
2289 error(ERR_NONFATAL
, "`%%stacksize' missing size parameter");
2290 free_tlist(origline
);
2291 return DIRECTIVE_FOUND
;
2293 if (nasm_stricmp(tline
->text
, "flat") == 0) {
2294 /* All subsequent ARG directives are for a 32-bit stack */
2296 StackPointer
= "ebp";
2299 } else if (nasm_stricmp(tline
->text
, "flat64") == 0) {
2300 /* All subsequent ARG directives are for a 64-bit stack */
2302 StackPointer
= "rbp";
2305 } else if (nasm_stricmp(tline
->text
, "large") == 0) {
2306 /* All subsequent ARG directives are for a 16-bit stack,
2307 * far function call.
2310 StackPointer
= "bp";
2313 } else if (nasm_stricmp(tline
->text
, "small") == 0) {
2314 /* All subsequent ARG directives are for a 16-bit stack,
2315 * far function call. We don't support near functions.
2318 StackPointer
= "bp";
2322 error(ERR_NONFATAL
, "`%%stacksize' invalid size type");
2323 free_tlist(origline
);
2324 return DIRECTIVE_FOUND
;
2326 free_tlist(origline
);
2327 return DIRECTIVE_FOUND
;
2330 /* TASM like ARG directive to define arguments to functions, in
2331 * the following form:
2333 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2337 char *arg
, directive
[256];
2338 int size
= StackSize
;
2340 /* Find the argument name */
2341 tline
= tline
->next
;
2342 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2343 tline
= tline
->next
;
2344 if (!tline
|| tline
->type
!= TOK_ID
) {
2345 error(ERR_NONFATAL
, "`%%arg' missing argument parameter");
2346 free_tlist(origline
);
2347 return DIRECTIVE_FOUND
;
2351 /* Find the argument size type */
2352 tline
= tline
->next
;
2353 if (!tline
|| tline
->type
!= TOK_OTHER
2354 || tline
->text
[0] != ':') {
2356 "Syntax error processing `%%arg' directive");
2357 free_tlist(origline
);
2358 return DIRECTIVE_FOUND
;
2360 tline
= tline
->next
;
2361 if (!tline
|| tline
->type
!= TOK_ID
) {
2362 error(ERR_NONFATAL
, "`%%arg' missing size type parameter");
2363 free_tlist(origline
);
2364 return DIRECTIVE_FOUND
;
2367 /* Allow macro expansion of type parameter */
2368 tt
= tokenize(tline
->text
);
2369 tt
= expand_smacro(tt
);
2370 size
= parse_size(tt
->text
);
2373 "Invalid size type for `%%arg' missing directive");
2375 free_tlist(origline
);
2376 return DIRECTIVE_FOUND
;
2380 /* Round up to even stack slots */
2381 size
= ALIGN(size
, StackSize
);
2383 /* Now define the macro for the argument */
2384 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
2385 arg
, StackPointer
, offset
);
2386 do_directive(tokenize(directive
));
2389 /* Move to the next argument in the list */
2390 tline
= tline
->next
;
2391 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2392 tline
= tline
->next
;
2393 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2395 free_tlist(origline
);
2396 return DIRECTIVE_FOUND
;
2399 /* TASM like LOCAL directive to define local variables for a
2400 * function, in the following form:
2402 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2404 * The '= LocalSize' at the end is ignored by NASM, but is
2405 * required by TASM to define the local parameter size (and used
2406 * by the TASM macro package).
2408 offset
= LocalOffset
;
2410 char *local
, directive
[256];
2411 int size
= StackSize
;
2413 /* Find the argument name */
2414 tline
= tline
->next
;
2415 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2416 tline
= tline
->next
;
2417 if (!tline
|| tline
->type
!= TOK_ID
) {
2419 "`%%local' missing argument parameter");
2420 free_tlist(origline
);
2421 return DIRECTIVE_FOUND
;
2423 local
= tline
->text
;
2425 /* Find the argument size type */
2426 tline
= tline
->next
;
2427 if (!tline
|| tline
->type
!= TOK_OTHER
2428 || tline
->text
[0] != ':') {
2430 "Syntax error processing `%%local' directive");
2431 free_tlist(origline
);
2432 return DIRECTIVE_FOUND
;
2434 tline
= tline
->next
;
2435 if (!tline
|| tline
->type
!= TOK_ID
) {
2437 "`%%local' missing size type parameter");
2438 free_tlist(origline
);
2439 return DIRECTIVE_FOUND
;
2442 /* Allow macro expansion of type parameter */
2443 tt
= tokenize(tline
->text
);
2444 tt
= expand_smacro(tt
);
2445 size
= parse_size(tt
->text
);
2448 "Invalid size type for `%%local' missing directive");
2450 free_tlist(origline
);
2451 return DIRECTIVE_FOUND
;
2455 /* Round up to even stack slots */
2456 size
= ALIGN(size
, StackSize
);
2458 offset
+= size
; /* Negative offset, increment before */
2460 /* Now define the macro for the argument */
2461 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
2462 local
, StackPointer
, offset
);
2463 do_directive(tokenize(directive
));
2465 /* Now define the assign to setup the enter_c macro correctly */
2466 snprintf(directive
, sizeof(directive
),
2467 "%%assign %%$localsize %%$localsize+%d", size
);
2468 do_directive(tokenize(directive
));
2470 /* Move to the next argument in the list */
2471 tline
= tline
->next
;
2472 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2473 tline
= tline
->next
;
2474 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2475 LocalOffset
= offset
;
2476 free_tlist(origline
);
2477 return DIRECTIVE_FOUND
;
2481 error(ERR_WARNING
|ERR_PASS1
,
2482 "trailing garbage after `%%clear' ignored");
2485 free_tlist(origline
);
2486 return DIRECTIVE_FOUND
;
2489 t
= tline
->next
= expand_smacro(tline
->next
);
2491 if (!t
|| (t
->type
!= TOK_STRING
&&
2492 t
->type
!= TOK_INTERNAL_STRING
)) {
2493 error(ERR_NONFATAL
, "`%%depend' expects a file name");
2494 free_tlist(origline
);
2495 return DIRECTIVE_FOUND
; /* but we did _something_ */
2498 error(ERR_WARNING
|ERR_PASS1
,
2499 "trailing garbage after `%%depend' ignored");
2501 if (t
->type
!= TOK_INTERNAL_STRING
)
2502 nasm_unquote_cstr(p
, i
);
2503 if (dephead
&& !in_list(*dephead
, p
)) {
2504 StrList
*sl
= nasm_malloc(strlen(p
)+1+sizeof sl
->next
);
2508 deptail
= &sl
->next
;
2510 free_tlist(origline
);
2511 return DIRECTIVE_FOUND
;
2514 t
= tline
->next
= expand_smacro(tline
->next
);
2517 if (!t
|| (t
->type
!= TOK_STRING
&&
2518 t
->type
!= TOK_INTERNAL_STRING
)) {
2519 error(ERR_NONFATAL
, "`%%include' expects a file name");
2520 free_tlist(origline
);
2521 return DIRECTIVE_FOUND
; /* but we did _something_ */
2524 error(ERR_WARNING
|ERR_PASS1
,
2525 "trailing garbage after `%%include' ignored");
2527 if (t
->type
!= TOK_INTERNAL_STRING
)
2528 nasm_unquote_cstr(p
, i
);
2529 inc
= nasm_malloc(sizeof(Include
));
2532 inc
->fp
= inc_fopen(p
, dephead
, &deptail
, pass
== 0);
2534 /* -MG given but file not found */
2537 inc
->fname
= src_set_fname(nasm_strdup(p
));
2538 inc
->lineno
= src_set_linnum(0);
2540 inc
->expansion
= NULL
;
2543 list
->uplevel(LIST_INCLUDE
);
2545 free_tlist(origline
);
2546 return DIRECTIVE_FOUND
;
2550 static macros_t
*use_pkg
;
2551 const char *pkg_macro
= NULL
;
2553 tline
= tline
->next
;
2555 tline
= expand_id(tline
);
2557 if (!tline
|| (tline
->type
!= TOK_STRING
&&
2558 tline
->type
!= TOK_INTERNAL_STRING
&&
2559 tline
->type
!= TOK_ID
)) {
2560 error(ERR_NONFATAL
, "`%%use' expects a package name");
2561 free_tlist(origline
);
2562 return DIRECTIVE_FOUND
; /* but we did _something_ */
2565 error(ERR_WARNING
|ERR_PASS1
,
2566 "trailing garbage after `%%use' ignored");
2567 if (tline
->type
== TOK_STRING
)
2568 nasm_unquote_cstr(tline
->text
, i
);
2569 use_pkg
= nasm_stdmac_find_package(tline
->text
);
2571 error(ERR_NONFATAL
, "unknown `%%use' package: %s", tline
->text
);
2573 pkg_macro
= (char *)use_pkg
+ 1; /* The first string will be <%define>__USE_*__ */
2574 if (use_pkg
&& ! smacro_defined(NULL
, pkg_macro
, 0, NULL
, true)) {
2575 /* Not already included, go ahead and include it */
2576 stdmacpos
= use_pkg
;
2578 free_tlist(origline
);
2579 return DIRECTIVE_FOUND
;
2584 tline
= tline
->next
;
2586 tline
= expand_id(tline
);
2588 if (!tok_type_(tline
, TOK_ID
)) {
2589 error(ERR_NONFATAL
, "`%s' expects a context identifier",
2591 free_tlist(origline
);
2592 return DIRECTIVE_FOUND
; /* but we did _something_ */
2595 error(ERR_WARNING
|ERR_PASS1
,
2596 "trailing garbage after `%s' ignored",
2598 p
= nasm_strdup(tline
->text
);
2600 p
= NULL
; /* Anonymous */
2604 ctx
= nasm_malloc(sizeof(Context
));
2606 hash_init(&ctx
->localmac
, HASH_SMALL
);
2608 ctx
->number
= unique
++;
2613 error(ERR_NONFATAL
, "`%s': context stack is empty",
2615 } else if (i
== PP_POP
) {
2616 if (p
&& (!cstk
->name
|| nasm_stricmp(p
, cstk
->name
)))
2617 error(ERR_NONFATAL
, "`%%pop' in wrong context: %s, "
2619 cstk
->name
? cstk
->name
: "anonymous", p
);
2624 nasm_free(cstk
->name
);
2630 free_tlist(origline
);
2631 return DIRECTIVE_FOUND
;
2633 severity
= ERR_FATAL
;
2636 severity
= ERR_NONFATAL
;
2639 severity
= ERR_WARNING
|ERR_WARN_USER
;
2644 /* Only error out if this is the final pass */
2645 if (pass
!= 2 && i
!= PP_FATAL
)
2646 return DIRECTIVE_FOUND
;
2648 tline
->next
= expand_smacro(tline
->next
);
2649 tline
= tline
->next
;
2651 t
= tline
? tline
->next
: NULL
;
2653 if (tok_type_(tline
, TOK_STRING
) && !t
) {
2654 /* The line contains only a quoted string */
2656 nasm_unquote(p
, NULL
); /* Ignore NUL character truncation */
2657 error(severity
, "%s", p
);
2659 /* Not a quoted string, or more than a quoted string */
2660 p
= detoken(tline
, false);
2661 error(severity
, "%s", p
);
2664 free_tlist(origline
);
2665 return DIRECTIVE_FOUND
;
2669 if (istk
->conds
&& !emitting(istk
->conds
->state
))
2672 j
= if_condition(tline
->next
, i
);
2673 tline
->next
= NULL
; /* it got freed */
2674 j
= j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2676 cond
= nasm_malloc(sizeof(Cond
));
2677 cond
->next
= istk
->conds
;
2681 istk
->mstk
->condcnt
++;
2682 free_tlist(origline
);
2683 return DIRECTIVE_FOUND
;
2687 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2688 switch(istk
->conds
->state
) {
2690 istk
->conds
->state
= COND_DONE
;
2697 case COND_ELSE_TRUE
:
2698 case COND_ELSE_FALSE
:
2699 error_precond(ERR_WARNING
|ERR_PASS1
,
2700 "`%%elif' after `%%else' ignored");
2701 istk
->conds
->state
= COND_NEVER
;
2706 * IMPORTANT: In the case of %if, we will already have
2707 * called expand_mmac_params(); however, if we're
2708 * processing an %elif we must have been in a
2709 * non-emitting mode, which would have inhibited
2710 * the normal invocation of expand_mmac_params().
2711 * Therefore, we have to do it explicitly here.
2713 j
= if_condition(expand_mmac_params(tline
->next
), i
);
2714 tline
->next
= NULL
; /* it got freed */
2715 istk
->conds
->state
=
2716 j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2719 free_tlist(origline
);
2720 return DIRECTIVE_FOUND
;
2724 error_precond(ERR_WARNING
|ERR_PASS1
,
2725 "trailing garbage after `%%else' ignored");
2727 error(ERR_FATAL
, "`%%else': no matching `%%if'");
2728 switch(istk
->conds
->state
) {
2731 istk
->conds
->state
= COND_ELSE_FALSE
;
2738 istk
->conds
->state
= COND_ELSE_TRUE
;
2741 case COND_ELSE_TRUE
:
2742 case COND_ELSE_FALSE
:
2743 error_precond(ERR_WARNING
|ERR_PASS1
,
2744 "`%%else' after `%%else' ignored.");
2745 istk
->conds
->state
= COND_NEVER
;
2748 free_tlist(origline
);
2749 return DIRECTIVE_FOUND
;
2753 error_precond(ERR_WARNING
|ERR_PASS1
,
2754 "trailing garbage after `%%endif' ignored");
2756 error(ERR_FATAL
, "`%%endif': no matching `%%if'");
2758 istk
->conds
= cond
->next
;
2761 istk
->mstk
->condcnt
--;
2762 free_tlist(origline
);
2763 return DIRECTIVE_FOUND
;
2770 error(ERR_FATAL
, "`%s': already defining a macro",
2772 return DIRECTIVE_FOUND
;
2774 defining
= nasm_malloc(sizeof(MMacro
));
2775 defining
->max_depth
=
2776 (i
== PP_RMACRO
) || (i
== PP_IRMACRO
) ? DEADMAN_LIMIT
: 0;
2777 defining
->casesense
= (i
== PP_MACRO
) || (i
== PP_RMACRO
);
2778 if (!parse_mmacro_spec(tline
, defining
, pp_directives
[i
])) {
2779 nasm_free(defining
);
2781 return DIRECTIVE_FOUND
;
2784 mmac
= (MMacro
*) hash_findix(&mmacros
, defining
->name
);
2786 if (!strcmp(mmac
->name
, defining
->name
) &&
2787 (mmac
->nparam_min
<= defining
->nparam_max
2789 && (defining
->nparam_min
<= mmac
->nparam_max
2791 error(ERR_WARNING
|ERR_PASS1
,
2792 "redefining multi-line macro `%s'", defining
->name
);
2793 return DIRECTIVE_FOUND
;
2797 free_tlist(origline
);
2798 return DIRECTIVE_FOUND
;
2802 if (! (defining
&& defining
->name
)) {
2803 error(ERR_NONFATAL
, "`%s': not defining a macro", tline
->text
);
2804 return DIRECTIVE_FOUND
;
2806 mmhead
= (MMacro
**) hash_findi_add(&mmacros
, defining
->name
);
2807 defining
->next
= *mmhead
;
2810 free_tlist(origline
);
2811 return DIRECTIVE_FOUND
;
2815 * We must search along istk->expansion until we hit a
2816 * macro-end marker for a macro with a name. Then we
2817 * bypass all lines between exitmacro and endmacro.
2819 list_for_each(l
, istk
->expansion
)
2820 if (l
->finishes
&& l
->finishes
->name
)
2825 * Remove all conditional entries relative to this
2826 * macro invocation. (safe to do in this context)
2828 for ( ; l
->finishes
->condcnt
> 0; l
->finishes
->condcnt
--) {
2830 istk
->conds
= cond
->next
;
2833 istk
->expansion
= l
;
2835 error(ERR_NONFATAL
, "`%%exitmacro' not within `%%macro' block");
2837 free_tlist(origline
);
2838 return DIRECTIVE_FOUND
;
2846 spec
.casesense
= (i
== PP_UNMACRO
);
2847 if (!parse_mmacro_spec(tline
, &spec
, pp_directives
[i
])) {
2848 return DIRECTIVE_FOUND
;
2850 mmac_p
= (MMacro
**) hash_findi(&mmacros
, spec
.name
, NULL
);
2851 while (mmac_p
&& *mmac_p
) {
2853 if (mmac
->casesense
== spec
.casesense
&&
2854 !mstrcmp(mmac
->name
, spec
.name
, spec
.casesense
) &&
2855 mmac
->nparam_min
== spec
.nparam_min
&&
2856 mmac
->nparam_max
== spec
.nparam_max
&&
2857 mmac
->plus
== spec
.plus
) {
2858 *mmac_p
= mmac
->next
;
2861 mmac_p
= &mmac
->next
;
2864 free_tlist(origline
);
2865 free_tlist(spec
.dlist
);
2866 return DIRECTIVE_FOUND
;
2870 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
2871 tline
= tline
->next
;
2873 free_tlist(origline
);
2874 error(ERR_NONFATAL
, "`%%rotate' missing rotate count");
2875 return DIRECTIVE_FOUND
;
2877 t
= expand_smacro(tline
->next
);
2879 free_tlist(origline
);
2882 tokval
.t_type
= TOKEN_INVALID
;
2884 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
2887 return DIRECTIVE_FOUND
;
2889 error(ERR_WARNING
|ERR_PASS1
,
2890 "trailing garbage after expression ignored");
2891 if (!is_simple(evalresult
)) {
2892 error(ERR_NONFATAL
, "non-constant value given to `%%rotate'");
2893 return DIRECTIVE_FOUND
;
2896 while (mmac
&& !mmac
->name
) /* avoid mistaking %reps for macros */
2897 mmac
= mmac
->next_active
;
2899 error(ERR_NONFATAL
, "`%%rotate' invoked outside a macro call");
2900 } else if (mmac
->nparam
== 0) {
2902 "`%%rotate' invoked within macro without parameters");
2904 int rotate
= mmac
->rotate
+ reloc_value(evalresult
);
2906 rotate
%= (int)mmac
->nparam
;
2908 rotate
+= mmac
->nparam
;
2910 mmac
->rotate
= rotate
;
2912 return DIRECTIVE_FOUND
;
2917 tline
= tline
->next
;
2918 } while (tok_type_(tline
, TOK_WHITESPACE
));
2920 if (tok_type_(tline
, TOK_ID
) &&
2921 nasm_stricmp(tline
->text
, ".nolist") == 0) {
2924 tline
= tline
->next
;
2925 } while (tok_type_(tline
, TOK_WHITESPACE
));
2929 t
= expand_smacro(tline
);
2931 tokval
.t_type
= TOKEN_INVALID
;
2933 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
2935 free_tlist(origline
);
2936 return DIRECTIVE_FOUND
;
2939 error(ERR_WARNING
|ERR_PASS1
,
2940 "trailing garbage after expression ignored");
2941 if (!is_simple(evalresult
)) {
2942 error(ERR_NONFATAL
, "non-constant value given to `%%rep'");
2943 return DIRECTIVE_FOUND
;
2945 count
= reloc_value(evalresult
);
2946 if (count
>= REP_LIMIT
) {
2947 error(ERR_NONFATAL
, "`%%rep' value exceeds limit");
2952 error(ERR_NONFATAL
, "`%%rep' expects a repeat count");
2955 free_tlist(origline
);
2957 tmp_defining
= defining
;
2958 defining
= nasm_malloc(sizeof(MMacro
));
2959 defining
->prev
= NULL
;
2960 defining
->name
= NULL
; /* flags this macro as a %rep block */
2961 defining
->casesense
= false;
2962 defining
->plus
= false;
2963 defining
->nolist
= nolist
;
2964 defining
->in_progress
= count
;
2965 defining
->max_depth
= 0;
2966 defining
->nparam_min
= defining
->nparam_max
= 0;
2967 defining
->defaults
= NULL
;
2968 defining
->dlist
= NULL
;
2969 defining
->expansion
= NULL
;
2970 defining
->next_active
= istk
->mstk
;
2971 defining
->rep_nest
= tmp_defining
;
2972 return DIRECTIVE_FOUND
;
2975 if (!defining
|| defining
->name
) {
2976 error(ERR_NONFATAL
, "`%%endrep': no matching `%%rep'");
2977 return DIRECTIVE_FOUND
;
2981 * Now we have a "macro" defined - although it has no name
2982 * and we won't be entering it in the hash tables - we must
2983 * push a macro-end marker for it on to istk->expansion.
2984 * After that, it will take care of propagating itself (a
2985 * macro-end marker line for a macro which is really a %rep
2986 * block will cause the macro to be re-expanded, complete
2987 * with another macro-end marker to ensure the process
2988 * continues) until the whole expansion is forcibly removed
2989 * from istk->expansion by a %exitrep.
2991 l
= nasm_malloc(sizeof(Line
));
2992 l
->next
= istk
->expansion
;
2993 l
->finishes
= defining
;
2995 istk
->expansion
= l
;
2997 istk
->mstk
= defining
;
2999 list
->uplevel(defining
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
3000 tmp_defining
= defining
;
3001 defining
= defining
->rep_nest
;
3002 free_tlist(origline
);
3003 return DIRECTIVE_FOUND
;
3007 * We must search along istk->expansion until we hit a
3008 * macro-end marker for a macro with no name. Then we set
3009 * its `in_progress' flag to 0.
3011 list_for_each(l
, istk
->expansion
)
3012 if (l
->finishes
&& !l
->finishes
->name
)
3016 l
->finishes
->in_progress
= 1;
3018 error(ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
3019 free_tlist(origline
);
3020 return DIRECTIVE_FOUND
;
3026 casesense
= (i
== PP_DEFINE
|| i
== PP_XDEFINE
);
3028 tline
= tline
->next
;
3030 tline
= expand_id(tline
);
3031 if (!tline
|| (tline
->type
!= TOK_ID
&&
3032 (tline
->type
!= TOK_PREPROC_ID
||
3033 tline
->text
[1] != '$'))) {
3034 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3036 free_tlist(origline
);
3037 return DIRECTIVE_FOUND
;
3040 ctx
= get_ctx(tline
->text
, &mname
, false);
3042 param_start
= tline
= tline
->next
;
3045 /* Expand the macro definition now for %xdefine and %ixdefine */
3046 if ((i
== PP_XDEFINE
) || (i
== PP_IXDEFINE
))
3047 tline
= expand_smacro(tline
);
3049 if (tok_is_(tline
, "(")) {
3051 * This macro has parameters.
3054 tline
= tline
->next
;
3058 error(ERR_NONFATAL
, "parameter identifier expected");
3059 free_tlist(origline
);
3060 return DIRECTIVE_FOUND
;
3062 if (tline
->type
!= TOK_ID
) {
3064 "`%s': parameter identifier expected",
3066 free_tlist(origline
);
3067 return DIRECTIVE_FOUND
;
3069 tline
->type
= TOK_SMAC_PARAM
+ nparam
++;
3070 tline
= tline
->next
;
3072 if (tok_is_(tline
, ",")) {
3073 tline
= tline
->next
;
3075 if (!tok_is_(tline
, ")")) {
3077 "`)' expected to terminate macro template");
3078 free_tlist(origline
);
3079 return DIRECTIVE_FOUND
;
3085 tline
= tline
->next
;
3087 if (tok_type_(tline
, TOK_WHITESPACE
))
3088 last
= tline
, tline
= tline
->next
;
3093 if (t
->type
== TOK_ID
) {
3094 list_for_each(tt
, param_start
)
3095 if (tt
->type
>= TOK_SMAC_PARAM
&&
3096 !strcmp(tt
->text
, t
->text
))
3100 t
->next
= macro_start
;
3105 * Good. We now have a macro name, a parameter count, and a
3106 * token list (in reverse order) for an expansion. We ought
3107 * to be OK just to create an SMacro, store it, and let
3108 * free_tlist have the rest of the line (which we have
3109 * carefully re-terminated after chopping off the expansion
3112 define_smacro(ctx
, mname
, casesense
, nparam
, macro_start
);
3113 free_tlist(origline
);
3114 return DIRECTIVE_FOUND
;
3117 tline
= tline
->next
;
3119 tline
= expand_id(tline
);
3120 if (!tline
|| (tline
->type
!= TOK_ID
&&
3121 (tline
->type
!= TOK_PREPROC_ID
||
3122 tline
->text
[1] != '$'))) {
3123 error(ERR_NONFATAL
, "`%%undef' expects a macro identifier");
3124 free_tlist(origline
);
3125 return DIRECTIVE_FOUND
;
3128 error(ERR_WARNING
|ERR_PASS1
,
3129 "trailing garbage after macro name ignored");
3132 /* Find the context that symbol belongs to */
3133 ctx
= get_ctx(tline
->text
, &mname
, false);
3134 undef_smacro(ctx
, mname
);
3135 free_tlist(origline
);
3136 return DIRECTIVE_FOUND
;
3140 casesense
= (i
== PP_DEFSTR
);
3142 tline
= tline
->next
;
3144 tline
= expand_id(tline
);
3145 if (!tline
|| (tline
->type
!= TOK_ID
&&
3146 (tline
->type
!= TOK_PREPROC_ID
||
3147 tline
->text
[1] != '$'))) {
3148 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3150 free_tlist(origline
);
3151 return DIRECTIVE_FOUND
;
3154 ctx
= get_ctx(tline
->text
, &mname
, false);
3156 tline
= expand_smacro(tline
->next
);
3159 while (tok_type_(tline
, TOK_WHITESPACE
))
3160 tline
= delete_Token(tline
);
3162 p
= detoken(tline
, false);
3163 macro_start
= nasm_malloc(sizeof(*macro_start
));
3164 macro_start
->next
= NULL
;
3165 macro_start
->text
= nasm_quote(p
, strlen(p
));
3166 macro_start
->type
= TOK_STRING
;
3167 macro_start
->a
.mac
= NULL
;
3171 * We now have a macro name, an implicit parameter count of
3172 * zero, and a string token to use as an expansion. Create
3173 * and store an SMacro.
3175 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3176 free_tlist(origline
);
3177 return DIRECTIVE_FOUND
;
3181 casesense
= (i
== PP_DEFTOK
);
3183 tline
= tline
->next
;
3185 tline
= expand_id(tline
);
3186 if (!tline
|| (tline
->type
!= TOK_ID
&&
3187 (tline
->type
!= TOK_PREPROC_ID
||
3188 tline
->text
[1] != '$'))) {
3190 "`%s' expects a macro identifier as first parameter",
3192 free_tlist(origline
);
3193 return DIRECTIVE_FOUND
;
3195 ctx
= get_ctx(tline
->text
, &mname
, false);
3197 tline
= expand_smacro(tline
->next
);
3201 while (tok_type_(t
, TOK_WHITESPACE
))
3203 /* t should now point to the string */
3204 if (!tok_type_(t
, TOK_STRING
)) {
3206 "`%s` requires string as second parameter",
3209 free_tlist(origline
);
3210 return DIRECTIVE_FOUND
;
3214 * Convert the string to a token stream. Note that smacros
3215 * are stored with the token stream reversed, so we have to
3216 * reverse the output of tokenize().
3218 nasm_unquote_cstr(t
->text
, i
);
3219 macro_start
= reverse_tokens(tokenize(t
->text
));
3222 * We now have a macro name, an implicit parameter count of
3223 * zero, and a numeric token to use as an expansion. Create
3224 * and store an SMacro.
3226 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3228 free_tlist(origline
);
3229 return DIRECTIVE_FOUND
;
3234 StrList
*xsl
= NULL
;
3235 StrList
**xst
= &xsl
;
3239 tline
= tline
->next
;
3241 tline
= expand_id(tline
);
3242 if (!tline
|| (tline
->type
!= TOK_ID
&&
3243 (tline
->type
!= TOK_PREPROC_ID
||
3244 tline
->text
[1] != '$'))) {
3246 "`%%pathsearch' expects a macro identifier as first parameter");
3247 free_tlist(origline
);
3248 return DIRECTIVE_FOUND
;
3250 ctx
= get_ctx(tline
->text
, &mname
, false);
3252 tline
= expand_smacro(tline
->next
);
3256 while (tok_type_(t
, TOK_WHITESPACE
))
3259 if (!t
|| (t
->type
!= TOK_STRING
&&
3260 t
->type
!= TOK_INTERNAL_STRING
)) {
3261 error(ERR_NONFATAL
, "`%%pathsearch' expects a file name");
3263 free_tlist(origline
);
3264 return DIRECTIVE_FOUND
; /* but we did _something_ */
3267 error(ERR_WARNING
|ERR_PASS1
,
3268 "trailing garbage after `%%pathsearch' ignored");
3270 if (t
->type
!= TOK_INTERNAL_STRING
)
3271 nasm_unquote(p
, NULL
);
3273 fp
= inc_fopen(p
, &xsl
, &xst
, true);
3276 fclose(fp
); /* Don't actually care about the file */
3278 macro_start
= nasm_malloc(sizeof(*macro_start
));
3279 macro_start
->next
= NULL
;
3280 macro_start
->text
= nasm_quote(p
, strlen(p
));
3281 macro_start
->type
= TOK_STRING
;
3282 macro_start
->a
.mac
= NULL
;
3287 * We now have a macro name, an implicit parameter count of
3288 * zero, and a string token to use as an expansion. Create
3289 * and store an SMacro.
3291 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3293 free_tlist(origline
);
3294 return DIRECTIVE_FOUND
;
3300 tline
= tline
->next
;
3302 tline
= expand_id(tline
);
3303 if (!tline
|| (tline
->type
!= TOK_ID
&&
3304 (tline
->type
!= TOK_PREPROC_ID
||
3305 tline
->text
[1] != '$'))) {
3307 "`%%strlen' expects a macro identifier as first parameter");
3308 free_tlist(origline
);
3309 return DIRECTIVE_FOUND
;
3311 ctx
= get_ctx(tline
->text
, &mname
, false);
3313 tline
= expand_smacro(tline
->next
);
3317 while (tok_type_(t
, TOK_WHITESPACE
))
3319 /* t should now point to the string */
3320 if (!tok_type_(t
, TOK_STRING
)) {
3322 "`%%strlen` requires string as second parameter");
3324 free_tlist(origline
);
3325 return DIRECTIVE_FOUND
;
3328 macro_start
= nasm_malloc(sizeof(*macro_start
));
3329 macro_start
->next
= NULL
;
3330 make_tok_num(macro_start
, nasm_unquote(t
->text
, NULL
));
3331 macro_start
->a
.mac
= NULL
;
3334 * We now have a macro name, an implicit parameter count of
3335 * zero, and a numeric token to use as an expansion. Create
3336 * and store an SMacro.
3338 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3340 free_tlist(origline
);
3341 return DIRECTIVE_FOUND
;
3346 tline
= tline
->next
;
3348 tline
= expand_id(tline
);
3349 if (!tline
|| (tline
->type
!= TOK_ID
&&
3350 (tline
->type
!= TOK_PREPROC_ID
||
3351 tline
->text
[1] != '$'))) {
3353 "`%%strcat' expects a macro identifier as first parameter");
3354 free_tlist(origline
);
3355 return DIRECTIVE_FOUND
;
3357 ctx
= get_ctx(tline
->text
, &mname
, false);
3359 tline
= expand_smacro(tline
->next
);
3363 list_for_each(t
, tline
) {
3365 case TOK_WHITESPACE
:
3368 len
+= t
->a
.len
= nasm_unquote(t
->text
, NULL
);
3371 if (!strcmp(t
->text
, ",")) /* permit comma separators */
3373 /* else fall through */
3376 "non-string passed to `%%strcat' (%d)", t
->type
);
3378 free_tlist(origline
);
3379 return DIRECTIVE_FOUND
;
3383 p
= pp
= nasm_malloc(len
);
3384 list_for_each(t
, tline
) {
3385 if (t
->type
== TOK_STRING
) {
3386 memcpy(p
, t
->text
, t
->a
.len
);
3392 * We now have a macro name, an implicit parameter count of
3393 * zero, and a numeric token to use as an expansion. Create
3394 * and store an SMacro.
3396 macro_start
= new_Token(NULL
, TOK_STRING
, NULL
, 0);
3397 macro_start
->text
= nasm_quote(pp
, len
);
3399 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3401 free_tlist(origline
);
3402 return DIRECTIVE_FOUND
;
3406 int64_t start
, count
;
3411 tline
= tline
->next
;
3413 tline
= expand_id(tline
);
3414 if (!tline
|| (tline
->type
!= TOK_ID
&&
3415 (tline
->type
!= TOK_PREPROC_ID
||
3416 tline
->text
[1] != '$'))) {
3418 "`%%substr' expects a macro identifier as first parameter");
3419 free_tlist(origline
);
3420 return DIRECTIVE_FOUND
;
3422 ctx
= get_ctx(tline
->text
, &mname
, false);
3424 tline
= expand_smacro(tline
->next
);
3427 if (tline
) /* skip expanded id */
3429 while (tok_type_(t
, TOK_WHITESPACE
))
3432 /* t should now point to the string */
3433 if (!tok_type_(t
, TOK_STRING
)) {
3435 "`%%substr` requires string as second parameter");
3437 free_tlist(origline
);
3438 return DIRECTIVE_FOUND
;
3443 tokval
.t_type
= TOKEN_INVALID
;
3444 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3448 free_tlist(origline
);
3449 return DIRECTIVE_FOUND
;
3450 } else if (!is_simple(evalresult
)) {
3451 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3453 free_tlist(origline
);
3454 return DIRECTIVE_FOUND
;
3456 start
= evalresult
->value
- 1;
3458 while (tok_type_(tt
, TOK_WHITESPACE
))
3461 count
= 1; /* Backwards compatibility: one character */
3463 tokval
.t_type
= TOKEN_INVALID
;
3464 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3468 free_tlist(origline
);
3469 return DIRECTIVE_FOUND
;
3470 } else if (!is_simple(evalresult
)) {
3471 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3473 free_tlist(origline
);
3474 return DIRECTIVE_FOUND
;
3476 count
= evalresult
->value
;
3479 len
= nasm_unquote(t
->text
, NULL
);
3481 /* make start and count being in range */
3485 count
= len
+ count
+ 1 - start
;
3486 if (start
+ count
> (int64_t)len
)
3487 count
= len
- start
;
3488 if (!len
|| count
< 0 || start
>=(int64_t)len
)
3489 start
= -1, count
= 0; /* empty string */
3491 macro_start
= nasm_malloc(sizeof(*macro_start
));
3492 macro_start
->next
= NULL
;
3493 macro_start
->text
= nasm_quote((start
< 0) ? "" : t
->text
+ start
, count
);
3494 macro_start
->type
= TOK_STRING
;
3495 macro_start
->a
.mac
= NULL
;
3498 * We now have a macro name, an implicit parameter count of
3499 * zero, and a numeric token to use as an expansion. Create
3500 * and store an SMacro.
3502 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3504 free_tlist(origline
);
3505 return DIRECTIVE_FOUND
;
3510 casesense
= (i
== PP_ASSIGN
);
3512 tline
= tline
->next
;
3514 tline
= expand_id(tline
);
3515 if (!tline
|| (tline
->type
!= TOK_ID
&&
3516 (tline
->type
!= TOK_PREPROC_ID
||
3517 tline
->text
[1] != '$'))) {
3519 "`%%%sassign' expects a macro identifier",
3520 (i
== PP_IASSIGN
? "i" : ""));
3521 free_tlist(origline
);
3522 return DIRECTIVE_FOUND
;
3524 ctx
= get_ctx(tline
->text
, &mname
, false);
3526 tline
= expand_smacro(tline
->next
);
3531 tokval
.t_type
= TOKEN_INVALID
;
3533 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3536 free_tlist(origline
);
3537 return DIRECTIVE_FOUND
;
3541 error(ERR_WARNING
|ERR_PASS1
,
3542 "trailing garbage after expression ignored");
3544 if (!is_simple(evalresult
)) {
3546 "non-constant value given to `%%%sassign'",
3547 (i
== PP_IASSIGN
? "i" : ""));
3548 free_tlist(origline
);
3549 return DIRECTIVE_FOUND
;
3552 macro_start
= nasm_malloc(sizeof(*macro_start
));
3553 macro_start
->next
= NULL
;
3554 make_tok_num(macro_start
, reloc_value(evalresult
));
3555 macro_start
->a
.mac
= NULL
;
3558 * We now have a macro name, an implicit parameter count of
3559 * zero, and a numeric token to use as an expansion. Create
3560 * and store an SMacro.
3562 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3563 free_tlist(origline
);
3564 return DIRECTIVE_FOUND
;
3568 * Syntax is `%line nnn[+mmm] [filename]'
3570 tline
= tline
->next
;
3572 if (!tok_type_(tline
, TOK_NUMBER
)) {
3573 error(ERR_NONFATAL
, "`%%line' expects line number");
3574 free_tlist(origline
);
3575 return DIRECTIVE_FOUND
;
3577 k
= readnum(tline
->text
, &err
);
3579 tline
= tline
->next
;
3580 if (tok_is_(tline
, "+")) {
3581 tline
= tline
->next
;
3582 if (!tok_type_(tline
, TOK_NUMBER
)) {
3583 error(ERR_NONFATAL
, "`%%line' expects line increment");
3584 free_tlist(origline
);
3585 return DIRECTIVE_FOUND
;
3587 m
= readnum(tline
->text
, &err
);
3588 tline
= tline
->next
;
3594 nasm_free(src_set_fname(detoken(tline
, false)));
3596 free_tlist(origline
);
3597 return DIRECTIVE_FOUND
;
3601 "preprocessor directive `%s' not yet implemented",
3603 return DIRECTIVE_FOUND
;
3608 * Ensure that a macro parameter contains a condition code and
3609 * nothing else. Return the condition code index if so, or -1
3612 static int find_cc(Token
* t
)
3618 return -1; /* Probably a %+ without a space */
3621 if (t
->type
!= TOK_ID
)
3625 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
3629 j
= ARRAY_SIZE(conditions
);
3632 m
= nasm_stricmp(t
->text
, conditions
[k
]);
3647 static bool paste_tokens(Token
**head
, const struct tokseq_match
*m
,
3648 int mnum
, bool handle_paste_tokens
)
3650 Token
**tail
, *t
, *tt
;
3652 bool did_paste
= false;
3656 /* Now handle token pasting... */
3659 while ((t
= *tail
) && (tt
= t
->next
)) {
3661 case TOK_WHITESPACE
:
3662 if (tt
->type
== TOK_WHITESPACE
) {
3663 /* Zap adjacent whitespace tokens */
3664 t
->next
= delete_Token(tt
);
3666 /* Do not advance paste_head here */
3670 case TOK_PASTE
: /* %+ */
3671 if (handle_paste_tokens
) {
3672 /* Zap %+ and whitespace tokens to the right */
3673 while (t
&& (t
->type
== TOK_WHITESPACE
||
3674 t
->type
== TOK_PASTE
))
3675 t
= *tail
= delete_Token(t
);
3676 if (!paste_head
|| !t
)
3677 break; /* Nothing to paste with */
3681 while (tok_type_(tt
, TOK_WHITESPACE
))
3682 tt
= t
->next
= delete_Token(tt
);
3684 tmp
= nasm_strcat(t
->text
, tt
->text
);
3686 tt
= delete_Token(tt
);
3687 t
= *tail
= tokenize(tmp
);
3693 t
->next
= tt
; /* Attach the remaining token chain */
3700 /* else fall through */
3703 * Concatenation of tokens might look nontrivial
3704 * but in real it's pretty simple -- the caller
3705 * prepares the masks of token types to be concatenated
3706 * and we simply find matched sequences and slip
3709 for (i
= 0; i
< mnum
; i
++) {
3710 if (PP_CONCAT_MASK(t
->type
) & m
[i
].mask_head
) {
3714 while (tt
&& (PP_CONCAT_MASK(tt
->type
) & m
[i
].mask_tail
)) {
3715 len
+= strlen(tt
->text
);
3720 * Now tt points to the first token after
3721 * the potential paste area...
3723 if (tt
!= t
->next
) {
3724 /* We have at least two tokens... */
3725 len
+= strlen(t
->text
);
3726 p
= tmp
= nasm_malloc(len
+1);
3729 p
= strchr(p
, '\0');
3730 t
= delete_Token(t
);
3732 t
= *tail
= tokenize(tmp
);
3738 t
->next
= tt
; /* Attach the remaining token chain */
3746 if (i
>= mnum
) { /* no match */
3748 if (!tok_type_(t
->next
, TOK_WHITESPACE
))
3758 * expands to a list of tokens from %{x:y}
3760 static Token
*expand_mmac_params_range(MMacro
*mac
, Token
*tline
, Token
***last
)
3762 Token
*t
= tline
, **tt
, *tm
, *head
;
3766 pos
= strchr(tline
->text
, ':');
3769 lst
= atoi(pos
+ 1);
3770 fst
= atoi(tline
->text
+ 1);
3773 * only macros params are accounted so
3774 * if someone passes %0 -- we reject such
3777 if (lst
== 0 || fst
== 0)
3780 /* the values should be sane */
3781 if ((fst
> (int)mac
->nparam
|| fst
< (-(int)mac
->nparam
)) ||
3782 (lst
> (int)mac
->nparam
|| lst
< (-(int)mac
->nparam
)))
3785 fst
= fst
< 0 ? fst
+ (int)mac
->nparam
+ 1: fst
;
3786 lst
= lst
< 0 ? lst
+ (int)mac
->nparam
+ 1: lst
;
3788 /* counted from zero */
3792 * it will be at least one token
3794 tm
= mac
->params
[(fst
+ mac
->rotate
) % mac
->nparam
];
3795 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3796 head
= t
, tt
= &t
->next
;
3798 for (i
= fst
+ 1; i
<= lst
; i
++) {
3799 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
3800 *tt
= t
, tt
= &t
->next
;
3801 j
= (i
+ mac
->rotate
) % mac
->nparam
;
3802 tm
= mac
->params
[j
];
3803 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3804 *tt
= t
, tt
= &t
->next
;
3807 for (i
= fst
- 1; i
>= lst
; i
--) {
3808 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
3809 *tt
= t
, tt
= &t
->next
;
3810 j
= (i
+ mac
->rotate
) % mac
->nparam
;
3811 tm
= mac
->params
[j
];
3812 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3813 *tt
= t
, tt
= &t
->next
;
3821 error(ERR_NONFATAL
, "`%%{%s}': macro parameters out of range",
3827 * Expand MMacro-local things: parameter references (%0, %n, %+n,
3828 * %-n) and MMacro-local identifiers (%%foo) as well as
3829 * macro indirection (%[...]) and range (%{..:..}).
3831 static Token
*expand_mmac_params(Token
* tline
)
3833 Token
*t
, *tt
, **tail
, *thead
;
3834 bool changed
= false;
3841 if (tline
->type
== TOK_PREPROC_ID
&&
3842 (((tline
->text
[1] == '+' || tline
->text
[1] == '-') && tline
->text
[2]) ||
3843 (tline
->text
[1] >= '0' && tline
->text
[1] <= '9') ||
3844 tline
->text
[1] == '%')) {
3846 int type
= 0, cc
; /* type = 0 to placate optimisers */
3853 tline
= tline
->next
;
3856 while (mac
&& !mac
->name
) /* avoid mistaking %reps for macros */
3857 mac
= mac
->next_active
;
3859 error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
3861 pos
= strchr(t
->text
, ':');
3863 switch (t
->text
[1]) {
3865 * We have to make a substitution of one of the
3866 * forms %1, %-1, %+1, %%foo, %0.
3870 snprintf(tmpbuf
, sizeof(tmpbuf
), "%d", mac
->nparam
);
3871 text
= nasm_strdup(tmpbuf
);
3875 snprintf(tmpbuf
, sizeof(tmpbuf
), "..@%"PRIu64
".",
3877 text
= nasm_strcat(tmpbuf
, t
->text
+ 2);
3880 n
= atoi(t
->text
+ 2) - 1;
3881 if (n
>= mac
->nparam
)
3884 if (mac
->nparam
> 1)
3885 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3886 tt
= mac
->params
[n
];
3891 "macro parameter %d is not a condition code",
3896 if (inverse_ccs
[cc
] == -1) {
3898 "condition code `%s' is not invertible",
3902 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
3906 n
= atoi(t
->text
+ 2) - 1;
3907 if (n
>= mac
->nparam
)
3910 if (mac
->nparam
> 1)
3911 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3912 tt
= mac
->params
[n
];
3917 "macro parameter %d is not a condition code",
3922 text
= nasm_strdup(conditions
[cc
]);
3926 n
= atoi(t
->text
+ 1) - 1;
3927 if (n
>= mac
->nparam
)
3930 if (mac
->nparam
> 1)
3931 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3932 tt
= mac
->params
[n
];
3935 for (i
= 0; i
< mac
->paramlen
[n
]; i
++) {
3936 *tail
= new_Token(NULL
, tt
->type
, tt
->text
, 0);
3937 tail
= &(*tail
)->next
;
3941 text
= NULL
; /* we've done it here */
3946 * seems we have a parameters range here
3948 Token
*head
, **last
;
3949 head
= expand_mmac_params_range(mac
, t
, &last
);
3970 } else if (tline
->type
== TOK_INDIRECT
) {
3972 tline
= tline
->next
;
3973 tt
= tokenize(t
->text
);
3974 tt
= expand_mmac_params(tt
);
3975 tt
= expand_smacro(tt
);
3978 tt
->a
.mac
= NULL
; /* Necessary? */
3986 tline
= tline
->next
;
3994 const struct tokseq_match t
[] = {
3996 PP_CONCAT_MASK(TOK_ID
) |
3997 PP_CONCAT_MASK(TOK_FLOAT
), /* head */
3998 PP_CONCAT_MASK(TOK_ID
) |
3999 PP_CONCAT_MASK(TOK_NUMBER
) |
4000 PP_CONCAT_MASK(TOK_FLOAT
) |
4001 PP_CONCAT_MASK(TOK_OTHER
) /* tail */
4004 PP_CONCAT_MASK(TOK_NUMBER
), /* head */
4005 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4008 paste_tokens(&thead
, t
, ARRAY_SIZE(t
), false);
4015 * Expand all single-line macro calls made in the given line.
4016 * Return the expanded version of the line. The original is deemed
4017 * to be destroyed in the process. (In reality we'll just move
4018 * Tokens from input to output a lot of the time, rather than
4019 * actually bothering to destroy and replicate.)
4022 static Token
*expand_smacro(Token
* tline
)
4024 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
4025 SMacro
*head
= NULL
, *m
;
4028 unsigned int nparam
, sparam
;
4030 Token
*org_tline
= tline
;
4033 int deadman
= DEADMAN_LIMIT
;
4037 * Trick: we should avoid changing the start token pointer since it can
4038 * be contained in "next" field of other token. Because of this
4039 * we allocate a copy of first token and work with it; at the end of
4040 * routine we copy it back
4043 tline
= new_Token(org_tline
->next
, org_tline
->type
,
4044 org_tline
->text
, 0);
4045 tline
->a
.mac
= org_tline
->a
.mac
;
4046 nasm_free(org_tline
->text
);
4047 org_tline
->text
= NULL
;
4050 expanded
= true; /* Always expand %+ at least once */
4056 while (tline
) { /* main token loop */
4058 error(ERR_NONFATAL
, "interminable macro recursion");
4062 if ((mname
= tline
->text
)) {
4063 /* if this token is a local macro, look in local context */
4064 if (tline
->type
== TOK_ID
) {
4065 head
= (SMacro
*)hash_findix(&smacros
, mname
);
4066 } else if (tline
->type
== TOK_PREPROC_ID
) {
4067 ctx
= get_ctx(mname
, &mname
, true);
4068 head
= ctx
? (SMacro
*)hash_findix(&ctx
->localmac
, mname
) : NULL
;
4073 * We've hit an identifier. As in is_mmacro below, we first
4074 * check whether the identifier is a single-line macro at
4075 * all, then think about checking for parameters if
4078 list_for_each(m
, head
)
4079 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
4085 if (m
->nparam
== 0) {
4087 * Simple case: the macro is parameterless. Discard the
4088 * one token that the macro call took, and push the
4089 * expansion back on the to-do stack.
4091 if (!m
->expansion
) {
4092 if (!strcmp("__FILE__", m
->name
)) {
4095 src_get(&num
, &file
);
4096 tline
->text
= nasm_quote(file
, strlen(file
));
4097 tline
->type
= TOK_STRING
;
4101 if (!strcmp("__LINE__", m
->name
)) {
4102 nasm_free(tline
->text
);
4103 make_tok_num(tline
, src_get_linnum());
4106 if (!strcmp("__BITS__", m
->name
)) {
4107 nasm_free(tline
->text
);
4108 make_tok_num(tline
, globalbits
);
4111 tline
= delete_Token(tline
);
4116 * Complicated case: at least one macro with this name
4117 * exists and takes parameters. We must find the
4118 * parameters in the call, count them, find the SMacro
4119 * that corresponds to that form of the macro call, and
4120 * substitute for the parameters when we expand. What a
4123 /*tline = tline->next;
4124 skip_white_(tline); */
4127 while (tok_type_(t
, TOK_SMAC_END
)) {
4128 t
->a
.mac
->in_progress
= false;
4130 t
= tline
->next
= delete_Token(t
);
4133 } while (tok_type_(tline
, TOK_WHITESPACE
));
4134 if (!tok_is_(tline
, "(")) {
4136 * This macro wasn't called with parameters: ignore
4137 * the call. (Behaviour borrowed from gnu cpp.)
4146 sparam
= PARAM_DELTA
;
4147 params
= nasm_malloc(sparam
* sizeof(Token
*));
4148 params
[0] = tline
->next
;
4149 paramsize
= nasm_malloc(sparam
* sizeof(int));
4151 while (true) { /* parameter loop */
4153 * For some unusual expansions
4154 * which concatenates function call
4157 while (tok_type_(t
, TOK_SMAC_END
)) {
4158 t
->a
.mac
->in_progress
= false;
4160 t
= tline
->next
= delete_Token(t
);
4166 "macro call expects terminating `)'");
4169 if (tline
->type
== TOK_WHITESPACE
4171 if (paramsize
[nparam
])
4174 params
[nparam
] = tline
->next
;
4175 continue; /* parameter loop */
4177 if (tline
->type
== TOK_OTHER
4178 && tline
->text
[1] == 0) {
4179 char ch
= tline
->text
[0];
4180 if (ch
== ',' && !paren
&& brackets
<= 0) {
4181 if (++nparam
>= sparam
) {
4182 sparam
+= PARAM_DELTA
;
4183 params
= nasm_realloc(params
,
4184 sparam
* sizeof(Token
*));
4185 paramsize
= nasm_realloc(paramsize
,
4186 sparam
* sizeof(int));
4188 params
[nparam
] = tline
->next
;
4189 paramsize
[nparam
] = 0;
4191 continue; /* parameter loop */
4194 (brackets
> 0 || (brackets
== 0 &&
4195 !paramsize
[nparam
])))
4197 if (!(brackets
++)) {
4198 params
[nparam
] = tline
->next
;
4199 continue; /* parameter loop */
4202 if (ch
== '}' && brackets
> 0)
4203 if (--brackets
== 0) {
4205 continue; /* parameter loop */
4207 if (ch
== '(' && !brackets
)
4209 if (ch
== ')' && brackets
<= 0)
4215 error(ERR_NONFATAL
, "braces do not "
4216 "enclose all of macro parameter");
4218 paramsize
[nparam
] += white
+ 1;
4220 } /* parameter loop */
4222 while (m
&& (m
->nparam
!= nparam
||
4223 mstrcmp(m
->name
, mname
,
4227 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4228 "macro `%s' exists, "
4229 "but not taking %d parameters",
4230 mstart
->text
, nparam
);
4233 if (m
&& m
->in_progress
)
4235 if (!m
) { /* in progess or didn't find '(' or wrong nparam */
4237 * Design question: should we handle !tline, which
4238 * indicates missing ')' here, or expand those
4239 * macros anyway, which requires the (t) test a few
4243 nasm_free(paramsize
);
4247 * Expand the macro: we are placed on the last token of the
4248 * call, so that we can easily split the call from the
4249 * following tokens. We also start by pushing an SMAC_END
4250 * token for the cycle removal.
4257 tt
= new_Token(tline
, TOK_SMAC_END
, NULL
, 0);
4259 m
->in_progress
= true;
4261 list_for_each(t
, m
->expansion
) {
4262 if (t
->type
>= TOK_SMAC_PARAM
) {
4263 Token
*pcopy
= tline
, **ptail
= &pcopy
;
4267 ttt
= params
[t
->type
- TOK_SMAC_PARAM
];
4268 i
= paramsize
[t
->type
- TOK_SMAC_PARAM
];
4270 pt
= *ptail
= new_Token(tline
, ttt
->type
,
4276 } else if (t
->type
== TOK_PREPROC_Q
) {
4277 tt
= new_Token(tline
, TOK_ID
, mname
, 0);
4279 } else if (t
->type
== TOK_PREPROC_QQ
) {
4280 tt
= new_Token(tline
, TOK_ID
, m
->name
, 0);
4283 tt
= new_Token(tline
, t
->type
, t
->text
, 0);
4289 * Having done that, get rid of the macro call, and clean
4290 * up the parameters.
4293 nasm_free(paramsize
);
4296 continue; /* main token loop */
4301 if (tline
->type
== TOK_SMAC_END
) {
4302 tline
->a
.mac
->in_progress
= false;
4303 tline
= delete_Token(tline
);
4306 tline
= tline
->next
;
4314 * Now scan the entire line and look for successive TOK_IDs that resulted
4315 * after expansion (they can't be produced by tokenize()). The successive
4316 * TOK_IDs should be concatenated.
4317 * Also we look for %+ tokens and concatenate the tokens before and after
4318 * them (without white spaces in between).
4321 const struct tokseq_match t
[] = {
4323 PP_CONCAT_MASK(TOK_ID
) |
4324 PP_CONCAT_MASK(TOK_PREPROC_ID
), /* head */
4325 PP_CONCAT_MASK(TOK_ID
) |
4326 PP_CONCAT_MASK(TOK_PREPROC_ID
) |
4327 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4330 if (paste_tokens(&thead
, t
, ARRAY_SIZE(t
), true)) {
4332 * If we concatenated something, *and* we had previously expanded
4333 * an actual macro, scan the lines again for macros...
4344 *org_tline
= *thead
;
4345 /* since we just gave text to org_line, don't free it */
4347 delete_Token(thead
);
4349 /* the expression expanded to empty line;
4350 we can't return NULL for some reasons
4351 we just set the line to a single WHITESPACE token. */
4352 memset(org_tline
, 0, sizeof(*org_tline
));
4353 org_tline
->text
= NULL
;
4354 org_tline
->type
= TOK_WHITESPACE
;
4363 * Similar to expand_smacro but used exclusively with macro identifiers
4364 * right before they are fetched in. The reason is that there can be
4365 * identifiers consisting of several subparts. We consider that if there
4366 * are more than one element forming the name, user wants a expansion,
4367 * otherwise it will be left as-is. Example:
4371 * the identifier %$abc will be left as-is so that the handler for %define
4372 * will suck it and define the corresponding value. Other case:
4374 * %define _%$abc cde
4376 * In this case user wants name to be expanded *before* %define starts
4377 * working, so we'll expand %$abc into something (if it has a value;
4378 * otherwise it will be left as-is) then concatenate all successive
4381 static Token
*expand_id(Token
* tline
)
4383 Token
*cur
, *oldnext
= NULL
;
4385 if (!tline
|| !tline
->next
)
4390 (cur
->next
->type
== TOK_ID
||
4391 cur
->next
->type
== TOK_PREPROC_ID
4392 || cur
->next
->type
== TOK_NUMBER
))
4395 /* If identifier consists of just one token, don't expand */
4400 oldnext
= cur
->next
; /* Detach the tail past identifier */
4401 cur
->next
= NULL
; /* so that expand_smacro stops here */
4404 tline
= expand_smacro(tline
);
4407 /* expand_smacro possibly changhed tline; re-scan for EOL */
4409 while (cur
&& cur
->next
)
4412 cur
->next
= oldnext
;
4419 * Determine whether the given line constitutes a multi-line macro
4420 * call, and return the MMacro structure called if so. Doesn't have
4421 * to check for an initial label - that's taken care of in
4422 * expand_mmacro - but must check numbers of parameters. Guaranteed
4423 * to be called with tline->type == TOK_ID, so the putative macro
4424 * name is easy to find.
4426 static MMacro
*is_mmacro(Token
* tline
, Token
*** params_array
)
4432 head
= (MMacro
*) hash_findix(&mmacros
, tline
->text
);
4435 * Efficiency: first we see if any macro exists with the given
4436 * name. If not, we can return NULL immediately. _Then_ we
4437 * count the parameters, and then we look further along the
4438 * list if necessary to find the proper MMacro.
4440 list_for_each(m
, head
)
4441 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
4447 * OK, we have a potential macro. Count and demarcate the
4450 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
4453 * So we know how many parameters we've got. Find the MMacro
4454 * structure that handles this number.
4457 if (m
->nparam_min
<= nparam
4458 && (m
->plus
|| nparam
<= m
->nparam_max
)) {
4460 * This one is right. Just check if cycle removal
4461 * prohibits us using it before we actually celebrate...
4463 if (m
->in_progress
> m
->max_depth
) {
4464 if (m
->max_depth
> 0) {
4466 "reached maximum recursion depth of %i",
4473 * It's right, and we can use it. Add its default
4474 * parameters to the end of our list if necessary.
4476 if (m
->defaults
&& nparam
< m
->nparam_min
+ m
->ndefs
) {
4478 nasm_realloc(params
,
4479 ((m
->nparam_min
+ m
->ndefs
+
4480 1) * sizeof(*params
)));
4481 while (nparam
< m
->nparam_min
+ m
->ndefs
) {
4482 params
[nparam
] = m
->defaults
[nparam
- m
->nparam_min
];
4487 * If we've gone over the maximum parameter count (and
4488 * we're in Plus mode), ignore parameters beyond
4491 if (m
->plus
&& nparam
> m
->nparam_max
)
4492 nparam
= m
->nparam_max
;
4494 * Then terminate the parameter list, and leave.
4496 if (!params
) { /* need this special case */
4497 params
= nasm_malloc(sizeof(*params
));
4500 params
[nparam
] = NULL
;
4501 *params_array
= params
;
4505 * This one wasn't right: look for the next one with the
4508 list_for_each(m
, m
->next
)
4509 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
4514 * After all that, we didn't find one with the right number of
4515 * parameters. Issue a warning, and fail to expand the macro.
4517 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4518 "macro `%s' exists, but not taking %d parameters",
4519 tline
->text
, nparam
);
4526 * Save MMacro invocation specific fields in
4527 * preparation for a recursive macro expansion
4529 static void push_mmacro(MMacro
*m
)
4531 MMacroInvocation
*i
;
4533 i
= nasm_malloc(sizeof(MMacroInvocation
));
4535 i
->params
= m
->params
;
4536 i
->iline
= m
->iline
;
4537 i
->nparam
= m
->nparam
;
4538 i
->rotate
= m
->rotate
;
4539 i
->paramlen
= m
->paramlen
;
4540 i
->unique
= m
->unique
;
4541 i
->condcnt
= m
->condcnt
;
4547 * Restore MMacro invocation specific fields that were
4548 * saved during a previous recursive macro expansion
4550 static void pop_mmacro(MMacro
*m
)
4552 MMacroInvocation
*i
;
4557 m
->params
= i
->params
;
4558 m
->iline
= i
->iline
;
4559 m
->nparam
= i
->nparam
;
4560 m
->rotate
= i
->rotate
;
4561 m
->paramlen
= i
->paramlen
;
4562 m
->unique
= i
->unique
;
4563 m
->condcnt
= i
->condcnt
;
4570 * Expand the multi-line macro call made by the given line, if
4571 * there is one to be expanded. If there is, push the expansion on
4572 * istk->expansion and return 1. Otherwise return 0.
4574 static int expand_mmacro(Token
* tline
)
4576 Token
*startline
= tline
;
4577 Token
*label
= NULL
;
4578 int dont_prepend
= 0;
4579 Token
**params
, *t
, *mtok
, *tt
;
4582 int i
, nparam
, *paramlen
;
4587 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4588 if (!tok_type_(t
, TOK_ID
) && !tok_type_(t
, TOK_PREPROC_ID
))
4591 m
= is_mmacro(t
, ¶ms
);
4597 * We have an id which isn't a macro call. We'll assume
4598 * it might be a label; we'll also check to see if a
4599 * colon follows it. Then, if there's another id after
4600 * that lot, we'll check it again for macro-hood.
4604 if (tok_type_(t
, TOK_WHITESPACE
))
4605 last
= t
, t
= t
->next
;
4606 if (tok_is_(t
, ":")) {
4608 last
= t
, t
= t
->next
;
4609 if (tok_type_(t
, TOK_WHITESPACE
))
4610 last
= t
, t
= t
->next
;
4612 if (!tok_type_(t
, TOK_ID
) || !(m
= is_mmacro(t
, ¶ms
)))
4620 * Fix up the parameters: this involves stripping leading and
4621 * trailing whitespace, then stripping braces if they are
4624 for (nparam
= 0; params
[nparam
]; nparam
++) ;
4625 paramlen
= nparam
? nasm_malloc(nparam
* sizeof(*paramlen
)) : NULL
;
4627 for (i
= 0; params
[i
]; i
++) {
4629 int comma
= (!m
->plus
|| i
< nparam
- 1);
4633 if (tok_is_(t
, "{"))
4634 t
= t
->next
, brace
= true, comma
= false;
4638 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
4639 break; /* ... because we have hit a comma */
4640 if (comma
&& t
->type
== TOK_WHITESPACE
4641 && tok_is_(t
->next
, ","))
4642 break; /* ... or a space then a comma */
4643 if (brace
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "}"))
4644 break; /* ... or a brace */
4651 * OK, we have a MMacro structure together with a set of
4652 * parameters. We must now go through the expansion and push
4653 * copies of each Line on to istk->expansion. Substitution of
4654 * parameter tokens and macro-local tokens doesn't get done
4655 * until the single-line macro substitution process; this is
4656 * because delaying them allows us to change the semantics
4657 * later through %rotate.
4659 * First, push an end marker on to istk->expansion, mark this
4660 * macro as in progress, and set up its invocation-specific
4663 ll
= nasm_malloc(sizeof(Line
));
4664 ll
->next
= istk
->expansion
;
4667 istk
->expansion
= ll
;
4670 * Save the previous MMacro expansion in the case of
4673 if (m
->max_depth
&& m
->in_progress
)
4681 m
->paramlen
= paramlen
;
4682 m
->unique
= unique
++;
4686 m
->next_active
= istk
->mstk
;
4689 list_for_each(l
, m
->expansion
) {
4692 ll
= nasm_malloc(sizeof(Line
));
4693 ll
->finishes
= NULL
;
4694 ll
->next
= istk
->expansion
;
4695 istk
->expansion
= ll
;
4698 list_for_each(t
, l
->first
) {
4702 tt
= *tail
= new_Token(NULL
, TOK_ID
, mname
, 0);
4704 case TOK_PREPROC_QQ
:
4705 tt
= *tail
= new_Token(NULL
, TOK_ID
, m
->name
, 0);
4707 case TOK_PREPROC_ID
:
4708 if (t
->text
[1] == '0' && t
->text
[2] == '0') {
4716 tt
= *tail
= new_Token(NULL
, x
->type
, x
->text
, 0);
4725 * If we had a label, push it on as the first line of
4726 * the macro expansion.
4729 if (dont_prepend
< 0)
4730 free_tlist(startline
);
4732 ll
= nasm_malloc(sizeof(Line
));
4733 ll
->finishes
= NULL
;
4734 ll
->next
= istk
->expansion
;
4735 istk
->expansion
= ll
;
4736 ll
->first
= startline
;
4737 if (!dont_prepend
) {
4739 label
= label
->next
;
4740 label
->next
= tt
= new_Token(NULL
, TOK_OTHER
, ":", 0);
4745 list
->uplevel(m
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
4750 /* The function that actually does the error reporting */
4751 static void verror(int severity
, const char *fmt
, va_list arg
)
4754 MMacro
*mmac
= NULL
;
4757 vsnprintf(buff
, sizeof(buff
), fmt
, arg
);
4759 /* get %macro name */
4760 if (istk
&& istk
->mstk
) {
4762 /* but %rep blocks should be skipped */
4763 while (mmac
&& !mmac
->name
)
4764 mmac
= mmac
->next_active
, delta
++;
4768 nasm_error(severity
, "(%s:%d) %s",
4769 mmac
->name
, mmac
->lineno
- delta
, buff
);
4771 nasm_error(severity
, "%s", buff
);
4775 * Since preprocessor always operate only on the line that didn't
4776 * arrived yet, we should always use ERR_OFFBY1.
4778 static void error(int severity
, const char *fmt
, ...)
4782 /* If we're in a dead branch of IF or something like it, ignore the error */
4783 if (istk
&& istk
->conds
&& !emitting(istk
->conds
->state
))
4787 verror(severity
, fmt
, arg
);
4792 * Because %else etc are evaluated in the state context
4793 * of the previous branch, errors might get lost with error():
4794 * %if 0 ... %else trailing garbage ... %endif
4795 * So %else etc should report errors with this function.
4797 static void error_precond(int severity
, const char *fmt
, ...)
4801 /* Only ignore the error if it's really in a dead branch */
4802 if (istk
&& istk
->conds
&& istk
->conds
->state
== COND_NEVER
)
4806 verror(severity
, fmt
, arg
);
4811 pp_reset(char *file
, int apass
, ListGen
* listgen
, StrList
**deplist
)
4816 istk
= nasm_malloc(sizeof(Include
));
4819 istk
->expansion
= NULL
;
4821 istk
->fp
= fopen(file
, "r");
4823 src_set_fname(nasm_strdup(file
));
4827 error(ERR_FATAL
|ERR_NOFILE
, "unable to open input file `%s'",
4830 nested_mac_count
= 0;
4831 nested_rep_count
= 0;
4834 if (tasm_compatible_mode
) {
4835 stdmacpos
= nasm_stdmac
;
4837 stdmacpos
= nasm_stdmac_after_tasm
;
4839 any_extrastdmac
= extrastdmac
&& *extrastdmac
;
4844 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
4845 * The caller, however, will also pass in 3 for preprocess-only so
4846 * we can set __PASS__ accordingly.
4848 pass
= apass
> 2 ? 2 : apass
;
4850 dephead
= deptail
= deplist
;
4852 StrList
*sl
= nasm_malloc(strlen(file
)+1+sizeof sl
->next
);
4854 strcpy(sl
->str
, file
);
4856 deptail
= &sl
->next
;
4860 * Define the __PASS__ macro. This is defined here unlike
4861 * all the other builtins, because it is special -- it varies between
4864 t
= nasm_malloc(sizeof(*t
));
4866 make_tok_num(t
, apass
);
4868 define_smacro(NULL
, "__PASS__", true, 0, t
);
4871 static char *pp_getline(void)
4878 * Fetch a tokenized line, either from the macro-expansion
4879 * buffer or from the input file.
4882 while (istk
->expansion
&& istk
->expansion
->finishes
) {
4883 Line
*l
= istk
->expansion
;
4884 if (!l
->finishes
->name
&& l
->finishes
->in_progress
> 1) {
4888 * This is a macro-end marker for a macro with no
4889 * name, which means it's not really a macro at all
4890 * but a %rep block, and the `in_progress' field is
4891 * more than 1, meaning that we still need to
4892 * repeat. (1 means the natural last repetition; 0
4893 * means termination by %exitrep.) We have
4894 * therefore expanded up to the %endrep, and must
4895 * push the whole block on to the expansion buffer
4896 * again. We don't bother to remove the macro-end
4897 * marker: we'd only have to generate another one
4900 l
->finishes
->in_progress
--;
4901 list_for_each(l
, l
->finishes
->expansion
) {
4902 Token
*t
, *tt
, **tail
;
4904 ll
= nasm_malloc(sizeof(Line
));
4905 ll
->next
= istk
->expansion
;
4906 ll
->finishes
= NULL
;
4910 list_for_each(t
, l
->first
) {
4911 if (t
->text
|| t
->type
== TOK_WHITESPACE
) {
4912 tt
= *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
4917 istk
->expansion
= ll
;
4921 * Check whether a `%rep' was started and not ended
4922 * within this macro expansion. This can happen and
4923 * should be detected. It's a fatal error because
4924 * I'm too confused to work out how to recover
4930 "defining with name in expansion");
4931 else if (istk
->mstk
->name
)
4933 "`%%rep' without `%%endrep' within"
4934 " expansion of macro `%s'",
4939 * FIXME: investigate the relationship at this point between
4940 * istk->mstk and l->finishes
4943 MMacro
*m
= istk
->mstk
;
4944 istk
->mstk
= m
->next_active
;
4947 * This was a real macro call, not a %rep, and
4948 * therefore the parameter information needs to
4953 l
->finishes
->in_progress
--;
4955 nasm_free(m
->params
);
4956 free_tlist(m
->iline
);
4957 nasm_free(m
->paramlen
);
4958 l
->finishes
->in_progress
= 0;
4963 istk
->expansion
= l
->next
;
4965 list
->downlevel(LIST_MACRO
);
4968 while (1) { /* until we get a line we can use */
4970 if (istk
->expansion
) { /* from a macro expansion */
4972 Line
*l
= istk
->expansion
;
4974 istk
->mstk
->lineno
++;
4976 istk
->expansion
= l
->next
;
4978 p
= detoken(tline
, false);
4979 list
->line(LIST_MACRO
, p
);
4984 if (line
) { /* from the current input file */
4985 line
= prepreproc(line
);
4986 tline
= tokenize(line
);
4991 * The current file has ended; work down the istk
4997 /* nasm_error can't be conditionally suppressed */
4998 nasm_error(ERR_FATAL
,
4999 "expected `%%endif' before end of file");
5001 /* only set line and file name if there's a next node */
5003 src_set_linnum(i
->lineno
);
5004 nasm_free(src_set_fname(i
->fname
));
5007 list
->downlevel(LIST_INCLUDE
);
5011 if (istk
->expansion
&& istk
->expansion
->finishes
)
5017 * We must expand MMacro parameters and MMacro-local labels
5018 * _before_ we plunge into directive processing, to cope
5019 * with things like `%define something %1' such as STRUC
5020 * uses. Unless we're _defining_ a MMacro, in which case
5021 * those tokens should be left alone to go into the
5022 * definition; and unless we're in a non-emitting
5023 * condition, in which case we don't want to meddle with
5026 if (!defining
&& !(istk
->conds
&& !emitting(istk
->conds
->state
))
5027 && !(istk
->mstk
&& !istk
->mstk
->in_progress
)) {
5028 tline
= expand_mmac_params(tline
);
5032 * Check the line to see if it's a preprocessor directive.
5034 if (do_directive(tline
) == DIRECTIVE_FOUND
) {
5036 } else if (defining
) {
5038 * We're defining a multi-line macro. We emit nothing
5040 * shove the tokenized line on to the macro definition.
5042 Line
*l
= nasm_malloc(sizeof(Line
));
5043 l
->next
= defining
->expansion
;
5046 defining
->expansion
= l
;
5048 } else if (istk
->conds
&& !emitting(istk
->conds
->state
)) {
5050 * We're in a non-emitting branch of a condition block.
5051 * Emit nothing at all, not even a blank line: when we
5052 * emerge from the condition we'll give a line-number
5053 * directive so we keep our place correctly.
5057 } else if (istk
->mstk
&& !istk
->mstk
->in_progress
) {
5059 * We're in a %rep block which has been terminated, so
5060 * we're walking through to the %endrep without
5061 * emitting anything. Emit nothing at all, not even a
5062 * blank line: when we emerge from the %rep block we'll
5063 * give a line-number directive so we keep our place
5069 tline
= expand_smacro(tline
);
5070 if (!expand_mmacro(tline
)) {
5072 * De-tokenize the line again, and emit it.
5074 line
= detoken(tline
, true);
5078 continue; /* expand_mmacro calls free_tlist */
5086 static void pp_cleanup(int pass
)
5089 if (defining
->name
) {
5091 "end of file while still defining macro `%s'",
5094 error(ERR_NONFATAL
, "end of file while still in %%rep");
5097 free_mmacro(defining
);
5107 nasm_free(i
->fname
);
5112 nasm_free(src_set_fname(NULL
));
5117 while ((i
= ipath
)) {
5126 void pp_include_path(char *path
)
5130 i
= nasm_malloc(sizeof(IncPath
));
5131 i
->path
= path
? nasm_strdup(path
) : NULL
;
5144 void pp_pre_include(char *fname
)
5146 Token
*inc
, *space
, *name
;
5149 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
5150 space
= new_Token(name
, TOK_WHITESPACE
, NULL
, 0);
5151 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
5153 l
= nasm_malloc(sizeof(Line
));
5160 void pp_pre_define(char *definition
)
5166 equals
= strchr(definition
, '=');
5167 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5168 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
5171 space
->next
= tokenize(definition
);
5175 l
= nasm_malloc(sizeof(Line
));
5182 void pp_pre_undefine(char *definition
)
5187 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5188 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
5189 space
->next
= tokenize(definition
);
5191 l
= nasm_malloc(sizeof(Line
));
5199 * Added by Keith Kanios:
5201 * This function is used to assist with "runtime" preprocessor
5202 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
5204 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
5205 * PASS A VALID STRING TO THIS FUNCTION!!!!!
5208 void pp_runtime(char *definition
)
5212 def
= tokenize(definition
);
5213 if (do_directive(def
) == NO_DIRECTIVE_FOUND
)
5218 void pp_extra_stdmac(macros_t
*macros
)
5220 extrastdmac
= macros
;
5223 static void make_tok_num(Token
* tok
, int64_t val
)
5226 snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
5227 tok
->text
= nasm_strdup(numbuf
);
5228 tok
->type
= TOK_NUMBER
;