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 */
219 SMacro
*mac
; /* associated macro for TOK_SMAC_END */
220 size_t len
; /* scratch length field */
221 } a
; /* Auxiliary data */
222 enum pp_token_type type
;
226 * Multi-line macro definitions are stored as a linked list of
227 * these, which is essentially a container to allow several linked
230 * Note that in this module, linked lists are treated as stacks
231 * wherever possible. For this reason, Lines are _pushed_ on to the
232 * `expansion' field in MMacro structures, so that the linked list,
233 * if walked, would give the macro lines in reverse order; this
234 * means that we can walk the list when expanding a macro, and thus
235 * push the lines on to the `expansion' field in _istk_ in reverse
236 * order (so that when popped back off they are in the right
237 * order). It may seem cockeyed, and it relies on my design having
238 * an even number of steps in, but it works...
240 * Some of these structures, rather than being actual lines, are
241 * markers delimiting the end of the expansion of a given macro.
242 * This is for use in the cycle-tracking and %rep-handling code.
243 * Such structures have `finishes' non-NULL, and `first' NULL. All
244 * others have `finishes' NULL, but `first' may still be NULL if
254 * To handle an arbitrary level of file inclusion, we maintain a
255 * stack (ie linked list) of these things.
264 MMacro
*mstk
; /* stack of active macros/reps */
268 * Include search path. This is simply a list of strings which get
269 * prepended, in turn, to the name of an include file, in an
270 * attempt to find the file if it's not in the current directory.
278 * Conditional assembly: we maintain a separate stack of these for
279 * each level of file inclusion. (The only reason we keep the
280 * stacks separate is to ensure that a stray `%endif' in a file
281 * included from within the true branch of a `%if' won't terminate
282 * it and cause confusion: instead, rightly, it'll cause an error.)
290 * These states are for use just after %if or %elif: IF_TRUE
291 * means the condition has evaluated to truth so we are
292 * currently emitting, whereas IF_FALSE means we are not
293 * currently emitting but will start doing so if a %else comes
294 * up. In these states, all directives are admissible: %elif,
295 * %else and %endif. (And of course %if.)
297 COND_IF_TRUE
, COND_IF_FALSE
,
299 * These states come up after a %else: ELSE_TRUE means we're
300 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
301 * any %elif or %else will cause an error.
303 COND_ELSE_TRUE
, COND_ELSE_FALSE
,
305 * These states mean that we're not emitting now, and also that
306 * nothing until %endif will be emitted at all. COND_DONE is
307 * used when we've had our moment of emission
308 * and have now started seeing %elifs. COND_NEVER is used when
309 * the condition construct in question is contained within a
310 * non-emitting branch of a larger condition construct,
311 * or if there is an error.
313 COND_DONE
, COND_NEVER
315 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
318 * These defines are used as the possible return values for do_directive
320 #define NO_DIRECTIVE_FOUND 0
321 #define DIRECTIVE_FOUND 1
324 * This define sets the upper limit for smacro and recursive mmacro
327 #define DEADMAN_LIMIT (1 << 20)
330 #define REP_LIMIT ((INT64_C(1) << 62))
333 * Condition codes. Note that we use c_ prefix not C_ because C_ is
334 * used in nasm.h for the "real" condition codes. At _this_ level,
335 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
336 * ones, so we need a different enum...
338 static const char * const conditions
[] = {
339 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
340 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
341 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
344 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
345 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
346 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_RCXZ
, c_S
, c_Z
,
349 static const enum pp_conds inverse_ccs
[] = {
350 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
351 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
,
352 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, -1, c_NS
, c_NZ
358 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
359 static int is_condition(enum preproc_token arg
)
361 return PP_IS_COND(arg
) || (arg
== PP_ELSE
) || (arg
== PP_ENDIF
);
364 /* For TASM compatibility we need to be able to recognise TASM compatible
365 * conditional compilation directives. Using the NASM pre-processor does
366 * not work, so we look for them specifically from the following list and
367 * then jam in the equivalent NASM directive into the input stream.
371 TM_ARG
, TM_ELIF
, TM_ELSE
, TM_ENDIF
, TM_IF
, TM_IFDEF
, TM_IFDIFI
,
372 TM_IFNDEF
, TM_INCLUDE
, TM_LOCAL
375 static const char * const tasm_directives
[] = {
376 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
377 "ifndef", "include", "local"
380 static int StackSize
= 4;
381 static char *StackPointer
= "ebp";
382 static int ArgOffset
= 8;
383 static int LocalOffset
= 0;
385 static Context
*cstk
;
386 static Include
*istk
;
387 static IncPath
*ipath
= NULL
;
389 static int pass
; /* HACK: pass 0 = generate dependencies only */
390 static StrList
**dephead
, **deptail
; /* Dependency list */
392 static uint64_t unique
; /* unique identifier numbers */
394 static Line
*predef
= NULL
;
395 static bool do_predef
;
397 static ListGen
*list
;
400 * The current set of multi-line macros we have defined.
402 static struct hash_table mmacros
;
405 * The current set of single-line macros we have defined.
407 static struct hash_table smacros
;
410 * The multi-line macro we are currently defining, or the %rep
411 * block we are currently reading, if any.
413 static MMacro
*defining
;
415 static uint64_t nested_mac_count
;
416 static uint64_t nested_rep_count
;
419 * The number of macro parameters to allocate space for at a time.
421 #define PARAM_DELTA 16
424 * The standard macro set: defined in macros.c in the array nasm_stdmac.
425 * This gives our position in the macro set, when we're processing it.
427 static macros_t
*stdmacpos
;
430 * The extra standard macros that come from the object format, if
433 static macros_t
*extrastdmac
= NULL
;
434 static bool any_extrastdmac
;
437 * Tokens are allocated in blocks to improve speed
439 #define TOKEN_BLOCKSIZE 4096
440 static Token
*freeTokens
= NULL
;
446 static Blocks blocks
= { NULL
, NULL
};
449 * Forward declarations.
451 static Token
*expand_mmac_params(Token
* tline
);
452 static Token
*expand_smacro(Token
* tline
);
453 static Token
*expand_id(Token
* tline
);
454 static Context
*get_ctx(const char *name
, const char **namep
,
456 static void make_tok_num(Token
* tok
, int64_t val
);
457 static void error(int severity
, const char *fmt
, ...);
458 static void error_precond(int severity
, const char *fmt
, ...);
459 static void *new_Block(size_t size
);
460 static void delete_Blocks(void);
461 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
462 const char *text
, int txtlen
);
463 static Token
*delete_Token(Token
* t
);
466 * Macros for safe checking of token pointers, avoid *(NULL)
468 #define tok_type_(x,t) ((x) && (x)->type == (t))
469 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
470 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
471 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
474 * nasm_unquote with error if the string contains NUL characters.
475 * If the string contains NUL characters, issue an error and return
476 * the C len, i.e. truncate at the NUL.
478 static size_t nasm_unquote_cstr(char *qstr
, enum preproc_token directive
)
480 size_t len
= nasm_unquote(qstr
, NULL
);
481 size_t clen
= strlen(qstr
);
484 error(ERR_NONFATAL
, "NUL character in `%s' directive",
485 pp_directives
[directive
]);
491 * Handle TASM specific directives, which do not contain a % in
492 * front of them. We do it here because I could not find any other
493 * place to do it for the moment, and it is a hack (ideally it would
494 * be nice to be able to use the NASM pre-processor to do it).
496 static char *check_tasm_directive(char *line
)
498 int32_t i
, j
, k
, m
, len
;
499 char *p
, *q
, *oldline
, oldchar
;
501 p
= nasm_skip_spaces(line
);
503 /* Binary search for the directive name */
505 j
= ARRAY_SIZE(tasm_directives
);
506 q
= nasm_skip_word(p
);
513 m
= nasm_stricmp(p
, tasm_directives
[k
]);
515 /* We have found a directive, so jam a % in front of it
516 * so that NASM will then recognise it as one if it's own.
521 line
= nasm_malloc(len
+ 2);
523 if (k
== TM_IFDIFI
) {
525 * NASM does not recognise IFDIFI, so we convert
526 * it to %if 0. This is not used in NASM
527 * compatible code, but does need to parse for the
528 * TASM macro package.
530 strcpy(line
+ 1, "if 0");
532 memcpy(line
+ 1, p
, len
+ 1);
547 * The pre-preprocessing stage... This function translates line
548 * number indications as they emerge from GNU cpp (`# lineno "file"
549 * flags') into NASM preprocessor line number indications (`%line
552 static char *prepreproc(char *line
)
555 char *fname
, *oldline
;
557 if (line
[0] == '#' && line
[1] == ' ') {
560 lineno
= atoi(fname
);
561 fname
+= strspn(fname
, "0123456789 ");
564 fnlen
= strcspn(fname
, "\"");
565 line
= nasm_malloc(20 + fnlen
);
566 snprintf(line
, 20 + fnlen
, "%%line %d %.*s", lineno
, fnlen
, fname
);
569 if (tasm_compatible_mode
)
570 return check_tasm_directive(line
);
575 * Free a linked list of tokens.
577 static void free_tlist(Token
* list
)
580 list
= delete_Token(list
);
584 * Free a linked list of lines.
586 static void free_llist(Line
* list
)
589 list_for_each_safe(l
, tmp
, list
) {
590 free_tlist(l
->first
);
598 static void free_mmacro(MMacro
* m
)
601 free_tlist(m
->dlist
);
602 nasm_free(m
->defaults
);
603 free_llist(m
->expansion
);
608 * Free all currently defined macros, and free the hash tables
610 static void free_smacro_table(struct hash_table
*smt
)
614 struct hash_tbl_node
*it
= NULL
;
616 while ((s
= hash_iterate(smt
, &it
, &key
)) != NULL
) {
617 nasm_free((void *)key
);
618 list_for_each_safe(s
, tmp
, s
) {
620 free_tlist(s
->expansion
);
627 static void free_mmacro_table(struct hash_table
*mmt
)
631 struct hash_tbl_node
*it
= NULL
;
634 while ((m
= hash_iterate(mmt
, &it
, &key
)) != NULL
) {
635 nasm_free((void *)key
);
636 list_for_each_safe(m
,tmp
, m
)
642 static void free_macros(void)
644 free_smacro_table(&smacros
);
645 free_mmacro_table(&mmacros
);
649 * Initialize the hash tables
651 static void init_macros(void)
653 hash_init(&smacros
, HASH_LARGE
);
654 hash_init(&mmacros
, HASH_LARGE
);
658 * Pop the context stack.
660 static void ctx_pop(void)
665 free_smacro_table(&c
->localmac
);
671 * Search for a key in the hash index; adding it if necessary
672 * (in which case we initialize the data pointer to NULL.)
675 hash_findi_add(struct hash_table
*hash
, const char *str
)
677 struct hash_insert hi
;
681 r
= hash_findi(hash
, str
, &hi
);
685 strx
= nasm_strdup(str
); /* Use a more efficient allocator here? */
686 return hash_add(&hi
, strx
, NULL
);
690 * Like hash_findi, but returns the data element rather than a pointer
691 * to it. Used only when not adding a new element, hence no third
695 hash_findix(struct hash_table
*hash
, const char *str
)
699 p
= hash_findi(hash
, str
, NULL
);
700 return p
? *p
: NULL
;
704 * read line from standart macros set,
705 * if there no more left -- return NULL
707 static char *line_from_stdmac(void)
710 const unsigned char *p
= stdmacpos
;
719 len
+= pp_directives_len
[c
- 0x80] + 1;
724 line
= nasm_malloc(len
+ 1);
726 while ((c
= *stdmacpos
++)) {
728 memcpy(q
, pp_directives
[c
- 0x80], pp_directives_len
[c
- 0x80]);
729 q
+= pp_directives_len
[c
- 0x80];
739 /* This was the last of the standard macro chain... */
741 if (any_extrastdmac
) {
742 stdmacpos
= extrastdmac
;
743 any_extrastdmac
= false;
744 } else if (do_predef
) {
746 Token
*head
, **tail
, *t
;
749 * Nasty hack: here we push the contents of
750 * `predef' on to the top-level expansion stack,
751 * since this is the most convenient way to
752 * implement the pre-include and pre-define
755 list_for_each(pd
, predef
) {
758 list_for_each(t
, pd
->first
) {
759 *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
760 tail
= &(*tail
)->next
;
763 l
= nasm_malloc(sizeof(Line
));
764 l
->next
= istk
->expansion
;
777 #define BUF_DELTA 512
779 * Read a line from the top file in istk, handling multiple CR/LFs
780 * at the end of the line read, and handling spurious ^Zs. Will
781 * return lines from the standard macro set if this has not already
784 static char *read_line(void)
786 char *buffer
, *p
, *q
;
787 int bufsize
, continued_count
;
790 * standart macros set (predefined) goes first
792 p
= line_from_stdmac();
797 * regular read from a file
800 buffer
= nasm_malloc(BUF_DELTA
);
804 q
= fgets(p
, bufsize
- (p
- buffer
), istk
->fp
);
808 if (p
> buffer
&& p
[-1] == '\n') {
810 * Convert backslash-CRLF line continuation sequences into
811 * nothing at all (for DOS and Windows)
813 if (((p
- 2) > buffer
) && (p
[-3] == '\\') && (p
[-2] == '\r')) {
819 * Also convert backslash-LF line continuation sequences into
820 * nothing at all (for Unix)
822 else if (((p
- 1) > buffer
) && (p
[-2] == '\\')) {
830 if (p
- buffer
> bufsize
- 10) {
831 int32_t offset
= p
- buffer
;
832 bufsize
+= BUF_DELTA
;
833 buffer
= nasm_realloc(buffer
, bufsize
);
834 p
= buffer
+ offset
; /* prevent stale-pointer problems */
838 if (!q
&& p
== buffer
) {
843 src_set_linnum(src_get_linnum() + istk
->lineinc
+
844 (continued_count
* istk
->lineinc
));
847 * Play safe: remove CRs as well as LFs, if any of either are
848 * present at the end of the line.
850 while (--p
>= buffer
&& (*p
== '\n' || *p
== '\r'))
854 * Handle spurious ^Z, which may be inserted into source files
855 * by some file transfer utilities.
857 buffer
[strcspn(buffer
, "\032")] = '\0';
859 list
->line(LIST_READ
, buffer
);
865 * Tokenize a line of text. This is a very simple process since we
866 * don't need to parse the value out of e.g. numeric tokens: we
867 * simply split one string into many.
869 static Token
*tokenize(char *line
)
872 enum pp_token_type type
;
874 Token
*t
, **tail
= &list
;
880 if (*p
== '+' && !nasm_isdigit(p
[1])) {
883 } else if (nasm_isdigit(*p
) ||
884 ((*p
== '-' || *p
== '+') && nasm_isdigit(p
[1]))) {
888 while (nasm_isdigit(*p
));
889 type
= TOK_PREPROC_ID
;
890 } else if (*p
== '{') {
892 while (*p
&& *p
!= '}') {
899 type
= TOK_PREPROC_ID
;
900 } else if (*p
== '[') {
902 line
+= 2; /* Skip the leading %[ */
904 while (lvl
&& (c
= *p
++)) {
916 p
= nasm_skip_string(p
- 1) + 1;
926 error(ERR_NONFATAL
, "unterminated %[ construct");
928 } else if (*p
== '?') {
929 type
= TOK_PREPROC_Q
; /* %? */
932 type
= TOK_PREPROC_QQ
; /* %?? */
935 } else if (*p
== '!') {
936 type
= TOK_PREPROC_ID
;
942 while (isidchar(*p
));
943 } else if (*p
== '\'' || *p
== '\"' || *p
== '`') {
944 p
= nasm_skip_string(p
);
948 error(ERR_NONFATAL
|ERR_PASS1
, "unterminated %! string");
950 /* %! without string or identifier */
951 type
= TOK_OTHER
; /* Legacy behavior... */
953 } else if (isidchar(*p
) ||
954 ((*p
== '!' || *p
== '%' || *p
== '$') &&
959 while (isidchar(*p
));
960 type
= TOK_PREPROC_ID
;
966 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
969 while (*p
&& isidchar(*p
))
971 } else if (*p
== '\'' || *p
== '"' || *p
== '`') {
976 p
= nasm_skip_string(p
);
981 error(ERR_WARNING
|ERR_PASS1
, "unterminated string");
982 /* Handling unterminated strings by UNV */
985 } else if (p
[0] == '$' && p
[1] == '$') {
986 type
= TOK_OTHER
; /* TOKEN_BASE */
988 } else if (isnumstart(*p
)) {
990 bool is_float
= false;
1006 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
1008 if (*p
== '+' || *p
== '-') {
1010 * e can only be followed by +/- if it is either a
1011 * prefixed hex number or a floating-point number
1016 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
1018 } else if (c
== 'P' || c
== 'p') {
1020 if (*p
== '+' || *p
== '-')
1022 } else if (isnumchar(c
) || c
== '_')
1023 ; /* just advance */
1024 else if (c
== '.') {
1026 * we need to deal with consequences of the legacy
1027 * parser, like "1.nolist" being two tokens
1028 * (TOK_NUMBER, TOK_ID) here; at least give it
1029 * a shot for now. In the future, we probably need
1030 * a flex-based scanner with proper pattern matching
1031 * to do it as well as it can be done. Nothing in
1032 * the world is going to help the person who wants
1033 * 0x123.p16 interpreted as two tokens, though.
1039 if (nasm_isdigit(*r
) || (is_hex
&& nasm_isxdigit(*r
)) ||
1040 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
1041 (*r
== 'p' || *r
== 'P')) {
1045 break; /* Terminate the token */
1049 p
--; /* Point to first character beyond number */
1051 if (p
== line
+1 && *line
== '$') {
1052 type
= TOK_OTHER
; /* TOKEN_HERE */
1054 if (has_e
&& !is_hex
) {
1055 /* 1e13 is floating-point, but 1e13h is not */
1059 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
1061 } else if (nasm_isspace(*p
)) {
1062 type
= TOK_WHITESPACE
;
1063 p
= nasm_skip_spaces(p
);
1065 * Whitespace just before end-of-line is discarded by
1066 * pretending it's a comment; whitespace just before a
1067 * comment gets lumped into the comment.
1069 if (!*p
|| *p
== ';') {
1074 } else if (*p
== ';') {
1080 * Anything else is an operator of some kind. We check
1081 * for all the double-character operators (>>, <<, //,
1082 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1083 * else is a single-character operator.
1086 if ((p
[0] == '>' && p
[1] == '>') ||
1087 (p
[0] == '<' && p
[1] == '<') ||
1088 (p
[0] == '/' && p
[1] == '/') ||
1089 (p
[0] == '<' && p
[1] == '=') ||
1090 (p
[0] == '>' && p
[1] == '=') ||
1091 (p
[0] == '=' && p
[1] == '=') ||
1092 (p
[0] == '!' && p
[1] == '=') ||
1093 (p
[0] == '<' && p
[1] == '>') ||
1094 (p
[0] == '&' && p
[1] == '&') ||
1095 (p
[0] == '|' && p
[1] == '|') ||
1096 (p
[0] == '^' && p
[1] == '^')) {
1102 /* Handling unterminated string by UNV */
1105 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1106 t->text[p-line] = *line;
1110 if (type
!= TOK_COMMENT
) {
1111 *tail
= t
= new_Token(NULL
, type
, line
, p
- line
);
1120 * this function allocates a new managed block of memory and
1121 * returns a pointer to the block. The managed blocks are
1122 * deleted only all at once by the delete_Blocks function.
1124 static void *new_Block(size_t size
)
1126 Blocks
*b
= &blocks
;
1128 /* first, get to the end of the linked list */
1131 /* now allocate the requested chunk */
1132 b
->chunk
= nasm_malloc(size
);
1134 /* now allocate a new block for the next request */
1135 b
->next
= nasm_malloc(sizeof(Blocks
));
1136 /* and initialize the contents of the new block */
1137 b
->next
->next
= NULL
;
1138 b
->next
->chunk
= NULL
;
1143 * this function deletes all managed blocks of memory
1145 static void delete_Blocks(void)
1147 Blocks
*a
, *b
= &blocks
;
1150 * keep in mind that the first block, pointed to by blocks
1151 * is a static and not dynamically allocated, so we don't
1156 nasm_free(b
->chunk
);
1165 * this function creates a new Token and passes a pointer to it
1166 * back to the caller. It sets the type and text elements, and
1167 * also the a.mac and next elements to NULL.
1169 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
1170 const char *text
, int txtlen
)
1176 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1177 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1178 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1179 freeTokens
[i
].next
= NULL
;
1182 freeTokens
= t
->next
;
1186 if (type
== TOK_WHITESPACE
|| !text
) {
1190 txtlen
= strlen(text
);
1191 t
->text
= nasm_malloc(txtlen
+1);
1192 memcpy(t
->text
, text
, txtlen
);
1193 t
->text
[txtlen
] = '\0';
1198 static Token
*delete_Token(Token
* t
)
1200 Token
*next
= t
->next
;
1202 t
->next
= freeTokens
;
1208 * Convert a line of tokens back into text.
1209 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1210 * will be transformed into ..@ctxnum.xxx
1212 static char *detoken(Token
* tlist
, bool expand_locals
)
1219 list_for_each(t
, tlist
) {
1220 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
1225 if (*v
== '\'' || *v
== '\"' || *v
== '`') {
1226 size_t len
= nasm_unquote(v
, NULL
);
1227 size_t clen
= strlen(v
);
1230 error(ERR_NONFATAL
| ERR_PASS1
,
1231 "NUL character in %! string");
1237 char *p
= getenv(v
);
1239 error(ERR_NONFATAL
| ERR_PASS1
,
1240 "nonexistent environment variable `%s'", v
);
1243 t
->text
= nasm_strdup(p
);
1248 /* Expand local macros here and not during preprocessing */
1249 if (expand_locals
&&
1250 t
->type
== TOK_PREPROC_ID
&& t
->text
&&
1251 t
->text
[0] == '%' && t
->text
[1] == '$') {
1254 Context
*ctx
= get_ctx(t
->text
, &q
, false);
1257 snprintf(buffer
, sizeof(buffer
), "..@%"PRIu32
".", ctx
->number
);
1258 p
= nasm_strcat(buffer
, q
);
1263 if (t
->type
== TOK_WHITESPACE
)
1266 len
+= strlen(t
->text
);
1269 p
= line
= nasm_malloc(len
+ 1);
1271 list_for_each(t
, tlist
) {
1272 if (t
->type
== TOK_WHITESPACE
) {
1274 } else if (t
->text
) {
1286 * A scanner, suitable for use by the expression evaluator, which
1287 * operates on a line of Tokens. Expects a pointer to a pointer to
1288 * the first token in the line to be passed in as its private_data
1291 * FIX: This really needs to be unified with stdscan.
1293 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1295 Token
**tlineptr
= private_data
;
1297 char ourcopy
[MAX_KEYWORD
+1], *p
, *r
, *s
;
1301 *tlineptr
= tline
? tline
->next
: NULL
;
1302 } while (tline
&& (tline
->type
== TOK_WHITESPACE
||
1303 tline
->type
== TOK_COMMENT
));
1306 return tokval
->t_type
= TOKEN_EOS
;
1308 tokval
->t_charptr
= tline
->text
;
1310 if (tline
->text
[0] == '$' && !tline
->text
[1])
1311 return tokval
->t_type
= TOKEN_HERE
;
1312 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[2])
1313 return tokval
->t_type
= TOKEN_BASE
;
1315 if (tline
->type
== TOK_ID
) {
1316 p
= tokval
->t_charptr
= tline
->text
;
1318 tokval
->t_charptr
++;
1319 return tokval
->t_type
= TOKEN_ID
;
1322 for (r
= p
, s
= ourcopy
; *r
; r
++) {
1323 if (r
>= p
+MAX_KEYWORD
)
1324 return tokval
->t_type
= TOKEN_ID
; /* Not a keyword */
1325 *s
++ = nasm_tolower(*r
);
1328 /* right, so we have an identifier sitting in temp storage. now,
1329 * is it actually a register or instruction name, or what? */
1330 return nasm_token_hash(ourcopy
, tokval
);
1333 if (tline
->type
== TOK_NUMBER
) {
1335 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
1336 tokval
->t_charptr
= tline
->text
;
1338 return tokval
->t_type
= TOKEN_ERRNUM
;
1340 return tokval
->t_type
= TOKEN_NUM
;
1343 if (tline
->type
== TOK_FLOAT
) {
1344 return tokval
->t_type
= TOKEN_FLOAT
;
1347 if (tline
->type
== TOK_STRING
) {
1350 bq
= tline
->text
[0];
1351 tokval
->t_charptr
= tline
->text
;
1352 tokval
->t_inttwo
= nasm_unquote(tline
->text
, &ep
);
1354 if (ep
[0] != bq
|| ep
[1] != '\0')
1355 return tokval
->t_type
= TOKEN_ERRSTR
;
1357 return tokval
->t_type
= TOKEN_STR
;
1360 if (tline
->type
== TOK_OTHER
) {
1361 if (!strcmp(tline
->text
, "<<"))
1362 return tokval
->t_type
= TOKEN_SHL
;
1363 if (!strcmp(tline
->text
, ">>"))
1364 return tokval
->t_type
= TOKEN_SHR
;
1365 if (!strcmp(tline
->text
, "//"))
1366 return tokval
->t_type
= TOKEN_SDIV
;
1367 if (!strcmp(tline
->text
, "%%"))
1368 return tokval
->t_type
= TOKEN_SMOD
;
1369 if (!strcmp(tline
->text
, "=="))
1370 return tokval
->t_type
= TOKEN_EQ
;
1371 if (!strcmp(tline
->text
, "<>"))
1372 return tokval
->t_type
= TOKEN_NE
;
1373 if (!strcmp(tline
->text
, "!="))
1374 return tokval
->t_type
= TOKEN_NE
;
1375 if (!strcmp(tline
->text
, "<="))
1376 return tokval
->t_type
= TOKEN_LE
;
1377 if (!strcmp(tline
->text
, ">="))
1378 return tokval
->t_type
= TOKEN_GE
;
1379 if (!strcmp(tline
->text
, "&&"))
1380 return tokval
->t_type
= TOKEN_DBL_AND
;
1381 if (!strcmp(tline
->text
, "^^"))
1382 return tokval
->t_type
= TOKEN_DBL_XOR
;
1383 if (!strcmp(tline
->text
, "||"))
1384 return tokval
->t_type
= TOKEN_DBL_OR
;
1388 * We have no other options: just return the first character of
1391 return tokval
->t_type
= tline
->text
[0];
1395 * Compare a string to the name of an existing macro; this is a
1396 * simple wrapper which calls either strcmp or nasm_stricmp
1397 * depending on the value of the `casesense' parameter.
1399 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
1401 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
1405 * Compare a string to the name of an existing macro; this is a
1406 * simple wrapper which calls either strcmp or nasm_stricmp
1407 * depending on the value of the `casesense' parameter.
1409 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
1411 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
1415 * Return the Context structure associated with a %$ token. Return
1416 * NULL, having _already_ reported an error condition, if the
1417 * context stack isn't deep enough for the supplied number of $
1419 * If all_contexts == true, contexts that enclose current are
1420 * also scanned for such smacro, until it is found; if not -
1421 * only the context that directly results from the number of $'s
1422 * in variable's name.
1424 * If "namep" is non-NULL, set it to the pointer to the macro name
1425 * tail, i.e. the part beyond %$...
1427 static Context
*get_ctx(const char *name
, const char **namep
,
1437 if (!name
|| name
[0] != '%' || name
[1] != '$')
1441 error(ERR_NONFATAL
, "`%s': context stack is empty", name
);
1448 while (ctx
&& *name
== '$') {
1454 error(ERR_NONFATAL
, "`%s': context stack is only"
1455 " %d level%s deep", name
, i
, (i
== 1 ? "" : "s"));
1466 /* Search for this smacro in found context */
1467 m
= hash_findix(&ctx
->localmac
, name
);
1469 if (!mstrcmp(m
->name
, name
, m
->casesense
)) {
1470 if ((i
> 0) && (all_contexts
== true)) {
1471 error(ERR_WARNING
, "context-local label expansion"
1472 " to outer contexts will be deprecated"
1473 " starting in NASM 2.10, please update your"
1474 " code accordingly");
1487 * Check to see if a file is already in a string list
1489 static bool in_list(const StrList
*list
, const char *str
)
1492 if (!strcmp(list
->str
, str
))
1500 * Open an include file. This routine must always return a valid
1501 * file pointer if it returns - it's responsible for throwing an
1502 * ERR_FATAL and bombing out completely if not. It should also try
1503 * the include path one by one until it finds the file or reaches
1504 * the end of the path.
1506 static FILE *inc_fopen(const char *file
, StrList
**dhead
, StrList
***dtail
,
1511 IncPath
*ip
= ipath
;
1512 int len
= strlen(file
);
1513 size_t prefix_len
= 0;
1517 sl
= nasm_malloc(prefix_len
+len
+1+sizeof sl
->next
);
1518 memcpy(sl
->str
, prefix
, prefix_len
);
1519 memcpy(sl
->str
+prefix_len
, file
, len
+1);
1520 fp
= fopen(sl
->str
, "r");
1521 if (fp
&& dhead
&& !in_list(*dhead
, sl
->str
)) {
1539 prefix_len
= strlen(prefix
);
1541 /* -MG given and file not found */
1542 if (dhead
&& !in_list(*dhead
, file
)) {
1543 sl
= nasm_malloc(len
+1+sizeof sl
->next
);
1545 strcpy(sl
->str
, file
);
1553 error(ERR_FATAL
, "unable to open include file `%s'", file
);
1558 * Determine if we should warn on defining a single-line macro of
1559 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1560 * return true if _any_ single-line macro of that name is defined.
1561 * Otherwise, will return true if a single-line macro with either
1562 * `nparam' or no parameters is defined.
1564 * If a macro with precisely the right number of parameters is
1565 * defined, or nparam is -1, the address of the definition structure
1566 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1567 * is NULL, no action will be taken regarding its contents, and no
1570 * Note that this is also called with nparam zero to resolve
1573 * If you already know which context macro belongs to, you can pass
1574 * the context pointer as first parameter; if you won't but name begins
1575 * with %$ the context will be automatically computed. If all_contexts
1576 * is true, macro will be searched in outer contexts as well.
1579 smacro_defined(Context
* ctx
, const char *name
, int nparam
, SMacro
** defn
,
1582 struct hash_table
*smtbl
;
1586 smtbl
= &ctx
->localmac
;
1587 } else if (name
[0] == '%' && name
[1] == '$') {
1589 ctx
= get_ctx(name
, &name
, false);
1591 return false; /* got to return _something_ */
1592 smtbl
= &ctx
->localmac
;
1596 m
= (SMacro
*) hash_findix(smtbl
, name
);
1599 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
1600 (nparam
<= 0 || m
->nparam
== 0 || nparam
== (int) m
->nparam
)) {
1602 if (nparam
== (int) m
->nparam
|| nparam
== -1)
1616 * Count and mark off the parameters in a multi-line macro call.
1617 * This is called both from within the multi-line macro expansion
1618 * code, and also to mark off the default parameters when provided
1619 * in a %macro definition line.
1621 static void count_mmac_params(Token
* t
, int *nparam
, Token
*** params
)
1623 int paramsize
, brace
;
1625 *nparam
= paramsize
= 0;
1628 /* +1: we need space for the final NULL */
1629 if (*nparam
+1 >= paramsize
) {
1630 paramsize
+= PARAM_DELTA
;
1631 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
1635 if (tok_is_(t
, "{"))
1637 (*params
)[(*nparam
)++] = t
;
1638 while (tok_isnt_(t
, brace
? "}" : ","))
1640 if (t
) { /* got a comma/brace */
1644 * Now we've found the closing brace, look further
1648 if (tok_isnt_(t
, ",")) {
1650 "braces do not enclose all of macro parameter");
1651 while (tok_isnt_(t
, ","))
1655 t
= t
->next
; /* eat the comma */
1662 * Determine whether one of the various `if' conditions is true or
1665 * We must free the tline we get passed.
1667 static bool if_condition(Token
* tline
, enum preproc_token ct
)
1669 enum pp_conditional i
= PP_COND(ct
);
1671 Token
*t
, *tt
, **tptr
, *origline
;
1672 struct tokenval tokval
;
1674 enum pp_token_type needtype
;
1681 j
= false; /* have we matched yet? */
1686 if (tline
->type
!= TOK_ID
) {
1688 "`%s' expects context identifiers", pp_directives
[ct
]);
1689 free_tlist(origline
);
1692 if (cstk
&& cstk
->name
&& !nasm_stricmp(tline
->text
, cstk
->name
))
1694 tline
= tline
->next
;
1699 j
= false; /* have we matched yet? */
1702 if (!tline
|| (tline
->type
!= TOK_ID
&&
1703 (tline
->type
!= TOK_PREPROC_ID
||
1704 tline
->text
[1] != '$'))) {
1706 "`%s' expects macro identifiers", pp_directives
[ct
]);
1709 if (smacro_defined(NULL
, tline
->text
, 0, NULL
, true))
1711 tline
= tline
->next
;
1716 tline
= expand_smacro(tline
);
1717 j
= false; /* have we matched yet? */
1720 if (!tline
|| (tline
->type
!= TOK_ID
&&
1721 tline
->type
!= TOK_STRING
&&
1722 (tline
->type
!= TOK_PREPROC_ID
||
1723 tline
->text
[1] != '!'))) {
1725 "`%s' expects environment variable names",
1730 if (tline
->type
== TOK_PREPROC_ID
)
1731 p
+= 2; /* Skip leading %! */
1732 if (*p
== '\'' || *p
== '\"' || *p
== '`')
1733 nasm_unquote_cstr(p
, ct
);
1736 tline
= tline
->next
;
1742 tline
= expand_smacro(tline
);
1744 while (tok_isnt_(tt
, ","))
1748 "`%s' expects two comma-separated arguments",
1753 j
= true; /* assume equality unless proved not */
1754 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1755 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1756 error(ERR_NONFATAL
, "`%s': more than one comma on line",
1760 if (t
->type
== TOK_WHITESPACE
) {
1764 if (tt
->type
== TOK_WHITESPACE
) {
1768 if (tt
->type
!= t
->type
) {
1769 j
= false; /* found mismatching tokens */
1772 /* When comparing strings, need to unquote them first */
1773 if (t
->type
== TOK_STRING
) {
1774 size_t l1
= nasm_unquote(t
->text
, NULL
);
1775 size_t l2
= nasm_unquote(tt
->text
, NULL
);
1781 if (mmemcmp(t
->text
, tt
->text
, l1
, i
== PPC_IFIDN
)) {
1785 } else if (mstrcmp(tt
->text
, t
->text
, i
== PPC_IFIDN
) != 0) {
1786 j
= false; /* found mismatching tokens */
1793 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
1794 j
= false; /* trailing gunk on one end or other */
1800 MMacro searching
, *mmac
;
1803 tline
= expand_id(tline
);
1804 if (!tok_type_(tline
, TOK_ID
)) {
1806 "`%s' expects a macro name", pp_directives
[ct
]);
1809 searching
.name
= nasm_strdup(tline
->text
);
1810 searching
.casesense
= true;
1811 searching
.plus
= false;
1812 searching
.nolist
= false;
1813 searching
.in_progress
= 0;
1814 searching
.max_depth
= 0;
1815 searching
.rep_nest
= NULL
;
1816 searching
.nparam_min
= 0;
1817 searching
.nparam_max
= INT_MAX
;
1818 tline
= expand_smacro(tline
->next
);
1821 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
1823 "`%s' expects a parameter count or nothing",
1826 searching
.nparam_min
= searching
.nparam_max
=
1827 readnum(tline
->text
, &j
);
1830 "unable to parse parameter count `%s'",
1833 if (tline
&& tok_is_(tline
->next
, "-")) {
1834 tline
= tline
->next
->next
;
1835 if (tok_is_(tline
, "*"))
1836 searching
.nparam_max
= INT_MAX
;
1837 else if (!tok_type_(tline
, TOK_NUMBER
))
1839 "`%s' expects a parameter count after `-'",
1842 searching
.nparam_max
= readnum(tline
->text
, &j
);
1845 "unable to parse parameter count `%s'",
1847 if (searching
.nparam_min
> searching
.nparam_max
)
1849 "minimum parameter count exceeds maximum");
1852 if (tline
&& tok_is_(tline
->next
, "+")) {
1853 tline
= tline
->next
;
1854 searching
.plus
= true;
1856 mmac
= (MMacro
*) hash_findix(&mmacros
, searching
.name
);
1858 if (!strcmp(mmac
->name
, searching
.name
) &&
1859 (mmac
->nparam_min
<= searching
.nparam_max
1861 && (searching
.nparam_min
<= mmac
->nparam_max
1868 if (tline
&& tline
->next
)
1869 error(ERR_WARNING
|ERR_PASS1
,
1870 "trailing garbage after %%ifmacro ignored");
1871 nasm_free(searching
.name
);
1880 needtype
= TOK_NUMBER
;
1883 needtype
= TOK_STRING
;
1887 t
= tline
= expand_smacro(tline
);
1889 while (tok_type_(t
, TOK_WHITESPACE
) ||
1890 (needtype
== TOK_NUMBER
&&
1891 tok_type_(t
, TOK_OTHER
) &&
1892 (t
->text
[0] == '-' || t
->text
[0] == '+') &&
1896 j
= tok_type_(t
, needtype
);
1900 t
= tline
= expand_smacro(tline
);
1901 while (tok_type_(t
, TOK_WHITESPACE
))
1906 t
= t
->next
; /* Skip the actual token */
1907 while (tok_type_(t
, TOK_WHITESPACE
))
1909 j
= !t
; /* Should be nothing left */
1914 t
= tline
= expand_smacro(tline
);
1915 while (tok_type_(t
, TOK_WHITESPACE
))
1918 j
= !t
; /* Should be empty */
1922 t
= tline
= expand_smacro(tline
);
1924 tokval
.t_type
= TOKEN_INVALID
;
1925 evalresult
= evaluate(ppscan
, tptr
, &tokval
,
1926 NULL
, pass
| CRITICAL
, error
, NULL
);
1930 error(ERR_WARNING
|ERR_PASS1
,
1931 "trailing garbage after expression ignored");
1932 if (!is_simple(evalresult
)) {
1934 "non-constant value given to `%s'", pp_directives
[ct
]);
1937 j
= reloc_value(evalresult
) != 0;
1942 "preprocessor directive `%s' not yet implemented",
1947 free_tlist(origline
);
1948 return j
^ PP_NEGATIVE(ct
);
1951 free_tlist(origline
);
1956 * Common code for defining an smacro
1958 static bool define_smacro(Context
*ctx
, const char *mname
, bool casesense
,
1959 int nparam
, Token
*expansion
)
1961 SMacro
*smac
, **smhead
;
1962 struct hash_table
*smtbl
;
1964 if (smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
)) {
1966 error(ERR_WARNING
|ERR_PASS1
,
1967 "single-line macro `%s' defined both with and"
1968 " without parameters", mname
);
1970 * Some instances of the old code considered this a failure,
1971 * some others didn't. What is the right thing to do here?
1973 free_tlist(expansion
);
1974 return false; /* Failure */
1977 * We're redefining, so we have to take over an
1978 * existing SMacro structure. This means freeing
1979 * what was already in it.
1981 nasm_free(smac
->name
);
1982 free_tlist(smac
->expansion
);
1985 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
1986 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
1987 smac
= nasm_malloc(sizeof(SMacro
));
1988 smac
->next
= *smhead
;
1991 smac
->name
= nasm_strdup(mname
);
1992 smac
->casesense
= casesense
;
1993 smac
->nparam
= nparam
;
1994 smac
->expansion
= expansion
;
1995 smac
->in_progress
= false;
1996 return true; /* Success */
2000 * Undefine an smacro
2002 static void undef_smacro(Context
*ctx
, const char *mname
)
2004 SMacro
**smhead
, *s
, **sp
;
2005 struct hash_table
*smtbl
;
2007 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2008 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
2012 * We now have a macro name... go hunt for it.
2015 while ((s
= *sp
) != NULL
) {
2016 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
2019 free_tlist(s
->expansion
);
2029 * Parse a mmacro specification.
2031 static bool parse_mmacro_spec(Token
*tline
, MMacro
*def
, const char *directive
)
2035 tline
= tline
->next
;
2037 tline
= expand_id(tline
);
2038 if (!tok_type_(tline
, TOK_ID
)) {
2039 error(ERR_NONFATAL
, "`%s' expects a macro name", directive
);
2044 def
->name
= nasm_strdup(tline
->text
);
2046 def
->nolist
= false;
2047 def
->in_progress
= 0;
2048 def
->rep_nest
= NULL
;
2049 def
->nparam_min
= 0;
2050 def
->nparam_max
= 0;
2052 tline
= expand_smacro(tline
->next
);
2054 if (!tok_type_(tline
, TOK_NUMBER
)) {
2055 error(ERR_NONFATAL
, "`%s' expects a parameter count", directive
);
2057 def
->nparam_min
= def
->nparam_max
=
2058 readnum(tline
->text
, &err
);
2061 "unable to parse parameter count `%s'", tline
->text
);
2063 if (tline
&& tok_is_(tline
->next
, "-")) {
2064 tline
= tline
->next
->next
;
2065 if (tok_is_(tline
, "*")) {
2066 def
->nparam_max
= INT_MAX
;
2067 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2069 "`%s' expects a parameter count after `-'", directive
);
2071 def
->nparam_max
= readnum(tline
->text
, &err
);
2073 error(ERR_NONFATAL
, "unable to parse parameter count `%s'",
2076 if (def
->nparam_min
> def
->nparam_max
) {
2077 error(ERR_NONFATAL
, "minimum parameter count exceeds maximum");
2081 if (tline
&& tok_is_(tline
->next
, "+")) {
2082 tline
= tline
->next
;
2085 if (tline
&& tok_type_(tline
->next
, TOK_ID
) &&
2086 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
2087 tline
= tline
->next
;
2092 * Handle default parameters.
2094 if (tline
&& tline
->next
) {
2095 def
->dlist
= tline
->next
;
2097 count_mmac_params(def
->dlist
, &def
->ndefs
, &def
->defaults
);
2100 def
->defaults
= NULL
;
2102 def
->expansion
= NULL
;
2104 if (def
->defaults
&& def
->ndefs
> def
->nparam_max
- def
->nparam_min
&&
2106 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MDP
,
2107 "too many default macro parameters");
2114 * Decode a size directive
2116 static int parse_size(const char *str
) {
2117 static const char *size_names
[] =
2118 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2119 static const int sizes
[] =
2120 { 0, 1, 4, 16, 8, 10, 2, 32 };
2122 return sizes
[bsii(str
, size_names
, ARRAY_SIZE(size_names
))+1];
2126 * find and process preprocessor directive in passed line
2127 * Find out if a line contains a preprocessor directive, and deal
2130 * If a directive _is_ found, it is the responsibility of this routine
2131 * (and not the caller) to free_tlist() the line.
2133 * @param tline a pointer to the current tokeninzed line linked list
2134 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2137 static int do_directive(Token
* tline
)
2139 enum preproc_token i
;
2152 MMacro
*mmac
, **mmhead
;
2153 Token
*t
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
2155 struct tokenval tokval
;
2157 MMacro
*tmp_defining
; /* Used when manipulating rep_nest */
2165 if (!tline
|| !tok_type_(tline
, TOK_PREPROC_ID
) ||
2166 (tline
->text
[1] == '%' || tline
->text
[1] == '$'
2167 || tline
->text
[1] == '!'))
2168 return NO_DIRECTIVE_FOUND
;
2170 i
= pp_token_hash(tline
->text
);
2173 * FIXME: We zap execution of PP_RMACRO, PP_IRMACRO, PP_EXITMACRO
2174 * since they are known to be buggy at moment, we need to fix them
2175 * in future release (2.09-2.10)
2177 if (i
== PP_RMACRO
|| i
== PP_RMACRO
|| i
== PP_EXITMACRO
) {
2178 error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2180 return NO_DIRECTIVE_FOUND
;
2184 * If we're in a non-emitting branch of a condition construct,
2185 * or walking to the end of an already terminated %rep block,
2186 * we should ignore all directives except for condition
2189 if (((istk
->conds
&& !emitting(istk
->conds
->state
)) ||
2190 (istk
->mstk
&& !istk
->mstk
->in_progress
)) && !is_condition(i
)) {
2191 return NO_DIRECTIVE_FOUND
;
2195 * If we're defining a macro or reading a %rep block, we should
2196 * ignore all directives except for %macro/%imacro (which nest),
2197 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2198 * If we're in a %rep block, another %rep nests, so should be let through.
2200 if (defining
&& i
!= PP_MACRO
&& i
!= PP_IMACRO
&&
2201 i
!= PP_RMACRO
&& i
!= PP_IRMACRO
&&
2202 i
!= PP_ENDMACRO
&& i
!= PP_ENDM
&&
2203 (defining
->name
|| (i
!= PP_ENDREP
&& i
!= PP_REP
))) {
2204 return NO_DIRECTIVE_FOUND
;
2208 if (i
== PP_MACRO
|| i
== PP_IMACRO
||
2209 i
== PP_RMACRO
|| i
== PP_IRMACRO
) {
2211 return NO_DIRECTIVE_FOUND
;
2212 } else if (nested_mac_count
> 0) {
2213 if (i
== PP_ENDMACRO
) {
2215 return NO_DIRECTIVE_FOUND
;
2218 if (!defining
->name
) {
2221 return NO_DIRECTIVE_FOUND
;
2222 } else if (nested_rep_count
> 0) {
2223 if (i
== PP_ENDREP
) {
2225 return NO_DIRECTIVE_FOUND
;
2233 error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2235 return NO_DIRECTIVE_FOUND
; /* didn't get it */
2238 /* Directive to tell NASM what the default stack size is. The
2239 * default is for a 16-bit stack, and this can be overriden with
2242 tline
= tline
->next
;
2243 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2244 tline
= tline
->next
;
2245 if (!tline
|| tline
->type
!= TOK_ID
) {
2246 error(ERR_NONFATAL
, "`%%stacksize' missing size parameter");
2247 free_tlist(origline
);
2248 return DIRECTIVE_FOUND
;
2250 if (nasm_stricmp(tline
->text
, "flat") == 0) {
2251 /* All subsequent ARG directives are for a 32-bit stack */
2253 StackPointer
= "ebp";
2256 } else if (nasm_stricmp(tline
->text
, "flat64") == 0) {
2257 /* All subsequent ARG directives are for a 64-bit stack */
2259 StackPointer
= "rbp";
2262 } else if (nasm_stricmp(tline
->text
, "large") == 0) {
2263 /* All subsequent ARG directives are for a 16-bit stack,
2264 * far function call.
2267 StackPointer
= "bp";
2270 } else if (nasm_stricmp(tline
->text
, "small") == 0) {
2271 /* All subsequent ARG directives are for a 16-bit stack,
2272 * far function call. We don't support near functions.
2275 StackPointer
= "bp";
2279 error(ERR_NONFATAL
, "`%%stacksize' invalid size type");
2280 free_tlist(origline
);
2281 return DIRECTIVE_FOUND
;
2283 free_tlist(origline
);
2284 return DIRECTIVE_FOUND
;
2287 /* TASM like ARG directive to define arguments to functions, in
2288 * the following form:
2290 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2294 char *arg
, directive
[256];
2295 int size
= StackSize
;
2297 /* Find the argument name */
2298 tline
= tline
->next
;
2299 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2300 tline
= tline
->next
;
2301 if (!tline
|| tline
->type
!= TOK_ID
) {
2302 error(ERR_NONFATAL
, "`%%arg' missing argument parameter");
2303 free_tlist(origline
);
2304 return DIRECTIVE_FOUND
;
2308 /* Find the argument size type */
2309 tline
= tline
->next
;
2310 if (!tline
|| tline
->type
!= TOK_OTHER
2311 || tline
->text
[0] != ':') {
2313 "Syntax error processing `%%arg' directive");
2314 free_tlist(origline
);
2315 return DIRECTIVE_FOUND
;
2317 tline
= tline
->next
;
2318 if (!tline
|| tline
->type
!= TOK_ID
) {
2319 error(ERR_NONFATAL
, "`%%arg' missing size type parameter");
2320 free_tlist(origline
);
2321 return DIRECTIVE_FOUND
;
2324 /* Allow macro expansion of type parameter */
2325 tt
= tokenize(tline
->text
);
2326 tt
= expand_smacro(tt
);
2327 size
= parse_size(tt
->text
);
2330 "Invalid size type for `%%arg' missing directive");
2332 free_tlist(origline
);
2333 return DIRECTIVE_FOUND
;
2337 /* Round up to even stack slots */
2338 size
= ALIGN(size
, StackSize
);
2340 /* Now define the macro for the argument */
2341 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
2342 arg
, StackPointer
, offset
);
2343 do_directive(tokenize(directive
));
2346 /* Move to the next argument in the list */
2347 tline
= tline
->next
;
2348 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2349 tline
= tline
->next
;
2350 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2352 free_tlist(origline
);
2353 return DIRECTIVE_FOUND
;
2356 /* TASM like LOCAL directive to define local variables for a
2357 * function, in the following form:
2359 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2361 * The '= LocalSize' at the end is ignored by NASM, but is
2362 * required by TASM to define the local parameter size (and used
2363 * by the TASM macro package).
2365 offset
= LocalOffset
;
2367 char *local
, directive
[256];
2368 int size
= StackSize
;
2370 /* Find the argument name */
2371 tline
= tline
->next
;
2372 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2373 tline
= tline
->next
;
2374 if (!tline
|| tline
->type
!= TOK_ID
) {
2376 "`%%local' missing argument parameter");
2377 free_tlist(origline
);
2378 return DIRECTIVE_FOUND
;
2380 local
= tline
->text
;
2382 /* Find the argument size type */
2383 tline
= tline
->next
;
2384 if (!tline
|| tline
->type
!= TOK_OTHER
2385 || tline
->text
[0] != ':') {
2387 "Syntax error processing `%%local' directive");
2388 free_tlist(origline
);
2389 return DIRECTIVE_FOUND
;
2391 tline
= tline
->next
;
2392 if (!tline
|| tline
->type
!= TOK_ID
) {
2394 "`%%local' missing size type parameter");
2395 free_tlist(origline
);
2396 return DIRECTIVE_FOUND
;
2399 /* Allow macro expansion of type parameter */
2400 tt
= tokenize(tline
->text
);
2401 tt
= expand_smacro(tt
);
2402 size
= parse_size(tt
->text
);
2405 "Invalid size type for `%%local' missing directive");
2407 free_tlist(origline
);
2408 return DIRECTIVE_FOUND
;
2412 /* Round up to even stack slots */
2413 size
= ALIGN(size
, StackSize
);
2415 offset
+= size
; /* Negative offset, increment before */
2417 /* Now define the macro for the argument */
2418 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
2419 local
, StackPointer
, offset
);
2420 do_directive(tokenize(directive
));
2422 /* Now define the assign to setup the enter_c macro correctly */
2423 snprintf(directive
, sizeof(directive
),
2424 "%%assign %%$localsize %%$localsize+%d", size
);
2425 do_directive(tokenize(directive
));
2427 /* Move to the next argument in the list */
2428 tline
= tline
->next
;
2429 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2430 tline
= tline
->next
;
2431 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2432 LocalOffset
= offset
;
2433 free_tlist(origline
);
2434 return DIRECTIVE_FOUND
;
2438 error(ERR_WARNING
|ERR_PASS1
,
2439 "trailing garbage after `%%clear' ignored");
2442 free_tlist(origline
);
2443 return DIRECTIVE_FOUND
;
2446 t
= tline
->next
= expand_smacro(tline
->next
);
2448 if (!t
|| (t
->type
!= TOK_STRING
&&
2449 t
->type
!= TOK_INTERNAL_STRING
)) {
2450 error(ERR_NONFATAL
, "`%%depend' expects a file name");
2451 free_tlist(origline
);
2452 return DIRECTIVE_FOUND
; /* but we did _something_ */
2455 error(ERR_WARNING
|ERR_PASS1
,
2456 "trailing garbage after `%%depend' ignored");
2458 if (t
->type
!= TOK_INTERNAL_STRING
)
2459 nasm_unquote_cstr(p
, i
);
2460 if (dephead
&& !in_list(*dephead
, p
)) {
2461 StrList
*sl
= nasm_malloc(strlen(p
)+1+sizeof sl
->next
);
2465 deptail
= &sl
->next
;
2467 free_tlist(origline
);
2468 return DIRECTIVE_FOUND
;
2471 t
= tline
->next
= expand_smacro(tline
->next
);
2474 if (!t
|| (t
->type
!= TOK_STRING
&&
2475 t
->type
!= TOK_INTERNAL_STRING
)) {
2476 error(ERR_NONFATAL
, "`%%include' expects a file name");
2477 free_tlist(origline
);
2478 return DIRECTIVE_FOUND
; /* but we did _something_ */
2481 error(ERR_WARNING
|ERR_PASS1
,
2482 "trailing garbage after `%%include' ignored");
2484 if (t
->type
!= TOK_INTERNAL_STRING
)
2485 nasm_unquote_cstr(p
, i
);
2486 inc
= nasm_malloc(sizeof(Include
));
2489 inc
->fp
= inc_fopen(p
, dephead
, &deptail
, pass
== 0);
2491 /* -MG given but file not found */
2494 inc
->fname
= src_set_fname(nasm_strdup(p
));
2495 inc
->lineno
= src_set_linnum(0);
2497 inc
->expansion
= NULL
;
2500 list
->uplevel(LIST_INCLUDE
);
2502 free_tlist(origline
);
2503 return DIRECTIVE_FOUND
;
2507 static macros_t
*use_pkg
;
2508 const char *pkg_macro
= NULL
;
2510 tline
= tline
->next
;
2512 tline
= expand_id(tline
);
2514 if (!tline
|| (tline
->type
!= TOK_STRING
&&
2515 tline
->type
!= TOK_INTERNAL_STRING
&&
2516 tline
->type
!= TOK_ID
)) {
2517 error(ERR_NONFATAL
, "`%%use' expects a package name");
2518 free_tlist(origline
);
2519 return DIRECTIVE_FOUND
; /* but we did _something_ */
2522 error(ERR_WARNING
|ERR_PASS1
,
2523 "trailing garbage after `%%use' ignored");
2524 if (tline
->type
== TOK_STRING
)
2525 nasm_unquote_cstr(tline
->text
, i
);
2526 use_pkg
= nasm_stdmac_find_package(tline
->text
);
2528 error(ERR_NONFATAL
, "unknown `%%use' package: %s", tline
->text
);
2530 pkg_macro
= (char *)use_pkg
+ 1; /* The first string will be <%define>__USE_*__ */
2531 if (use_pkg
&& ! smacro_defined(NULL
, pkg_macro
, 0, NULL
, true)) {
2532 /* Not already included, go ahead and include it */
2533 stdmacpos
= use_pkg
;
2535 free_tlist(origline
);
2536 return DIRECTIVE_FOUND
;
2541 tline
= tline
->next
;
2543 tline
= expand_id(tline
);
2545 if (!tok_type_(tline
, TOK_ID
)) {
2546 error(ERR_NONFATAL
, "`%s' expects a context identifier",
2548 free_tlist(origline
);
2549 return DIRECTIVE_FOUND
; /* but we did _something_ */
2552 error(ERR_WARNING
|ERR_PASS1
,
2553 "trailing garbage after `%s' ignored",
2555 p
= nasm_strdup(tline
->text
);
2557 p
= NULL
; /* Anonymous */
2561 ctx
= nasm_malloc(sizeof(Context
));
2563 hash_init(&ctx
->localmac
, HASH_SMALL
);
2565 ctx
->number
= unique
++;
2570 error(ERR_NONFATAL
, "`%s': context stack is empty",
2572 } else if (i
== PP_POP
) {
2573 if (p
&& (!cstk
->name
|| nasm_stricmp(p
, cstk
->name
)))
2574 error(ERR_NONFATAL
, "`%%pop' in wrong context: %s, "
2576 cstk
->name
? cstk
->name
: "anonymous", p
);
2581 nasm_free(cstk
->name
);
2587 free_tlist(origline
);
2588 return DIRECTIVE_FOUND
;
2590 severity
= ERR_FATAL
;
2593 severity
= ERR_NONFATAL
;
2596 severity
= ERR_WARNING
|ERR_WARN_USER
;
2601 /* Only error out if this is the final pass */
2602 if (pass
!= 2 && i
!= PP_FATAL
)
2603 return DIRECTIVE_FOUND
;
2605 tline
->next
= expand_smacro(tline
->next
);
2606 tline
= tline
->next
;
2608 t
= tline
? tline
->next
: NULL
;
2610 if (tok_type_(tline
, TOK_STRING
) && !t
) {
2611 /* The line contains only a quoted string */
2613 nasm_unquote(p
, NULL
); /* Ignore NUL character truncation */
2614 error(severity
, "%s", p
);
2616 /* Not a quoted string, or more than a quoted string */
2617 p
= detoken(tline
, false);
2618 error(severity
, "%s", p
);
2621 free_tlist(origline
);
2622 return DIRECTIVE_FOUND
;
2626 if (istk
->conds
&& !emitting(istk
->conds
->state
))
2629 j
= if_condition(tline
->next
, i
);
2630 tline
->next
= NULL
; /* it got freed */
2631 j
= j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2633 cond
= nasm_malloc(sizeof(Cond
));
2634 cond
->next
= istk
->conds
;
2638 istk
->mstk
->condcnt
++;
2639 free_tlist(origline
);
2640 return DIRECTIVE_FOUND
;
2644 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2645 switch(istk
->conds
->state
) {
2647 istk
->conds
->state
= COND_DONE
;
2654 case COND_ELSE_TRUE
:
2655 case COND_ELSE_FALSE
:
2656 error_precond(ERR_WARNING
|ERR_PASS1
,
2657 "`%%elif' after `%%else' ignored");
2658 istk
->conds
->state
= COND_NEVER
;
2663 * IMPORTANT: In the case of %if, we will already have
2664 * called expand_mmac_params(); however, if we're
2665 * processing an %elif we must have been in a
2666 * non-emitting mode, which would have inhibited
2667 * the normal invocation of expand_mmac_params().
2668 * Therefore, we have to do it explicitly here.
2670 j
= if_condition(expand_mmac_params(tline
->next
), i
);
2671 tline
->next
= NULL
; /* it got freed */
2672 istk
->conds
->state
=
2673 j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2676 free_tlist(origline
);
2677 return DIRECTIVE_FOUND
;
2681 error_precond(ERR_WARNING
|ERR_PASS1
,
2682 "trailing garbage after `%%else' ignored");
2684 error(ERR_FATAL
, "`%%else': no matching `%%if'");
2685 switch(istk
->conds
->state
) {
2688 istk
->conds
->state
= COND_ELSE_FALSE
;
2695 istk
->conds
->state
= COND_ELSE_TRUE
;
2698 case COND_ELSE_TRUE
:
2699 case COND_ELSE_FALSE
:
2700 error_precond(ERR_WARNING
|ERR_PASS1
,
2701 "`%%else' after `%%else' ignored.");
2702 istk
->conds
->state
= COND_NEVER
;
2705 free_tlist(origline
);
2706 return DIRECTIVE_FOUND
;
2710 error_precond(ERR_WARNING
|ERR_PASS1
,
2711 "trailing garbage after `%%endif' ignored");
2713 error(ERR_FATAL
, "`%%endif': no matching `%%if'");
2715 istk
->conds
= cond
->next
;
2718 istk
->mstk
->condcnt
--;
2719 free_tlist(origline
);
2720 return DIRECTIVE_FOUND
;
2727 error(ERR_FATAL
, "`%s': already defining a macro",
2729 return DIRECTIVE_FOUND
;
2731 defining
= nasm_malloc(sizeof(MMacro
));
2732 defining
->max_depth
=
2733 (i
== PP_RMACRO
) || (i
== PP_IRMACRO
) ? DEADMAN_LIMIT
: 0;
2734 defining
->casesense
= (i
== PP_MACRO
) || (i
== PP_RMACRO
);
2735 if (!parse_mmacro_spec(tline
, defining
, pp_directives
[i
])) {
2736 nasm_free(defining
);
2738 return DIRECTIVE_FOUND
;
2741 mmac
= (MMacro
*) hash_findix(&mmacros
, defining
->name
);
2743 if (!strcmp(mmac
->name
, defining
->name
) &&
2744 (mmac
->nparam_min
<= defining
->nparam_max
2746 && (defining
->nparam_min
<= mmac
->nparam_max
2748 error(ERR_WARNING
|ERR_PASS1
,
2749 "redefining multi-line macro `%s'", defining
->name
);
2750 return DIRECTIVE_FOUND
;
2754 free_tlist(origline
);
2755 return DIRECTIVE_FOUND
;
2759 if (! (defining
&& defining
->name
)) {
2760 error(ERR_NONFATAL
, "`%s': not defining a macro", tline
->text
);
2761 return DIRECTIVE_FOUND
;
2763 mmhead
= (MMacro
**) hash_findi_add(&mmacros
, defining
->name
);
2764 defining
->next
= *mmhead
;
2767 free_tlist(origline
);
2768 return DIRECTIVE_FOUND
;
2772 * We must search along istk->expansion until we hit a
2773 * macro-end marker for a macro with a name. Then we
2774 * bypass all lines between exitmacro and endmacro.
2776 list_for_each(l
, istk
->expansion
)
2777 if (l
->finishes
&& l
->finishes
->name
)
2782 * Remove all conditional entries relative to this
2783 * macro invocation. (safe to do in this context)
2785 for ( ; l
->finishes
->condcnt
> 0; l
->finishes
->condcnt
--) {
2787 istk
->conds
= cond
->next
;
2790 istk
->expansion
= l
;
2792 error(ERR_NONFATAL
, "`%%exitmacro' not within `%%macro' block");
2794 free_tlist(origline
);
2795 return DIRECTIVE_FOUND
;
2803 spec
.casesense
= (i
== PP_UNMACRO
);
2804 if (!parse_mmacro_spec(tline
, &spec
, pp_directives
[i
])) {
2805 return DIRECTIVE_FOUND
;
2807 mmac_p
= (MMacro
**) hash_findi(&mmacros
, spec
.name
, NULL
);
2808 while (mmac_p
&& *mmac_p
) {
2810 if (mmac
->casesense
== spec
.casesense
&&
2811 !mstrcmp(mmac
->name
, spec
.name
, spec
.casesense
) &&
2812 mmac
->nparam_min
== spec
.nparam_min
&&
2813 mmac
->nparam_max
== spec
.nparam_max
&&
2814 mmac
->plus
== spec
.plus
) {
2815 *mmac_p
= mmac
->next
;
2818 mmac_p
= &mmac
->next
;
2821 free_tlist(origline
);
2822 free_tlist(spec
.dlist
);
2823 return DIRECTIVE_FOUND
;
2827 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
2828 tline
= tline
->next
;
2830 free_tlist(origline
);
2831 error(ERR_NONFATAL
, "`%%rotate' missing rotate count");
2832 return DIRECTIVE_FOUND
;
2834 t
= expand_smacro(tline
->next
);
2836 free_tlist(origline
);
2839 tokval
.t_type
= TOKEN_INVALID
;
2841 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
2844 return DIRECTIVE_FOUND
;
2846 error(ERR_WARNING
|ERR_PASS1
,
2847 "trailing garbage after expression ignored");
2848 if (!is_simple(evalresult
)) {
2849 error(ERR_NONFATAL
, "non-constant value given to `%%rotate'");
2850 return DIRECTIVE_FOUND
;
2853 while (mmac
&& !mmac
->name
) /* avoid mistaking %reps for macros */
2854 mmac
= mmac
->next_active
;
2856 error(ERR_NONFATAL
, "`%%rotate' invoked outside a macro call");
2857 } else if (mmac
->nparam
== 0) {
2859 "`%%rotate' invoked within macro without parameters");
2861 int rotate
= mmac
->rotate
+ reloc_value(evalresult
);
2863 rotate
%= (int)mmac
->nparam
;
2865 rotate
+= mmac
->nparam
;
2867 mmac
->rotate
= rotate
;
2869 return DIRECTIVE_FOUND
;
2874 tline
= tline
->next
;
2875 } while (tok_type_(tline
, TOK_WHITESPACE
));
2877 if (tok_type_(tline
, TOK_ID
) &&
2878 nasm_stricmp(tline
->text
, ".nolist") == 0) {
2881 tline
= tline
->next
;
2882 } while (tok_type_(tline
, TOK_WHITESPACE
));
2886 t
= expand_smacro(tline
);
2888 tokval
.t_type
= TOKEN_INVALID
;
2890 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
2892 free_tlist(origline
);
2893 return DIRECTIVE_FOUND
;
2896 error(ERR_WARNING
|ERR_PASS1
,
2897 "trailing garbage after expression ignored");
2898 if (!is_simple(evalresult
)) {
2899 error(ERR_NONFATAL
, "non-constant value given to `%%rep'");
2900 return DIRECTIVE_FOUND
;
2902 count
= reloc_value(evalresult
);
2903 if (count
>= REP_LIMIT
) {
2904 error(ERR_NONFATAL
, "`%%rep' value exceeds limit");
2909 error(ERR_NONFATAL
, "`%%rep' expects a repeat count");
2912 free_tlist(origline
);
2914 tmp_defining
= defining
;
2915 defining
= nasm_malloc(sizeof(MMacro
));
2916 defining
->prev
= NULL
;
2917 defining
->name
= NULL
; /* flags this macro as a %rep block */
2918 defining
->casesense
= false;
2919 defining
->plus
= false;
2920 defining
->nolist
= nolist
;
2921 defining
->in_progress
= count
;
2922 defining
->max_depth
= 0;
2923 defining
->nparam_min
= defining
->nparam_max
= 0;
2924 defining
->defaults
= NULL
;
2925 defining
->dlist
= NULL
;
2926 defining
->expansion
= NULL
;
2927 defining
->next_active
= istk
->mstk
;
2928 defining
->rep_nest
= tmp_defining
;
2929 return DIRECTIVE_FOUND
;
2932 if (!defining
|| defining
->name
) {
2933 error(ERR_NONFATAL
, "`%%endrep': no matching `%%rep'");
2934 return DIRECTIVE_FOUND
;
2938 * Now we have a "macro" defined - although it has no name
2939 * and we won't be entering it in the hash tables - we must
2940 * push a macro-end marker for it on to istk->expansion.
2941 * After that, it will take care of propagating itself (a
2942 * macro-end marker line for a macro which is really a %rep
2943 * block will cause the macro to be re-expanded, complete
2944 * with another macro-end marker to ensure the process
2945 * continues) until the whole expansion is forcibly removed
2946 * from istk->expansion by a %exitrep.
2948 l
= nasm_malloc(sizeof(Line
));
2949 l
->next
= istk
->expansion
;
2950 l
->finishes
= defining
;
2952 istk
->expansion
= l
;
2954 istk
->mstk
= defining
;
2956 list
->uplevel(defining
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
2957 tmp_defining
= defining
;
2958 defining
= defining
->rep_nest
;
2959 free_tlist(origline
);
2960 return DIRECTIVE_FOUND
;
2964 * We must search along istk->expansion until we hit a
2965 * macro-end marker for a macro with no name. Then we set
2966 * its `in_progress' flag to 0.
2968 list_for_each(l
, istk
->expansion
)
2969 if (l
->finishes
&& !l
->finishes
->name
)
2973 l
->finishes
->in_progress
= 1;
2975 error(ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
2976 free_tlist(origline
);
2977 return DIRECTIVE_FOUND
;
2983 casesense
= (i
== PP_DEFINE
|| i
== PP_XDEFINE
);
2985 tline
= tline
->next
;
2987 tline
= expand_id(tline
);
2988 if (!tline
|| (tline
->type
!= TOK_ID
&&
2989 (tline
->type
!= TOK_PREPROC_ID
||
2990 tline
->text
[1] != '$'))) {
2991 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
2993 free_tlist(origline
);
2994 return DIRECTIVE_FOUND
;
2997 ctx
= get_ctx(tline
->text
, &mname
, false);
2999 param_start
= tline
= tline
->next
;
3002 /* Expand the macro definition now for %xdefine and %ixdefine */
3003 if ((i
== PP_XDEFINE
) || (i
== PP_IXDEFINE
))
3004 tline
= expand_smacro(tline
);
3006 if (tok_is_(tline
, "(")) {
3008 * This macro has parameters.
3011 tline
= tline
->next
;
3015 error(ERR_NONFATAL
, "parameter identifier expected");
3016 free_tlist(origline
);
3017 return DIRECTIVE_FOUND
;
3019 if (tline
->type
!= TOK_ID
) {
3021 "`%s': parameter identifier expected",
3023 free_tlist(origline
);
3024 return DIRECTIVE_FOUND
;
3026 tline
->type
= TOK_SMAC_PARAM
+ nparam
++;
3027 tline
= tline
->next
;
3029 if (tok_is_(tline
, ",")) {
3030 tline
= tline
->next
;
3032 if (!tok_is_(tline
, ")")) {
3034 "`)' expected to terminate macro template");
3035 free_tlist(origline
);
3036 return DIRECTIVE_FOUND
;
3042 tline
= tline
->next
;
3044 if (tok_type_(tline
, TOK_WHITESPACE
))
3045 last
= tline
, tline
= tline
->next
;
3050 if (t
->type
== TOK_ID
) {
3051 list_for_each(tt
, param_start
)
3052 if (tt
->type
>= TOK_SMAC_PARAM
&&
3053 !strcmp(tt
->text
, t
->text
))
3057 t
->next
= macro_start
;
3062 * Good. We now have a macro name, a parameter count, and a
3063 * token list (in reverse order) for an expansion. We ought
3064 * to be OK just to create an SMacro, store it, and let
3065 * free_tlist have the rest of the line (which we have
3066 * carefully re-terminated after chopping off the expansion
3069 define_smacro(ctx
, mname
, casesense
, nparam
, macro_start
);
3070 free_tlist(origline
);
3071 return DIRECTIVE_FOUND
;
3074 tline
= tline
->next
;
3076 tline
= expand_id(tline
);
3077 if (!tline
|| (tline
->type
!= TOK_ID
&&
3078 (tline
->type
!= TOK_PREPROC_ID
||
3079 tline
->text
[1] != '$'))) {
3080 error(ERR_NONFATAL
, "`%%undef' expects a macro identifier");
3081 free_tlist(origline
);
3082 return DIRECTIVE_FOUND
;
3085 error(ERR_WARNING
|ERR_PASS1
,
3086 "trailing garbage after macro name ignored");
3089 /* Find the context that symbol belongs to */
3090 ctx
= get_ctx(tline
->text
, &mname
, false);
3091 undef_smacro(ctx
, mname
);
3092 free_tlist(origline
);
3093 return DIRECTIVE_FOUND
;
3097 casesense
= (i
== PP_DEFSTR
);
3099 tline
= tline
->next
;
3101 tline
= expand_id(tline
);
3102 if (!tline
|| (tline
->type
!= TOK_ID
&&
3103 (tline
->type
!= TOK_PREPROC_ID
||
3104 tline
->text
[1] != '$'))) {
3105 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3107 free_tlist(origline
);
3108 return DIRECTIVE_FOUND
;
3111 ctx
= get_ctx(tline
->text
, &mname
, false);
3113 tline
= expand_smacro(tline
->next
);
3116 while (tok_type_(tline
, TOK_WHITESPACE
))
3117 tline
= delete_Token(tline
);
3119 p
= detoken(tline
, false);
3120 macro_start
= nasm_malloc(sizeof(*macro_start
));
3121 macro_start
->next
= NULL
;
3122 macro_start
->text
= nasm_quote(p
, strlen(p
));
3123 macro_start
->type
= TOK_STRING
;
3124 macro_start
->a
.mac
= NULL
;
3128 * We now have a macro name, an implicit parameter count of
3129 * zero, and a string token to use as an expansion. Create
3130 * and store an SMacro.
3132 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3133 free_tlist(origline
);
3134 return DIRECTIVE_FOUND
;
3138 casesense
= (i
== PP_DEFTOK
);
3140 tline
= tline
->next
;
3142 tline
= expand_id(tline
);
3143 if (!tline
|| (tline
->type
!= TOK_ID
&&
3144 (tline
->type
!= TOK_PREPROC_ID
||
3145 tline
->text
[1] != '$'))) {
3147 "`%s' expects a macro identifier as first parameter",
3149 free_tlist(origline
);
3150 return DIRECTIVE_FOUND
;
3152 ctx
= get_ctx(tline
->text
, &mname
, false);
3154 tline
= expand_smacro(tline
->next
);
3158 while (tok_type_(t
, TOK_WHITESPACE
))
3160 /* t should now point to the string */
3161 if (t
->type
!= TOK_STRING
) {
3163 "`%s` requires string as second parameter",
3166 free_tlist(origline
);
3167 return DIRECTIVE_FOUND
;
3170 nasm_unquote_cstr(t
->text
, i
);
3171 macro_start
= tokenize(t
->text
);
3174 * We now have a macro name, an implicit parameter count of
3175 * zero, and a numeric token to use as an expansion. Create
3176 * and store an SMacro.
3178 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3180 free_tlist(origline
);
3181 return DIRECTIVE_FOUND
;
3186 StrList
*xsl
= NULL
;
3187 StrList
**xst
= &xsl
;
3191 tline
= tline
->next
;
3193 tline
= expand_id(tline
);
3194 if (!tline
|| (tline
->type
!= TOK_ID
&&
3195 (tline
->type
!= TOK_PREPROC_ID
||
3196 tline
->text
[1] != '$'))) {
3198 "`%%pathsearch' expects a macro identifier as first parameter");
3199 free_tlist(origline
);
3200 return DIRECTIVE_FOUND
;
3202 ctx
= get_ctx(tline
->text
, &mname
, false);
3204 tline
= expand_smacro(tline
->next
);
3208 while (tok_type_(t
, TOK_WHITESPACE
))
3211 if (!t
|| (t
->type
!= TOK_STRING
&&
3212 t
->type
!= TOK_INTERNAL_STRING
)) {
3213 error(ERR_NONFATAL
, "`%%pathsearch' expects a file name");
3215 free_tlist(origline
);
3216 return DIRECTIVE_FOUND
; /* but we did _something_ */
3219 error(ERR_WARNING
|ERR_PASS1
,
3220 "trailing garbage after `%%pathsearch' ignored");
3222 if (t
->type
!= TOK_INTERNAL_STRING
)
3223 nasm_unquote(p
, NULL
);
3225 fp
= inc_fopen(p
, &xsl
, &xst
, true);
3228 fclose(fp
); /* Don't actually care about the file */
3230 macro_start
= nasm_malloc(sizeof(*macro_start
));
3231 macro_start
->next
= NULL
;
3232 macro_start
->text
= nasm_quote(p
, strlen(p
));
3233 macro_start
->type
= TOK_STRING
;
3234 macro_start
->a
.mac
= NULL
;
3239 * We now have a macro name, an implicit parameter count of
3240 * zero, and a string token to use as an expansion. Create
3241 * and store an SMacro.
3243 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3245 free_tlist(origline
);
3246 return DIRECTIVE_FOUND
;
3252 tline
= tline
->next
;
3254 tline
= expand_id(tline
);
3255 if (!tline
|| (tline
->type
!= TOK_ID
&&
3256 (tline
->type
!= TOK_PREPROC_ID
||
3257 tline
->text
[1] != '$'))) {
3259 "`%%strlen' expects a macro identifier as first parameter");
3260 free_tlist(origline
);
3261 return DIRECTIVE_FOUND
;
3263 ctx
= get_ctx(tline
->text
, &mname
, false);
3265 tline
= expand_smacro(tline
->next
);
3269 while (tok_type_(t
, TOK_WHITESPACE
))
3271 /* t should now point to the string */
3272 if (!tok_type_(t
, TOK_STRING
)) {
3274 "`%%strlen` requires string as second parameter");
3276 free_tlist(origline
);
3277 return DIRECTIVE_FOUND
;
3280 macro_start
= nasm_malloc(sizeof(*macro_start
));
3281 macro_start
->next
= NULL
;
3282 make_tok_num(macro_start
, nasm_unquote(t
->text
, NULL
));
3283 macro_start
->a
.mac
= NULL
;
3286 * We now have a macro name, an implicit parameter count of
3287 * zero, and a numeric token to use as an expansion. Create
3288 * and store an SMacro.
3290 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3292 free_tlist(origline
);
3293 return DIRECTIVE_FOUND
;
3298 tline
= tline
->next
;
3300 tline
= expand_id(tline
);
3301 if (!tline
|| (tline
->type
!= TOK_ID
&&
3302 (tline
->type
!= TOK_PREPROC_ID
||
3303 tline
->text
[1] != '$'))) {
3305 "`%%strcat' expects a macro identifier as first parameter");
3306 free_tlist(origline
);
3307 return DIRECTIVE_FOUND
;
3309 ctx
= get_ctx(tline
->text
, &mname
, false);
3311 tline
= expand_smacro(tline
->next
);
3315 list_for_each(t
, tline
) {
3317 case TOK_WHITESPACE
:
3320 len
+= t
->a
.len
= nasm_unquote(t
->text
, NULL
);
3323 if (!strcmp(t
->text
, ",")) /* permit comma separators */
3325 /* else fall through */
3328 "non-string passed to `%%strcat' (%d)", t
->type
);
3330 free_tlist(origline
);
3331 return DIRECTIVE_FOUND
;
3335 p
= pp
= nasm_malloc(len
);
3336 list_for_each(t
, tline
) {
3337 if (t
->type
== TOK_STRING
) {
3338 memcpy(p
, t
->text
, t
->a
.len
);
3344 * We now have a macro name, an implicit parameter count of
3345 * zero, and a numeric token to use as an expansion. Create
3346 * and store an SMacro.
3348 macro_start
= new_Token(NULL
, TOK_STRING
, NULL
, 0);
3349 macro_start
->text
= nasm_quote(pp
, len
);
3351 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3353 free_tlist(origline
);
3354 return DIRECTIVE_FOUND
;
3363 tline
= tline
->next
;
3365 tline
= expand_id(tline
);
3366 if (!tline
|| (tline
->type
!= TOK_ID
&&
3367 (tline
->type
!= TOK_PREPROC_ID
||
3368 tline
->text
[1] != '$'))) {
3370 "`%%substr' expects a macro identifier as first parameter");
3371 free_tlist(origline
);
3372 return DIRECTIVE_FOUND
;
3374 ctx
= get_ctx(tline
->text
, &mname
, false);
3376 tline
= expand_smacro(tline
->next
);
3380 while (tok_type_(t
, TOK_WHITESPACE
))
3383 /* t should now point to the string */
3384 if (t
->type
!= TOK_STRING
) {
3386 "`%%substr` requires string as second parameter");
3388 free_tlist(origline
);
3389 return DIRECTIVE_FOUND
;
3394 tokval
.t_type
= TOKEN_INVALID
;
3395 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3399 free_tlist(origline
);
3400 return DIRECTIVE_FOUND
;
3401 } else if (!is_simple(evalresult
)) {
3402 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3404 free_tlist(origline
);
3405 return DIRECTIVE_FOUND
;
3407 a1
= evalresult
->value
-1;
3409 while (tok_type_(tt
, TOK_WHITESPACE
))
3412 a2
= 1; /* Backwards compatibility: one character */
3414 tokval
.t_type
= TOKEN_INVALID
;
3415 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3419 free_tlist(origline
);
3420 return DIRECTIVE_FOUND
;
3421 } else if (!is_simple(evalresult
)) {
3422 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3424 free_tlist(origline
);
3425 return DIRECTIVE_FOUND
;
3427 a2
= evalresult
->value
;
3430 len
= nasm_unquote(t
->text
, NULL
);
3433 if (a1
+a2
> (int64_t)len
)
3436 macro_start
= nasm_malloc(sizeof(*macro_start
));
3437 macro_start
->next
= NULL
;
3438 macro_start
->text
= nasm_quote((a1
< 0) ? "" : t
->text
+a1
, a2
);
3439 macro_start
->type
= TOK_STRING
;
3440 macro_start
->a
.mac
= NULL
;
3443 * We now have a macro name, an implicit parameter count of
3444 * zero, and a numeric token to use as an expansion. Create
3445 * and store an SMacro.
3447 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3449 free_tlist(origline
);
3450 return DIRECTIVE_FOUND
;
3455 casesense
= (i
== PP_ASSIGN
);
3457 tline
= tline
->next
;
3459 tline
= expand_id(tline
);
3460 if (!tline
|| (tline
->type
!= TOK_ID
&&
3461 (tline
->type
!= TOK_PREPROC_ID
||
3462 tline
->text
[1] != '$'))) {
3464 "`%%%sassign' expects a macro identifier",
3465 (i
== PP_IASSIGN
? "i" : ""));
3466 free_tlist(origline
);
3467 return DIRECTIVE_FOUND
;
3469 ctx
= get_ctx(tline
->text
, &mname
, false);
3471 tline
= expand_smacro(tline
->next
);
3476 tokval
.t_type
= TOKEN_INVALID
;
3478 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3481 free_tlist(origline
);
3482 return DIRECTIVE_FOUND
;
3486 error(ERR_WARNING
|ERR_PASS1
,
3487 "trailing garbage after expression ignored");
3489 if (!is_simple(evalresult
)) {
3491 "non-constant value given to `%%%sassign'",
3492 (i
== PP_IASSIGN
? "i" : ""));
3493 free_tlist(origline
);
3494 return DIRECTIVE_FOUND
;
3497 macro_start
= nasm_malloc(sizeof(*macro_start
));
3498 macro_start
->next
= NULL
;
3499 make_tok_num(macro_start
, reloc_value(evalresult
));
3500 macro_start
->a
.mac
= NULL
;
3503 * We now have a macro name, an implicit parameter count of
3504 * zero, and a numeric token to use as an expansion. Create
3505 * and store an SMacro.
3507 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3508 free_tlist(origline
);
3509 return DIRECTIVE_FOUND
;
3513 * Syntax is `%line nnn[+mmm] [filename]'
3515 tline
= tline
->next
;
3517 if (!tok_type_(tline
, TOK_NUMBER
)) {
3518 error(ERR_NONFATAL
, "`%%line' expects line number");
3519 free_tlist(origline
);
3520 return DIRECTIVE_FOUND
;
3522 k
= readnum(tline
->text
, &err
);
3524 tline
= tline
->next
;
3525 if (tok_is_(tline
, "+")) {
3526 tline
= tline
->next
;
3527 if (!tok_type_(tline
, TOK_NUMBER
)) {
3528 error(ERR_NONFATAL
, "`%%line' expects line increment");
3529 free_tlist(origline
);
3530 return DIRECTIVE_FOUND
;
3532 m
= readnum(tline
->text
, &err
);
3533 tline
= tline
->next
;
3539 nasm_free(src_set_fname(detoken(tline
, false)));
3541 free_tlist(origline
);
3542 return DIRECTIVE_FOUND
;
3546 "preprocessor directive `%s' not yet implemented",
3548 return DIRECTIVE_FOUND
;
3553 * Ensure that a macro parameter contains a condition code and
3554 * nothing else. Return the condition code index if so, or -1
3557 static int find_cc(Token
* t
)
3563 return -1; /* Probably a %+ without a space */
3566 if (t
->type
!= TOK_ID
)
3570 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
3574 j
= ARRAY_SIZE(conditions
);
3577 m
= nasm_stricmp(t
->text
, conditions
[k
]);
3592 static bool paste_tokens(Token
**head
, bool handle_paste_tokens
)
3594 Token
**tail
, *t
, *tt
;
3596 bool did_paste
= false;
3599 /* Now handle token pasting... */
3602 while ((t
= *tail
) && (tt
= t
->next
)) {
3604 case TOK_WHITESPACE
:
3605 if (tt
->type
== TOK_WHITESPACE
) {
3606 /* Zap adjacent whitespace tokens */
3607 t
->next
= delete_Token(tt
);
3609 /* Do not advance paste_head here */
3620 while (tt
&& (tt
->type
== TOK_ID
|| tt
->type
== TOK_PREPROC_ID
||
3621 tt
->type
== TOK_NUMBER
|| tt
->type
== TOK_FLOAT
||
3622 tt
->type
== TOK_OTHER
)) {
3623 len
+= strlen(tt
->text
);
3628 * Now tt points to the first token after
3629 * the potential paste area...
3631 if (tt
!= t
->next
) {
3632 /* We have at least two tokens... */
3633 len
+= strlen(t
->text
);
3634 p
= tmp
= nasm_malloc(len
+1);
3638 p
= strchr(p
, '\0');
3639 t
= delete_Token(t
);
3642 t
= *tail
= tokenize(tmp
);
3649 t
->next
= tt
; /* Attach the remaining token chain */
3657 case TOK_PASTE
: /* %+ */
3658 if (handle_paste_tokens
) {
3659 /* Zap %+ and whitespace tokens to the right */
3660 while (t
&& (t
->type
== TOK_WHITESPACE
||
3661 t
->type
== TOK_PASTE
))
3662 t
= *tail
= delete_Token(t
);
3663 if (!paste_head
|| !t
)
3664 break; /* Nothing to paste with */
3668 while (tok_type_(tt
, TOK_WHITESPACE
))
3669 tt
= t
->next
= delete_Token(tt
);
3672 tmp
= nasm_strcat(t
->text
, tt
->text
);
3674 tt
= delete_Token(tt
);
3675 t
= *tail
= tokenize(tmp
);
3681 t
->next
= tt
; /* Attach the remaining token chain */
3688 /* else fall through */
3691 if (!tok_type_(t
->next
, TOK_WHITESPACE
))
3700 * expands to a list of tokens from %{x:y}
3702 static Token
*expand_mmac_params_range(MMacro
*mac
, Token
*tline
, Token
***last
)
3704 Token
*t
= tline
, **tt
, *tm
, *head
;
3708 pos
= strchr(tline
->text
, ':');
3711 lst
= atoi(pos
+ 1);
3712 fst
= atoi(tline
->text
+ 1);
3715 * only macros params are accounted so
3716 * if someone passes %0 -- we reject such
3719 if (lst
== 0 || fst
== 0)
3722 /* the values should be sane */
3723 if ((fst
> (int)mac
->nparam
|| fst
< (-(int)mac
->nparam
)) ||
3724 (lst
> (int)mac
->nparam
|| lst
< (-(int)mac
->nparam
)))
3727 fst
= fst
< 0 ? fst
+ (int)mac
->nparam
+ 1: fst
;
3728 lst
= lst
< 0 ? lst
+ (int)mac
->nparam
+ 1: lst
;
3730 /* counted from zero */
3734 * it will be at least one token
3736 tm
= mac
->params
[(fst
+ mac
->rotate
) % mac
->nparam
];
3737 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3738 head
= t
, tt
= &t
->next
;
3740 for (i
= fst
+ 1; i
<= lst
; i
++) {
3741 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
3742 *tt
= t
, tt
= &t
->next
;
3743 j
= (i
+ mac
->rotate
) % mac
->nparam
;
3744 tm
= mac
->params
[j
];
3745 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3746 *tt
= t
, tt
= &t
->next
;
3749 for (i
= fst
- 1; i
>= lst
; i
--) {
3750 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
3751 *tt
= t
, tt
= &t
->next
;
3752 j
= (i
+ mac
->rotate
) % mac
->nparam
;
3753 tm
= mac
->params
[j
];
3754 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
3755 *tt
= t
, tt
= &t
->next
;
3763 error(ERR_NONFATAL
, "`%%{%s}': macro parameters out of range",
3769 * Expand MMacro-local things: parameter references (%0, %n, %+n,
3770 * %-n) and MMacro-local identifiers (%%foo) as well as
3771 * macro indirection (%[...]) and range (%{..:..}).
3773 static Token
*expand_mmac_params(Token
* tline
)
3775 Token
*t
, *tt
, **tail
, *thead
;
3776 bool changed
= false;
3783 if (tline
->type
== TOK_PREPROC_ID
&&
3784 (((tline
->text
[1] == '+' || tline
->text
[1] == '-') && tline
->text
[2]) ||
3785 (tline
->text
[1] >= '0' && tline
->text
[1] <= '9') ||
3786 tline
->text
[1] == '%')) {
3788 int type
= 0, cc
; /* type = 0 to placate optimisers */
3795 tline
= tline
->next
;
3798 while (mac
&& !mac
->name
) /* avoid mistaking %reps for macros */
3799 mac
= mac
->next_active
;
3801 error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
3803 pos
= strchr(t
->text
, ':');
3805 switch (t
->text
[1]) {
3807 * We have to make a substitution of one of the
3808 * forms %1, %-1, %+1, %%foo, %0.
3812 snprintf(tmpbuf
, sizeof(tmpbuf
), "%d", mac
->nparam
);
3813 text
= nasm_strdup(tmpbuf
);
3817 snprintf(tmpbuf
, sizeof(tmpbuf
), "..@%"PRIu64
".",
3819 text
= nasm_strcat(tmpbuf
, t
->text
+ 2);
3822 n
= atoi(t
->text
+ 2) - 1;
3823 if (n
>= mac
->nparam
)
3826 if (mac
->nparam
> 1)
3827 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3828 tt
= mac
->params
[n
];
3833 "macro parameter %d is not a condition code",
3838 if (inverse_ccs
[cc
] == -1) {
3840 "condition code `%s' is not invertible",
3844 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
3848 n
= atoi(t
->text
+ 2) - 1;
3849 if (n
>= mac
->nparam
)
3852 if (mac
->nparam
> 1)
3853 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3854 tt
= mac
->params
[n
];
3859 "macro parameter %d is not a condition code",
3864 text
= nasm_strdup(conditions
[cc
]);
3868 n
= atoi(t
->text
+ 1) - 1;
3869 if (n
>= mac
->nparam
)
3872 if (mac
->nparam
> 1)
3873 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3874 tt
= mac
->params
[n
];
3877 for (i
= 0; i
< mac
->paramlen
[n
]; i
++) {
3878 *tail
= new_Token(NULL
, tt
->type
, tt
->text
, 0);
3879 tail
= &(*tail
)->next
;
3883 text
= NULL
; /* we've done it here */
3888 * seems we have a parameters range here
3890 Token
*head
, **last
;
3891 head
= expand_mmac_params_range(mac
, t
, &last
);
3912 } else if (tline
->type
== TOK_INDIRECT
) {
3914 tline
= tline
->next
;
3915 tt
= tokenize(t
->text
);
3916 tt
= expand_mmac_params(tt
);
3917 tt
= expand_smacro(tt
);
3920 tt
->a
.mac
= NULL
; /* Necessary? */
3928 tline
= tline
->next
;
3936 paste_tokens(&thead
, false);
3942 * Expand all single-line macro calls made in the given line.
3943 * Return the expanded version of the line. The original is deemed
3944 * to be destroyed in the process. (In reality we'll just move
3945 * Tokens from input to output a lot of the time, rather than
3946 * actually bothering to destroy and replicate.)
3949 static Token
*expand_smacro(Token
* tline
)
3951 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
3952 SMacro
*head
= NULL
, *m
;
3955 unsigned int nparam
, sparam
;
3957 Token
*org_tline
= tline
;
3960 int deadman
= DEADMAN_LIMIT
;
3964 * Trick: we should avoid changing the start token pointer since it can
3965 * be contained in "next" field of other token. Because of this
3966 * we allocate a copy of first token and work with it; at the end of
3967 * routine we copy it back
3970 tline
= new_Token(org_tline
->next
, org_tline
->type
,
3971 org_tline
->text
, 0);
3972 tline
->a
.mac
= org_tline
->a
.mac
;
3973 nasm_free(org_tline
->text
);
3974 org_tline
->text
= NULL
;
3977 expanded
= true; /* Always expand %+ at least once */
3983 while (tline
) { /* main token loop */
3985 error(ERR_NONFATAL
, "interminable macro recursion");
3989 if ((mname
= tline
->text
)) {
3990 /* if this token is a local macro, look in local context */
3991 if (tline
->type
== TOK_ID
) {
3992 head
= (SMacro
*)hash_findix(&smacros
, mname
);
3993 } else if (tline
->type
== TOK_PREPROC_ID
) {
3994 ctx
= get_ctx(mname
, &mname
, true);
3995 head
= ctx
? (SMacro
*)hash_findix(&ctx
->localmac
, mname
) : NULL
;
4000 * We've hit an identifier. As in is_mmacro below, we first
4001 * check whether the identifier is a single-line macro at
4002 * all, then think about checking for parameters if
4005 list_for_each(m
, head
)
4006 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
4012 if (m
->nparam
== 0) {
4014 * Simple case: the macro is parameterless. Discard the
4015 * one token that the macro call took, and push the
4016 * expansion back on the to-do stack.
4018 if (!m
->expansion
) {
4019 if (!strcmp("__FILE__", m
->name
)) {
4022 src_get(&num
, &file
);
4023 tline
->text
= nasm_quote(file
, strlen(file
));
4024 tline
->type
= TOK_STRING
;
4028 if (!strcmp("__LINE__", m
->name
)) {
4029 nasm_free(tline
->text
);
4030 make_tok_num(tline
, src_get_linnum());
4033 if (!strcmp("__BITS__", m
->name
)) {
4034 nasm_free(tline
->text
);
4035 make_tok_num(tline
, globalbits
);
4038 tline
= delete_Token(tline
);
4043 * Complicated case: at least one macro with this name
4044 * exists and takes parameters. We must find the
4045 * parameters in the call, count them, find the SMacro
4046 * that corresponds to that form of the macro call, and
4047 * substitute for the parameters when we expand. What a
4050 /*tline = tline->next;
4051 skip_white_(tline); */
4054 while (tok_type_(t
, TOK_SMAC_END
)) {
4055 t
->a
.mac
->in_progress
= false;
4057 t
= tline
->next
= delete_Token(t
);
4060 } while (tok_type_(tline
, TOK_WHITESPACE
));
4061 if (!tok_is_(tline
, "(")) {
4063 * This macro wasn't called with parameters: ignore
4064 * the call. (Behaviour borrowed from gnu cpp.)
4073 sparam
= PARAM_DELTA
;
4074 params
= nasm_malloc(sparam
* sizeof(Token
*));
4075 params
[0] = tline
->next
;
4076 paramsize
= nasm_malloc(sparam
* sizeof(int));
4078 while (true) { /* parameter loop */
4080 * For some unusual expansions
4081 * which concatenates function call
4084 while (tok_type_(t
, TOK_SMAC_END
)) {
4085 t
->a
.mac
->in_progress
= false;
4087 t
= tline
->next
= delete_Token(t
);
4093 "macro call expects terminating `)'");
4096 if (tline
->type
== TOK_WHITESPACE
4098 if (paramsize
[nparam
])
4101 params
[nparam
] = tline
->next
;
4102 continue; /* parameter loop */
4104 if (tline
->type
== TOK_OTHER
4105 && tline
->text
[1] == 0) {
4106 char ch
= tline
->text
[0];
4107 if (ch
== ',' && !paren
&& brackets
<= 0) {
4108 if (++nparam
>= sparam
) {
4109 sparam
+= PARAM_DELTA
;
4110 params
= nasm_realloc(params
,
4111 sparam
* sizeof(Token
*));
4112 paramsize
= nasm_realloc(paramsize
,
4113 sparam
* sizeof(int));
4115 params
[nparam
] = tline
->next
;
4116 paramsize
[nparam
] = 0;
4118 continue; /* parameter loop */
4121 (brackets
> 0 || (brackets
== 0 &&
4122 !paramsize
[nparam
])))
4124 if (!(brackets
++)) {
4125 params
[nparam
] = tline
->next
;
4126 continue; /* parameter loop */
4129 if (ch
== '}' && brackets
> 0)
4130 if (--brackets
== 0) {
4132 continue; /* parameter loop */
4134 if (ch
== '(' && !brackets
)
4136 if (ch
== ')' && brackets
<= 0)
4142 error(ERR_NONFATAL
, "braces do not "
4143 "enclose all of macro parameter");
4145 paramsize
[nparam
] += white
+ 1;
4147 } /* parameter loop */
4149 while (m
&& (m
->nparam
!= nparam
||
4150 mstrcmp(m
->name
, mname
,
4154 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4155 "macro `%s' exists, "
4156 "but not taking %d parameters",
4157 mstart
->text
, nparam
);
4160 if (m
&& m
->in_progress
)
4162 if (!m
) { /* in progess or didn't find '(' or wrong nparam */
4164 * Design question: should we handle !tline, which
4165 * indicates missing ')' here, or expand those
4166 * macros anyway, which requires the (t) test a few
4170 nasm_free(paramsize
);
4174 * Expand the macro: we are placed on the last token of the
4175 * call, so that we can easily split the call from the
4176 * following tokens. We also start by pushing an SMAC_END
4177 * token for the cycle removal.
4184 tt
= new_Token(tline
, TOK_SMAC_END
, NULL
, 0);
4186 m
->in_progress
= true;
4188 list_for_each(t
, m
->expansion
) {
4189 if (t
->type
>= TOK_SMAC_PARAM
) {
4190 Token
*pcopy
= tline
, **ptail
= &pcopy
;
4194 ttt
= params
[t
->type
- TOK_SMAC_PARAM
];
4195 i
= paramsize
[t
->type
- TOK_SMAC_PARAM
];
4197 pt
= *ptail
= new_Token(tline
, ttt
->type
,
4203 } else if (t
->type
== TOK_PREPROC_Q
) {
4204 tt
= new_Token(tline
, TOK_ID
, mname
, 0);
4206 } else if (t
->type
== TOK_PREPROC_QQ
) {
4207 tt
= new_Token(tline
, TOK_ID
, m
->name
, 0);
4210 tt
= new_Token(tline
, t
->type
, t
->text
, 0);
4216 * Having done that, get rid of the macro call, and clean
4217 * up the parameters.
4220 nasm_free(paramsize
);
4223 continue; /* main token loop */
4228 if (tline
->type
== TOK_SMAC_END
) {
4229 tline
->a
.mac
->in_progress
= false;
4230 tline
= delete_Token(tline
);
4233 tline
= tline
->next
;
4241 * Now scan the entire line and look for successive TOK_IDs that resulted
4242 * after expansion (they can't be produced by tokenize()). The successive
4243 * TOK_IDs should be concatenated.
4244 * Also we look for %+ tokens and concatenate the tokens before and after
4245 * them (without white spaces in between).
4247 if (expanded
&& paste_tokens(&thead
, true)) {
4249 * If we concatenated something, *and* we had previously expanded
4250 * an actual macro, scan the lines again for macros...
4260 *org_tline
= *thead
;
4261 /* since we just gave text to org_line, don't free it */
4263 delete_Token(thead
);
4265 /* the expression expanded to empty line;
4266 we can't return NULL for some reasons
4267 we just set the line to a single WHITESPACE token. */
4268 memset(org_tline
, 0, sizeof(*org_tline
));
4269 org_tline
->text
= NULL
;
4270 org_tline
->type
= TOK_WHITESPACE
;
4279 * Similar to expand_smacro but used exclusively with macro identifiers
4280 * right before they are fetched in. The reason is that there can be
4281 * identifiers consisting of several subparts. We consider that if there
4282 * are more than one element forming the name, user wants a expansion,
4283 * otherwise it will be left as-is. Example:
4287 * the identifier %$abc will be left as-is so that the handler for %define
4288 * will suck it and define the corresponding value. Other case:
4290 * %define _%$abc cde
4292 * In this case user wants name to be expanded *before* %define starts
4293 * working, so we'll expand %$abc into something (if it has a value;
4294 * otherwise it will be left as-is) then concatenate all successive
4297 static Token
*expand_id(Token
* tline
)
4299 Token
*cur
, *oldnext
= NULL
;
4301 if (!tline
|| !tline
->next
)
4306 (cur
->next
->type
== TOK_ID
||
4307 cur
->next
->type
== TOK_PREPROC_ID
4308 || cur
->next
->type
== TOK_NUMBER
))
4311 /* If identifier consists of just one token, don't expand */
4316 oldnext
= cur
->next
; /* Detach the tail past identifier */
4317 cur
->next
= NULL
; /* so that expand_smacro stops here */
4320 tline
= expand_smacro(tline
);
4323 /* expand_smacro possibly changhed tline; re-scan for EOL */
4325 while (cur
&& cur
->next
)
4328 cur
->next
= oldnext
;
4335 * Determine whether the given line constitutes a multi-line macro
4336 * call, and return the MMacro structure called if so. Doesn't have
4337 * to check for an initial label - that's taken care of in
4338 * expand_mmacro - but must check numbers of parameters. Guaranteed
4339 * to be called with tline->type == TOK_ID, so the putative macro
4340 * name is easy to find.
4342 static MMacro
*is_mmacro(Token
* tline
, Token
*** params_array
)
4348 head
= (MMacro
*) hash_findix(&mmacros
, tline
->text
);
4351 * Efficiency: first we see if any macro exists with the given
4352 * name. If not, we can return NULL immediately. _Then_ we
4353 * count the parameters, and then we look further along the
4354 * list if necessary to find the proper MMacro.
4356 list_for_each(m
, head
)
4357 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
4363 * OK, we have a potential macro. Count and demarcate the
4366 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
4369 * So we know how many parameters we've got. Find the MMacro
4370 * structure that handles this number.
4373 if (m
->nparam_min
<= nparam
4374 && (m
->plus
|| nparam
<= m
->nparam_max
)) {
4376 * This one is right. Just check if cycle removal
4377 * prohibits us using it before we actually celebrate...
4379 if (m
->in_progress
> m
->max_depth
) {
4380 if (m
->max_depth
> 0) {
4382 "reached maximum recursion depth of %i",
4389 * It's right, and we can use it. Add its default
4390 * parameters to the end of our list if necessary.
4392 if (m
->defaults
&& nparam
< m
->nparam_min
+ m
->ndefs
) {
4394 nasm_realloc(params
,
4395 ((m
->nparam_min
+ m
->ndefs
+
4396 1) * sizeof(*params
)));
4397 while (nparam
< m
->nparam_min
+ m
->ndefs
) {
4398 params
[nparam
] = m
->defaults
[nparam
- m
->nparam_min
];
4403 * If we've gone over the maximum parameter count (and
4404 * we're in Plus mode), ignore parameters beyond
4407 if (m
->plus
&& nparam
> m
->nparam_max
)
4408 nparam
= m
->nparam_max
;
4410 * Then terminate the parameter list, and leave.
4412 if (!params
) { /* need this special case */
4413 params
= nasm_malloc(sizeof(*params
));
4416 params
[nparam
] = NULL
;
4417 *params_array
= params
;
4421 * This one wasn't right: look for the next one with the
4424 list_for_each(m
, m
->next
)
4425 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
4430 * After all that, we didn't find one with the right number of
4431 * parameters. Issue a warning, and fail to expand the macro.
4433 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4434 "macro `%s' exists, but not taking %d parameters",
4435 tline
->text
, nparam
);
4442 * Save MMacro invocation specific fields in
4443 * preparation for a recursive macro expansion
4445 static void push_mmacro(MMacro
*m
)
4447 MMacroInvocation
*i
;
4449 i
= nasm_malloc(sizeof(MMacroInvocation
));
4451 i
->params
= m
->params
;
4452 i
->iline
= m
->iline
;
4453 i
->nparam
= m
->nparam
;
4454 i
->rotate
= m
->rotate
;
4455 i
->paramlen
= m
->paramlen
;
4456 i
->unique
= m
->unique
;
4457 i
->condcnt
= m
->condcnt
;
4463 * Restore MMacro invocation specific fields that were
4464 * saved during a previous recursive macro expansion
4466 static void pop_mmacro(MMacro
*m
)
4468 MMacroInvocation
*i
;
4473 m
->params
= i
->params
;
4474 m
->iline
= i
->iline
;
4475 m
->nparam
= i
->nparam
;
4476 m
->rotate
= i
->rotate
;
4477 m
->paramlen
= i
->paramlen
;
4478 m
->unique
= i
->unique
;
4479 m
->condcnt
= i
->condcnt
;
4486 * Expand the multi-line macro call made by the given line, if
4487 * there is one to be expanded. If there is, push the expansion on
4488 * istk->expansion and return 1. Otherwise return 0.
4490 static int expand_mmacro(Token
* tline
)
4492 Token
*startline
= tline
;
4493 Token
*label
= NULL
;
4494 int dont_prepend
= 0;
4495 Token
**params
, *t
, *mtok
, *tt
;
4498 int i
, nparam
, *paramlen
;
4503 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4504 if (!tok_type_(t
, TOK_ID
) && !tok_type_(t
, TOK_PREPROC_ID
))
4507 m
= is_mmacro(t
, ¶ms
);
4513 * We have an id which isn't a macro call. We'll assume
4514 * it might be a label; we'll also check to see if a
4515 * colon follows it. Then, if there's another id after
4516 * that lot, we'll check it again for macro-hood.
4520 if (tok_type_(t
, TOK_WHITESPACE
))
4521 last
= t
, t
= t
->next
;
4522 if (tok_is_(t
, ":")) {
4524 last
= t
, t
= t
->next
;
4525 if (tok_type_(t
, TOK_WHITESPACE
))
4526 last
= t
, t
= t
->next
;
4528 if (!tok_type_(t
, TOK_ID
) || !(m
= is_mmacro(t
, ¶ms
)))
4536 * Fix up the parameters: this involves stripping leading and
4537 * trailing whitespace, then stripping braces if they are
4540 for (nparam
= 0; params
[nparam
]; nparam
++) ;
4541 paramlen
= nparam
? nasm_malloc(nparam
* sizeof(*paramlen
)) : NULL
;
4543 for (i
= 0; params
[i
]; i
++) {
4545 int comma
= (!m
->plus
|| i
< nparam
- 1);
4549 if (tok_is_(t
, "{"))
4550 t
= t
->next
, brace
= true, comma
= false;
4554 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
4555 break; /* ... because we have hit a comma */
4556 if (comma
&& t
->type
== TOK_WHITESPACE
4557 && tok_is_(t
->next
, ","))
4558 break; /* ... or a space then a comma */
4559 if (brace
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "}"))
4560 break; /* ... or a brace */
4567 * OK, we have a MMacro structure together with a set of
4568 * parameters. We must now go through the expansion and push
4569 * copies of each Line on to istk->expansion. Substitution of
4570 * parameter tokens and macro-local tokens doesn't get done
4571 * until the single-line macro substitution process; this is
4572 * because delaying them allows us to change the semantics
4573 * later through %rotate.
4575 * First, push an end marker on to istk->expansion, mark this
4576 * macro as in progress, and set up its invocation-specific
4579 ll
= nasm_malloc(sizeof(Line
));
4580 ll
->next
= istk
->expansion
;
4583 istk
->expansion
= ll
;
4586 * Save the previous MMacro expansion in the case of
4589 if (m
->max_depth
&& m
->in_progress
)
4597 m
->paramlen
= paramlen
;
4598 m
->unique
= unique
++;
4602 m
->next_active
= istk
->mstk
;
4605 list_for_each(l
, m
->expansion
) {
4608 ll
= nasm_malloc(sizeof(Line
));
4609 ll
->finishes
= NULL
;
4610 ll
->next
= istk
->expansion
;
4611 istk
->expansion
= ll
;
4614 list_for_each(t
, l
->first
) {
4618 tt
= *tail
= new_Token(NULL
, TOK_ID
, mname
, 0);
4620 case TOK_PREPROC_QQ
:
4621 tt
= *tail
= new_Token(NULL
, TOK_ID
, m
->name
, 0);
4623 case TOK_PREPROC_ID
:
4624 if (t
->text
[1] == '0' && t
->text
[2] == '0') {
4632 tt
= *tail
= new_Token(NULL
, x
->type
, x
->text
, 0);
4641 * If we had a label, push it on as the first line of
4642 * the macro expansion.
4645 if (dont_prepend
< 0)
4646 free_tlist(startline
);
4648 ll
= nasm_malloc(sizeof(Line
));
4649 ll
->finishes
= NULL
;
4650 ll
->next
= istk
->expansion
;
4651 istk
->expansion
= ll
;
4652 ll
->first
= startline
;
4653 if (!dont_prepend
) {
4655 label
= label
->next
;
4656 label
->next
= tt
= new_Token(NULL
, TOK_OTHER
, ":", 0);
4661 list
->uplevel(m
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
4666 /* The function that actually does the error reporting */
4667 static void verror(int severity
, const char *fmt
, va_list arg
)
4671 vsnprintf(buff
, sizeof(buff
), fmt
, arg
);
4673 if (istk
&& istk
->mstk
&& istk
->mstk
->name
)
4674 nasm_error(severity
, "(%s:%d) %s", istk
->mstk
->name
,
4675 istk
->mstk
->lineno
, buff
);
4677 nasm_error(severity
, "%s", buff
);
4681 * Since preprocessor always operate only on the line that didn't
4682 * arrived yet, we should always use ERR_OFFBY1.
4684 static void error(int severity
, const char *fmt
, ...)
4688 /* If we're in a dead branch of IF or something like it, ignore the error */
4689 if (istk
&& istk
->conds
&& !emitting(istk
->conds
->state
))
4693 verror(severity
, fmt
, arg
);
4698 * Because %else etc are evaluated in the state context
4699 * of the previous branch, errors might get lost with error():
4700 * %if 0 ... %else trailing garbage ... %endif
4701 * So %else etc should report errors with this function.
4703 static void error_precond(int severity
, const char *fmt
, ...)
4707 /* Only ignore the error if it's really in a dead branch */
4708 if (istk
&& istk
->conds
&& istk
->conds
->state
== COND_NEVER
)
4712 verror(severity
, fmt
, arg
);
4717 pp_reset(char *file
, int apass
, ListGen
* listgen
, StrList
**deplist
)
4722 istk
= nasm_malloc(sizeof(Include
));
4725 istk
->expansion
= NULL
;
4727 istk
->fp
= fopen(file
, "r");
4729 src_set_fname(nasm_strdup(file
));
4733 error(ERR_FATAL
|ERR_NOFILE
, "unable to open input file `%s'",
4736 nested_mac_count
= 0;
4737 nested_rep_count
= 0;
4740 if (tasm_compatible_mode
) {
4741 stdmacpos
= nasm_stdmac
;
4743 stdmacpos
= nasm_stdmac_after_tasm
;
4745 any_extrastdmac
= extrastdmac
&& *extrastdmac
;
4750 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
4751 * The caller, however, will also pass in 3 for preprocess-only so
4752 * we can set __PASS__ accordingly.
4754 pass
= apass
> 2 ? 2 : apass
;
4756 dephead
= deptail
= deplist
;
4758 StrList
*sl
= nasm_malloc(strlen(file
)+1+sizeof sl
->next
);
4760 strcpy(sl
->str
, file
);
4762 deptail
= &sl
->next
;
4766 * Define the __PASS__ macro. This is defined here unlike
4767 * all the other builtins, because it is special -- it varies between
4770 t
= nasm_malloc(sizeof(*t
));
4772 make_tok_num(t
, apass
);
4774 define_smacro(NULL
, "__PASS__", true, 0, t
);
4777 static char *pp_getline(void)
4784 * Fetch a tokenized line, either from the macro-expansion
4785 * buffer or from the input file.
4788 while (istk
->expansion
&& istk
->expansion
->finishes
) {
4789 Line
*l
= istk
->expansion
;
4790 if (!l
->finishes
->name
&& l
->finishes
->in_progress
> 1) {
4794 * This is a macro-end marker for a macro with no
4795 * name, which means it's not really a macro at all
4796 * but a %rep block, and the `in_progress' field is
4797 * more than 1, meaning that we still need to
4798 * repeat. (1 means the natural last repetition; 0
4799 * means termination by %exitrep.) We have
4800 * therefore expanded up to the %endrep, and must
4801 * push the whole block on to the expansion buffer
4802 * again. We don't bother to remove the macro-end
4803 * marker: we'd only have to generate another one
4806 l
->finishes
->in_progress
--;
4807 list_for_each(l
, l
->finishes
->expansion
) {
4808 Token
*t
, *tt
, **tail
;
4810 ll
= nasm_malloc(sizeof(Line
));
4811 ll
->next
= istk
->expansion
;
4812 ll
->finishes
= NULL
;
4816 list_for_each(t
, l
->first
) {
4817 if (t
->text
|| t
->type
== TOK_WHITESPACE
) {
4818 tt
= *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
4823 istk
->expansion
= ll
;
4827 * Check whether a `%rep' was started and not ended
4828 * within this macro expansion. This can happen and
4829 * should be detected. It's a fatal error because
4830 * I'm too confused to work out how to recover
4836 "defining with name in expansion");
4837 else if (istk
->mstk
->name
)
4839 "`%%rep' without `%%endrep' within"
4840 " expansion of macro `%s'",
4845 * FIXME: investigate the relationship at this point between
4846 * istk->mstk and l->finishes
4849 MMacro
*m
= istk
->mstk
;
4850 istk
->mstk
= m
->next_active
;
4853 * This was a real macro call, not a %rep, and
4854 * therefore the parameter information needs to
4859 l
->finishes
->in_progress
--;
4861 nasm_free(m
->params
);
4862 free_tlist(m
->iline
);
4863 nasm_free(m
->paramlen
);
4864 l
->finishes
->in_progress
= 0;
4869 istk
->expansion
= l
->next
;
4871 list
->downlevel(LIST_MACRO
);
4874 while (1) { /* until we get a line we can use */
4876 if (istk
->expansion
) { /* from a macro expansion */
4878 Line
*l
= istk
->expansion
;
4880 istk
->mstk
->lineno
++;
4882 istk
->expansion
= l
->next
;
4884 p
= detoken(tline
, false);
4885 list
->line(LIST_MACRO
, p
);
4890 if (line
) { /* from the current input file */
4891 line
= prepreproc(line
);
4892 tline
= tokenize(line
);
4897 * The current file has ended; work down the istk
4904 "expected `%%endif' before end of file");
4905 /* only set line and file name if there's a next node */
4907 src_set_linnum(i
->lineno
);
4908 nasm_free(src_set_fname(i
->fname
));
4911 list
->downlevel(LIST_INCLUDE
);
4915 if (istk
->expansion
&& istk
->expansion
->finishes
)
4921 * We must expand MMacro parameters and MMacro-local labels
4922 * _before_ we plunge into directive processing, to cope
4923 * with things like `%define something %1' such as STRUC
4924 * uses. Unless we're _defining_ a MMacro, in which case
4925 * those tokens should be left alone to go into the
4926 * definition; and unless we're in a non-emitting
4927 * condition, in which case we don't want to meddle with
4930 if (!defining
&& !(istk
->conds
&& !emitting(istk
->conds
->state
))
4931 && !(istk
->mstk
&& !istk
->mstk
->in_progress
)) {
4932 tline
= expand_mmac_params(tline
);
4936 * Check the line to see if it's a preprocessor directive.
4938 if (do_directive(tline
) == DIRECTIVE_FOUND
) {
4940 } else if (defining
) {
4942 * We're defining a multi-line macro. We emit nothing
4944 * shove the tokenized line on to the macro definition.
4946 Line
*l
= nasm_malloc(sizeof(Line
));
4947 l
->next
= defining
->expansion
;
4950 defining
->expansion
= l
;
4952 } else if (istk
->conds
&& !emitting(istk
->conds
->state
)) {
4954 * We're in a non-emitting branch of a condition block.
4955 * Emit nothing at all, not even a blank line: when we
4956 * emerge from the condition we'll give a line-number
4957 * directive so we keep our place correctly.
4961 } else if (istk
->mstk
&& !istk
->mstk
->in_progress
) {
4963 * We're in a %rep block which has been terminated, so
4964 * we're walking through to the %endrep without
4965 * emitting anything. Emit nothing at all, not even a
4966 * blank line: when we emerge from the %rep block we'll
4967 * give a line-number directive so we keep our place
4973 tline
= expand_smacro(tline
);
4974 if (!expand_mmacro(tline
)) {
4976 * De-tokenize the line again, and emit it.
4978 line
= detoken(tline
, true);
4982 continue; /* expand_mmacro calls free_tlist */
4990 static void pp_cleanup(int pass
)
4993 if (defining
->name
) {
4995 "end of file while still defining macro `%s'",
4998 error(ERR_NONFATAL
, "end of file while still in %%rep");
5001 free_mmacro(defining
);
5011 nasm_free(i
->fname
);
5016 nasm_free(src_set_fname(NULL
));
5021 while ((i
= ipath
)) {
5030 void pp_include_path(char *path
)
5034 i
= nasm_malloc(sizeof(IncPath
));
5035 i
->path
= path
? nasm_strdup(path
) : NULL
;
5048 void pp_pre_include(char *fname
)
5050 Token
*inc
, *space
, *name
;
5053 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
5054 space
= new_Token(name
, TOK_WHITESPACE
, NULL
, 0);
5055 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
5057 l
= nasm_malloc(sizeof(Line
));
5064 void pp_pre_define(char *definition
)
5070 equals
= strchr(definition
, '=');
5071 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5072 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
5075 space
->next
= tokenize(definition
);
5079 l
= nasm_malloc(sizeof(Line
));
5086 void pp_pre_undefine(char *definition
)
5091 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5092 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
5093 space
->next
= tokenize(definition
);
5095 l
= nasm_malloc(sizeof(Line
));
5103 * Added by Keith Kanios:
5105 * This function is used to assist with "runtime" preprocessor
5106 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
5108 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
5109 * PASS A VALID STRING TO THIS FUNCTION!!!!!
5112 void pp_runtime(char *definition
)
5116 def
= tokenize(definition
);
5117 if (do_directive(def
) == NO_DIRECTIVE_FOUND
)
5122 void pp_extra_stdmac(macros_t
*macros
)
5124 extrastdmac
= macros
;
5127 static void make_tok_num(Token
* tok
, int64_t val
)
5130 snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
5131 tok
->text
= nasm_strdup(numbuf
);
5132 tok
->type
= TOK_NUMBER
;