1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2009 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 * Condition codes. Note that we use c_ prefix not C_ because C_ is
331 * used in nasm.h for the "real" condition codes. At _this_ level,
332 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
333 * ones, so we need a different enum...
335 static const char * const conditions
[] = {
336 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
337 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
338 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
341 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
342 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
343 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_RCXZ
, c_S
, c_Z
,
346 static const enum pp_conds inverse_ccs
[] = {
347 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
348 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
,
349 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, -1, c_NS
, c_NZ
355 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
356 static int is_condition(enum preproc_token arg
)
358 return PP_IS_COND(arg
) || (arg
== PP_ELSE
) || (arg
== PP_ENDIF
);
361 /* For TASM compatibility we need to be able to recognise TASM compatible
362 * conditional compilation directives. Using the NASM pre-processor does
363 * not work, so we look for them specifically from the following list and
364 * then jam in the equivalent NASM directive into the input stream.
368 TM_ARG
, TM_ELIF
, TM_ELSE
, TM_ENDIF
, TM_IF
, TM_IFDEF
, TM_IFDIFI
,
369 TM_IFNDEF
, TM_INCLUDE
, TM_LOCAL
372 static const char * const tasm_directives
[] = {
373 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
374 "ifndef", "include", "local"
377 static int StackSize
= 4;
378 static char *StackPointer
= "ebp";
379 static int ArgOffset
= 8;
380 static int LocalOffset
= 0;
382 static Context
*cstk
;
383 static Include
*istk
;
384 static IncPath
*ipath
= NULL
;
386 static int pass
; /* HACK: pass 0 = generate dependencies only */
387 static StrList
**dephead
, **deptail
; /* Dependency list */
389 static uint64_t unique
; /* unique identifier numbers */
391 static Line
*predef
= NULL
;
392 static bool do_predef
;
394 static ListGen
*list
;
397 * The current set of multi-line macros we have defined.
399 static struct hash_table mmacros
;
402 * The current set of single-line macros we have defined.
404 static struct hash_table smacros
;
407 * The multi-line macro we are currently defining, or the %rep
408 * block we are currently reading, if any.
410 static MMacro
*defining
;
412 static uint64_t nested_mac_count
;
413 static uint64_t nested_rep_count
;
416 * The number of macro parameters to allocate space for at a time.
418 #define PARAM_DELTA 16
421 * The standard macro set: defined in macros.c in the array nasm_stdmac.
422 * This gives our position in the macro set, when we're processing it.
424 static macros_t
*stdmacpos
;
427 * The extra standard macros that come from the object format, if
430 static macros_t
*extrastdmac
= NULL
;
431 static bool any_extrastdmac
;
434 * Tokens are allocated in blocks to improve speed
436 #define TOKEN_BLOCKSIZE 4096
437 static Token
*freeTokens
= NULL
;
443 static Blocks blocks
= { NULL
, NULL
};
446 * Forward declarations.
448 static Token
*expand_mmac_params(Token
* tline
);
449 static Token
*expand_smacro(Token
* tline
);
450 static Token
*expand_id(Token
* tline
);
451 static Context
*get_ctx(const char *name
, const char **namep
,
453 static void make_tok_num(Token
* tok
, int64_t val
);
454 static void error(int severity
, const char *fmt
, ...);
455 static void error_precond(int severity
, const char *fmt
, ...);
456 static void *new_Block(size_t size
);
457 static void delete_Blocks(void);
458 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
459 const char *text
, int txtlen
);
460 static Token
*delete_Token(Token
* t
);
463 * Macros for safe checking of token pointers, avoid *(NULL)
465 #define tok_type_(x,t) ((x) && (x)->type == (t))
466 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
467 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
468 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
470 /* Handle TASM specific directives, which do not contain a % in
471 * front of them. We do it here because I could not find any other
472 * place to do it for the moment, and it is a hack (ideally it would
473 * be nice to be able to use the NASM pre-processor to do it).
475 static char *check_tasm_directive(char *line
)
477 int32_t i
, j
, k
, m
, len
;
478 char *p
, *q
, *oldline
, oldchar
;
480 p
= nasm_skip_spaces(line
);
482 /* Binary search for the directive name */
484 j
= elements(tasm_directives
);
485 q
= nasm_skip_word(p
);
492 m
= nasm_stricmp(p
, tasm_directives
[k
]);
494 /* We have found a directive, so jam a % in front of it
495 * so that NASM will then recognise it as one if it's own.
500 line
= nasm_malloc(len
+ 2);
502 if (k
== TM_IFDIFI
) {
504 * NASM does not recognise IFDIFI, so we convert
505 * it to %if 0. This is not used in NASM
506 * compatible code, but does need to parse for the
507 * TASM macro package.
509 strcpy(line
+ 1, "if 0");
511 memcpy(line
+ 1, p
, len
+ 1);
526 * The pre-preprocessing stage... This function translates line
527 * number indications as they emerge from GNU cpp (`# lineno "file"
528 * flags') into NASM preprocessor line number indications (`%line
531 static char *prepreproc(char *line
)
534 char *fname
, *oldline
;
536 if (line
[0] == '#' && line
[1] == ' ') {
539 lineno
= atoi(fname
);
540 fname
+= strspn(fname
, "0123456789 ");
543 fnlen
= strcspn(fname
, "\"");
544 line
= nasm_malloc(20 + fnlen
);
545 snprintf(line
, 20 + fnlen
, "%%line %d %.*s", lineno
, fnlen
, fname
);
548 if (tasm_compatible_mode
)
549 return check_tasm_directive(line
);
554 * Free a linked list of tokens.
556 static void free_tlist(Token
* list
)
559 list
= delete_Token(list
);
564 * Free a linked list of lines.
566 static void free_llist(Line
* list
)
572 free_tlist(l
->first
);
580 static void free_mmacro(MMacro
* m
)
583 free_tlist(m
->dlist
);
584 nasm_free(m
->defaults
);
585 free_llist(m
->expansion
);
590 * Free all currently defined macros, and free the hash tables
592 static void free_smacro_table(struct hash_table
*smt
)
596 struct hash_tbl_node
*it
= NULL
;
598 while ((s
= hash_iterate(smt
, &it
, &key
)) != NULL
) {
599 nasm_free((void *)key
);
601 SMacro
*ns
= s
->next
;
603 free_tlist(s
->expansion
);
611 static void free_mmacro_table(struct hash_table
*mmt
)
615 struct hash_tbl_node
*it
= NULL
;
618 while ((m
= hash_iterate(mmt
, &it
, &key
)) != NULL
) {
619 nasm_free((void *)key
);
621 MMacro
*nm
= m
->next
;
629 static void free_macros(void)
631 free_smacro_table(&smacros
);
632 free_mmacro_table(&mmacros
);
636 * Initialize the hash tables
638 static void init_macros(void)
640 hash_init(&smacros
, HASH_LARGE
);
641 hash_init(&mmacros
, HASH_LARGE
);
645 * Pop the context stack.
647 static void ctx_pop(void)
652 free_smacro_table(&c
->localmac
);
658 * Search for a key in the hash index; adding it if necessary
659 * (in which case we initialize the data pointer to NULL.)
662 hash_findi_add(struct hash_table
*hash
, const char *str
)
664 struct hash_insert hi
;
668 r
= hash_findi(hash
, str
, &hi
);
672 strx
= nasm_strdup(str
); /* Use a more efficient allocator here? */
673 return hash_add(&hi
, strx
, NULL
);
677 * Like hash_findi, but returns the data element rather than a pointer
678 * to it. Used only when not adding a new element, hence no third
682 hash_findix(struct hash_table
*hash
, const char *str
)
686 p
= hash_findi(hash
, str
, NULL
);
687 return p
? *p
: NULL
;
690 #define BUF_DELTA 512
692 * Read a line from the top file in istk, handling multiple CR/LFs
693 * at the end of the line read, and handling spurious ^Zs. Will
694 * return lines from the standard macro set if this has not already
697 static char *read_line(void)
699 char *buffer
, *p
, *q
;
700 int bufsize
, continued_count
;
704 const unsigned char *p
= stdmacpos
;
709 len
+= pp_directives_len
[c
-0x80]+1;
713 ret
= nasm_malloc(len
+1);
715 while ((c
= *stdmacpos
++)) {
717 memcpy(q
, pp_directives
[c
-0x80], pp_directives_len
[c
-0x80]);
718 q
+= pp_directives_len
[c
-0x80];
728 /* This was the last of the standard macro chain... */
730 if (any_extrastdmac
) {
731 stdmacpos
= extrastdmac
;
732 any_extrastdmac
= false;
733 } else if (do_predef
) {
735 Token
*head
, **tail
, *t
;
738 * Nasty hack: here we push the contents of
739 * `predef' on to the top-level expansion stack,
740 * since this is the most convenient way to
741 * implement the pre-include and pre-define
744 for (pd
= predef
; pd
; pd
= pd
->next
) {
747 for (t
= pd
->first
; t
; t
= t
->next
) {
748 *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
749 tail
= &(*tail
)->next
;
751 l
= nasm_malloc(sizeof(Line
));
752 l
->next
= istk
->expansion
;
764 buffer
= nasm_malloc(BUF_DELTA
);
768 q
= fgets(p
, bufsize
- (p
- buffer
), istk
->fp
);
772 if (p
> buffer
&& p
[-1] == '\n') {
773 /* Convert backslash-CRLF line continuation sequences into
774 nothing at all (for DOS and Windows) */
775 if (((p
- 2) > buffer
) && (p
[-3] == '\\') && (p
[-2] == '\r')) {
780 /* Also convert backslash-LF line continuation sequences into
781 nothing at all (for Unix) */
782 else if (((p
- 1) > buffer
) && (p
[-2] == '\\')) {
790 if (p
- buffer
> bufsize
- 10) {
791 int32_t offset
= p
- buffer
;
792 bufsize
+= BUF_DELTA
;
793 buffer
= nasm_realloc(buffer
, bufsize
);
794 p
= buffer
+ offset
; /* prevent stale-pointer problems */
798 if (!q
&& p
== buffer
) {
803 src_set_linnum(src_get_linnum() + istk
->lineinc
+
804 (continued_count
* istk
->lineinc
));
807 * Play safe: remove CRs as well as LFs, if any of either are
808 * present at the end of the line.
810 while (--p
>= buffer
&& (*p
== '\n' || *p
== '\r'))
814 * Handle spurious ^Z, which may be inserted into source files
815 * by some file transfer utilities.
817 buffer
[strcspn(buffer
, "\032")] = '\0';
819 list
->line(LIST_READ
, buffer
);
825 * Tokenize a line of text. This is a very simple process since we
826 * don't need to parse the value out of e.g. numeric tokens: we
827 * simply split one string into many.
829 static Token
*tokenize(char *line
)
832 enum pp_token_type type
;
834 Token
*t
, **tail
= &list
;
840 if (*p
== '+' && !nasm_isdigit(p
[1])) {
843 } else if (nasm_isdigit(*p
) ||
844 ((*p
== '-' || *p
== '+') && nasm_isdigit(p
[1]))) {
848 while (nasm_isdigit(*p
));
849 type
= TOK_PREPROC_ID
;
850 } else if (*p
== '{') {
852 while (*p
&& *p
!= '}') {
859 type
= TOK_PREPROC_ID
;
860 } else if (*p
== '[') {
862 line
+= 2; /* Skip the leading %[ */
864 while (lvl
&& (c
= *p
++)) {
876 p
= nasm_skip_string(p
)+1;
886 error(ERR_NONFATAL
, "unterminated %[ construct");
888 } else if (*p
== '?') {
889 type
= TOK_PREPROC_Q
; /* %? */
892 type
= TOK_PREPROC_QQ
; /* %?? */
895 } else if (isidchar(*p
) ||
896 ((*p
== '!' || *p
== '%' || *p
== '$') &&
901 while (isidchar(*p
));
902 type
= TOK_PREPROC_ID
;
908 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
911 while (*p
&& isidchar(*p
))
913 } else if (*p
== '\'' || *p
== '"' || *p
== '`') {
918 p
= nasm_skip_string(p
);
923 error(ERR_WARNING
|ERR_PASS1
, "unterminated string");
924 /* Handling unterminated strings by UNV */
927 } else if (p
[0] == '$' && p
[1] == '$') {
928 type
= TOK_OTHER
; /* TOKEN_BASE */
930 } else if (isnumstart(*p
)) {
932 bool is_float
= false;
948 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
950 if (*p
== '+' || *p
== '-') {
951 /* e can only be followed by +/- if it is either a
952 prefixed hex number or a floating-point number */
956 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
958 } else if (c
== 'P' || c
== 'p') {
960 if (*p
== '+' || *p
== '-')
962 } else if (isnumchar(c
) || c
== '_')
965 /* we need to deal with consequences of the legacy
966 parser, like "1.nolist" being two tokens
967 (TOK_NUMBER, TOK_ID) here; at least give it
968 a shot for now. In the future, we probably need
969 a flex-based scanner with proper pattern matching
970 to do it as well as it can be done. Nothing in
971 the world is going to help the person who wants
972 0x123.p16 interpreted as two tokens, though. */
977 if (nasm_isdigit(*r
) || (is_hex
&& nasm_isxdigit(*r
)) ||
978 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
979 (*r
== 'p' || *r
== 'P')) {
983 break; /* Terminate the token */
987 p
--; /* Point to first character beyond number */
989 if (p
== line
+1 && *line
== '$') {
990 type
= TOK_OTHER
; /* TOKEN_HERE */
992 if (has_e
&& !is_hex
) {
993 /* 1e13 is floating-point, but 1e13h is not */
997 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
999 } else if (nasm_isspace(*p
)) {
1000 type
= TOK_WHITESPACE
;
1001 p
= nasm_skip_spaces(p
);
1003 * Whitespace just before end-of-line is discarded by
1004 * pretending it's a comment; whitespace just before a
1005 * comment gets lumped into the comment.
1007 if (!*p
|| *p
== ';') {
1012 } else if (*p
== ';') {
1018 * Anything else is an operator of some kind. We check
1019 * for all the double-character operators (>>, <<, //,
1020 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1021 * else is a single-character operator.
1024 if ((p
[0] == '>' && p
[1] == '>') ||
1025 (p
[0] == '<' && p
[1] == '<') ||
1026 (p
[0] == '/' && p
[1] == '/') ||
1027 (p
[0] == '<' && p
[1] == '=') ||
1028 (p
[0] == '>' && p
[1] == '=') ||
1029 (p
[0] == '=' && p
[1] == '=') ||
1030 (p
[0] == '!' && p
[1] == '=') ||
1031 (p
[0] == '<' && p
[1] == '>') ||
1032 (p
[0] == '&' && p
[1] == '&') ||
1033 (p
[0] == '|' && p
[1] == '|') ||
1034 (p
[0] == '^' && p
[1] == '^')) {
1040 /* Handling unterminated string by UNV */
1043 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1044 t->text[p-line] = *line;
1048 if (type
!= TOK_COMMENT
) {
1049 *tail
= t
= new_Token(NULL
, type
, line
, p
- line
);
1058 * this function allocates a new managed block of memory and
1059 * returns a pointer to the block. The managed blocks are
1060 * deleted only all at once by the delete_Blocks function.
1062 static void *new_Block(size_t size
)
1064 Blocks
*b
= &blocks
;
1066 /* first, get to the end of the linked list */
1069 /* now allocate the requested chunk */
1070 b
->chunk
= nasm_malloc(size
);
1072 /* now allocate a new block for the next request */
1073 b
->next
= nasm_malloc(sizeof(Blocks
));
1074 /* and initialize the contents of the new block */
1075 b
->next
->next
= NULL
;
1076 b
->next
->chunk
= NULL
;
1081 * this function deletes all managed blocks of memory
1083 static void delete_Blocks(void)
1085 Blocks
*a
, *b
= &blocks
;
1088 * keep in mind that the first block, pointed to by blocks
1089 * is a static and not dynamically allocated, so we don't
1094 nasm_free(b
->chunk
);
1103 * this function creates a new Token and passes a pointer to it
1104 * back to the caller. It sets the type and text elements, and
1105 * also the a.mac and next elements to NULL.
1107 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
1108 const char *text
, int txtlen
)
1114 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1115 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1116 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1117 freeTokens
[i
].next
= NULL
;
1120 freeTokens
= t
->next
;
1124 if (type
== TOK_WHITESPACE
|| !text
) {
1128 txtlen
= strlen(text
);
1129 t
->text
= nasm_malloc(txtlen
+1);
1130 memcpy(t
->text
, text
, txtlen
);
1131 t
->text
[txtlen
] = '\0';
1136 static Token
*delete_Token(Token
* t
)
1138 Token
*next
= t
->next
;
1140 t
->next
= freeTokens
;
1146 * Convert a line of tokens back into text.
1147 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1148 * will be transformed into ..@ctxnum.xxx
1150 static char *detoken(Token
* tlist
, bool expand_locals
)
1158 for (t
= tlist
; t
; t
= t
->next
) {
1159 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
1160 char *p
= getenv(t
->text
+ 2);
1163 t
->text
= nasm_strdup(p
);
1167 /* Expand local macros here and not during preprocessing */
1168 if (expand_locals
&&
1169 t
->type
== TOK_PREPROC_ID
&& t
->text
&&
1170 t
->text
[0] == '%' && t
->text
[1] == '$') {
1173 Context
*ctx
= get_ctx(t
->text
, &q
, false);
1176 snprintf(buffer
, sizeof(buffer
), "..@%"PRIu32
".", ctx
->number
);
1177 p
= nasm_strcat(buffer
, q
);
1182 if (t
->type
== TOK_WHITESPACE
) {
1184 } else if (t
->text
) {
1185 len
+= strlen(t
->text
);
1188 p
= line
= nasm_malloc(len
+ 1);
1189 for (t
= tlist
; t
; t
= t
->next
) {
1190 if (t
->type
== TOK_WHITESPACE
) {
1192 } else if (t
->text
) {
1203 * A scanner, suitable for use by the expression evaluator, which
1204 * operates on a line of Tokens. Expects a pointer to a pointer to
1205 * the first token in the line to be passed in as its private_data
1208 * FIX: This really needs to be unified with stdscan.
1210 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1212 Token
**tlineptr
= private_data
;
1214 char ourcopy
[MAX_KEYWORD
+1], *p
, *r
, *s
;
1218 *tlineptr
= tline
? tline
->next
: NULL
;
1220 while (tline
&& (tline
->type
== TOK_WHITESPACE
||
1221 tline
->type
== TOK_COMMENT
));
1224 return tokval
->t_type
= TOKEN_EOS
;
1226 tokval
->t_charptr
= tline
->text
;
1228 if (tline
->text
[0] == '$' && !tline
->text
[1])
1229 return tokval
->t_type
= TOKEN_HERE
;
1230 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[2])
1231 return tokval
->t_type
= TOKEN_BASE
;
1233 if (tline
->type
== TOK_ID
) {
1234 p
= tokval
->t_charptr
= tline
->text
;
1236 tokval
->t_charptr
++;
1237 return tokval
->t_type
= TOKEN_ID
;
1240 for (r
= p
, s
= ourcopy
; *r
; r
++) {
1241 if (r
>= p
+MAX_KEYWORD
)
1242 return tokval
->t_type
= TOKEN_ID
; /* Not a keyword */
1243 *s
++ = nasm_tolower(*r
);
1246 /* right, so we have an identifier sitting in temp storage. now,
1247 * is it actually a register or instruction name, or what? */
1248 return nasm_token_hash(ourcopy
, tokval
);
1251 if (tline
->type
== TOK_NUMBER
) {
1253 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
1254 tokval
->t_charptr
= tline
->text
;
1256 return tokval
->t_type
= TOKEN_ERRNUM
;
1258 return tokval
->t_type
= TOKEN_NUM
;
1261 if (tline
->type
== TOK_FLOAT
) {
1262 return tokval
->t_type
= TOKEN_FLOAT
;
1265 if (tline
->type
== TOK_STRING
) {
1268 bq
= tline
->text
[0];
1269 tokval
->t_charptr
= tline
->text
;
1270 tokval
->t_inttwo
= nasm_unquote(tline
->text
, &ep
);
1272 if (ep
[0] != bq
|| ep
[1] != '\0')
1273 return tokval
->t_type
= TOKEN_ERRSTR
;
1275 return tokval
->t_type
= TOKEN_STR
;
1278 if (tline
->type
== TOK_OTHER
) {
1279 if (!strcmp(tline
->text
, "<<"))
1280 return tokval
->t_type
= TOKEN_SHL
;
1281 if (!strcmp(tline
->text
, ">>"))
1282 return tokval
->t_type
= TOKEN_SHR
;
1283 if (!strcmp(tline
->text
, "//"))
1284 return tokval
->t_type
= TOKEN_SDIV
;
1285 if (!strcmp(tline
->text
, "%%"))
1286 return tokval
->t_type
= TOKEN_SMOD
;
1287 if (!strcmp(tline
->text
, "=="))
1288 return tokval
->t_type
= TOKEN_EQ
;
1289 if (!strcmp(tline
->text
, "<>"))
1290 return tokval
->t_type
= TOKEN_NE
;
1291 if (!strcmp(tline
->text
, "!="))
1292 return tokval
->t_type
= TOKEN_NE
;
1293 if (!strcmp(tline
->text
, "<="))
1294 return tokval
->t_type
= TOKEN_LE
;
1295 if (!strcmp(tline
->text
, ">="))
1296 return tokval
->t_type
= TOKEN_GE
;
1297 if (!strcmp(tline
->text
, "&&"))
1298 return tokval
->t_type
= TOKEN_DBL_AND
;
1299 if (!strcmp(tline
->text
, "^^"))
1300 return tokval
->t_type
= TOKEN_DBL_XOR
;
1301 if (!strcmp(tline
->text
, "||"))
1302 return tokval
->t_type
= TOKEN_DBL_OR
;
1306 * We have no other options: just return the first character of
1309 return tokval
->t_type
= tline
->text
[0];
1313 * Compare a string to the name of an existing macro; this is a
1314 * simple wrapper which calls either strcmp or nasm_stricmp
1315 * depending on the value of the `casesense' parameter.
1317 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
1319 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
1323 * Compare a string to the name of an existing macro; this is a
1324 * simple wrapper which calls either strcmp or nasm_stricmp
1325 * depending on the value of the `casesense' parameter.
1327 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
1329 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
1333 * Return the Context structure associated with a %$ token. Return
1334 * NULL, having _already_ reported an error condition, if the
1335 * context stack isn't deep enough for the supplied number of $
1337 * If all_contexts == true, contexts that enclose current are
1338 * also scanned for such smacro, until it is found; if not -
1339 * only the context that directly results from the number of $'s
1340 * in variable's name.
1342 * If "namep" is non-NULL, set it to the pointer to the macro name
1343 * tail, i.e. the part beyond %$...
1345 static Context
*get_ctx(const char *name
, const char **namep
,
1355 if (!name
|| name
[0] != '%' || name
[1] != '$')
1359 error(ERR_NONFATAL
, "`%s': context stack is empty", name
);
1366 while (ctx
&& *name
== '$') {
1372 error(ERR_NONFATAL
, "`%s': context stack is only"
1373 " %d level%s deep", name
, i
, (i
== 1 ? "" : "s"));
1384 /* Search for this smacro in found context */
1385 m
= hash_findix(&ctx
->localmac
, name
);
1387 if (!mstrcmp(m
->name
, name
, m
->casesense
))
1398 * Check to see if a file is already in a string list
1400 static bool in_list(const StrList
*list
, const char *str
)
1403 if (!strcmp(list
->str
, str
))
1411 * Open an include file. This routine must always return a valid
1412 * file pointer if it returns - it's responsible for throwing an
1413 * ERR_FATAL and bombing out completely if not. It should also try
1414 * the include path one by one until it finds the file or reaches
1415 * the end of the path.
1417 static FILE *inc_fopen(const char *file
, StrList
**dhead
, StrList
***dtail
,
1422 IncPath
*ip
= ipath
;
1423 int len
= strlen(file
);
1424 size_t prefix_len
= 0;
1428 sl
= nasm_malloc(prefix_len
+len
+1+sizeof sl
->next
);
1429 memcpy(sl
->str
, prefix
, prefix_len
);
1430 memcpy(sl
->str
+prefix_len
, file
, len
+1);
1431 fp
= fopen(sl
->str
, "r");
1432 if (fp
&& dhead
&& !in_list(*dhead
, sl
->str
)) {
1450 prefix_len
= strlen(prefix
);
1452 /* -MG given and file not found */
1453 if (dhead
&& !in_list(*dhead
, file
)) {
1454 sl
= nasm_malloc(len
+1+sizeof sl
->next
);
1456 strcpy(sl
->str
, file
);
1464 error(ERR_FATAL
, "unable to open include file `%s'", file
);
1465 return NULL
; /* never reached - placate compilers */
1469 * Determine if we should warn on defining a single-line macro of
1470 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1471 * return true if _any_ single-line macro of that name is defined.
1472 * Otherwise, will return true if a single-line macro with either
1473 * `nparam' or no parameters is defined.
1475 * If a macro with precisely the right number of parameters is
1476 * defined, or nparam is -1, the address of the definition structure
1477 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1478 * is NULL, no action will be taken regarding its contents, and no
1481 * Note that this is also called with nparam zero to resolve
1484 * If you already know which context macro belongs to, you can pass
1485 * the context pointer as first parameter; if you won't but name begins
1486 * with %$ the context will be automatically computed. If all_contexts
1487 * is true, macro will be searched in outer contexts as well.
1490 smacro_defined(Context
* ctx
, const char *name
, int nparam
, SMacro
** defn
,
1493 struct hash_table
*smtbl
;
1497 smtbl
= &ctx
->localmac
;
1498 } else if (name
[0] == '%' && name
[1] == '$') {
1500 ctx
= get_ctx(name
, &name
, false);
1502 return false; /* got to return _something_ */
1503 smtbl
= &ctx
->localmac
;
1507 m
= (SMacro
*) hash_findix(smtbl
, name
);
1510 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
1511 (nparam
<= 0 || m
->nparam
== 0 || nparam
== (int) m
->nparam
)) {
1513 if (nparam
== (int) m
->nparam
|| nparam
== -1)
1527 * Count and mark off the parameters in a multi-line macro call.
1528 * This is called both from within the multi-line macro expansion
1529 * code, and also to mark off the default parameters when provided
1530 * in a %macro definition line.
1532 static void count_mmac_params(Token
* t
, int *nparam
, Token
*** params
)
1534 int paramsize
, brace
;
1536 *nparam
= paramsize
= 0;
1539 /* +1: we need space for the final NULL */
1540 if (*nparam
+1 >= paramsize
) {
1541 paramsize
+= PARAM_DELTA
;
1542 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
1546 if (tok_is_(t
, "{"))
1548 (*params
)[(*nparam
)++] = t
;
1549 while (tok_isnt_(t
, brace
? "}" : ","))
1551 if (t
) { /* got a comma/brace */
1555 * Now we've found the closing brace, look further
1559 if (tok_isnt_(t
, ",")) {
1561 "braces do not enclose all of macro parameter");
1562 while (tok_isnt_(t
, ","))
1566 t
= t
->next
; /* eat the comma */
1573 * Determine whether one of the various `if' conditions is true or
1576 * We must free the tline we get passed.
1578 static bool if_condition(Token
* tline
, enum preproc_token ct
)
1580 enum pp_conditional i
= PP_COND(ct
);
1582 Token
*t
, *tt
, **tptr
, *origline
;
1583 struct tokenval tokval
;
1585 enum pp_token_type needtype
;
1591 j
= false; /* have we matched yet? */
1596 if (tline
->type
!= TOK_ID
) {
1598 "`%s' expects context identifiers", pp_directives
[ct
]);
1599 free_tlist(origline
);
1602 if (cstk
&& cstk
->name
&& !nasm_stricmp(tline
->text
, cstk
->name
))
1604 tline
= tline
->next
;
1609 j
= false; /* have we matched yet? */
1612 if (!tline
|| (tline
->type
!= TOK_ID
&&
1613 (tline
->type
!= TOK_PREPROC_ID
||
1614 tline
->text
[1] != '$'))) {
1616 "`%s' expects macro identifiers", pp_directives
[ct
]);
1619 if (smacro_defined(NULL
, tline
->text
, 0, NULL
, true))
1621 tline
= tline
->next
;
1627 tline
= expand_smacro(tline
);
1629 while (tok_isnt_(tt
, ","))
1633 "`%s' expects two comma-separated arguments",
1638 j
= true; /* assume equality unless proved not */
1639 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1640 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1641 error(ERR_NONFATAL
, "`%s': more than one comma on line",
1645 if (t
->type
== TOK_WHITESPACE
) {
1649 if (tt
->type
== TOK_WHITESPACE
) {
1653 if (tt
->type
!= t
->type
) {
1654 j
= false; /* found mismatching tokens */
1657 /* When comparing strings, need to unquote them first */
1658 if (t
->type
== TOK_STRING
) {
1659 size_t l1
= nasm_unquote(t
->text
, NULL
);
1660 size_t l2
= nasm_unquote(tt
->text
, NULL
);
1666 if (mmemcmp(t
->text
, tt
->text
, l1
, i
== PPC_IFIDN
)) {
1670 } else if (mstrcmp(tt
->text
, t
->text
, i
== PPC_IFIDN
) != 0) {
1671 j
= false; /* found mismatching tokens */
1678 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
1679 j
= false; /* trailing gunk on one end or other */
1685 MMacro searching
, *mmac
;
1688 tline
= expand_id(tline
);
1689 if (!tok_type_(tline
, TOK_ID
)) {
1691 "`%s' expects a macro name", pp_directives
[ct
]);
1694 searching
.name
= nasm_strdup(tline
->text
);
1695 searching
.casesense
= true;
1696 searching
.plus
= false;
1697 searching
.nolist
= false;
1698 searching
.in_progress
= 0;
1699 searching
.max_depth
= 0;
1700 searching
.rep_nest
= NULL
;
1701 searching
.nparam_min
= 0;
1702 searching
.nparam_max
= INT_MAX
;
1703 tline
= expand_smacro(tline
->next
);
1706 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
1708 "`%s' expects a parameter count or nothing",
1711 searching
.nparam_min
= searching
.nparam_max
=
1712 readnum(tline
->text
, &j
);
1715 "unable to parse parameter count `%s'",
1718 if (tline
&& tok_is_(tline
->next
, "-")) {
1719 tline
= tline
->next
->next
;
1720 if (tok_is_(tline
, "*"))
1721 searching
.nparam_max
= INT_MAX
;
1722 else if (!tok_type_(tline
, TOK_NUMBER
))
1724 "`%s' expects a parameter count after `-'",
1727 searching
.nparam_max
= readnum(tline
->text
, &j
);
1730 "unable to parse parameter count `%s'",
1732 if (searching
.nparam_min
> searching
.nparam_max
)
1734 "minimum parameter count exceeds maximum");
1737 if (tline
&& tok_is_(tline
->next
, "+")) {
1738 tline
= tline
->next
;
1739 searching
.plus
= true;
1741 mmac
= (MMacro
*) hash_findix(&mmacros
, searching
.name
);
1743 if (!strcmp(mmac
->name
, searching
.name
) &&
1744 (mmac
->nparam_min
<= searching
.nparam_max
1746 && (searching
.nparam_min
<= mmac
->nparam_max
1753 if (tline
&& tline
->next
)
1754 error(ERR_WARNING
|ERR_PASS1
,
1755 "trailing garbage after %%ifmacro ignored");
1756 nasm_free(searching
.name
);
1765 needtype
= TOK_NUMBER
;
1768 needtype
= TOK_STRING
;
1772 t
= tline
= expand_smacro(tline
);
1774 while (tok_type_(t
, TOK_WHITESPACE
) ||
1775 (needtype
== TOK_NUMBER
&&
1776 tok_type_(t
, TOK_OTHER
) &&
1777 (t
->text
[0] == '-' || t
->text
[0] == '+') &&
1781 j
= tok_type_(t
, needtype
);
1785 t
= tline
= expand_smacro(tline
);
1786 while (tok_type_(t
, TOK_WHITESPACE
))
1791 t
= t
->next
; /* Skip the actual token */
1792 while (tok_type_(t
, TOK_WHITESPACE
))
1794 j
= !t
; /* Should be nothing left */
1799 t
= tline
= expand_smacro(tline
);
1800 while (tok_type_(t
, TOK_WHITESPACE
))
1803 j
= !t
; /* Should be empty */
1807 t
= tline
= expand_smacro(tline
);
1809 tokval
.t_type
= TOKEN_INVALID
;
1810 evalresult
= evaluate(ppscan
, tptr
, &tokval
,
1811 NULL
, pass
| CRITICAL
, error
, NULL
);
1815 error(ERR_WARNING
|ERR_PASS1
,
1816 "trailing garbage after expression ignored");
1817 if (!is_simple(evalresult
)) {
1819 "non-constant value given to `%s'", pp_directives
[ct
]);
1822 j
= reloc_value(evalresult
) != 0;
1827 "preprocessor directive `%s' not yet implemented",
1832 free_tlist(origline
);
1833 return j
^ PP_NEGATIVE(ct
);
1836 free_tlist(origline
);
1841 * Common code for defining an smacro
1843 static bool define_smacro(Context
*ctx
, const char *mname
, bool casesense
,
1844 int nparam
, Token
*expansion
)
1846 SMacro
*smac
, **smhead
;
1847 struct hash_table
*smtbl
;
1849 if (smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
)) {
1851 error(ERR_WARNING
|ERR_PASS1
,
1852 "single-line macro `%s' defined both with and"
1853 " without parameters", mname
);
1855 /* Some instances of the old code considered this a failure,
1856 some others didn't. What is the right thing to do here? */
1857 free_tlist(expansion
);
1858 return false; /* Failure */
1861 * We're redefining, so we have to take over an
1862 * existing SMacro structure. This means freeing
1863 * what was already in it.
1865 nasm_free(smac
->name
);
1866 free_tlist(smac
->expansion
);
1869 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
1870 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
1871 smac
= nasm_malloc(sizeof(SMacro
));
1872 smac
->next
= *smhead
;
1875 smac
->name
= nasm_strdup(mname
);
1876 smac
->casesense
= casesense
;
1877 smac
->nparam
= nparam
;
1878 smac
->expansion
= expansion
;
1879 smac
->in_progress
= false;
1880 return true; /* Success */
1884 * Undefine an smacro
1886 static void undef_smacro(Context
*ctx
, const char *mname
)
1888 SMacro
**smhead
, *s
, **sp
;
1889 struct hash_table
*smtbl
;
1891 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
1892 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
1896 * We now have a macro name... go hunt for it.
1899 while ((s
= *sp
) != NULL
) {
1900 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
1903 free_tlist(s
->expansion
);
1913 * Parse a mmacro specification.
1915 static bool parse_mmacro_spec(Token
*tline
, MMacro
*def
, const char *directive
)
1919 tline
= tline
->next
;
1921 tline
= expand_id(tline
);
1922 if (!tok_type_(tline
, TOK_ID
)) {
1923 error(ERR_NONFATAL
, "`%s' expects a macro name", directive
);
1928 def
->name
= nasm_strdup(tline
->text
);
1930 def
->nolist
= false;
1931 def
->in_progress
= 0;
1932 def
->rep_nest
= NULL
;
1933 def
->nparam_min
= 0;
1934 def
->nparam_max
= 0;
1936 tline
= expand_smacro(tline
->next
);
1938 if (!tok_type_(tline
, TOK_NUMBER
)) {
1939 error(ERR_NONFATAL
, "`%s' expects a parameter count", directive
);
1941 def
->nparam_min
= def
->nparam_max
=
1942 readnum(tline
->text
, &err
);
1945 "unable to parse parameter count `%s'", tline
->text
);
1947 if (tline
&& tok_is_(tline
->next
, "-")) {
1948 tline
= tline
->next
->next
;
1949 if (tok_is_(tline
, "*")) {
1950 def
->nparam_max
= INT_MAX
;
1951 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
1953 "`%s' expects a parameter count after `-'", directive
);
1955 def
->nparam_max
= readnum(tline
->text
, &err
);
1957 error(ERR_NONFATAL
, "unable to parse parameter count `%s'",
1960 if (def
->nparam_min
> def
->nparam_max
) {
1961 error(ERR_NONFATAL
, "minimum parameter count exceeds maximum");
1965 if (tline
&& tok_is_(tline
->next
, "+")) {
1966 tline
= tline
->next
;
1969 if (tline
&& tok_type_(tline
->next
, TOK_ID
) &&
1970 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
1971 tline
= tline
->next
;
1976 * Handle default parameters.
1978 if (tline
&& tline
->next
) {
1979 def
->dlist
= tline
->next
;
1981 count_mmac_params(def
->dlist
, &def
->ndefs
, &def
->defaults
);
1984 def
->defaults
= NULL
;
1986 def
->expansion
= NULL
;
1988 if (def
->defaults
&& def
->ndefs
> def
->nparam_max
- def
->nparam_min
&&
1990 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MDP
,
1991 "too many default macro parameters");
1998 * Decode a size directive
2000 static int parse_size(const char *str
) {
2001 static const char *size_names
[] =
2002 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2003 static const int sizes
[] =
2004 { 0, 1, 4, 16, 8, 10, 2, 32 };
2006 return sizes
[bsii(str
, size_names
, elements(size_names
))+1];
2010 * nasm_unquote with error if the string contains NUL characters.
2011 * If the string contains NUL characters, issue an error and return
2012 * the C len, i.e. truncate at the NUL.
2014 static size_t nasm_unquote_cstr(char *qstr
, enum preproc_token directive
)
2016 size_t len
= nasm_unquote(qstr
, NULL
);
2017 size_t clen
= strlen(qstr
);
2020 error(ERR_NONFATAL
, "NUL character in `%s' directive",
2021 pp_directives
[directive
]);
2027 * find and process preprocessor directive in passed line
2028 * Find out if a line contains a preprocessor directive, and deal
2031 * If a directive _is_ found, it is the responsibility of this routine
2032 * (and not the caller) to free_tlist() the line.
2034 * @param tline a pointer to the current tokeninzed line linked list
2035 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2038 static int do_directive(Token
* tline
)
2040 enum preproc_token i
;
2053 MMacro
*mmac
, **mmhead
;
2054 Token
*t
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
2056 struct tokenval tokval
;
2058 MMacro
*tmp_defining
; /* Used when manipulating rep_nest */
2066 if (!tline
|| !tok_type_(tline
, TOK_PREPROC_ID
) ||
2067 (tline
->text
[1] == '%' || tline
->text
[1] == '$'
2068 || tline
->text
[1] == '!'))
2069 return NO_DIRECTIVE_FOUND
;
2071 i
= pp_token_hash(tline
->text
);
2074 * If we're in a non-emitting branch of a condition construct,
2075 * or walking to the end of an already terminated %rep block,
2076 * we should ignore all directives except for condition
2079 if (((istk
->conds
&& !emitting(istk
->conds
->state
)) ||
2080 (istk
->mstk
&& !istk
->mstk
->in_progress
)) && !is_condition(i
)) {
2081 return NO_DIRECTIVE_FOUND
;
2085 * If we're defining a macro or reading a %rep block, we should
2086 * ignore all directives except for %macro/%imacro (which nest),
2087 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2088 * If we're in a %rep block, another %rep nests, so should be let through.
2090 if (defining
&& i
!= PP_MACRO
&& i
!= PP_IMACRO
&&
2091 i
!= PP_RMACRO
&& i
!= PP_IRMACRO
&&
2092 i
!= PP_ENDMACRO
&& i
!= PP_ENDM
&&
2093 (defining
->name
|| (i
!= PP_ENDREP
&& i
!= PP_REP
))) {
2094 return NO_DIRECTIVE_FOUND
;
2098 if (i
== PP_MACRO
|| i
== PP_IMACRO
||
2099 i
== PP_RMACRO
|| i
== PP_IRMACRO
) {
2101 return NO_DIRECTIVE_FOUND
;
2102 } else if (nested_mac_count
> 0) {
2103 if (i
== PP_ENDMACRO
) {
2105 return NO_DIRECTIVE_FOUND
;
2108 if (!defining
->name
) {
2111 return NO_DIRECTIVE_FOUND
;
2112 } else if (nested_rep_count
> 0) {
2113 if (i
== PP_ENDREP
) {
2115 return NO_DIRECTIVE_FOUND
;
2123 error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2125 return NO_DIRECTIVE_FOUND
; /* didn't get it */
2128 /* Directive to tell NASM what the default stack size is. The
2129 * default is for a 16-bit stack, and this can be overriden with
2131 * the following form:
2133 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2135 tline
= tline
->next
;
2136 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2137 tline
= tline
->next
;
2138 if (!tline
|| tline
->type
!= TOK_ID
) {
2139 error(ERR_NONFATAL
, "`%%stacksize' missing size parameter");
2140 free_tlist(origline
);
2141 return DIRECTIVE_FOUND
;
2143 if (nasm_stricmp(tline
->text
, "flat") == 0) {
2144 /* All subsequent ARG directives are for a 32-bit stack */
2146 StackPointer
= "ebp";
2149 } else if (nasm_stricmp(tline
->text
, "flat64") == 0) {
2150 /* All subsequent ARG directives are for a 64-bit stack */
2152 StackPointer
= "rbp";
2155 } else if (nasm_stricmp(tline
->text
, "large") == 0) {
2156 /* All subsequent ARG directives are for a 16-bit stack,
2157 * far function call.
2160 StackPointer
= "bp";
2163 } else if (nasm_stricmp(tline
->text
, "small") == 0) {
2164 /* All subsequent ARG directives are for a 16-bit stack,
2165 * far function call. We don't support near functions.
2168 StackPointer
= "bp";
2172 error(ERR_NONFATAL
, "`%%stacksize' invalid size type");
2173 free_tlist(origline
);
2174 return DIRECTIVE_FOUND
;
2176 free_tlist(origline
);
2177 return DIRECTIVE_FOUND
;
2180 /* TASM like ARG directive to define arguments to functions, in
2181 * the following form:
2183 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2187 char *arg
, directive
[256];
2188 int size
= StackSize
;
2190 /* Find the argument name */
2191 tline
= tline
->next
;
2192 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2193 tline
= tline
->next
;
2194 if (!tline
|| tline
->type
!= TOK_ID
) {
2195 error(ERR_NONFATAL
, "`%%arg' missing argument parameter");
2196 free_tlist(origline
);
2197 return DIRECTIVE_FOUND
;
2201 /* Find the argument size type */
2202 tline
= tline
->next
;
2203 if (!tline
|| tline
->type
!= TOK_OTHER
2204 || tline
->text
[0] != ':') {
2206 "Syntax error processing `%%arg' directive");
2207 free_tlist(origline
);
2208 return DIRECTIVE_FOUND
;
2210 tline
= tline
->next
;
2211 if (!tline
|| tline
->type
!= TOK_ID
) {
2212 error(ERR_NONFATAL
, "`%%arg' missing size type parameter");
2213 free_tlist(origline
);
2214 return DIRECTIVE_FOUND
;
2217 /* Allow macro expansion of type parameter */
2218 tt
= tokenize(tline
->text
);
2219 tt
= expand_smacro(tt
);
2220 size
= parse_size(tt
->text
);
2223 "Invalid size type for `%%arg' missing directive");
2225 free_tlist(origline
);
2226 return DIRECTIVE_FOUND
;
2230 /* Round up to even stack slots */
2231 size
= (size
+StackSize
-1) & ~(StackSize
-1);
2233 /* Now define the macro for the argument */
2234 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
2235 arg
, StackPointer
, offset
);
2236 do_directive(tokenize(directive
));
2239 /* Move to the next argument in the list */
2240 tline
= tline
->next
;
2241 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2242 tline
= tline
->next
;
2243 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2245 free_tlist(origline
);
2246 return DIRECTIVE_FOUND
;
2249 /* TASM like LOCAL directive to define local variables for a
2250 * function, in the following form:
2252 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2254 * The '= LocalSize' at the end is ignored by NASM, but is
2255 * required by TASM to define the local parameter size (and used
2256 * by the TASM macro package).
2258 offset
= LocalOffset
;
2260 char *local
, directive
[256];
2261 int size
= StackSize
;
2263 /* Find the argument name */
2264 tline
= tline
->next
;
2265 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2266 tline
= tline
->next
;
2267 if (!tline
|| tline
->type
!= TOK_ID
) {
2269 "`%%local' missing argument parameter");
2270 free_tlist(origline
);
2271 return DIRECTIVE_FOUND
;
2273 local
= tline
->text
;
2275 /* Find the argument size type */
2276 tline
= tline
->next
;
2277 if (!tline
|| tline
->type
!= TOK_OTHER
2278 || tline
->text
[0] != ':') {
2280 "Syntax error processing `%%local' directive");
2281 free_tlist(origline
);
2282 return DIRECTIVE_FOUND
;
2284 tline
= tline
->next
;
2285 if (!tline
|| tline
->type
!= TOK_ID
) {
2287 "`%%local' missing size type parameter");
2288 free_tlist(origline
);
2289 return DIRECTIVE_FOUND
;
2292 /* Allow macro expansion of type parameter */
2293 tt
= tokenize(tline
->text
);
2294 tt
= expand_smacro(tt
);
2295 size
= parse_size(tt
->text
);
2298 "Invalid size type for `%%local' missing directive");
2300 free_tlist(origline
);
2301 return DIRECTIVE_FOUND
;
2305 /* Round up to even stack slots */
2306 size
= (size
+StackSize
-1) & ~(StackSize
-1);
2308 offset
+= size
; /* Negative offset, increment before */
2310 /* Now define the macro for the argument */
2311 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
2312 local
, StackPointer
, offset
);
2313 do_directive(tokenize(directive
));
2315 /* Now define the assign to setup the enter_c macro correctly */
2316 snprintf(directive
, sizeof(directive
),
2317 "%%assign %%$localsize %%$localsize+%d", size
);
2318 do_directive(tokenize(directive
));
2320 /* Move to the next argument in the list */
2321 tline
= tline
->next
;
2322 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2323 tline
= tline
->next
;
2324 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2325 LocalOffset
= offset
;
2326 free_tlist(origline
);
2327 return DIRECTIVE_FOUND
;
2331 error(ERR_WARNING
|ERR_PASS1
,
2332 "trailing garbage after `%%clear' ignored");
2335 free_tlist(origline
);
2336 return DIRECTIVE_FOUND
;
2339 t
= tline
->next
= expand_smacro(tline
->next
);
2341 if (!t
|| (t
->type
!= TOK_STRING
&&
2342 t
->type
!= TOK_INTERNAL_STRING
)) {
2343 error(ERR_NONFATAL
, "`%%depend' expects a file name");
2344 free_tlist(origline
);
2345 return DIRECTIVE_FOUND
; /* but we did _something_ */
2348 error(ERR_WARNING
|ERR_PASS1
,
2349 "trailing garbage after `%%depend' ignored");
2351 if (t
->type
!= TOK_INTERNAL_STRING
)
2352 nasm_unquote_cstr(p
, i
);
2353 if (dephead
&& !in_list(*dephead
, p
)) {
2354 StrList
*sl
= nasm_malloc(strlen(p
)+1+sizeof sl
->next
);
2358 deptail
= &sl
->next
;
2360 free_tlist(origline
);
2361 return DIRECTIVE_FOUND
;
2364 t
= tline
->next
= expand_smacro(tline
->next
);
2367 if (!t
|| (t
->type
!= TOK_STRING
&&
2368 t
->type
!= TOK_INTERNAL_STRING
)) {
2369 error(ERR_NONFATAL
, "`%%include' expects a file name");
2370 free_tlist(origline
);
2371 return DIRECTIVE_FOUND
; /* but we did _something_ */
2374 error(ERR_WARNING
|ERR_PASS1
,
2375 "trailing garbage after `%%include' ignored");
2377 if (t
->type
!= TOK_INTERNAL_STRING
)
2378 nasm_unquote_cstr(p
, i
);
2379 inc
= nasm_malloc(sizeof(Include
));
2382 inc
->fp
= inc_fopen(p
, dephead
, &deptail
, pass
== 0);
2384 /* -MG given but file not found */
2387 inc
->fname
= src_set_fname(nasm_strdup(p
));
2388 inc
->lineno
= src_set_linnum(0);
2390 inc
->expansion
= NULL
;
2393 list
->uplevel(LIST_INCLUDE
);
2395 free_tlist(origline
);
2396 return DIRECTIVE_FOUND
;
2400 static macros_t
*use_pkg
;
2401 const char *pkg_macro
;
2403 tline
= tline
->next
;
2405 tline
= expand_id(tline
);
2407 if (!tline
|| (tline
->type
!= TOK_STRING
&&
2408 tline
->type
!= TOK_INTERNAL_STRING
&&
2409 tline
->type
!= TOK_ID
)) {
2410 error(ERR_NONFATAL
, "`%%use' expects a package name");
2411 free_tlist(origline
);
2412 return DIRECTIVE_FOUND
; /* but we did _something_ */
2415 error(ERR_WARNING
|ERR_PASS1
,
2416 "trailing garbage after `%%use' ignored");
2417 if (tline
->type
== TOK_STRING
)
2418 nasm_unquote_cstr(tline
->text
, i
);
2419 use_pkg
= nasm_stdmac_find_package(tline
->text
);
2421 error(ERR_NONFATAL
, "unknown `%%use' package: %s", tline
->text
);
2422 /* The first string will be <%define>__USE_*__ */
2423 pkg_macro
= (char *)use_pkg
+ 1;
2424 if (!smacro_defined(NULL
, pkg_macro
, 0, NULL
, true)) {
2425 /* Not already included, go ahead and include it */
2426 stdmacpos
= use_pkg
;
2428 free_tlist(origline
);
2429 return DIRECTIVE_FOUND
;
2434 tline
= tline
->next
;
2436 tline
= expand_id(tline
);
2438 if (!tok_type_(tline
, TOK_ID
)) {
2439 error(ERR_NONFATAL
, "`%s' expects a context identifier",
2441 free_tlist(origline
);
2442 return DIRECTIVE_FOUND
; /* but we did _something_ */
2445 error(ERR_WARNING
|ERR_PASS1
,
2446 "trailing garbage after `%s' ignored",
2448 p
= nasm_strdup(tline
->text
);
2450 p
= NULL
; /* Anonymous */
2454 ctx
= nasm_malloc(sizeof(Context
));
2456 hash_init(&ctx
->localmac
, HASH_SMALL
);
2458 ctx
->number
= unique
++;
2463 error(ERR_NONFATAL
, "`%s': context stack is empty",
2465 } else if (i
== PP_POP
) {
2466 if (p
&& (!cstk
->name
|| nasm_stricmp(p
, cstk
->name
)))
2467 error(ERR_NONFATAL
, "`%%pop' in wrong context: %s, "
2469 cstk
->name
? cstk
->name
: "anonymous", p
);
2474 nasm_free(cstk
->name
);
2480 free_tlist(origline
);
2481 return DIRECTIVE_FOUND
;
2483 severity
= ERR_FATAL
;
2486 severity
= ERR_NONFATAL
;
2489 severity
= ERR_WARNING
|ERR_WARN_USER
;
2494 /* Only error out if this is the final pass */
2495 if (pass
!= 2 && i
!= PP_FATAL
)
2496 return DIRECTIVE_FOUND
;
2498 tline
->next
= expand_smacro(tline
->next
);
2499 tline
= tline
->next
;
2501 t
= tline
? tline
->next
: NULL
;
2503 if (tok_type_(tline
, TOK_STRING
) && !t
) {
2504 /* The line contains only a quoted string */
2506 nasm_unquote(p
, NULL
); /* Ignore NUL character truncation */
2507 error(severity
, "%s", p
);
2509 /* Not a quoted string, or more than a quoted string */
2510 p
= detoken(tline
, false);
2511 error(severity
, "%s", p
);
2514 free_tlist(origline
);
2515 return DIRECTIVE_FOUND
;
2519 if (istk
->conds
&& !emitting(istk
->conds
->state
))
2522 j
= if_condition(tline
->next
, i
);
2523 tline
->next
= NULL
; /* it got freed */
2524 j
= j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2526 cond
= nasm_malloc(sizeof(Cond
));
2527 cond
->next
= istk
->conds
;
2531 istk
->mstk
->condcnt
++;
2532 free_tlist(origline
);
2533 return DIRECTIVE_FOUND
;
2537 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2538 switch(istk
->conds
->state
) {
2540 istk
->conds
->state
= COND_DONE
;
2547 case COND_ELSE_TRUE
:
2548 case COND_ELSE_FALSE
:
2549 error_precond(ERR_WARNING
|ERR_PASS1
,
2550 "`%%elif' after `%%else' ignored");
2551 istk
->conds
->state
= COND_NEVER
;
2556 * IMPORTANT: In the case of %if, we will already have
2557 * called expand_mmac_params(); however, if we're
2558 * processing an %elif we must have been in a
2559 * non-emitting mode, which would have inhibited
2560 * the normal invocation of expand_mmac_params().
2561 * Therefore, we have to do it explicitly here.
2563 j
= if_condition(expand_mmac_params(tline
->next
), i
);
2564 tline
->next
= NULL
; /* it got freed */
2565 istk
->conds
->state
=
2566 j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2569 free_tlist(origline
);
2570 return DIRECTIVE_FOUND
;
2574 error_precond(ERR_WARNING
|ERR_PASS1
,
2575 "trailing garbage after `%%else' ignored");
2577 error(ERR_FATAL
, "`%%else': no matching `%%if'");
2578 switch(istk
->conds
->state
) {
2581 istk
->conds
->state
= COND_ELSE_FALSE
;
2588 istk
->conds
->state
= COND_ELSE_TRUE
;
2591 case COND_ELSE_TRUE
:
2592 case COND_ELSE_FALSE
:
2593 error_precond(ERR_WARNING
|ERR_PASS1
,
2594 "`%%else' after `%%else' ignored.");
2595 istk
->conds
->state
= COND_NEVER
;
2598 free_tlist(origline
);
2599 return DIRECTIVE_FOUND
;
2603 error_precond(ERR_WARNING
|ERR_PASS1
,
2604 "trailing garbage after `%%endif' ignored");
2606 error(ERR_FATAL
, "`%%endif': no matching `%%if'");
2608 istk
->conds
= cond
->next
;
2611 istk
->mstk
->condcnt
--;
2612 free_tlist(origline
);
2613 return DIRECTIVE_FOUND
;
2620 error(ERR_FATAL
, "`%s': already defining a macro",
2622 return DIRECTIVE_FOUND
;
2624 defining
= nasm_malloc(sizeof(MMacro
));
2625 defining
->max_depth
=
2626 (i
== PP_RMACRO
) || (i
== PP_IRMACRO
) ? DEADMAN_LIMIT
: 0;
2627 defining
->casesense
= (i
== PP_MACRO
) || (i
== PP_RMACRO
);
2628 if (!parse_mmacro_spec(tline
, defining
, pp_directives
[i
])) {
2629 nasm_free(defining
);
2631 return DIRECTIVE_FOUND
;
2634 mmac
= (MMacro
*) hash_findix(&mmacros
, defining
->name
);
2636 if (!strcmp(mmac
->name
, defining
->name
) &&
2637 (mmac
->nparam_min
<= defining
->nparam_max
2639 && (defining
->nparam_min
<= mmac
->nparam_max
2641 error(ERR_WARNING
|ERR_PASS1
,
2642 "redefining multi-line macro `%s'", defining
->name
);
2643 return DIRECTIVE_FOUND
;
2647 free_tlist(origline
);
2648 return DIRECTIVE_FOUND
;
2652 if (! (defining
&& defining
->name
)) {
2653 error(ERR_NONFATAL
, "`%s': not defining a macro", tline
->text
);
2654 return DIRECTIVE_FOUND
;
2656 mmhead
= (MMacro
**) hash_findi_add(&mmacros
, defining
->name
);
2657 defining
->next
= *mmhead
;
2660 free_tlist(origline
);
2661 return DIRECTIVE_FOUND
;
2665 * We must search along istk->expansion until we hit a
2666 * macro-end marker for a macro with a name. Then we
2667 * bypass all lines between exitmacro and endmacro.
2669 for (l
= istk
->expansion
; l
; l
= l
->next
)
2670 if (l
->finishes
&& l
->finishes
->name
)
2675 * Remove all conditional entries relative to this
2676 * macro invocation. (safe to do in this context)
2678 for ( ; l
->finishes
->condcnt
> 0; l
->finishes
->condcnt
--) {
2680 istk
->conds
= cond
->next
;
2683 istk
->expansion
= l
;
2685 error(ERR_NONFATAL
, "`%%exitmacro' not within `%%macro' block");
2687 free_tlist(origline
);
2688 return DIRECTIVE_FOUND
;
2696 spec
.casesense
= (i
== PP_UNMACRO
);
2697 if (!parse_mmacro_spec(tline
, &spec
, pp_directives
[i
])) {
2698 return DIRECTIVE_FOUND
;
2700 mmac_p
= (MMacro
**) hash_findi(&mmacros
, spec
.name
, NULL
);
2701 while (mmac_p
&& *mmac_p
) {
2703 if (mmac
->casesense
== spec
.casesense
&&
2704 !mstrcmp(mmac
->name
, spec
.name
, spec
.casesense
) &&
2705 mmac
->nparam_min
== spec
.nparam_min
&&
2706 mmac
->nparam_max
== spec
.nparam_max
&&
2707 mmac
->plus
== spec
.plus
) {
2708 *mmac_p
= mmac
->next
;
2711 mmac_p
= &mmac
->next
;
2714 free_tlist(origline
);
2715 free_tlist(spec
.dlist
);
2716 return DIRECTIVE_FOUND
;
2720 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
2721 tline
= tline
->next
;
2723 free_tlist(origline
);
2724 error(ERR_NONFATAL
, "`%%rotate' missing rotate count");
2725 return DIRECTIVE_FOUND
;
2727 t
= expand_smacro(tline
->next
);
2729 free_tlist(origline
);
2732 tokval
.t_type
= TOKEN_INVALID
;
2734 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
2737 return DIRECTIVE_FOUND
;
2739 error(ERR_WARNING
|ERR_PASS1
,
2740 "trailing garbage after expression ignored");
2741 if (!is_simple(evalresult
)) {
2742 error(ERR_NONFATAL
, "non-constant value given to `%%rotate'");
2743 return DIRECTIVE_FOUND
;
2746 while (mmac
&& !mmac
->name
) /* avoid mistaking %reps for macros */
2747 mmac
= mmac
->next_active
;
2749 error(ERR_NONFATAL
, "`%%rotate' invoked outside a macro call");
2750 } else if (mmac
->nparam
== 0) {
2752 "`%%rotate' invoked within macro without parameters");
2754 int rotate
= mmac
->rotate
+ reloc_value(evalresult
);
2756 rotate
%= (int)mmac
->nparam
;
2758 rotate
+= mmac
->nparam
;
2760 mmac
->rotate
= rotate
;
2762 return DIRECTIVE_FOUND
;
2767 tline
= tline
->next
;
2768 } while (tok_type_(tline
, TOK_WHITESPACE
));
2770 if (tok_type_(tline
, TOK_ID
) &&
2771 nasm_stricmp(tline
->text
, ".nolist") == 0) {
2774 tline
= tline
->next
;
2775 } while (tok_type_(tline
, TOK_WHITESPACE
));
2779 t
= expand_smacro(tline
);
2781 tokval
.t_type
= TOKEN_INVALID
;
2783 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
2785 free_tlist(origline
);
2786 return DIRECTIVE_FOUND
;
2789 error(ERR_WARNING
|ERR_PASS1
,
2790 "trailing garbage after expression ignored");
2791 if (!is_simple(evalresult
)) {
2792 error(ERR_NONFATAL
, "non-constant value given to `%%rep'");
2793 return DIRECTIVE_FOUND
;
2795 count
= reloc_value(evalresult
) + 1;
2797 error(ERR_NONFATAL
, "`%%rep' expects a repeat count");
2800 free_tlist(origline
);
2802 tmp_defining
= defining
;
2803 defining
= nasm_malloc(sizeof(MMacro
));
2804 defining
->prev
= NULL
;
2805 defining
->name
= NULL
; /* flags this macro as a %rep block */
2806 defining
->casesense
= false;
2807 defining
->plus
= false;
2808 defining
->nolist
= nolist
;
2809 defining
->in_progress
= count
;
2810 defining
->max_depth
= 0;
2811 defining
->nparam_min
= defining
->nparam_max
= 0;
2812 defining
->defaults
= NULL
;
2813 defining
->dlist
= NULL
;
2814 defining
->expansion
= NULL
;
2815 defining
->next_active
= istk
->mstk
;
2816 defining
->rep_nest
= tmp_defining
;
2817 return DIRECTIVE_FOUND
;
2820 if (!defining
|| defining
->name
) {
2821 error(ERR_NONFATAL
, "`%%endrep': no matching `%%rep'");
2822 return DIRECTIVE_FOUND
;
2826 * Now we have a "macro" defined - although it has no name
2827 * and we won't be entering it in the hash tables - we must
2828 * push a macro-end marker for it on to istk->expansion.
2829 * After that, it will take care of propagating itself (a
2830 * macro-end marker line for a macro which is really a %rep
2831 * block will cause the macro to be re-expanded, complete
2832 * with another macro-end marker to ensure the process
2833 * continues) until the whole expansion is forcibly removed
2834 * from istk->expansion by a %exitrep.
2836 l
= nasm_malloc(sizeof(Line
));
2837 l
->next
= istk
->expansion
;
2838 l
->finishes
= defining
;
2840 istk
->expansion
= l
;
2842 istk
->mstk
= defining
;
2844 list
->uplevel(defining
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
2845 tmp_defining
= defining
;
2846 defining
= defining
->rep_nest
;
2847 free_tlist(origline
);
2848 return DIRECTIVE_FOUND
;
2852 * We must search along istk->expansion until we hit a
2853 * macro-end marker for a macro with no name. Then we set
2854 * its `in_progress' flag to 0.
2856 for (l
= istk
->expansion
; l
; l
= l
->next
)
2857 if (l
->finishes
&& !l
->finishes
->name
)
2861 l
->finishes
->in_progress
= 1;
2863 error(ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
2864 free_tlist(origline
);
2865 return DIRECTIVE_FOUND
;
2871 casesense
= (i
== PP_DEFINE
|| i
== PP_XDEFINE
);
2873 tline
= tline
->next
;
2875 tline
= expand_id(tline
);
2876 if (!tline
|| (tline
->type
!= TOK_ID
&&
2877 (tline
->type
!= TOK_PREPROC_ID
||
2878 tline
->text
[1] != '$'))) {
2879 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
2881 free_tlist(origline
);
2882 return DIRECTIVE_FOUND
;
2885 ctx
= get_ctx(tline
->text
, &mname
, false);
2887 param_start
= tline
= tline
->next
;
2890 /* Expand the macro definition now for %xdefine and %ixdefine */
2891 if ((i
== PP_XDEFINE
) || (i
== PP_IXDEFINE
))
2892 tline
= expand_smacro(tline
);
2894 if (tok_is_(tline
, "(")) {
2896 * This macro has parameters.
2899 tline
= tline
->next
;
2903 error(ERR_NONFATAL
, "parameter identifier expected");
2904 free_tlist(origline
);
2905 return DIRECTIVE_FOUND
;
2907 if (tline
->type
!= TOK_ID
) {
2909 "`%s': parameter identifier expected",
2911 free_tlist(origline
);
2912 return DIRECTIVE_FOUND
;
2914 tline
->type
= TOK_SMAC_PARAM
+ nparam
++;
2915 tline
= tline
->next
;
2917 if (tok_is_(tline
, ",")) {
2918 tline
= tline
->next
;
2920 if (!tok_is_(tline
, ")")) {
2922 "`)' expected to terminate macro template");
2923 free_tlist(origline
);
2924 return DIRECTIVE_FOUND
;
2930 tline
= tline
->next
;
2932 if (tok_type_(tline
, TOK_WHITESPACE
))
2933 last
= tline
, tline
= tline
->next
;
2938 if (t
->type
== TOK_ID
) {
2939 for (tt
= param_start
; tt
; tt
= tt
->next
)
2940 if (tt
->type
>= TOK_SMAC_PARAM
&&
2941 !strcmp(tt
->text
, t
->text
))
2945 t
->next
= macro_start
;
2950 * Good. We now have a macro name, a parameter count, and a
2951 * token list (in reverse order) for an expansion. We ought
2952 * to be OK just to create an SMacro, store it, and let
2953 * free_tlist have the rest of the line (which we have
2954 * carefully re-terminated after chopping off the expansion
2957 define_smacro(ctx
, mname
, casesense
, nparam
, macro_start
);
2958 free_tlist(origline
);
2959 return DIRECTIVE_FOUND
;
2962 tline
= tline
->next
;
2964 tline
= expand_id(tline
);
2965 if (!tline
|| (tline
->type
!= TOK_ID
&&
2966 (tline
->type
!= TOK_PREPROC_ID
||
2967 tline
->text
[1] != '$'))) {
2968 error(ERR_NONFATAL
, "`%%undef' expects a macro identifier");
2969 free_tlist(origline
);
2970 return DIRECTIVE_FOUND
;
2973 error(ERR_WARNING
|ERR_PASS1
,
2974 "trailing garbage after macro name ignored");
2977 /* Find the context that symbol belongs to */
2978 ctx
= get_ctx(tline
->text
, &mname
, false);
2979 undef_smacro(ctx
, mname
);
2980 free_tlist(origline
);
2981 return DIRECTIVE_FOUND
;
2985 casesense
= (i
== PP_DEFSTR
);
2987 tline
= tline
->next
;
2989 tline
= expand_id(tline
);
2990 if (!tline
|| (tline
->type
!= TOK_ID
&&
2991 (tline
->type
!= TOK_PREPROC_ID
||
2992 tline
->text
[1] != '$'))) {
2993 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
2995 free_tlist(origline
);
2996 return DIRECTIVE_FOUND
;
2999 ctx
= get_ctx(tline
->text
, &mname
, false);
3001 tline
= expand_smacro(tline
->next
);
3004 while (tok_type_(tline
, TOK_WHITESPACE
))
3005 tline
= delete_Token(tline
);
3007 p
= detoken(tline
, false);
3008 macro_start
= nasm_malloc(sizeof(*macro_start
));
3009 macro_start
->next
= NULL
;
3010 macro_start
->text
= nasm_quote(p
, strlen(p
));
3011 macro_start
->type
= TOK_STRING
;
3012 macro_start
->a
.mac
= NULL
;
3016 * We now have a macro name, an implicit parameter count of
3017 * zero, and a string token to use as an expansion. Create
3018 * and store an SMacro.
3020 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3021 free_tlist(origline
);
3022 return DIRECTIVE_FOUND
;
3026 casesense
= (i
== PP_DEFTOK
);
3028 tline
= tline
->next
;
3030 tline
= expand_id(tline
);
3031 if (!tline
|| (tline
->type
!= TOK_ID
&&
3032 (tline
->type
!= TOK_PREPROC_ID
||
3033 tline
->text
[1] != '$'))) {
3035 "`%s' expects a macro identifier as first parameter",
3037 free_tlist(origline
);
3038 return DIRECTIVE_FOUND
;
3040 ctx
= get_ctx(tline
->text
, &mname
, false);
3042 tline
= expand_smacro(tline
->next
);
3046 while (tok_type_(t
, TOK_WHITESPACE
))
3048 /* t should now point to the string */
3049 if (t
->type
!= TOK_STRING
) {
3051 "`%s` requires string as second parameter",
3054 free_tlist(origline
);
3055 return DIRECTIVE_FOUND
;
3058 nasm_unquote_cstr(t
->text
, i
);
3059 macro_start
= tokenize(t
->text
);
3062 * We now have a macro name, an implicit parameter count of
3063 * zero, and a numeric token to use as an expansion. Create
3064 * and store an SMacro.
3066 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3068 free_tlist(origline
);
3069 return DIRECTIVE_FOUND
;
3074 StrList
*xsl
= NULL
;
3075 StrList
**xst
= &xsl
;
3079 tline
= tline
->next
;
3081 tline
= expand_id(tline
);
3082 if (!tline
|| (tline
->type
!= TOK_ID
&&
3083 (tline
->type
!= TOK_PREPROC_ID
||
3084 tline
->text
[1] != '$'))) {
3086 "`%%pathsearch' expects a macro identifier as first parameter");
3087 free_tlist(origline
);
3088 return DIRECTIVE_FOUND
;
3090 ctx
= get_ctx(tline
->text
, &mname
, false);
3092 tline
= expand_smacro(tline
->next
);
3096 while (tok_type_(t
, TOK_WHITESPACE
))
3099 if (!t
|| (t
->type
!= TOK_STRING
&&
3100 t
->type
!= TOK_INTERNAL_STRING
)) {
3101 error(ERR_NONFATAL
, "`%%pathsearch' expects a file name");
3103 free_tlist(origline
);
3104 return DIRECTIVE_FOUND
; /* but we did _something_ */
3107 error(ERR_WARNING
|ERR_PASS1
,
3108 "trailing garbage after `%%pathsearch' ignored");
3110 if (t
->type
!= TOK_INTERNAL_STRING
)
3111 nasm_unquote(p
, NULL
);
3113 fp
= inc_fopen(p
, &xsl
, &xst
, true);
3116 fclose(fp
); /* Don't actually care about the file */
3118 macro_start
= nasm_malloc(sizeof(*macro_start
));
3119 macro_start
->next
= NULL
;
3120 macro_start
->text
= nasm_quote(p
, strlen(p
));
3121 macro_start
->type
= TOK_STRING
;
3122 macro_start
->a
.mac
= NULL
;
3127 * We now have a macro name, an implicit parameter count of
3128 * zero, and a string token to use as an expansion. Create
3129 * and store an SMacro.
3131 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3133 free_tlist(origline
);
3134 return DIRECTIVE_FOUND
;
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 "`%%strlen' expects a macro identifier as first parameter");
3148 free_tlist(origline
);
3149 return DIRECTIVE_FOUND
;
3151 ctx
= get_ctx(tline
->text
, &mname
, false);
3153 tline
= expand_smacro(tline
->next
);
3157 while (tok_type_(t
, TOK_WHITESPACE
))
3159 /* t should now point to the string */
3160 if (t
->type
!= TOK_STRING
) {
3162 "`%%strlen` requires string as second parameter");
3164 free_tlist(origline
);
3165 return DIRECTIVE_FOUND
;
3168 macro_start
= nasm_malloc(sizeof(*macro_start
));
3169 macro_start
->next
= NULL
;
3170 make_tok_num(macro_start
, nasm_unquote(t
->text
, NULL
));
3171 macro_start
->a
.mac
= NULL
;
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 tline
= tline
->next
;
3188 tline
= expand_id(tline
);
3189 if (!tline
|| (tline
->type
!= TOK_ID
&&
3190 (tline
->type
!= TOK_PREPROC_ID
||
3191 tline
->text
[1] != '$'))) {
3193 "`%%strcat' expects a macro identifier as first parameter");
3194 free_tlist(origline
);
3195 return DIRECTIVE_FOUND
;
3197 ctx
= get_ctx(tline
->text
, &mname
, false);
3199 tline
= expand_smacro(tline
->next
);
3203 for (t
= tline
; t
; t
= t
->next
) {
3205 case TOK_WHITESPACE
:
3208 len
+= t
->a
.len
= nasm_unquote(t
->text
, NULL
);
3211 if (!strcmp(t
->text
, ",")) /* permit comma separators */
3213 /* else fall through */
3216 "non-string passed to `%%strcat' (%d)", t
->type
);
3218 free_tlist(origline
);
3219 return DIRECTIVE_FOUND
;
3223 p
= pp
= nasm_malloc(len
);
3224 for (t
= tline
; t
; t
= t
->next
) {
3225 if (t
->type
== TOK_STRING
) {
3226 memcpy(p
, t
->text
, t
->a
.len
);
3232 * We now have a macro name, an implicit parameter count of
3233 * zero, and a numeric token to use as an expansion. Create
3234 * and store an SMacro.
3236 macro_start
= new_Token(NULL
, TOK_STRING
, NULL
, 0);
3237 macro_start
->text
= nasm_quote(pp
, len
);
3239 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3241 free_tlist(origline
);
3242 return DIRECTIVE_FOUND
;
3251 tline
= tline
->next
;
3253 tline
= expand_id(tline
);
3254 if (!tline
|| (tline
->type
!= TOK_ID
&&
3255 (tline
->type
!= TOK_PREPROC_ID
||
3256 tline
->text
[1] != '$'))) {
3258 "`%%substr' expects a macro identifier as first parameter");
3259 free_tlist(origline
);
3260 return DIRECTIVE_FOUND
;
3262 ctx
= get_ctx(tline
->text
, &mname
, false);
3264 tline
= expand_smacro(tline
->next
);
3268 while (tok_type_(t
, TOK_WHITESPACE
))
3271 /* t should now point to the string */
3272 if (t
->type
!= TOK_STRING
) {
3274 "`%%substr` requires string as second parameter");
3276 free_tlist(origline
);
3277 return DIRECTIVE_FOUND
;
3282 tokval
.t_type
= TOKEN_INVALID
;
3283 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3287 free_tlist(origline
);
3288 return DIRECTIVE_FOUND
;
3289 } else if (!is_simple(evalresult
)) {
3290 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3292 free_tlist(origline
);
3293 return DIRECTIVE_FOUND
;
3295 a1
= evalresult
->value
-1;
3297 while (tok_type_(tt
, TOK_WHITESPACE
))
3300 a2
= 1; /* Backwards compatibility: one character */
3302 tokval
.t_type
= TOKEN_INVALID
;
3303 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3307 free_tlist(origline
);
3308 return DIRECTIVE_FOUND
;
3309 } else if (!is_simple(evalresult
)) {
3310 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3312 free_tlist(origline
);
3313 return DIRECTIVE_FOUND
;
3315 a2
= evalresult
->value
;
3318 len
= nasm_unquote(t
->text
, NULL
);
3321 if (a1
+a2
> (int64_t)len
)
3324 macro_start
= nasm_malloc(sizeof(*macro_start
));
3325 macro_start
->next
= NULL
;
3326 macro_start
->text
= nasm_quote((a1
< 0) ? "" : t
->text
+a1
, a2
);
3327 macro_start
->type
= TOK_STRING
;
3328 macro_start
->a
.mac
= NULL
;
3331 * We now have a macro name, an implicit parameter count of
3332 * zero, and a numeric token to use as an expansion. Create
3333 * and store an SMacro.
3335 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3337 free_tlist(origline
);
3338 return DIRECTIVE_FOUND
;
3343 casesense
= (i
== PP_ASSIGN
);
3345 tline
= tline
->next
;
3347 tline
= expand_id(tline
);
3348 if (!tline
|| (tline
->type
!= TOK_ID
&&
3349 (tline
->type
!= TOK_PREPROC_ID
||
3350 tline
->text
[1] != '$'))) {
3352 "`%%%sassign' expects a macro identifier",
3353 (i
== PP_IASSIGN
? "i" : ""));
3354 free_tlist(origline
);
3355 return DIRECTIVE_FOUND
;
3357 ctx
= get_ctx(tline
->text
, &mname
, false);
3359 tline
= expand_smacro(tline
->next
);
3364 tokval
.t_type
= TOKEN_INVALID
;
3366 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3369 free_tlist(origline
);
3370 return DIRECTIVE_FOUND
;
3374 error(ERR_WARNING
|ERR_PASS1
,
3375 "trailing garbage after expression ignored");
3377 if (!is_simple(evalresult
)) {
3379 "non-constant value given to `%%%sassign'",
3380 (i
== PP_IASSIGN
? "i" : ""));
3381 free_tlist(origline
);
3382 return DIRECTIVE_FOUND
;
3385 macro_start
= nasm_malloc(sizeof(*macro_start
));
3386 macro_start
->next
= NULL
;
3387 make_tok_num(macro_start
, reloc_value(evalresult
));
3388 macro_start
->a
.mac
= NULL
;
3391 * We now have a macro name, an implicit parameter count of
3392 * zero, and a numeric token to use as an expansion. Create
3393 * and store an SMacro.
3395 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3396 free_tlist(origline
);
3397 return DIRECTIVE_FOUND
;
3401 * Syntax is `%line nnn[+mmm] [filename]'
3403 tline
= tline
->next
;
3405 if (!tok_type_(tline
, TOK_NUMBER
)) {
3406 error(ERR_NONFATAL
, "`%%line' expects line number");
3407 free_tlist(origline
);
3408 return DIRECTIVE_FOUND
;
3410 k
= readnum(tline
->text
, &err
);
3412 tline
= tline
->next
;
3413 if (tok_is_(tline
, "+")) {
3414 tline
= tline
->next
;
3415 if (!tok_type_(tline
, TOK_NUMBER
)) {
3416 error(ERR_NONFATAL
, "`%%line' expects line increment");
3417 free_tlist(origline
);
3418 return DIRECTIVE_FOUND
;
3420 m
= readnum(tline
->text
, &err
);
3421 tline
= tline
->next
;
3427 nasm_free(src_set_fname(detoken(tline
, false)));
3429 free_tlist(origline
);
3430 return DIRECTIVE_FOUND
;
3434 "preprocessor directive `%s' not yet implemented",
3436 return DIRECTIVE_FOUND
;
3441 * Ensure that a macro parameter contains a condition code and
3442 * nothing else. Return the condition code index if so, or -1
3445 static int find_cc(Token
* t
)
3451 return -1; /* Probably a %+ without a space */
3454 if (t
->type
!= TOK_ID
)
3458 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
3462 j
= elements(conditions
);
3465 m
= nasm_stricmp(t
->text
, conditions
[k
]);
3480 static bool paste_tokens(Token
**head
, bool handle_paste_tokens
)
3482 Token
**tail
, *t
, *tt
;
3484 bool did_paste
= false;
3487 /* Now handle token pasting... */
3490 while ((t
= *tail
) && (tt
= t
->next
)) {
3492 case TOK_WHITESPACE
:
3493 if (tt
->type
== TOK_WHITESPACE
) {
3494 /* Zap adjacent whitespace tokens */
3495 t
->next
= delete_Token(tt
);
3497 /* Do not advance paste_head here */
3502 case TOK_PREPROC_ID
:
3509 while (tt
&& (tt
->type
== TOK_ID
|| tt
->type
== TOK_PREPROC_ID
||
3510 tt
->type
== TOK_NUMBER
|| tt
->type
== TOK_FLOAT
||
3511 tt
->type
== TOK_OTHER
)) {
3512 len
+= strlen(tt
->text
);
3516 /* Now tt points to the first token after the potential
3518 if (tt
!= t
->next
) {
3519 /* We have at least two tokens... */
3520 len
+= strlen(t
->text
);
3521 p
= tmp
= nasm_malloc(len
+1);
3525 p
= strchr(p
, '\0');
3526 t
= delete_Token(t
);
3529 t
= *tail
= tokenize(tmp
);
3536 t
->next
= tt
; /* Attach the remaining token chain */
3544 case TOK_PASTE
: /* %+ */
3545 if (handle_paste_tokens
) {
3546 /* Zap %+ and whitespace tokens to the right */
3547 while (t
&& (t
->type
== TOK_WHITESPACE
||
3548 t
->type
== TOK_PASTE
))
3549 t
= *tail
= delete_Token(t
);
3550 if (!paste_head
|| !t
)
3551 break; /* Nothing to paste with */
3555 while (tok_type_(tt
, TOK_WHITESPACE
))
3556 tt
= t
->next
= delete_Token(tt
);
3559 tmp
= nasm_strcat(t
->text
, tt
->text
);
3561 tt
= delete_Token(tt
);
3562 t
= *tail
= tokenize(tmp
);
3568 t
->next
= tt
; /* Attach the remaining token chain */
3575 /* else fall through */
3577 tail
= paste_head
= &t
->next
;
3584 * Expand MMacro-local things: parameter references (%0, %n, %+n,
3585 * %-n) and MMacro-local identifiers (%%foo) as well as
3586 * macro indirection (%[...]).
3588 static Token
*expand_mmac_params(Token
* tline
)
3590 Token
*t
, *tt
, **tail
, *thead
;
3591 bool changed
= false;
3597 if (tline
->type
== TOK_PREPROC_ID
&&
3598 (((tline
->text
[1] == '+' || tline
->text
[1] == '-')
3599 && tline
->text
[2]) || tline
->text
[1] == '%'
3600 || (tline
->text
[1] >= '0' && tline
->text
[1] <= '9'))) {
3602 int type
= 0, cc
; /* type = 0 to placate optimisers */
3609 tline
= tline
->next
;
3612 while (mac
&& !mac
->name
) /* avoid mistaking %reps for macros */
3613 mac
= mac
->next_active
;
3615 error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
3617 switch (t
->text
[1]) {
3619 * We have to make a substitution of one of the
3620 * forms %1, %-1, %+1, %%foo, %0.
3624 snprintf(tmpbuf
, sizeof(tmpbuf
), "%d", mac
->nparam
);
3625 text
= nasm_strdup(tmpbuf
);
3629 snprintf(tmpbuf
, sizeof(tmpbuf
), "..@%"PRIu64
".",
3631 text
= nasm_strcat(tmpbuf
, t
->text
+ 2);
3634 n
= atoi(t
->text
+ 2) - 1;
3635 if (n
>= mac
->nparam
)
3638 if (mac
->nparam
> 1)
3639 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3640 tt
= mac
->params
[n
];
3645 "macro parameter %d is not a condition code",
3650 if (inverse_ccs
[cc
] == -1) {
3652 "condition code `%s' is not invertible",
3656 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
3660 n
= atoi(t
->text
+ 2) - 1;
3661 if (n
>= mac
->nparam
)
3664 if (mac
->nparam
> 1)
3665 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3666 tt
= mac
->params
[n
];
3671 "macro parameter %d is not a condition code",
3676 text
= nasm_strdup(conditions
[cc
]);
3680 n
= atoi(t
->text
+ 1) - 1;
3681 if (n
>= mac
->nparam
)
3684 if (mac
->nparam
> 1)
3685 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3686 tt
= mac
->params
[n
];
3689 for (i
= 0; i
< mac
->paramlen
[n
]; i
++) {
3690 *tail
= new_Token(NULL
, tt
->type
, tt
->text
, 0);
3691 tail
= &(*tail
)->next
;
3695 text
= NULL
; /* we've done it here */
3710 } else if (tline
->type
== TOK_INDIRECT
) {
3712 tline
= tline
->next
;
3713 tt
= tokenize(t
->text
);
3714 tt
= expand_mmac_params(tt
);
3715 tt
= expand_smacro(tt
);
3718 tt
->a
.mac
= NULL
; /* Necessary? */
3726 tline
= tline
->next
;
3734 paste_tokens(&thead
, false);
3740 * Expand all single-line macro calls made in the given line.
3741 * Return the expanded version of the line. The original is deemed
3742 * to be destroyed in the process. (In reality we'll just move
3743 * Tokens from input to output a lot of the time, rather than
3744 * actually bothering to destroy and replicate.)
3747 static Token
*expand_smacro(Token
* tline
)
3749 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
3750 struct hash_table
*smtbl
;
3751 SMacro
*head
= NULL
, *m
;
3754 unsigned int nparam
, sparam
;
3756 Token
*org_tline
= tline
;
3759 int deadman
= DEADMAN_LIMIT
;
3763 * Trick: we should avoid changing the start token pointer since it can
3764 * be contained in "next" field of other token. Because of this
3765 * we allocate a copy of first token and work with it; at the end of
3766 * routine we copy it back
3770 new_Token(org_tline
->next
, org_tline
->type
, org_tline
->text
,
3772 tline
->a
.mac
= org_tline
->a
.mac
;
3773 nasm_free(org_tline
->text
);
3774 org_tline
->text
= NULL
;
3777 expanded
= true; /* Always expand %+ at least once */
3783 while (tline
) { /* main token loop */
3785 error(ERR_NONFATAL
, "interminable macro recursion");
3789 if ((mname
= tline
->text
)) {
3790 /* if this token is a local macro, look in local context */
3791 if (tline
->type
== TOK_ID
|| tline
->type
== TOK_PREPROC_ID
)
3792 ctx
= get_ctx(mname
, &mname
, true);
3795 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
3796 head
= (SMacro
*) hash_findix(smtbl
, mname
);
3799 * We've hit an identifier. As in is_mmacro below, we first
3800 * check whether the identifier is a single-line macro at
3801 * all, then think about checking for parameters if
3804 for (m
= head
; m
; m
= m
->next
)
3805 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
3811 if (m
->nparam
== 0) {
3813 * Simple case: the macro is parameterless. Discard the
3814 * one token that the macro call took, and push the
3815 * expansion back on the to-do stack.
3817 if (!m
->expansion
) {
3818 if (!strcmp("__FILE__", m
->name
)) {
3821 src_get(&num
, &file
);
3822 tline
->text
= nasm_quote(file
, strlen(file
));
3823 tline
->type
= TOK_STRING
;
3827 if (!strcmp("__LINE__", m
->name
)) {
3828 nasm_free(tline
->text
);
3829 make_tok_num(tline
, src_get_linnum());
3832 if (!strcmp("__BITS__", m
->name
)) {
3833 nasm_free(tline
->text
);
3834 make_tok_num(tline
, globalbits
);
3837 tline
= delete_Token(tline
);
3842 * Complicated case: at least one macro with this name
3843 * exists and takes parameters. We must find the
3844 * parameters in the call, count them, find the SMacro
3845 * that corresponds to that form of the macro call, and
3846 * substitute for the parameters when we expand. What a
3849 /*tline = tline->next;
3850 skip_white_(tline); */
3853 while (tok_type_(t
, TOK_SMAC_END
)) {
3854 t
->a
.mac
->in_progress
= false;
3856 t
= tline
->next
= delete_Token(t
);
3859 } while (tok_type_(tline
, TOK_WHITESPACE
));
3860 if (!tok_is_(tline
, "(")) {
3862 * This macro wasn't called with parameters: ignore
3863 * the call. (Behaviour borrowed from gnu cpp.)
3872 sparam
= PARAM_DELTA
;
3873 params
= nasm_malloc(sparam
* sizeof(Token
*));
3874 params
[0] = tline
->next
;
3875 paramsize
= nasm_malloc(sparam
* sizeof(int));
3877 while (true) { /* parameter loop */
3879 * For some unusual expansions
3880 * which concatenates function call
3883 while (tok_type_(t
, TOK_SMAC_END
)) {
3884 t
->a
.mac
->in_progress
= false;
3886 t
= tline
->next
= delete_Token(t
);
3892 "macro call expects terminating `)'");
3895 if (tline
->type
== TOK_WHITESPACE
3897 if (paramsize
[nparam
])
3900 params
[nparam
] = tline
->next
;
3901 continue; /* parameter loop */
3903 if (tline
->type
== TOK_OTHER
3904 && tline
->text
[1] == 0) {
3905 char ch
= tline
->text
[0];
3906 if (ch
== ',' && !paren
&& brackets
<= 0) {
3907 if (++nparam
>= sparam
) {
3908 sparam
+= PARAM_DELTA
;
3909 params
= nasm_realloc(params
,
3914 nasm_realloc(paramsize
,
3918 params
[nparam
] = tline
->next
;
3919 paramsize
[nparam
] = 0;
3921 continue; /* parameter loop */
3924 (brackets
> 0 || (brackets
== 0 &&
3925 !paramsize
[nparam
])))
3927 if (!(brackets
++)) {
3928 params
[nparam
] = tline
->next
;
3929 continue; /* parameter loop */
3932 if (ch
== '}' && brackets
> 0)
3933 if (--brackets
== 0) {
3935 continue; /* parameter loop */
3937 if (ch
== '(' && !brackets
)
3939 if (ch
== ')' && brackets
<= 0)
3945 error(ERR_NONFATAL
, "braces do not "
3946 "enclose all of macro parameter");
3948 paramsize
[nparam
] += white
+ 1;
3950 } /* parameter loop */
3952 while (m
&& (m
->nparam
!= nparam
||
3953 mstrcmp(m
->name
, mname
,
3957 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
3958 "macro `%s' exists, "
3959 "but not taking %d parameters",
3960 mstart
->text
, nparam
);
3963 if (m
&& m
->in_progress
)
3965 if (!m
) { /* in progess or didn't find '(' or wrong nparam */
3967 * Design question: should we handle !tline, which
3968 * indicates missing ')' here, or expand those
3969 * macros anyway, which requires the (t) test a few
3973 nasm_free(paramsize
);
3977 * Expand the macro: we are placed on the last token of the
3978 * call, so that we can easily split the call from the
3979 * following tokens. We also start by pushing an SMAC_END
3980 * token for the cycle removal.
3987 tt
= new_Token(tline
, TOK_SMAC_END
, NULL
, 0);
3989 m
->in_progress
= true;
3991 for (t
= m
->expansion
; t
; t
= t
->next
) {
3992 if (t
->type
>= TOK_SMAC_PARAM
) {
3993 Token
*pcopy
= tline
, **ptail
= &pcopy
;
3997 ttt
= params
[t
->type
- TOK_SMAC_PARAM
];
3998 for (i
= paramsize
[t
->type
- TOK_SMAC_PARAM
];
4001 new_Token(tline
, ttt
->type
, ttt
->text
,
4007 } else if (t
->type
== TOK_PREPROC_Q
) {
4008 tt
= new_Token(tline
, TOK_ID
, mname
, 0);
4010 } else if (t
->type
== TOK_PREPROC_QQ
) {
4011 tt
= new_Token(tline
, TOK_ID
, m
->name
, 0);
4014 tt
= new_Token(tline
, t
->type
, t
->text
, 0);
4020 * Having done that, get rid of the macro call, and clean
4021 * up the parameters.
4024 nasm_free(paramsize
);
4027 continue; /* main token loop */
4032 if (tline
->type
== TOK_SMAC_END
) {
4033 tline
->a
.mac
->in_progress
= false;
4034 tline
= delete_Token(tline
);
4037 tline
= tline
->next
;
4045 * Now scan the entire line and look for successive TOK_IDs that resulted
4046 * after expansion (they can't be produced by tokenize()). The successive
4047 * TOK_IDs should be concatenated.
4048 * Also we look for %+ tokens and concatenate the tokens before and after
4049 * them (without white spaces in between).
4051 if (expanded
&& paste_tokens(&thead
, true)) {
4053 * If we concatenated something, *and* we had previously expanded
4054 * an actual macro, scan the lines again for macros...
4063 *org_tline
= *thead
;
4064 /* since we just gave text to org_line, don't free it */
4066 delete_Token(thead
);
4068 /* the expression expanded to empty line;
4069 we can't return NULL for some reasons
4070 we just set the line to a single WHITESPACE token. */
4071 memset(org_tline
, 0, sizeof(*org_tline
));
4072 org_tline
->text
= NULL
;
4073 org_tline
->type
= TOK_WHITESPACE
;
4082 * Similar to expand_smacro but used exclusively with macro identifiers
4083 * right before they are fetched in. The reason is that there can be
4084 * identifiers consisting of several subparts. We consider that if there
4085 * are more than one element forming the name, user wants a expansion,
4086 * otherwise it will be left as-is. Example:
4090 * the identifier %$abc will be left as-is so that the handler for %define
4091 * will suck it and define the corresponding value. Other case:
4093 * %define _%$abc cde
4095 * In this case user wants name to be expanded *before* %define starts
4096 * working, so we'll expand %$abc into something (if it has a value;
4097 * otherwise it will be left as-is) then concatenate all successive
4100 static Token
*expand_id(Token
* tline
)
4102 Token
*cur
, *oldnext
= NULL
;
4104 if (!tline
|| !tline
->next
)
4109 (cur
->next
->type
== TOK_ID
||
4110 cur
->next
->type
== TOK_PREPROC_ID
4111 || cur
->next
->type
== TOK_NUMBER
))
4114 /* If identifier consists of just one token, don't expand */
4119 oldnext
= cur
->next
; /* Detach the tail past identifier */
4120 cur
->next
= NULL
; /* so that expand_smacro stops here */
4123 tline
= expand_smacro(tline
);
4126 /* expand_smacro possibly changhed tline; re-scan for EOL */
4128 while (cur
&& cur
->next
)
4131 cur
->next
= oldnext
;
4138 * Determine whether the given line constitutes a multi-line macro
4139 * call, and return the MMacro structure called if so. Doesn't have
4140 * to check for an initial label - that's taken care of in
4141 * expand_mmacro - but must check numbers of parameters. Guaranteed
4142 * to be called with tline->type == TOK_ID, so the putative macro
4143 * name is easy to find.
4145 static MMacro
*is_mmacro(Token
* tline
, Token
*** params_array
)
4151 head
= (MMacro
*) hash_findix(&mmacros
, tline
->text
);
4154 * Efficiency: first we see if any macro exists with the given
4155 * name. If not, we can return NULL immediately. _Then_ we
4156 * count the parameters, and then we look further along the
4157 * list if necessary to find the proper MMacro.
4159 for (m
= head
; m
; m
= m
->next
)
4160 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
4166 * OK, we have a potential macro. Count and demarcate the
4169 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
4172 * So we know how many parameters we've got. Find the MMacro
4173 * structure that handles this number.
4176 if (m
->nparam_min
<= nparam
4177 && (m
->plus
|| nparam
<= m
->nparam_max
)) {
4179 * This one is right. Just check if cycle removal
4180 * prohibits us using it before we actually celebrate...
4182 if (m
->in_progress
> m
->max_depth
) {
4183 if (m
->max_depth
> 0) {
4185 "reached maximum recursion depth of %i",
4192 * It's right, and we can use it. Add its default
4193 * parameters to the end of our list if necessary.
4195 if (m
->defaults
&& nparam
< m
->nparam_min
+ m
->ndefs
) {
4197 nasm_realloc(params
,
4198 ((m
->nparam_min
+ m
->ndefs
+
4199 1) * sizeof(*params
)));
4200 while (nparam
< m
->nparam_min
+ m
->ndefs
) {
4201 params
[nparam
] = m
->defaults
[nparam
- m
->nparam_min
];
4206 * If we've gone over the maximum parameter count (and
4207 * we're in Plus mode), ignore parameters beyond
4210 if (m
->plus
&& nparam
> m
->nparam_max
)
4211 nparam
= m
->nparam_max
;
4213 * Then terminate the parameter list, and leave.
4215 if (!params
) { /* need this special case */
4216 params
= nasm_malloc(sizeof(*params
));
4219 params
[nparam
] = NULL
;
4220 *params_array
= params
;
4224 * This one wasn't right: look for the next one with the
4227 for (m
= m
->next
; m
; m
= m
->next
)
4228 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
4233 * After all that, we didn't find one with the right number of
4234 * parameters. Issue a warning, and fail to expand the macro.
4236 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4237 "macro `%s' exists, but not taking %d parameters",
4238 tline
->text
, nparam
);
4245 * Save MMacro invocation specific fields in
4246 * preparation for a recursive macro expansion
4248 static void push_mmacro(MMacro
*m
)
4250 MMacroInvocation
*i
;
4252 i
= nasm_malloc(sizeof(MMacroInvocation
));
4254 i
->params
= m
->params
;
4255 i
->iline
= m
->iline
;
4256 i
->nparam
= m
->nparam
;
4257 i
->rotate
= m
->rotate
;
4258 i
->paramlen
= m
->paramlen
;
4259 i
->unique
= m
->unique
;
4260 i
->condcnt
= m
->condcnt
;
4266 * Restore MMacro invocation specific fields that were
4267 * saved during a previous recursive macro expansion
4269 static void pop_mmacro(MMacro
*m
)
4271 MMacroInvocation
*i
;
4276 m
->params
= i
->params
;
4277 m
->iline
= i
->iline
;
4278 m
->nparam
= i
->nparam
;
4279 m
->rotate
= i
->rotate
;
4280 m
->paramlen
= i
->paramlen
;
4281 m
->unique
= i
->unique
;
4282 m
->condcnt
= i
->condcnt
;
4289 * Expand the multi-line macro call made by the given line, if
4290 * there is one to be expanded. If there is, push the expansion on
4291 * istk->expansion and return 1. Otherwise return 0.
4293 static int expand_mmacro(Token
* tline
)
4295 Token
*startline
= tline
;
4296 Token
*label
= NULL
;
4297 int dont_prepend
= 0;
4298 Token
**params
, *t
, *mtok
, *tt
;
4301 int i
, nparam
, *paramlen
;
4306 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4307 if (!tok_type_(t
, TOK_ID
) && !tok_type_(t
, TOK_PREPROC_ID
))
4310 m
= is_mmacro(t
, ¶ms
);
4316 * We have an id which isn't a macro call. We'll assume
4317 * it might be a label; we'll also check to see if a
4318 * colon follows it. Then, if there's another id after
4319 * that lot, we'll check it again for macro-hood.
4323 if (tok_type_(t
, TOK_WHITESPACE
))
4324 last
= t
, t
= t
->next
;
4325 if (tok_is_(t
, ":")) {
4327 last
= t
, t
= t
->next
;
4328 if (tok_type_(t
, TOK_WHITESPACE
))
4329 last
= t
, t
= t
->next
;
4331 if (!tok_type_(t
, TOK_ID
) || !(m
= is_mmacro(t
, ¶ms
)))
4339 * Fix up the parameters: this involves stripping leading and
4340 * trailing whitespace, then stripping braces if they are
4343 for (nparam
= 0; params
[nparam
]; nparam
++) ;
4344 paramlen
= nparam
? nasm_malloc(nparam
* sizeof(*paramlen
)) : NULL
;
4346 for (i
= 0; params
[i
]; i
++) {
4348 int comma
= (!m
->plus
|| i
< nparam
- 1);
4352 if (tok_is_(t
, "{"))
4353 t
= t
->next
, brace
= true, comma
= false;
4357 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
4358 break; /* ... because we have hit a comma */
4359 if (comma
&& t
->type
== TOK_WHITESPACE
4360 && tok_is_(t
->next
, ","))
4361 break; /* ... or a space then a comma */
4362 if (brace
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "}"))
4363 break; /* ... or a brace */
4370 * OK, we have a MMacro structure together with a set of
4371 * parameters. We must now go through the expansion and push
4372 * copies of each Line on to istk->expansion. Substitution of
4373 * parameter tokens and macro-local tokens doesn't get done
4374 * until the single-line macro substitution process; this is
4375 * because delaying them allows us to change the semantics
4376 * later through %rotate.
4378 * First, push an end marker on to istk->expansion, mark this
4379 * macro as in progress, and set up its invocation-specific
4382 ll
= nasm_malloc(sizeof(Line
));
4383 ll
->next
= istk
->expansion
;
4386 istk
->expansion
= ll
;
4389 * Save the previous MMacro expansion in the case of
4392 if (m
->max_depth
&& m
->in_progress
)
4400 m
->paramlen
= paramlen
;
4401 m
->unique
= unique
++;
4405 m
->next_active
= istk
->mstk
;
4408 for (l
= m
->expansion
; l
; l
= l
->next
) {
4411 ll
= nasm_malloc(sizeof(Line
));
4412 ll
->finishes
= NULL
;
4413 ll
->next
= istk
->expansion
;
4414 istk
->expansion
= ll
;
4417 for (t
= l
->first
; t
; t
= t
->next
) {
4421 tt
= *tail
= new_Token(NULL
, TOK_ID
, mname
, 0);
4423 case TOK_PREPROC_QQ
:
4424 tt
= *tail
= new_Token(NULL
, TOK_ID
, m
->name
, 0);
4426 case TOK_PREPROC_ID
:
4427 if (t
->text
[1] == '0' && t
->text
[2] == '0') {
4435 tt
= *tail
= new_Token(NULL
, x
->type
, x
->text
, 0);
4444 * If we had a label, push it on as the first line of
4445 * the macro expansion.
4448 if (dont_prepend
< 0)
4449 free_tlist(startline
);
4451 ll
= nasm_malloc(sizeof(Line
));
4452 ll
->finishes
= NULL
;
4453 ll
->next
= istk
->expansion
;
4454 istk
->expansion
= ll
;
4455 ll
->first
= startline
;
4456 if (!dont_prepend
) {
4458 label
= label
->next
;
4459 label
->next
= tt
= new_Token(NULL
, TOK_OTHER
, ":", 0);
4464 list
->uplevel(m
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
4469 /* The function that actually does the error reporting */
4470 static void verror(int severity
, const char *fmt
, va_list arg
)
4474 vsnprintf(buff
, sizeof(buff
), fmt
, arg
);
4476 if (istk
&& istk
->mstk
&& istk
->mstk
->name
)
4477 nasm_error(severity
, "(%s:%d) %s", istk
->mstk
->name
,
4478 istk
->mstk
->lineno
, buff
);
4480 nasm_error(severity
, "%s", buff
);
4484 * Since preprocessor always operate only on the line that didn't
4485 * arrived yet, we should always use ERR_OFFBY1.
4487 static void error(int severity
, const char *fmt
, ...)
4491 /* If we're in a dead branch of IF or something like it, ignore the error */
4492 if (istk
&& istk
->conds
&& !emitting(istk
->conds
->state
))
4496 verror(severity
, fmt
, arg
);
4501 * Because %else etc are evaluated in the state context
4502 * of the previous branch, errors might get lost with error():
4503 * %if 0 ... %else trailing garbage ... %endif
4504 * So %else etc should report errors with this function.
4506 static void error_precond(int severity
, const char *fmt
, ...)
4510 /* Only ignore the error if it's really in a dead branch */
4511 if (istk
&& istk
->conds
&& istk
->conds
->state
== COND_NEVER
)
4515 verror(severity
, fmt
, arg
);
4520 pp_reset(char *file
, int apass
, ListGen
* listgen
, StrList
**deplist
)
4525 istk
= nasm_malloc(sizeof(Include
));
4528 istk
->expansion
= NULL
;
4530 istk
->fp
= fopen(file
, "r");
4532 src_set_fname(nasm_strdup(file
));
4536 error(ERR_FATAL
|ERR_NOFILE
, "unable to open input file `%s'",
4539 nested_mac_count
= 0;
4540 nested_rep_count
= 0;
4543 if (tasm_compatible_mode
) {
4544 stdmacpos
= nasm_stdmac
;
4546 stdmacpos
= nasm_stdmac_after_tasm
;
4548 any_extrastdmac
= extrastdmac
&& *extrastdmac
;
4553 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
4554 * The caller, however, will also pass in 3 for preprocess-only so
4555 * we can set __PASS__ accordingly.
4557 pass
= apass
> 2 ? 2 : apass
;
4559 dephead
= deptail
= deplist
;
4561 StrList
*sl
= nasm_malloc(strlen(file
)+1+sizeof sl
->next
);
4563 strcpy(sl
->str
, file
);
4565 deptail
= &sl
->next
;
4569 * Define the __PASS__ macro. This is defined here unlike
4570 * all the other builtins, because it is special -- it varies between
4573 t
= nasm_malloc(sizeof(*t
));
4575 make_tok_num(t
, apass
);
4577 define_smacro(NULL
, "__PASS__", true, 0, t
);
4580 static char *pp_getline(void)
4587 * Fetch a tokenized line, either from the macro-expansion
4588 * buffer or from the input file.
4591 while (istk
->expansion
&& istk
->expansion
->finishes
) {
4592 Line
*l
= istk
->expansion
;
4593 if (!l
->finishes
->name
&& l
->finishes
->in_progress
> 1) {
4597 * This is a macro-end marker for a macro with no
4598 * name, which means it's not really a macro at all
4599 * but a %rep block, and the `in_progress' field is
4600 * more than 1, meaning that we still need to
4601 * repeat. (1 means the natural last repetition; 0
4602 * means termination by %exitrep.) We have
4603 * therefore expanded up to the %endrep, and must
4604 * push the whole block on to the expansion buffer
4605 * again. We don't bother to remove the macro-end
4606 * marker: we'd only have to generate another one
4609 l
->finishes
->in_progress
--;
4610 for (l
= l
->finishes
->expansion
; l
; l
= l
->next
) {
4611 Token
*t
, *tt
, **tail
;
4613 ll
= nasm_malloc(sizeof(Line
));
4614 ll
->next
= istk
->expansion
;
4615 ll
->finishes
= NULL
;
4619 for (t
= l
->first
; t
; t
= t
->next
) {
4620 if (t
->text
|| t
->type
== TOK_WHITESPACE
) {
4622 new_Token(NULL
, t
->type
, t
->text
, 0);
4627 istk
->expansion
= ll
;
4631 * Check whether a `%rep' was started and not ended
4632 * within this macro expansion. This can happen and
4633 * should be detected. It's a fatal error because
4634 * I'm too confused to work out how to recover
4640 "defining with name in expansion");
4641 else if (istk
->mstk
->name
)
4643 "`%%rep' without `%%endrep' within"
4644 " expansion of macro `%s'",
4649 * FIXME: investigate the relationship at this point between
4650 * istk->mstk and l->finishes
4653 MMacro
*m
= istk
->mstk
;
4654 istk
->mstk
= m
->next_active
;
4657 * This was a real macro call, not a %rep, and
4658 * therefore the parameter information needs to
4663 l
->finishes
->in_progress
--;
4665 nasm_free(m
->params
);
4666 free_tlist(m
->iline
);
4667 nasm_free(m
->paramlen
);
4668 l
->finishes
->in_progress
= 0;
4673 istk
->expansion
= l
->next
;
4675 list
->downlevel(LIST_MACRO
);
4678 while (1) { /* until we get a line we can use */
4680 if (istk
->expansion
) { /* from a macro expansion */
4682 Line
*l
= istk
->expansion
;
4684 istk
->mstk
->lineno
++;
4686 istk
->expansion
= l
->next
;
4688 p
= detoken(tline
, false);
4689 list
->line(LIST_MACRO
, p
);
4694 if (line
) { /* from the current input file */
4695 line
= prepreproc(line
);
4696 tline
= tokenize(line
);
4701 * The current file has ended; work down the istk
4708 "expected `%%endif' before end of file");
4709 /* only set line and file name if there's a next node */
4711 src_set_linnum(i
->lineno
);
4712 nasm_free(src_set_fname(i
->fname
));
4715 list
->downlevel(LIST_INCLUDE
);
4719 if (istk
->expansion
&& istk
->expansion
->finishes
)
4725 * We must expand MMacro parameters and MMacro-local labels
4726 * _before_ we plunge into directive processing, to cope
4727 * with things like `%define something %1' such as STRUC
4728 * uses. Unless we're _defining_ a MMacro, in which case
4729 * those tokens should be left alone to go into the
4730 * definition; and unless we're in a non-emitting
4731 * condition, in which case we don't want to meddle with
4734 if (!defining
&& !(istk
->conds
&& !emitting(istk
->conds
->state
))
4735 && !(istk
->mstk
&& !istk
->mstk
->in_progress
)) {
4736 tline
= expand_mmac_params(tline
);
4740 * Check the line to see if it's a preprocessor directive.
4742 if (do_directive(tline
) == DIRECTIVE_FOUND
) {
4744 } else if (defining
) {
4746 * We're defining a multi-line macro. We emit nothing
4748 * shove the tokenized line on to the macro definition.
4750 Line
*l
= nasm_malloc(sizeof(Line
));
4751 l
->next
= defining
->expansion
;
4754 defining
->expansion
= l
;
4756 } else if (istk
->conds
&& !emitting(istk
->conds
->state
)) {
4758 * We're in a non-emitting branch of a condition block.
4759 * Emit nothing at all, not even a blank line: when we
4760 * emerge from the condition we'll give a line-number
4761 * directive so we keep our place correctly.
4765 } else if (istk
->mstk
&& !istk
->mstk
->in_progress
) {
4767 * We're in a %rep block which has been terminated, so
4768 * we're walking through to the %endrep without
4769 * emitting anything. Emit nothing at all, not even a
4770 * blank line: when we emerge from the %rep block we'll
4771 * give a line-number directive so we keep our place
4777 tline
= expand_smacro(tline
);
4778 if (!expand_mmacro(tline
)) {
4780 * De-tokenize the line again, and emit it.
4782 line
= detoken(tline
, true);
4786 continue; /* expand_mmacro calls free_tlist */
4794 static void pp_cleanup(int pass
)
4797 if (defining
->name
) {
4799 "end of file while still defining macro `%s'",
4802 error(ERR_NONFATAL
, "end of file while still in %%rep");
4805 free_mmacro(defining
);
4814 nasm_free(i
->fname
);
4819 nasm_free(src_set_fname(NULL
));
4824 while ((i
= ipath
)) {
4833 void pp_include_path(char *path
)
4837 i
= nasm_malloc(sizeof(IncPath
));
4838 i
->path
= path
? nasm_strdup(path
) : NULL
;
4851 void pp_pre_include(char *fname
)
4853 Token
*inc
, *space
, *name
;
4856 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
4857 space
= new_Token(name
, TOK_WHITESPACE
, NULL
, 0);
4858 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
4860 l
= nasm_malloc(sizeof(Line
));
4867 void pp_pre_define(char *definition
)
4873 equals
= strchr(definition
, '=');
4874 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
4875 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
4878 space
->next
= tokenize(definition
);
4882 l
= nasm_malloc(sizeof(Line
));
4889 void pp_pre_undefine(char *definition
)
4894 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
4895 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
4896 space
->next
= tokenize(definition
);
4898 l
= nasm_malloc(sizeof(Line
));
4906 * Added by Keith Kanios:
4908 * This function is used to assist with "runtime" preprocessor
4909 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
4911 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
4912 * PASS A VALID STRING TO THIS FUNCTION!!!!!
4915 void pp_runtime(char *definition
)
4919 def
= tokenize(definition
);
4920 if (do_directive(def
) == NO_DIRECTIVE_FOUND
)
4925 void pp_extra_stdmac(macros_t
*macros
)
4927 extrastdmac
= macros
;
4930 static void make_tok_num(Token
* tok
, int64_t val
)
4933 snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
4934 tok
->text
= nasm_strdup(numbuf
);
4935 tok
->type
= TOK_NUMBER
;