1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2010 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
35 * preproc.c macro preprocessor for the Netwide Assembler
38 /* Typical flow of text through preproc
40 * pp_getline gets tokenized lines, either
42 * from a macro expansion
46 * read_line gets raw text from stdmacpos, or predef, or current input file
47 * tokenize converts to tokens
50 * expand_mmac_params is used to expand %1 etc., unless a macro is being
51 * defined or a false conditional is being processed
52 * (%0, %1, %+1, %-1, %%foo
54 * do_directive checks for directives
56 * expand_smacro is used to expand single line macros
58 * expand_mmacro is used to expand multi-line macros
60 * detoken is used to convert the line back to text
84 typedef struct SMacro SMacro
;
85 typedef struct ExpDef ExpDef
;
86 typedef struct ExpInv ExpInv
;
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 * The context stack is composed of a linked list of these.
122 struct hash_table localmac
;
127 * This is the internal form which we break input lines up into.
128 * Typically stored in linked lists.
130 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
131 * necessarily used as-is, but is intended to denote the number of
132 * the substituted parameter. So in the definition
134 * %define a(x,y) ( (x) & ~(y) )
136 * the token representing `x' will have its type changed to
137 * TOK_SMAC_PARAM, but the one representing `y' will be
140 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
141 * which doesn't need quotes around it. Used in the pre-include
142 * mechanism as an alternative to trying to find a sensible type of
143 * quote to use on the filename we were passed.
146 TOK_NONE
= 0, TOK_WHITESPACE
, TOK_COMMENT
, TOK_ID
,
147 TOK_PREPROC_ID
, TOK_STRING
,
148 TOK_NUMBER
, TOK_FLOAT
, TOK_SMAC_END
, TOK_OTHER
,
150 TOK_PREPROC_Q
, TOK_PREPROC_QQ
,
152 TOK_INDIRECT
, /* %[...] */
153 TOK_SMAC_PARAM
, /* MUST BE LAST IN THE LIST!!! */
154 TOK_MAX
= INT_MAX
/* Keep compiler from reducing the range */
161 SMacro
*mac
; /* associated macro for TOK_SMAC_END */
162 size_t len
; /* scratch length field */
163 } a
; /* Auxiliary data */
164 enum pp_token_type type
;
168 * Expansion definitions are stored as a linked list of
169 * these, which is essentially a container to allow several linked
172 * Note that in this module, linked lists are treated as stacks
173 * wherever possible. For this reason, Lines are _pushed_ on to the
174 * `last' field in ExpDef structures, so that the linked list,
175 * if walked, would emit the expansion lines in the proper order.
186 EXP_NONE
= 0, EXP_PREDEF
,
189 EXP_COMMENT
, EXP_FINAL
,
190 EXP_MAX
= INT_MAX
/* Keep compiler from reducing the range */
194 * Store the definition of an expansion, in which is any
195 * preprocessor directive that has an ending pair.
197 * This design allows for arbitrary expansion/recursion depth,
198 * upto the DEADMAN_LIMIT.
200 * The `next' field is used for storing ExpDef in hash tables; the
201 * `prev' field is for the global `expansions` linked-list.
204 ExpDef
*prev
; /* previous definition */
205 ExpDef
*next
; /* next in hash table */
206 enum pp_exp_type type
; /* expansion type */
208 int nparam_min
, nparam_max
;
210 bool plus
; /* is the last parameter greedy? */
211 bool nolist
; /* is this expansion listing-inhibited? */
212 Token
*dlist
; /* all defaults as one list */
213 Token
**defaults
; /* parameter default pointers */
214 int ndefs
; /* number of default parameters */
216 int prepend
; /* label prepend state */
220 int linecount
; /* number of lines within expansion */
222 uint32_t def_depth
; /* current number of definition pairs deep */
223 uint32_t cur_depth
; /* current number of expansions */
224 uint32_t max_depth
; /* maximum number of expansions allowed */
226 int state
; /* condition state */
227 bool ignoring
; /* ignoring definition lines */
231 * Store the invocation of an expansion.
233 * The `prev' field is for the `istk->expansion` linked-list.
235 * When an expansion is being expanded, `params', `iline', `nparam',
236 * `paramlen', `rotate' and `unique' are local to the invocation.
239 ExpInv
*prev
; /* previous invocation */
240 enum pp_exp_type type
; /* expansion type */
241 ExpDef
*def
; /* pointer to expansion definition */
242 Line
*label
; /* pointer to label */
243 char *label_text
; /* pointer to label text */
244 Line
*current
; /* pointer to current line in invocation */
246 Token
**params
; /* actual parameters */
247 Token
*iline
; /* invocation line */
248 unsigned int nparam
, rotate
;
253 int lineno
; /* current line number in expansion */
254 int linnum
; /* line number at invocation */
255 int relno
; /* relative line number at invocation */
259 * To handle an arbitrary level of file inclusion, we maintain a
260 * stack (ie linked list) of these things.
273 * Include search path. This is simply a list of strings which get
274 * prepended, in turn, to the name of an include file, in an
275 * attempt to find the file if it's not in the current directory.
283 * Conditional assembly: we maintain a separate stack of these for
284 * each level of file inclusion. (The only reason we keep the
285 * stacks separate is to ensure that a stray `%endif' in a file
286 * included from within the true branch of a `%if' won't terminate
287 * it and cause confusion: instead, rightly, it'll cause an error.)
291 * These states are for use just after %if or %elif: IF_TRUE
292 * means the condition has evaluated to truth so we are
293 * currently emitting, whereas IF_FALSE means we are not
294 * currently emitting but will start doing so if a %else comes
295 * up. In these states, all directives are admissible: %elif,
296 * %else and %endif. (And of course %if.)
298 COND_IF_TRUE
, COND_IF_FALSE
,
300 * These states come up after a %else: ELSE_TRUE means we're
301 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
302 * any %elif or %else will cause an error.
304 COND_ELSE_TRUE
, COND_ELSE_FALSE
,
306 * These states mean that we're not emitting now, and also that
307 * nothing until %endif will be emitted at all. COND_DONE is
308 * used when we've had our moment of emission
309 * and have now started seeing %elifs. COND_NEVER is used when
310 * the condition construct in question is contained within a
311 * non-emitting branch of a larger condition construct,
312 * or if there is an error.
314 COND_DONE
, COND_NEVER
316 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
319 * These defines are used as the possible return values for do_directive
321 #define NO_DIRECTIVE_FOUND 0
322 #define DIRECTIVE_FOUND 1
325 * This define sets the upper limit for smacro and expansions
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
352 /* For TASM compatibility we need to be able to recognise TASM compatible
353 * conditional compilation directives. Using the NASM pre-processor does
354 * not work, so we look for them specifically from the following list and
355 * then jam in the equivalent NASM directive into the input stream.
359 TM_ARG
, TM_ELIF
, TM_ELSE
, TM_ENDIF
, TM_IF
, TM_IFDEF
, TM_IFDIFI
,
360 TM_IFNDEF
, TM_INCLUDE
, TM_LOCAL
363 static const char * const tasm_directives
[] = {
364 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
365 "ifndef", "include", "local"
368 static int StackSize
= 4;
369 static char *StackPointer
= "ebp";
370 static int ArgOffset
= 8;
371 static int LocalOffset
= 0;
373 static Context
*cstk
;
374 static Include
*istk
;
375 static IncPath
*ipath
= NULL
;
377 static int pass
; /* HACK: pass 0 = generate dependencies only */
378 static StrList
**dephead
, **deptail
; /* Dependency list */
380 static uint64_t unique
; /* unique identifier numbers */
382 static Line
*predef
= NULL
;
383 static bool do_predef
;
385 static ListGen
*list
;
388 * The current set of expansion definitions we have defined.
390 static struct hash_table expdefs
;
393 * The current set of single-line macros we have defined.
395 static struct hash_table smacros
;
398 * Linked List of all active expansion definitions
400 struct ExpDef
*expansions
= NULL
;
403 * The expansion we are currently defining
405 static ExpDef
*defining
= NULL
;
407 static uint64_t nested_mac_count
;
408 static uint64_t nested_rep_count
;
411 * Linked-list of lines to preprocess, prior to cleanup
413 static Line
*finals
= NULL
;
414 static bool in_final
= false;
417 * The number of macro parameters to allocate space for at a time.
419 #define PARAM_DELTA 16
422 * The standard macro set: defined in macros.c in the array nasm_stdmac.
423 * This gives our position in the macro set, when we're processing it.
425 static macros_t
*stdmacpos
;
428 * The extra standard macros that come from the object format, if
431 static macros_t
*extrastdmac
= NULL
;
432 static bool any_extrastdmac
;
435 * Tokens are allocated in blocks to improve speed
437 #define TOKEN_BLOCKSIZE 4096
438 static Token
*freeTokens
= NULL
;
444 static Blocks blocks
= { NULL
, NULL
};
447 * Forward declarations.
449 static Token
*expand_mmac_params(Token
* tline
);
450 static Token
*expand_smacro(Token
* tline
);
451 static Token
*expand_id(Token
* tline
);
452 static Context
*get_ctx(const char *name
, const char **namep
,
454 static void make_tok_num(Token
* tok
, int64_t val
);
455 static void error(int severity
, const char *fmt
, ...);
456 static void error_precond(int severity
, const char *fmt
, ...);
457 static void *new_Block(size_t size
);
458 static void delete_Blocks(void);
459 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
460 const char *text
, int txtlen
);
461 static Token
*copy_Token(Token
* tline
);
462 static Token
*delete_Token(Token
* t
);
463 static Line
*new_Line(void);
464 static ExpDef
*new_ExpDef(int exp_type
);
465 static ExpInv
*new_ExpInv(int exp_type
, ExpDef
*ed
);
468 * Macros for safe checking of token pointers, avoid *(NULL)
470 #define tok_type_(x,t) ((x) && (x)->type == (t))
471 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
472 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
473 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
476 * nasm_unquote with error if the string contains NUL characters.
477 * If the string contains NUL characters, issue an error and return
478 * the C len, i.e. truncate at the NUL.
480 static size_t nasm_unquote_cstr(char *qstr
, enum preproc_token directive
)
482 size_t len
= nasm_unquote(qstr
, NULL
);
483 size_t clen
= strlen(qstr
);
486 error(ERR_NONFATAL
, "NUL character in `%s' directive",
487 pp_directives
[directive
]);
493 * Handle TASM specific directives, which do not contain a % in
494 * front of them. We do it here because I could not find any other
495 * place to do it for the moment, and it is a hack (ideally it would
496 * be nice to be able to use the NASM pre-processor to do it).
498 static char *check_tasm_directive(char *line
)
500 int32_t i
, j
, k
, m
, len
;
501 char *p
, *q
, *oldline
, oldchar
;
503 p
= nasm_skip_spaces(line
);
505 /* Binary search for the directive name */
507 j
= ARRAY_SIZE(tasm_directives
);
508 q
= nasm_skip_word(p
);
515 m
= nasm_stricmp(p
, tasm_directives
[k
]);
517 /* We have found a directive, so jam a % in front of it
518 * so that NASM will then recognise it as one if it's own.
523 line
= nasm_malloc(len
+ 2);
525 if (k
== TM_IFDIFI
) {
527 * NASM does not recognise IFDIFI, so we convert
528 * it to %if 0. This is not used in NASM
529 * compatible code, but does need to parse for the
530 * TASM macro package.
532 strcpy(line
+ 1, "if 0");
534 memcpy(line
+ 1, p
, len
+ 1);
549 * The pre-preprocessing stage... This function translates line
550 * number indications as they emerge from GNU cpp (`# lineno "file"
551 * flags') into NASM preprocessor line number indications (`%line
554 static char *prepreproc(char *line
)
557 char *fname
, *oldline
;
559 if (line
[0] == '#' && line
[1] == ' ') {
562 lineno
= atoi(fname
);
563 fname
+= strspn(fname
, "0123456789 ");
566 fnlen
= strcspn(fname
, "\"");
567 line
= nasm_malloc(20 + fnlen
);
568 snprintf(line
, 20 + fnlen
, "%%line %d %.*s", lineno
, fnlen
, fname
);
571 if (tasm_compatible_mode
)
572 return check_tasm_directive(line
);
577 * Free a linked list of tokens.
579 static void free_tlist(Token
* list
)
582 list
= delete_Token(list
);
586 * Free a linked list of lines.
588 static void free_llist(Line
* list
)
591 list_for_each_safe(l
, tmp
, list
) {
592 free_tlist(l
->first
);
600 static void free_expdef(ExpDef
* ed
)
603 free_tlist(ed
->dlist
);
604 nasm_free(ed
->defaults
);
605 free_llist(ed
->line
);
610 * Free all currently defined macros, and free the hash tables
612 static void free_smacro_table(struct hash_table
*smt
)
616 struct hash_tbl_node
*it
= NULL
;
618 while ((s
= hash_iterate(smt
, &it
, &key
)) != NULL
) {
619 nasm_free((void *)key
);
620 list_for_each_safe(s
, tmp
, s
) {
622 free_tlist(s
->expansion
);
629 static void free_expdef_table(struct hash_table
*edt
)
633 struct hash_tbl_node
*it
= NULL
;
636 while ((ed
= hash_iterate(edt
, &it
, &key
)) != NULL
) {
637 nasm_free((void *)key
);
638 list_for_each_safe(ed
,tmp
, ed
)
644 static void free_macros(void)
646 free_smacro_table(&smacros
);
647 free_expdef_table(&expdefs
);
651 * Initialize the hash tables
653 static void init_macros(void)
655 hash_init(&smacros
, HASH_LARGE
);
656 hash_init(&expdefs
, HASH_LARGE
);
660 * Pop the context stack.
662 static void ctx_pop(void)
667 free_smacro_table(&c
->localmac
);
673 * Search for a key in the hash index; adding it if necessary
674 * (in which case we initialize the data pointer to NULL.)
677 hash_findi_add(struct hash_table
*hash
, const char *str
)
679 struct hash_insert hi
;
683 r
= hash_findi(hash
, str
, &hi
);
687 strx
= nasm_strdup(str
); /* Use a more efficient allocator here? */
688 return hash_add(&hi
, strx
, NULL
);
692 * Like hash_findi, but returns the data element rather than a pointer
693 * to it. Used only when not adding a new element, hence no third
697 hash_findix(struct hash_table
*hash
, const char *str
)
701 p
= hash_findi(hash
, str
, NULL
);
702 return p
? *p
: NULL
;
706 * read line from standard macros set,
707 * if there no more left -- return NULL
709 static char *line_from_stdmac(void)
712 const unsigned char *p
= stdmacpos
;
721 len
+= pp_directives_len
[c
- 0x80] + 1;
726 line
= nasm_malloc(len
+ 1);
728 while ((c
= *stdmacpos
++)) {
730 memcpy(q
, pp_directives
[c
- 0x80], pp_directives_len
[c
- 0x80]);
731 q
+= pp_directives_len
[c
- 0x80];
741 /* This was the last of the standard macro chain... */
743 if (any_extrastdmac
) {
744 stdmacpos
= extrastdmac
;
745 any_extrastdmac
= false;
746 } else if (do_predef
) {
749 Token
*head
, **tail
, *t
;
752 * Nasty hack: here we push the contents of
753 * `predef' on to the top-level expansion stack,
754 * since this is the most convenient way to
755 * implement the pre-include and pre-define
758 list_for_each(pd
, predef
) {
761 list_for_each(t
, pd
->first
) {
762 *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
763 tail
= &(*tail
)->next
;
768 ei
= new_ExpInv(EXP_PREDEF
, NULL
);
771 ei
->prev
= istk
->expansion
;
772 istk
->expansion
= ei
;
781 #define BUF_DELTA 512
783 * Read a line from the top file in istk, handling multiple CR/LFs
784 * at the end of the line read, and handling spurious ^Zs. Will
785 * return lines from the standard macro set if this has not already
788 static char *read_line(void)
790 char *buffer
, *p
, *q
;
791 int bufsize
, continued_count
;
794 * standart macros set (predefined) goes first
796 p
= line_from_stdmac();
801 * regular read from a file
804 buffer
= nasm_malloc(BUF_DELTA
);
808 q
= fgets(p
, bufsize
- (p
- buffer
), istk
->fp
);
812 if (p
> buffer
&& p
[-1] == '\n') {
814 * Convert backslash-CRLF line continuation sequences into
815 * nothing at all (for DOS and Windows)
817 if (((p
- 2) > buffer
) && (p
[-3] == '\\') && (p
[-2] == '\r')) {
823 * Also convert backslash-LF line continuation sequences into
824 * nothing at all (for Unix)
826 else if (((p
- 1) > buffer
) && (p
[-2] == '\\')) {
834 if (p
- buffer
> bufsize
- 10) {
835 int32_t offset
= p
- buffer
;
836 bufsize
+= BUF_DELTA
;
837 buffer
= nasm_realloc(buffer
, bufsize
);
838 p
= buffer
+ offset
; /* prevent stale-pointer problems */
842 if (!q
&& p
== buffer
) {
847 src_set_linnum(src_get_linnum() + istk
->lineinc
+
848 (continued_count
* istk
->lineinc
));
851 * Play safe: remove CRs as well as LFs, if any of either are
852 * present at the end of the line.
854 while (--p
>= buffer
&& (*p
== '\n' || *p
== '\r'))
858 * Handle spurious ^Z, which may be inserted into source files
859 * by some file transfer utilities.
861 buffer
[strcspn(buffer
, "\032")] = '\0';
863 list
->line(LIST_READ
, buffer
);
869 * Tokenize a line of text. This is a very simple process since we
870 * don't need to parse the value out of e.g. numeric tokens: we
871 * simply split one string into many.
873 static Token
*tokenize(char *line
)
876 enum pp_token_type type
;
878 Token
*t
, **tail
= &list
;
884 if (*p
== '+' && !nasm_isdigit(p
[1])) {
887 } else if (nasm_isdigit(*p
) ||
888 ((*p
== '-' || *p
== '+') && nasm_isdigit(p
[1]))) {
892 while (nasm_isdigit(*p
));
893 type
= TOK_PREPROC_ID
;
894 } else if (*p
== '{') {
896 while (*p
&& *p
!= '}') {
903 type
= TOK_PREPROC_ID
;
904 } else if (*p
== '[') {
906 line
+= 2; /* Skip the leading %[ */
908 while (lvl
&& (c
= *p
++)) {
920 p
= nasm_skip_string(p
- 1) + 1;
930 error(ERR_NONFATAL
, "unterminated %[ construct");
932 } else if (*p
== '?') {
933 type
= TOK_PREPROC_Q
; /* %? */
936 type
= TOK_PREPROC_QQ
; /* %?? */
939 } else if (*p
== '!') {
940 type
= TOK_PREPROC_ID
;
946 while (isidchar(*p
));
947 } else if (*p
== '\'' || *p
== '\"' || *p
== '`') {
948 p
= nasm_skip_string(p
);
952 error(ERR_NONFATAL
|ERR_PASS1
, "unterminated %! string");
954 /* %! without string or identifier */
955 type
= TOK_OTHER
; /* Legacy behavior... */
957 } else if (isidchar(*p
) ||
958 ((*p
== '!' || *p
== '%' || *p
== '$') &&
963 while (isidchar(*p
));
964 type
= TOK_PREPROC_ID
;
970 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
973 while (*p
&& isidchar(*p
))
975 } else if (*p
== '\'' || *p
== '"' || *p
== '`') {
980 p
= nasm_skip_string(p
);
985 error(ERR_WARNING
|ERR_PASS1
, "unterminated string");
986 /* Handling unterminated strings by UNV */
989 } else if (p
[0] == '$' && p
[1] == '$') {
990 type
= TOK_OTHER
; /* TOKEN_BASE */
992 } else if (isnumstart(*p
)) {
994 bool is_float
= false;
1010 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
1012 if (*p
== '+' || *p
== '-') {
1014 * e can only be followed by +/- if it is either a
1015 * prefixed hex number or a floating-point number
1020 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
1022 } else if (c
== 'P' || c
== 'p') {
1024 if (*p
== '+' || *p
== '-')
1026 } else if (isnumchar(c
) || c
== '_')
1027 ; /* just advance */
1028 else if (c
== '.') {
1030 * we need to deal with consequences of the legacy
1031 * parser, like "1.nolist" being two tokens
1032 * (TOK_NUMBER, TOK_ID) here; at least give it
1033 * a shot for now. In the future, we probably need
1034 * a flex-based scanner with proper pattern matching
1035 * to do it as well as it can be done. Nothing in
1036 * the world is going to help the person who wants
1037 * 0x123.p16 interpreted as two tokens, though.
1043 if (nasm_isdigit(*r
) || (is_hex
&& nasm_isxdigit(*r
)) ||
1044 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
1045 (*r
== 'p' || *r
== 'P')) {
1049 break; /* Terminate the token */
1053 p
--; /* Point to first character beyond number */
1055 if (p
== line
+1 && *line
== '$') {
1056 type
= TOK_OTHER
; /* TOKEN_HERE */
1058 if (has_e
&& !is_hex
) {
1059 /* 1e13 is floating-point, but 1e13h is not */
1063 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
1065 } else if (nasm_isspace(*p
)) {
1066 type
= TOK_WHITESPACE
;
1067 p
= nasm_skip_spaces(p
);
1069 * Whitespace just before end-of-line is discarded by
1070 * pretending it's a comment; whitespace just before a
1071 * comment gets lumped into the comment.
1073 if (!*p
|| *p
== ';') {
1078 } else if (*p
== ';') {
1084 * Anything else is an operator of some kind. We check
1085 * for all the double-character operators (>>, <<, //,
1086 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1087 * else is a single-character operator.
1090 if ((p
[0] == '>' && p
[1] == '>') ||
1091 (p
[0] == '<' && p
[1] == '<') ||
1092 (p
[0] == '/' && p
[1] == '/') ||
1093 (p
[0] == '<' && p
[1] == '=') ||
1094 (p
[0] == '>' && p
[1] == '=') ||
1095 (p
[0] == '=' && p
[1] == '=') ||
1096 (p
[0] == '!' && p
[1] == '=') ||
1097 (p
[0] == '<' && p
[1] == '>') ||
1098 (p
[0] == '&' && p
[1] == '&') ||
1099 (p
[0] == '|' && p
[1] == '|') ||
1100 (p
[0] == '^' && p
[1] == '^')) {
1106 /* Handling unterminated string by UNV */
1109 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1110 t->text[p-line] = *line;
1114 if (type
!= TOK_COMMENT
) {
1115 *tail
= t
= new_Token(NULL
, type
, line
, p
- line
);
1124 * this function allocates a new managed block of memory and
1125 * returns a pointer to the block. The managed blocks are
1126 * deleted only all at once by the delete_Blocks function.
1128 static void *new_Block(size_t size
)
1130 Blocks
*b
= &blocks
;
1132 /* first, get to the end of the linked list */
1135 /* now allocate the requested chunk */
1136 b
->chunk
= nasm_malloc(size
);
1138 /* now allocate a new block for the next request */
1139 b
->next
= nasm_malloc(sizeof(Blocks
));
1140 /* and initialize the contents of the new block */
1141 b
->next
->next
= NULL
;
1142 b
->next
->chunk
= NULL
;
1147 * this function deletes all managed blocks of memory
1149 static void delete_Blocks(void)
1151 Blocks
*a
, *b
= &blocks
;
1154 * keep in mind that the first block, pointed to by blocks
1155 * is a static and not dynamically allocated, so we don't
1160 nasm_free(b
->chunk
);
1169 * this function creates a new Token and passes a pointer to it
1170 * back to the caller. It sets the type and text elements, and
1171 * also the a.mac and next elements to NULL.
1173 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
1174 const char *text
, int txtlen
)
1180 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1181 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1182 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1183 freeTokens
[i
].next
= NULL
;
1186 freeTokens
= t
->next
;
1190 if (type
== TOK_WHITESPACE
|| !text
) {
1194 txtlen
= strlen(text
);
1195 t
->text
= nasm_malloc(txtlen
+1);
1196 memcpy(t
->text
, text
, txtlen
);
1197 t
->text
[txtlen
] = '\0';
1202 static Token
*copy_Token(Token
* tline
)
1204 Token
*t
, *tt
, *first
= NULL
, *prev
= NULL
;
1206 for (tt
= tline
; tt
!= NULL
; tt
= tt
->next
) {
1208 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1209 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1210 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1211 freeTokens
[i
].next
= NULL
;
1214 freeTokens
= t
->next
;
1216 t
->text
= ((tt
->text
!= NULL
) ? strdup(tt
->text
) : NULL
);
1217 t
->a
.mac
= tt
->a
.mac
;
1218 t
->a
.len
= tt
->a
.len
;
1230 static Token
*delete_Token(Token
* t
)
1232 Token
*next
= t
->next
;
1234 t
->next
= freeTokens
;
1240 * Convert a line of tokens back into text.
1241 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1242 * will be transformed into ..@ctxnum.xxx
1244 static char *detoken(Token
* tlist
, bool expand_locals
)
1251 list_for_each(t
, tlist
) {
1252 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
1257 if (*v
== '\'' || *v
== '\"' || *v
== '`') {
1258 size_t len
= nasm_unquote(v
, NULL
);
1259 size_t clen
= strlen(v
);
1262 error(ERR_NONFATAL
| ERR_PASS1
,
1263 "NUL character in %! string");
1269 char *p
= getenv(v
);
1271 error(ERR_NONFATAL
| ERR_PASS1
,
1272 "nonexistent environment variable `%s'", v
);
1275 t
->text
= nasm_strdup(p
);
1280 /* Expand local macros here and not during preprocessing */
1281 if (expand_locals
&&
1282 t
->type
== TOK_PREPROC_ID
&& t
->text
&&
1283 t
->text
[0] == '%' && t
->text
[1] == '$') {
1286 Context
*ctx
= get_ctx(t
->text
, &q
, false);
1289 snprintf(buffer
, sizeof(buffer
), "..@%"PRIu32
".", ctx
->number
);
1290 p
= nasm_strcat(buffer
, q
);
1295 if (t
->type
== TOK_WHITESPACE
)
1298 len
+= strlen(t
->text
);
1301 p
= line
= nasm_malloc(len
+ 1);
1303 list_for_each(t
, tlist
) {
1304 if (t
->type
== TOK_WHITESPACE
) {
1306 } else if (t
->text
) {
1318 * Initialize a new Line
1320 static Line
*new_Line(void)
1322 Line
*l
= nasm_malloc(sizeof(Line
));
1330 * Initialize a new Expansion Definition
1332 static ExpDef
*new_ExpDef(int exp_type
)
1334 ExpDef
*ed
= nasm_malloc(sizeof(ExpDef
));
1337 ed
->type
= exp_type
;
1341 ed
->casesense
= true;
1349 ed
->defaults
= NULL
;
1351 ed
->state
= COND_NEVER
;
1356 ed
->ignoring
= false;
1362 * Initialize a new Expansion Instance
1364 static ExpInv
*new_ExpInv(int exp_type
, ExpDef
*ed
)
1367 ExpInv
*ei
= nasm_malloc(sizeof(ExpInv
));
1369 ei
->type
= exp_type
;
1372 ei
->label_text
= NULL
;
1378 ei
->paramlen
= NULL
;
1379 ei
->unique
= unique
;
1380 ei
->emitting
= false;
1382 if ((istk
->mmac_depth
< 1) &&
1383 (istk
->expansion
== NULL
) &&
1385 (ed
->type
!= EXP_MMACRO
) &&
1386 (ed
->type
!= EXP_REP
) &&
1387 (ed
->type
!= EXP_WHILE
)) {
1388 ei
->linnum
= src_get_linnum();
1389 src_set_linnum(ei
->linnum
- ed
->linecount
- 1);
1393 if ((istk
->expansion
== NULL
) ||
1394 (ei
->type
== EXP_MMACRO
)) {
1397 ei
->relno
= istk
->expansion
->lineno
;
1399 ei
->relno
-= (ed
->linecount
+ 1);
1406 * A scanner, suitable for use by the expression evaluator, which
1407 * operates on a line of Tokens. Expects a pointer to a pointer to
1408 * the first token in the line to be passed in as its private_data
1411 * FIX: This really needs to be unified with stdscan.
1413 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1415 Token
**tlineptr
= private_data
;
1417 char ourcopy
[MAX_KEYWORD
+1], *p
, *r
, *s
;
1421 *tlineptr
= tline
? tline
->next
: NULL
;
1422 } while (tline
&& (tline
->type
== TOK_WHITESPACE
||
1423 tline
->type
== TOK_COMMENT
));
1426 return tokval
->t_type
= TOKEN_EOS
;
1428 tokval
->t_charptr
= tline
->text
;
1430 if (tline
->text
[0] == '$' && !tline
->text
[1])
1431 return tokval
->t_type
= TOKEN_HERE
;
1432 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[2])
1433 return tokval
->t_type
= TOKEN_BASE
;
1435 if (tline
->type
== TOK_ID
) {
1436 p
= tokval
->t_charptr
= tline
->text
;
1438 tokval
->t_charptr
++;
1439 return tokval
->t_type
= TOKEN_ID
;
1442 for (r
= p
, s
= ourcopy
; *r
; r
++) {
1443 if (r
>= p
+MAX_KEYWORD
)
1444 return tokval
->t_type
= TOKEN_ID
; /* Not a keyword */
1445 *s
++ = nasm_tolower(*r
);
1448 /* right, so we have an identifier sitting in temp storage. now,
1449 * is it actually a register or instruction name, or what? */
1450 return nasm_token_hash(ourcopy
, tokval
);
1453 if (tline
->type
== TOK_NUMBER
) {
1455 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
1456 tokval
->t_charptr
= tline
->text
;
1458 return tokval
->t_type
= TOKEN_ERRNUM
;
1460 return tokval
->t_type
= TOKEN_NUM
;
1463 if (tline
->type
== TOK_FLOAT
) {
1464 return tokval
->t_type
= TOKEN_FLOAT
;
1467 if (tline
->type
== TOK_STRING
) {
1470 bq
= tline
->text
[0];
1471 tokval
->t_charptr
= tline
->text
;
1472 tokval
->t_inttwo
= nasm_unquote(tline
->text
, &ep
);
1474 if (ep
[0] != bq
|| ep
[1] != '\0')
1475 return tokval
->t_type
= TOKEN_ERRSTR
;
1477 return tokval
->t_type
= TOKEN_STR
;
1480 if (tline
->type
== TOK_OTHER
) {
1481 if (!strcmp(tline
->text
, "<<"))
1482 return tokval
->t_type
= TOKEN_SHL
;
1483 if (!strcmp(tline
->text
, ">>"))
1484 return tokval
->t_type
= TOKEN_SHR
;
1485 if (!strcmp(tline
->text
, "//"))
1486 return tokval
->t_type
= TOKEN_SDIV
;
1487 if (!strcmp(tline
->text
, "%%"))
1488 return tokval
->t_type
= TOKEN_SMOD
;
1489 if (!strcmp(tline
->text
, "=="))
1490 return tokval
->t_type
= TOKEN_EQ
;
1491 if (!strcmp(tline
->text
, "<>"))
1492 return tokval
->t_type
= TOKEN_NE
;
1493 if (!strcmp(tline
->text
, "!="))
1494 return tokval
->t_type
= TOKEN_NE
;
1495 if (!strcmp(tline
->text
, "<="))
1496 return tokval
->t_type
= TOKEN_LE
;
1497 if (!strcmp(tline
->text
, ">="))
1498 return tokval
->t_type
= TOKEN_GE
;
1499 if (!strcmp(tline
->text
, "&&"))
1500 return tokval
->t_type
= TOKEN_DBL_AND
;
1501 if (!strcmp(tline
->text
, "^^"))
1502 return tokval
->t_type
= TOKEN_DBL_XOR
;
1503 if (!strcmp(tline
->text
, "||"))
1504 return tokval
->t_type
= TOKEN_DBL_OR
;
1508 * We have no other options: just return the first character of
1511 return tokval
->t_type
= tline
->text
[0];
1515 * Compare a string to the name of an existing macro; this is a
1516 * simple wrapper which calls either strcmp or nasm_stricmp
1517 * depending on the value of the `casesense' parameter.
1519 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
1521 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
1525 * Compare a string to the name of an existing macro; this is a
1526 * simple wrapper which calls either strcmp or nasm_stricmp
1527 * depending on the value of the `casesense' parameter.
1529 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
1531 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
1535 * Return the Context structure associated with a %$ token. Return
1536 * NULL, having _already_ reported an error condition, if the
1537 * context stack isn't deep enough for the supplied number of $
1539 * If all_contexts == true, contexts that enclose current are
1540 * also scanned for such smacro, until it is found; if not -
1541 * only the context that directly results from the number of $'s
1542 * in variable's name.
1544 * If "namep" is non-NULL, set it to the pointer to the macro name
1545 * tail, i.e. the part beyond %$...
1547 static Context
*get_ctx(const char *name
, const char **namep
,
1557 if (!name
|| name
[0] != '%' || name
[1] != '$')
1561 error(ERR_NONFATAL
, "`%s': context stack is empty", name
);
1568 while (ctx
&& *name
== '$') {
1574 error(ERR_NONFATAL
, "`%s': context stack is only"
1575 " %d level%s deep", name
, i
, (i
== 1 ? "" : "s"));
1586 /* Search for this smacro in found context */
1587 m
= hash_findix(&ctx
->localmac
, name
);
1589 if (!mstrcmp(m
->name
, name
, m
->casesense
))
1600 * Check to see if a file is already in a string list
1602 static bool in_list(const StrList
*list
, const char *str
)
1605 if (!strcmp(list
->str
, str
))
1613 * Open an include file. This routine must always return a valid
1614 * file pointer if it returns - it's responsible for throwing an
1615 * ERR_FATAL and bombing out completely if not. It should also try
1616 * the include path one by one until it finds the file or reaches
1617 * the end of the path.
1619 static FILE *inc_fopen(const char *file
, StrList
**dhead
, StrList
***dtail
,
1624 IncPath
*ip
= ipath
;
1625 int len
= strlen(file
);
1626 size_t prefix_len
= 0;
1630 sl
= nasm_malloc(prefix_len
+len
+1+sizeof sl
->next
);
1631 memcpy(sl
->str
, prefix
, prefix_len
);
1632 memcpy(sl
->str
+prefix_len
, file
, len
+1);
1633 fp
= fopen(sl
->str
, "r");
1634 if (fp
&& dhead
&& !in_list(*dhead
, sl
->str
)) {
1652 prefix_len
= strlen(prefix
);
1654 /* -MG given and file not found */
1655 if (dhead
&& !in_list(*dhead
, file
)) {
1656 sl
= nasm_malloc(len
+1+sizeof sl
->next
);
1658 strcpy(sl
->str
, file
);
1666 error(ERR_FATAL
, "unable to open include file `%s'", file
);
1671 * Determine if we should warn on defining a single-line macro of
1672 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1673 * return true if _any_ single-line macro of that name is defined.
1674 * Otherwise, will return true if a single-line macro with either
1675 * `nparam' or no parameters is defined.
1677 * If a macro with precisely the right number of parameters is
1678 * defined, or nparam is -1, the address of the definition structure
1679 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1680 * is NULL, no action will be taken regarding its contents, and no
1683 * Note that this is also called with nparam zero to resolve
1686 * If you already know which context macro belongs to, you can pass
1687 * the context pointer as first parameter; if you won't but name begins
1688 * with %$ the context will be automatically computed. If all_contexts
1689 * is true, macro will be searched in outer contexts as well.
1692 smacro_defined(Context
* ctx
, const char *name
, int nparam
, SMacro
** defn
,
1695 struct hash_table
*smtbl
;
1699 smtbl
= &ctx
->localmac
;
1700 } else if (name
[0] == '%' && name
[1] == '$') {
1702 ctx
= get_ctx(name
, &name
, false);
1704 return false; /* got to return _something_ */
1705 smtbl
= &ctx
->localmac
;
1709 m
= (SMacro
*) hash_findix(smtbl
, name
);
1712 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
1713 (nparam
<= 0 || m
->nparam
== 0 || nparam
== (int) m
->nparam
)) {
1715 if (nparam
== (int) m
->nparam
|| nparam
== -1)
1729 * Count and mark off the parameters in a multi-line macro call.
1730 * This is called both from within the multi-line macro expansion
1731 * code, and also to mark off the default parameters when provided
1732 * in a %macro definition line.
1734 static void count_mmac_params(Token
* t
, int *nparam
, Token
*** params
)
1736 int paramsize
, brace
;
1738 *nparam
= paramsize
= 0;
1741 /* +1: we need space for the final NULL */
1742 if (*nparam
+1 >= paramsize
) {
1743 paramsize
+= PARAM_DELTA
;
1744 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
1748 if (tok_is_(t
, "{"))
1750 (*params
)[(*nparam
)++] = t
;
1751 while (tok_isnt_(t
, brace
? "}" : ","))
1753 if (t
) { /* got a comma/brace */
1757 * Now we've found the closing brace, look further
1761 if (tok_isnt_(t
, ",")) {
1763 "braces do not enclose all of macro parameter");
1764 while (tok_isnt_(t
, ","))
1768 t
= t
->next
; /* eat the comma */
1775 * Determine whether one of the various `if' conditions is true or
1778 * We must free the tline we get passed.
1780 static bool if_condition(Token
* tline
, enum preproc_token ct
)
1782 enum pp_conditional i
= PP_COND(ct
);
1784 Token
*t
, *tt
, **tptr
, *origline
;
1785 struct tokenval tokval
;
1787 enum pp_token_type needtype
;
1794 j
= false; /* have we matched yet? */
1799 if (tline
->type
!= TOK_ID
) {
1801 "`%s' expects context identifiers", pp_directives
[ct
]);
1802 free_tlist(origline
);
1805 if (cstk
&& cstk
->name
&& !nasm_stricmp(tline
->text
, cstk
->name
))
1807 tline
= tline
->next
;
1812 j
= false; /* have we matched yet? */
1815 if (!tline
|| (tline
->type
!= TOK_ID
&&
1816 (tline
->type
!= TOK_PREPROC_ID
||
1817 tline
->text
[1] != '$'))) {
1819 "`%s' expects macro identifiers", pp_directives
[ct
]);
1822 if (smacro_defined(NULL
, tline
->text
, 0, NULL
, true))
1824 tline
= tline
->next
;
1829 tline
= expand_smacro(tline
);
1830 j
= false; /* have we matched yet? */
1833 if (!tline
|| (tline
->type
!= TOK_ID
&&
1834 tline
->type
!= TOK_STRING
&&
1835 (tline
->type
!= TOK_PREPROC_ID
||
1836 tline
->text
[1] != '!'))) {
1838 "`%s' expects environment variable names",
1843 if (tline
->type
== TOK_PREPROC_ID
)
1844 p
+= 2; /* Skip leading %! */
1845 if (*p
== '\'' || *p
== '\"' || *p
== '`')
1846 nasm_unquote_cstr(p
, ct
);
1849 tline
= tline
->next
;
1855 tline
= expand_smacro(tline
);
1857 while (tok_isnt_(tt
, ","))
1861 "`%s' expects two comma-separated arguments",
1866 j
= true; /* assume equality unless proved not */
1867 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1868 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1869 error(ERR_NONFATAL
, "`%s': more than one comma on line",
1873 if (t
->type
== TOK_WHITESPACE
) {
1877 if (tt
->type
== TOK_WHITESPACE
) {
1881 if (tt
->type
!= t
->type
) {
1882 j
= false; /* found mismatching tokens */
1885 /* When comparing strings, need to unquote them first */
1886 if (t
->type
== TOK_STRING
) {
1887 size_t l1
= nasm_unquote(t
->text
, NULL
);
1888 size_t l2
= nasm_unquote(tt
->text
, NULL
);
1894 if (mmemcmp(t
->text
, tt
->text
, l1
, i
== PPC_IFIDN
)) {
1898 } else if (mstrcmp(tt
->text
, t
->text
, i
== PPC_IFIDN
) != 0) {
1899 j
= false; /* found mismatching tokens */
1906 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
1907 j
= false; /* trailing gunk on one end or other */
1913 ExpDef searching
, *ed
;
1916 tline
= expand_id(tline
);
1917 if (!tok_type_(tline
, TOK_ID
)) {
1919 "`%s' expects a macro name", pp_directives
[ct
]);
1922 searching
.name
= nasm_strdup(tline
->text
);
1923 searching
.casesense
= true;
1924 searching
.plus
= false;
1925 searching
.nolist
= false;
1926 //searching.in_progress = 0;
1927 searching
.max_depth
= 0;
1928 //searching.rep_nest = NULL;
1929 searching
.nparam_min
= 0;
1930 searching
.nparam_max
= INT_MAX
;
1931 tline
= expand_smacro(tline
->next
);
1934 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
1936 "`%s' expects a parameter count or nothing",
1939 searching
.nparam_min
= searching
.nparam_max
=
1940 readnum(tline
->text
, &j
);
1943 "unable to parse parameter count `%s'",
1946 if (tline
&& tok_is_(tline
->next
, "-")) {
1947 tline
= tline
->next
->next
;
1948 if (tok_is_(tline
, "*"))
1949 searching
.nparam_max
= INT_MAX
;
1950 else if (!tok_type_(tline
, TOK_NUMBER
))
1952 "`%s' expects a parameter count after `-'",
1955 searching
.nparam_max
= readnum(tline
->text
, &j
);
1958 "unable to parse parameter count `%s'",
1960 if (searching
.nparam_min
> searching
.nparam_max
)
1962 "minimum parameter count exceeds maximum");
1965 if (tline
&& tok_is_(tline
->next
, "+")) {
1966 tline
= tline
->next
;
1967 searching
.plus
= true;
1969 ed
= (ExpDef
*) hash_findix(&expdefs
, searching
.name
);
1970 while (ed
!= NULL
) {
1971 if (!strcmp(ed
->name
, searching
.name
) &&
1972 (ed
->nparam_min
<= searching
.nparam_max
1974 && (searching
.nparam_min
<= ed
->nparam_max
1981 if (tline
&& tline
->next
)
1982 error(ERR_WARNING
|ERR_PASS1
,
1983 "trailing garbage after %%ifmacro ignored");
1984 nasm_free(searching
.name
);
1993 needtype
= TOK_NUMBER
;
1996 needtype
= TOK_STRING
;
2000 t
= tline
= expand_smacro(tline
);
2002 while (tok_type_(t
, TOK_WHITESPACE
) ||
2003 (needtype
== TOK_NUMBER
&&
2004 tok_type_(t
, TOK_OTHER
) &&
2005 (t
->text
[0] == '-' || t
->text
[0] == '+') &&
2009 j
= tok_type_(t
, needtype
);
2013 t
= tline
= expand_smacro(tline
);
2014 while (tok_type_(t
, TOK_WHITESPACE
))
2019 t
= t
->next
; /* Skip the actual token */
2020 while (tok_type_(t
, TOK_WHITESPACE
))
2022 j
= !t
; /* Should be nothing left */
2027 t
= tline
= expand_smacro(tline
);
2028 while (tok_type_(t
, TOK_WHITESPACE
))
2031 j
= !t
; /* Should be empty */
2035 t
= tline
= expand_smacro(tline
);
2037 tokval
.t_type
= TOKEN_INVALID
;
2038 evalresult
= evaluate(ppscan
, tptr
, &tokval
,
2039 NULL
, pass
| CRITICAL
, error
, NULL
);
2043 error(ERR_WARNING
|ERR_PASS1
,
2044 "trailing garbage after expression ignored");
2045 if (!is_simple(evalresult
)) {
2047 "non-constant value given to `%s'", pp_directives
[ct
]);
2050 j
= reloc_value(evalresult
) != 0;
2055 "preprocessor directive `%s' not yet implemented",
2060 free_tlist(origline
);
2061 return j
^ PP_NEGATIVE(ct
);
2064 free_tlist(origline
);
2069 * Common code for defining an smacro
2071 static bool define_smacro(Context
*ctx
, const char *mname
, bool casesense
,
2072 int nparam
, Token
*expansion
)
2074 SMacro
*smac
, **smhead
;
2075 struct hash_table
*smtbl
;
2077 if (smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
)) {
2079 error(ERR_WARNING
|ERR_PASS1
,
2080 "single-line macro `%s' defined both with and"
2081 " without parameters", mname
);
2083 * Some instances of the old code considered this a failure,
2084 * some others didn't. What is the right thing to do here?
2086 free_tlist(expansion
);
2087 return false; /* Failure */
2090 * We're redefining, so we have to take over an
2091 * existing SMacro structure. This means freeing
2092 * what was already in it.
2094 nasm_free(smac
->name
);
2095 free_tlist(smac
->expansion
);
2098 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2099 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
2100 smac
= nasm_malloc(sizeof(SMacro
));
2101 smac
->next
= *smhead
;
2104 smac
->name
= nasm_strdup(mname
);
2105 smac
->casesense
= casesense
;
2106 smac
->nparam
= nparam
;
2107 smac
->expansion
= expansion
;
2108 smac
->in_progress
= false;
2109 return true; /* Success */
2113 * Undefine an smacro
2115 static void undef_smacro(Context
*ctx
, const char *mname
)
2117 SMacro
**smhead
, *s
, **sp
;
2118 struct hash_table
*smtbl
;
2120 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2121 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
2125 * We now have a macro name... go hunt for it.
2128 while ((s
= *sp
) != NULL
) {
2129 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
2132 free_tlist(s
->expansion
);
2142 * Parse a mmacro specification.
2144 static bool parse_mmacro_spec(Token
*tline
, ExpDef
*def
, const char *directive
)
2148 tline
= tline
->next
;
2150 tline
= expand_id(tline
);
2151 if (!tok_type_(tline
, TOK_ID
)) {
2152 error(ERR_NONFATAL
, "`%s' expects a macro name", directive
);
2156 def
->name
= nasm_strdup(tline
->text
);
2158 def
->nolist
= false;
2159 // def->in_progress = 0;
2160 // def->rep_nest = NULL;
2161 def
->nparam_min
= 0;
2162 def
->nparam_max
= 0;
2164 tline
= expand_smacro(tline
->next
);
2166 if (!tok_type_(tline
, TOK_NUMBER
)) {
2167 error(ERR_NONFATAL
, "`%s' expects a parameter count", directive
);
2169 def
->nparam_min
= def
->nparam_max
=
2170 readnum(tline
->text
, &err
);
2173 "unable to parse parameter count `%s'", tline
->text
);
2175 if (tline
&& tok_is_(tline
->next
, "-")) {
2176 tline
= tline
->next
->next
;
2177 if (tok_is_(tline
, "*")) {
2178 def
->nparam_max
= INT_MAX
;
2179 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2181 "`%s' expects a parameter count after `-'", directive
);
2183 def
->nparam_max
= readnum(tline
->text
, &err
);
2185 error(ERR_NONFATAL
, "unable to parse parameter count `%s'",
2188 if (def
->nparam_min
> def
->nparam_max
) {
2189 error(ERR_NONFATAL
, "minimum parameter count exceeds maximum");
2193 if (tline
&& tok_is_(tline
->next
, "+")) {
2194 tline
= tline
->next
;
2197 if (tline
&& tok_type_(tline
->next
, TOK_ID
) &&
2198 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
2199 tline
= tline
->next
;
2204 * Handle default parameters.
2206 if (tline
&& tline
->next
) {
2207 def
->dlist
= tline
->next
;
2209 count_mmac_params(def
->dlist
, &def
->ndefs
, &def
->defaults
);
2212 def
->defaults
= NULL
;
2216 if (def
->defaults
&& def
->ndefs
> def
->nparam_max
- def
->nparam_min
&&
2218 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MDP
,
2219 "too many default macro parameters");
2226 * Decode a size directive
2228 static int parse_size(const char *str
) {
2229 static const char *size_names
[] =
2230 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2231 static const int sizes
[] =
2232 { 0, 1, 4, 16, 8, 10, 2, 32 };
2234 return sizes
[bsii(str
, size_names
, ARRAY_SIZE(size_names
))+1];
2238 * find and process preprocessor directive in passed line
2239 * Find out if a line contains a preprocessor directive, and deal
2242 * If a directive _is_ found, it is the responsibility of this routine
2243 * (and not the caller) to free_tlist() the line.
2245 * @param tline a pointer to the current tokeninzed line linked list
2246 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2249 static int do_directive(Token
* tline
)
2251 enum preproc_token i
;
2264 Token
*t
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
2265 struct tokenval tokval
;
2267 ExpDef
*ed
, *eed
, **edhead
;
2276 if (!tline
|| !tok_type_(tline
, TOK_PREPROC_ID
) ||
2277 (tline
->text
[1] == '%' || tline
->text
[1] == '$'
2278 || tline
->text
[1] == '!'))
2279 return NO_DIRECTIVE_FOUND
;
2281 i
= pp_token_hash(tline
->text
);
2285 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2286 error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2288 return NO_DIRECTIVE_FOUND
; /* didn't get it */
2291 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2292 /* Directive to tell NASM what the default stack size is. The
2293 * default is for a 16-bit stack, and this can be overriden with
2296 tline
= tline
->next
;
2297 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2298 tline
= tline
->next
;
2299 if (!tline
|| tline
->type
!= TOK_ID
) {
2300 error(ERR_NONFATAL
, "`%%stacksize' missing size parameter");
2301 free_tlist(origline
);
2302 return DIRECTIVE_FOUND
;
2304 if (nasm_stricmp(tline
->text
, "flat") == 0) {
2305 /* All subsequent ARG directives are for a 32-bit stack */
2307 StackPointer
= "ebp";
2310 } else if (nasm_stricmp(tline
->text
, "flat64") == 0) {
2311 /* All subsequent ARG directives are for a 64-bit stack */
2313 StackPointer
= "rbp";
2316 } else if (nasm_stricmp(tline
->text
, "large") == 0) {
2317 /* All subsequent ARG directives are for a 16-bit stack,
2318 * far function call.
2321 StackPointer
= "bp";
2324 } else if (nasm_stricmp(tline
->text
, "small") == 0) {
2325 /* All subsequent ARG directives are for a 16-bit stack,
2326 * far function call. We don't support near functions.
2329 StackPointer
= "bp";
2333 error(ERR_NONFATAL
, "`%%stacksize' invalid size type");
2334 free_tlist(origline
);
2335 return DIRECTIVE_FOUND
;
2337 free_tlist(origline
);
2338 return DIRECTIVE_FOUND
;
2341 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2342 /* TASM like ARG directive to define arguments to functions, in
2343 * the following form:
2345 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2349 char *arg
, directive
[256];
2350 int size
= StackSize
;
2352 /* Find the argument name */
2353 tline
= tline
->next
;
2354 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2355 tline
= tline
->next
;
2356 if (!tline
|| tline
->type
!= TOK_ID
) {
2357 error(ERR_NONFATAL
, "`%%arg' missing argument parameter");
2358 free_tlist(origline
);
2359 return DIRECTIVE_FOUND
;
2363 /* Find the argument size type */
2364 tline
= tline
->next
;
2365 if (!tline
|| tline
->type
!= TOK_OTHER
2366 || tline
->text
[0] != ':') {
2368 "Syntax error processing `%%arg' directive");
2369 free_tlist(origline
);
2370 return DIRECTIVE_FOUND
;
2372 tline
= tline
->next
;
2373 if (!tline
|| tline
->type
!= TOK_ID
) {
2374 error(ERR_NONFATAL
, "`%%arg' missing size type parameter");
2375 free_tlist(origline
);
2376 return DIRECTIVE_FOUND
;
2379 /* Allow macro expansion of type parameter */
2380 tt
= tokenize(tline
->text
);
2381 tt
= expand_smacro(tt
);
2382 size
= parse_size(tt
->text
);
2385 "Invalid size type for `%%arg' missing directive");
2387 free_tlist(origline
);
2388 return DIRECTIVE_FOUND
;
2392 /* Round up to even stack slots */
2393 size
= ALIGN(size
, StackSize
);
2395 /* Now define the macro for the argument */
2396 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
2397 arg
, StackPointer
, offset
);
2398 do_directive(tokenize(directive
));
2401 /* Move to the next argument in the list */
2402 tline
= tline
->next
;
2403 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2404 tline
= tline
->next
;
2405 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2407 free_tlist(origline
);
2408 return DIRECTIVE_FOUND
;
2411 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2412 /* TASM like LOCAL directive to define local variables for a
2413 * function, in the following form:
2415 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2417 * The '= LocalSize' at the end is ignored by NASM, but is
2418 * required by TASM to define the local parameter size (and used
2419 * by the TASM macro package).
2421 offset
= LocalOffset
;
2423 char *local
, directive
[256];
2424 int size
= StackSize
;
2426 /* Find the argument name */
2427 tline
= tline
->next
;
2428 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2429 tline
= tline
->next
;
2430 if (!tline
|| tline
->type
!= TOK_ID
) {
2432 "`%%local' missing argument parameter");
2433 free_tlist(origline
);
2434 return DIRECTIVE_FOUND
;
2436 local
= tline
->text
;
2438 /* Find the argument size type */
2439 tline
= tline
->next
;
2440 if (!tline
|| tline
->type
!= TOK_OTHER
2441 || tline
->text
[0] != ':') {
2443 "Syntax error processing `%%local' directive");
2444 free_tlist(origline
);
2445 return DIRECTIVE_FOUND
;
2447 tline
= tline
->next
;
2448 if (!tline
|| tline
->type
!= TOK_ID
) {
2450 "`%%local' missing size type parameter");
2451 free_tlist(origline
);
2452 return DIRECTIVE_FOUND
;
2455 /* Allow macro expansion of type parameter */
2456 tt
= tokenize(tline
->text
);
2457 tt
= expand_smacro(tt
);
2458 size
= parse_size(tt
->text
);
2461 "Invalid size type for `%%local' missing directive");
2463 free_tlist(origline
);
2464 return DIRECTIVE_FOUND
;
2468 /* Round up to even stack slots */
2469 size
= ALIGN(size
, StackSize
);
2471 offset
+= size
; /* Negative offset, increment before */
2473 /* Now define the macro for the argument */
2474 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
2475 local
, StackPointer
, offset
);
2476 do_directive(tokenize(directive
));
2478 /* Now define the assign to setup the enter_c macro correctly */
2479 snprintf(directive
, sizeof(directive
),
2480 "%%assign %%$localsize %%$localsize+%d", size
);
2481 do_directive(tokenize(directive
));
2483 /* Move to the next argument in the list */
2484 tline
= tline
->next
;
2485 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2486 tline
= tline
->next
;
2487 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2488 LocalOffset
= offset
;
2489 free_tlist(origline
);
2490 return DIRECTIVE_FOUND
;
2493 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2495 error(ERR_WARNING
|ERR_PASS1
,
2496 "trailing garbage after `%%clear' ignored");
2499 free_tlist(origline
);
2500 return DIRECTIVE_FOUND
;
2503 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2504 t
= tline
->next
= expand_smacro(tline
->next
);
2506 if (!t
|| (t
->type
!= TOK_STRING
&&
2507 t
->type
!= TOK_INTERNAL_STRING
)) {
2508 error(ERR_NONFATAL
, "`%%depend' expects a file name");
2509 free_tlist(origline
);
2510 return DIRECTIVE_FOUND
; /* but we did _something_ */
2513 error(ERR_WARNING
|ERR_PASS1
,
2514 "trailing garbage after `%%depend' ignored");
2516 if (t
->type
!= TOK_INTERNAL_STRING
)
2517 nasm_unquote_cstr(p
, i
);
2518 if (dephead
&& !in_list(*dephead
, p
)) {
2519 StrList
*sl
= nasm_malloc(strlen(p
)+1+sizeof sl
->next
);
2523 deptail
= &sl
->next
;
2525 free_tlist(origline
);
2526 return DIRECTIVE_FOUND
;
2529 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2530 t
= tline
->next
= expand_smacro(tline
->next
);
2533 if (!t
|| (t
->type
!= TOK_STRING
&&
2534 t
->type
!= TOK_INTERNAL_STRING
)) {
2535 error(ERR_NONFATAL
, "`%%include' expects a file name");
2536 free_tlist(origline
);
2537 return DIRECTIVE_FOUND
; /* but we did _something_ */
2540 error(ERR_WARNING
|ERR_PASS1
,
2541 "trailing garbage after `%%include' ignored");
2543 if (t
->type
!= TOK_INTERNAL_STRING
)
2544 nasm_unquote_cstr(p
, i
);
2545 inc
= nasm_malloc(sizeof(Include
));
2547 inc
->fp
= inc_fopen(p
, dephead
, &deptail
, pass
== 0);
2549 /* -MG given but file not found */
2552 inc
->fname
= src_set_fname(nasm_strdup(p
));
2553 inc
->lineno
= src_set_linnum(0);
2555 inc
->expansion
= NULL
;
2557 list
->uplevel(LIST_INCLUDE
);
2559 free_tlist(origline
);
2560 return DIRECTIVE_FOUND
;
2563 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2565 static macros_t
*use_pkg
;
2566 const char *pkg_macro
= NULL
;
2568 tline
= tline
->next
;
2570 tline
= expand_id(tline
);
2572 if (!tline
|| (tline
->type
!= TOK_STRING
&&
2573 tline
->type
!= TOK_INTERNAL_STRING
&&
2574 tline
->type
!= TOK_ID
)) {
2575 error(ERR_NONFATAL
, "`%%use' expects a package name");
2576 free_tlist(origline
);
2577 return DIRECTIVE_FOUND
; /* but we did _something_ */
2580 error(ERR_WARNING
|ERR_PASS1
,
2581 "trailing garbage after `%%use' ignored");
2582 if (tline
->type
== TOK_STRING
)
2583 nasm_unquote_cstr(tline
->text
, i
);
2584 use_pkg
= nasm_stdmac_find_package(tline
->text
);
2586 error(ERR_NONFATAL
, "unknown `%%use' package: %s", tline
->text
);
2588 pkg_macro
= (char *)use_pkg
+ 1; /* The first string will be <%define>__USE_*__ */
2589 if (use_pkg
&& ! smacro_defined(NULL
, pkg_macro
, 0, NULL
, true)) {
2590 /* Not already included, go ahead and include it */
2591 stdmacpos
= use_pkg
;
2593 free_tlist(origline
);
2594 return DIRECTIVE_FOUND
;
2599 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2600 tline
= tline
->next
;
2602 tline
= expand_id(tline
);
2604 if (!tok_type_(tline
, TOK_ID
)) {
2605 error(ERR_NONFATAL
, "`%s' expects a context identifier",
2607 free_tlist(origline
);
2608 return DIRECTIVE_FOUND
; /* but we did _something_ */
2611 error(ERR_WARNING
|ERR_PASS1
,
2612 "trailing garbage after `%s' ignored",
2614 p
= nasm_strdup(tline
->text
);
2616 p
= NULL
; /* Anonymous */
2620 ctx
= nasm_malloc(sizeof(Context
));
2622 hash_init(&ctx
->localmac
, HASH_SMALL
);
2624 ctx
->number
= unique
++;
2629 error(ERR_NONFATAL
, "`%s': context stack is empty",
2631 } else if (i
== PP_POP
) {
2632 if (p
&& (!cstk
->name
|| nasm_stricmp(p
, cstk
->name
)))
2633 error(ERR_NONFATAL
, "`%%pop' in wrong context: %s, "
2635 cstk
->name
? cstk
->name
: "anonymous", p
);
2640 nasm_free(cstk
->name
);
2646 free_tlist(origline
);
2647 return DIRECTIVE_FOUND
;
2649 severity
= ERR_FATAL
;
2652 severity
= ERR_NONFATAL
;
2655 severity
= ERR_WARNING
|ERR_WARN_USER
;
2659 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2661 /* Only error out if this is the final pass */
2662 if (pass
!= 2 && i
!= PP_FATAL
)
2663 return DIRECTIVE_FOUND
;
2665 tline
->next
= expand_smacro(tline
->next
);
2666 tline
= tline
->next
;
2668 t
= tline
? tline
->next
: NULL
;
2670 if (tok_type_(tline
, TOK_STRING
) && !t
) {
2671 /* The line contains only a quoted string */
2673 nasm_unquote(p
, NULL
); /* Ignore NUL character truncation */
2674 error(severity
, "%s", p
);
2676 /* Not a quoted string, or more than a quoted string */
2677 p
= detoken(tline
, false);
2678 error(severity
, "%s", p
);
2681 free_tlist(origline
);
2682 return DIRECTIVE_FOUND
;
2686 if (defining
!= NULL
) {
2687 if (defining
->type
== EXP_IF
) {
2688 defining
->def_depth
++;
2690 return NO_DIRECTIVE_FOUND
;
2692 if ((istk
->expansion
!= NULL
) &&
2693 (istk
->expansion
->emitting
== false)) {
2696 j
= if_condition(tline
->next
, i
);
2697 tline
->next
= NULL
; /* it got freed */
2698 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
2700 ed
= new_ExpDef(EXP_IF
);
2706 ed
->ignoring
= ((ed
->state
== COND_IF_TRUE
) ? false : true);
2707 ed
->prev
= defining
;
2709 free_tlist(origline
);
2710 return DIRECTIVE_FOUND
;
2713 if (defining
!= NULL
) {
2714 if ((defining
->type
!= EXP_IF
) || (defining
->def_depth
> 0)) {
2715 return NO_DIRECTIVE_FOUND
;
2718 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2719 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2721 switch (defining
->state
) {
2723 defining
->state
= COND_DONE
;
2724 defining
->ignoring
= true;
2729 defining
->ignoring
= true;
2732 case COND_ELSE_TRUE
:
2733 case COND_ELSE_FALSE
:
2734 error_precond(ERR_WARNING
|ERR_PASS1
,
2735 "`%%elif' after `%%else' ignored");
2736 defining
->state
= COND_NEVER
;
2737 defining
->ignoring
= true;
2742 * IMPORTANT: In the case of %if, we will already have
2743 * called expand_mmac_params(); however, if we're
2744 * processing an %elif we must have been in a
2745 * non-emitting mode, which would have inhibited
2746 * the normal invocation of expand_mmac_params().
2747 * Therefore, we have to do it explicitly here.
2749 j
= if_condition(expand_mmac_params(tline
->next
), i
);
2750 tline
->next
= NULL
; /* it got freed */
2752 j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2753 defining
->ignoring
= ((defining
->state
== COND_IF_TRUE
) ? false : true);
2756 free_tlist(origline
);
2757 return DIRECTIVE_FOUND
;
2760 if (defining
!= NULL
) {
2761 if ((defining
->type
!= EXP_IF
) || (defining
->def_depth
> 0)) {
2762 return NO_DIRECTIVE_FOUND
;
2766 error_precond(ERR_WARNING
|ERR_PASS1
,
2767 "trailing garbage after `%%else' ignored");
2768 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2769 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2771 switch (defining
->state
) {
2774 defining
->state
= COND_ELSE_FALSE
;
2775 defining
->ignoring
= true;
2779 defining
->ignoring
= true;
2783 defining
->state
= COND_ELSE_TRUE
;
2784 defining
->ignoring
= false;
2787 case COND_ELSE_TRUE
:
2788 case COND_ELSE_FALSE
:
2789 error_precond(ERR_WARNING
|ERR_PASS1
,
2790 "`%%else' after `%%else' ignored.");
2791 defining
->state
= COND_NEVER
;
2792 defining
->ignoring
= true;
2795 free_tlist(origline
);
2796 return DIRECTIVE_FOUND
;
2799 if (defining
!= NULL
) {
2800 if (defining
->type
== EXP_IF
) {
2801 if (defining
->def_depth
> 0) {
2802 defining
->def_depth
--;
2803 return NO_DIRECTIVE_FOUND
;
2806 return NO_DIRECTIVE_FOUND
;
2810 error_precond(ERR_WARNING
|ERR_PASS1
,
2811 "trailing garbage after `%%endif' ignored");
2812 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2813 error(ERR_NONFATAL
, "`%%endif': no matching `%%if'");
2816 defining
= ed
->prev
;
2817 ed
->prev
= expansions
;
2819 ei
= new_ExpInv(EXP_IF
, ed
);
2820 ei
->current
= ed
->line
;
2821 ei
->emitting
= true;
2822 ei
->prev
= istk
->expansion
;
2823 istk
->expansion
= ei
;
2824 free_tlist(origline
);
2825 return DIRECTIVE_FOUND
;
2831 if (defining
!= NULL
) {
2832 if (defining
->type
== EXP_MMACRO
) {
2833 defining
->def_depth
++;
2835 return NO_DIRECTIVE_FOUND
;
2837 ed
= new_ExpDef(EXP_MMACRO
);
2839 (i
== PP_RMACRO
) || (i
== PP_IRMACRO
) ? DEADMAN_LIMIT
: 0;
2840 ed
->casesense
= (i
== PP_MACRO
) || (i
== PP_RMACRO
);
2841 if (!parse_mmacro_spec(tline
, ed
, pp_directives
[i
])) {
2844 return DIRECTIVE_FOUND
;
2848 ed
->max_depth
= (ed
->max_depth
+ 1);
2849 ed
->ignoring
= false;
2850 ed
->prev
= defining
;
2853 eed
= (ExpDef
*) hash_findix(&expdefs
, ed
->name
);
2855 if (!strcmp(eed
->name
, ed
->name
) &&
2856 (eed
->nparam_min
<= ed
->nparam_max
2858 && (ed
->nparam_min
<= eed
->nparam_max
2860 error(ERR_WARNING
|ERR_PASS1
,
2861 "redefining multi-line macro `%s'", ed
->name
);
2862 return DIRECTIVE_FOUND
;
2866 free_tlist(origline
);
2867 return DIRECTIVE_FOUND
;
2871 if (defining
!= NULL
) {
2872 if (defining
->type
== EXP_MMACRO
) {
2873 if (defining
->def_depth
> 0) {
2874 defining
->def_depth
--;
2875 return NO_DIRECTIVE_FOUND
;
2878 return NO_DIRECTIVE_FOUND
;
2881 if (!(defining
) || (defining
->type
!= EXP_MMACRO
)) {
2882 error(ERR_NONFATAL
, "`%s': not defining a macro", tline
->text
);
2883 return DIRECTIVE_FOUND
;
2885 edhead
= (ExpDef
**) hash_findi_add(&expdefs
, defining
->name
);
2886 defining
->next
= *edhead
;
2889 defining
= ed
->prev
;
2890 ed
->prev
= expansions
;
2893 free_tlist(origline
);
2894 return DIRECTIVE_FOUND
;
2897 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2899 * We must search along istk->expansion until we hit a
2900 * macro invocation. Then we disable the emitting state(s)
2901 * between exitmacro and endmacro.
2903 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
2904 if(ei
->type
== EXP_MMACRO
) {
2911 * Set all invocations leading back to the macro
2912 * invocation to a non-emitting state.
2914 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
2915 eei
->emitting
= false;
2917 eei
->emitting
= false;
2919 error(ERR_NONFATAL
, "`%%exitmacro' not within `%%macro' block");
2921 free_tlist(origline
);
2922 return DIRECTIVE_FOUND
;
2926 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2931 spec
.casesense
= (i
== PP_UNMACRO
);
2932 if (!parse_mmacro_spec(tline
, &spec
, pp_directives
[i
])) {
2933 return DIRECTIVE_FOUND
;
2935 ed_p
= (ExpDef
**) hash_findi(&expdefs
, spec
.name
, NULL
);
2936 while (ed_p
&& *ed_p
) {
2938 if (ed
->casesense
== spec
.casesense
&&
2939 !mstrcmp(ed
->name
, spec
.name
, spec
.casesense
) &&
2940 ed
->nparam_min
== spec
.nparam_min
&&
2941 ed
->nparam_max
== spec
.nparam_max
&&
2942 ed
->plus
== spec
.plus
) {
2949 free_tlist(origline
);
2950 free_tlist(spec
.dlist
);
2951 return DIRECTIVE_FOUND
;
2955 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2956 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
2957 tline
= tline
->next
;
2959 free_tlist(origline
);
2960 error(ERR_NONFATAL
, "`%%rotate' missing rotate count");
2961 return DIRECTIVE_FOUND
;
2963 t
= expand_smacro(tline
->next
);
2965 free_tlist(origline
);
2968 tokval
.t_type
= TOKEN_INVALID
;
2970 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
2973 return DIRECTIVE_FOUND
;
2975 error(ERR_WARNING
|ERR_PASS1
,
2976 "trailing garbage after expression ignored");
2977 if (!is_simple(evalresult
)) {
2978 error(ERR_NONFATAL
, "non-constant value given to `%%rotate'");
2979 return DIRECTIVE_FOUND
;
2981 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
2982 if (ei
->type
== EXP_MMACRO
) {
2987 error(ERR_NONFATAL
, "`%%rotate' invoked outside a macro call");
2988 } else if (ei
->nparam
== 0) {
2990 "`%%rotate' invoked within macro without parameters");
2992 int rotate
= ei
->rotate
+ reloc_value(evalresult
);
2994 rotate
%= (int)ei
->nparam
;
2996 rotate
+= ei
->nparam
;
2997 ei
->rotate
= rotate
;
2999 return DIRECTIVE_FOUND
;
3002 if (defining
!= NULL
) {
3003 if (defining
->type
== EXP_REP
) {
3004 defining
->def_depth
++;
3006 return NO_DIRECTIVE_FOUND
;
3010 tline
= tline
->next
;
3011 } while (tok_type_(tline
, TOK_WHITESPACE
));
3013 if (tok_type_(tline
, TOK_ID
) &&
3014 nasm_stricmp(tline
->text
, ".nolist") == 0) {
3017 tline
= tline
->next
;
3018 } while (tok_type_(tline
, TOK_WHITESPACE
));
3022 t
= expand_smacro(tline
);
3024 tokval
.t_type
= TOKEN_INVALID
;
3026 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3028 free_tlist(origline
);
3029 return DIRECTIVE_FOUND
;
3032 error(ERR_WARNING
|ERR_PASS1
,
3033 "trailing garbage after expression ignored");
3034 if (!is_simple(evalresult
)) {
3035 error(ERR_NONFATAL
, "non-constant value given to `%%rep'");
3036 return DIRECTIVE_FOUND
;
3038 count
= reloc_value(evalresult
) + 1;
3040 error(ERR_NONFATAL
, "`%%rep' expects a repeat count");
3043 free_tlist(origline
);
3044 ed
= new_ExpDef(EXP_REP
);
3045 ed
->nolist
= nolist
;
3048 ed
->max_depth
= (count
- 1);
3049 ed
->ignoring
= false;
3050 ed
->prev
= defining
;
3052 return DIRECTIVE_FOUND
;
3055 if (defining
!= NULL
) {
3056 if (defining
->type
== EXP_REP
) {
3057 if (defining
->def_depth
> 0) {
3058 defining
->def_depth
--;
3059 return NO_DIRECTIVE_FOUND
;
3062 return NO_DIRECTIVE_FOUND
;
3065 if ((defining
== NULL
) || (defining
->type
!= EXP_REP
)) {
3066 error(ERR_NONFATAL
, "`%%endrep': no matching `%%rep'");
3067 return DIRECTIVE_FOUND
;
3071 * Now we have a "macro" defined - although it has no name
3072 * and we won't be entering it in the hash tables - we must
3073 * push a macro-end marker for it on to istk->expansion.
3074 * After that, it will take care of propagating itself (a
3075 * macro-end marker line for a macro which is really a %rep
3076 * block will cause the macro to be re-expanded, complete
3077 * with another macro-end marker to ensure the process
3078 * continues) until the whole expansion is forcibly removed
3079 * from istk->expansion by a %exitrep.
3082 defining
= ed
->prev
;
3083 ed
->prev
= expansions
;
3085 ei
= new_ExpInv(EXP_REP
, ed
);
3086 ei
->current
= ed
->line
;
3087 ei
->emitting
= ((ed
->max_depth
> 0) ? true : false);
3088 list
->uplevel(ed
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
3089 ei
->prev
= istk
->expansion
;
3090 istk
->expansion
= ei
;
3091 free_tlist(origline
);
3092 return DIRECTIVE_FOUND
;
3095 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3097 * We must search along istk->expansion until we hit a
3098 * rep invocation. Then we disable the emitting state(s)
3099 * between exitrep and endrep.
3101 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3102 if (ei
->type
== EXP_REP
) {
3109 * Set all invocations leading back to the rep
3110 * invocation to a non-emitting state.
3112 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3113 eei
->emitting
= false;
3115 eei
->emitting
= false;
3116 eei
->current
= NULL
;
3117 eei
->def
->cur_depth
= eei
->def
->max_depth
;
3119 error(ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
3121 free_tlist(origline
);
3122 return DIRECTIVE_FOUND
;
3128 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3129 casesense
= (i
== PP_DEFINE
|| i
== PP_XDEFINE
);
3131 tline
= tline
->next
;
3133 tline
= expand_id(tline
);
3134 if (!tline
|| (tline
->type
!= TOK_ID
&&
3135 (tline
->type
!= TOK_PREPROC_ID
||
3136 tline
->text
[1] != '$'))) {
3137 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3139 free_tlist(origline
);
3140 return DIRECTIVE_FOUND
;
3143 ctx
= get_ctx(tline
->text
, &mname
, false);
3145 param_start
= tline
= tline
->next
;
3148 /* Expand the macro definition now for %xdefine and %ixdefine */
3149 if ((i
== PP_XDEFINE
) || (i
== PP_IXDEFINE
))
3150 tline
= expand_smacro(tline
);
3152 if (tok_is_(tline
, "(")) {
3154 * This macro has parameters.
3157 tline
= tline
->next
;
3161 error(ERR_NONFATAL
, "parameter identifier expected");
3162 free_tlist(origline
);
3163 return DIRECTIVE_FOUND
;
3165 if (tline
->type
!= TOK_ID
) {
3167 "`%s': parameter identifier expected",
3169 free_tlist(origline
);
3170 return DIRECTIVE_FOUND
;
3172 tline
->type
= TOK_SMAC_PARAM
+ nparam
++;
3173 tline
= tline
->next
;
3175 if (tok_is_(tline
, ",")) {
3176 tline
= tline
->next
;
3178 if (!tok_is_(tline
, ")")) {
3180 "`)' expected to terminate macro template");
3181 free_tlist(origline
);
3182 return DIRECTIVE_FOUND
;
3188 tline
= tline
->next
;
3190 if (tok_type_(tline
, TOK_WHITESPACE
))
3191 last
= tline
, tline
= tline
->next
;
3196 if (t
->type
== TOK_ID
) {
3197 list_for_each(tt
, param_start
)
3198 if (tt
->type
>= TOK_SMAC_PARAM
&&
3199 !strcmp(tt
->text
, t
->text
))
3203 t
->next
= macro_start
;
3208 * Good. We now have a macro name, a parameter count, and a
3209 * token list (in reverse order) for an expansion. We ought
3210 * to be OK just to create an SMacro, store it, and let
3211 * free_tlist have the rest of the line (which we have
3212 * carefully re-terminated after chopping off the expansion
3215 define_smacro(ctx
, mname
, casesense
, nparam
, macro_start
);
3216 free_tlist(origline
);
3217 return DIRECTIVE_FOUND
;
3220 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3221 tline
= tline
->next
;
3223 tline
= expand_id(tline
);
3224 if (!tline
|| (tline
->type
!= TOK_ID
&&
3225 (tline
->type
!= TOK_PREPROC_ID
||
3226 tline
->text
[1] != '$'))) {
3227 error(ERR_NONFATAL
, "`%%undef' expects a macro identifier");
3228 free_tlist(origline
);
3229 return DIRECTIVE_FOUND
;
3232 error(ERR_WARNING
|ERR_PASS1
,
3233 "trailing garbage after macro name ignored");
3236 /* Find the context that symbol belongs to */
3237 ctx
= get_ctx(tline
->text
, &mname
, false);
3238 undef_smacro(ctx
, mname
);
3239 free_tlist(origline
);
3240 return DIRECTIVE_FOUND
;
3244 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3245 casesense
= (i
== PP_DEFSTR
);
3247 tline
= tline
->next
;
3249 tline
= expand_id(tline
);
3250 if (!tline
|| (tline
->type
!= TOK_ID
&&
3251 (tline
->type
!= TOK_PREPROC_ID
||
3252 tline
->text
[1] != '$'))) {
3253 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3255 free_tlist(origline
);
3256 return DIRECTIVE_FOUND
;
3259 ctx
= get_ctx(tline
->text
, &mname
, false);
3261 tline
= expand_smacro(tline
->next
);
3264 while (tok_type_(tline
, TOK_WHITESPACE
))
3265 tline
= delete_Token(tline
);
3267 p
= detoken(tline
, false);
3268 macro_start
= nasm_malloc(sizeof(*macro_start
));
3269 macro_start
->next
= NULL
;
3270 macro_start
->text
= nasm_quote(p
, strlen(p
));
3271 macro_start
->type
= TOK_STRING
;
3272 macro_start
->a
.mac
= NULL
;
3276 * We now have a macro name, an implicit parameter count of
3277 * zero, and a string token to use as an expansion. Create
3278 * and store an SMacro.
3280 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3281 free_tlist(origline
);
3282 return DIRECTIVE_FOUND
;
3286 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3287 casesense
= (i
== PP_DEFTOK
);
3289 tline
= tline
->next
;
3291 tline
= expand_id(tline
);
3292 if (!tline
|| (tline
->type
!= TOK_ID
&&
3293 (tline
->type
!= TOK_PREPROC_ID
||
3294 tline
->text
[1] != '$'))) {
3296 "`%s' expects a macro identifier as first parameter",
3298 free_tlist(origline
);
3299 return DIRECTIVE_FOUND
;
3301 ctx
= get_ctx(tline
->text
, &mname
, false);
3303 tline
= expand_smacro(tline
->next
);
3307 while (tok_type_(t
, TOK_WHITESPACE
))
3309 /* t should now point to the string */
3310 if (t
->type
!= TOK_STRING
) {
3312 "`%s` requires string as second parameter",
3315 free_tlist(origline
);
3316 return DIRECTIVE_FOUND
;
3319 nasm_unquote_cstr(t
->text
, i
);
3320 macro_start
= tokenize(t
->text
);
3323 * We now have a macro name, an implicit parameter count of
3324 * zero, and a numeric token to use as an expansion. Create
3325 * and store an SMacro.
3327 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3329 free_tlist(origline
);
3330 return DIRECTIVE_FOUND
;
3333 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3336 StrList
*xsl
= NULL
;
3337 StrList
**xst
= &xsl
;
3341 tline
= tline
->next
;
3343 tline
= expand_id(tline
);
3344 if (!tline
|| (tline
->type
!= TOK_ID
&&
3345 (tline
->type
!= TOK_PREPROC_ID
||
3346 tline
->text
[1] != '$'))) {
3348 "`%%pathsearch' expects a macro identifier as first parameter");
3349 free_tlist(origline
);
3350 return DIRECTIVE_FOUND
;
3352 ctx
= get_ctx(tline
->text
, &mname
, false);
3354 tline
= expand_smacro(tline
->next
);
3358 while (tok_type_(t
, TOK_WHITESPACE
))
3361 if (!t
|| (t
->type
!= TOK_STRING
&&
3362 t
->type
!= TOK_INTERNAL_STRING
)) {
3363 error(ERR_NONFATAL
, "`%%pathsearch' expects a file name");
3365 free_tlist(origline
);
3366 return DIRECTIVE_FOUND
; /* but we did _something_ */
3369 error(ERR_WARNING
|ERR_PASS1
,
3370 "trailing garbage after `%%pathsearch' ignored");
3372 if (t
->type
!= TOK_INTERNAL_STRING
)
3373 nasm_unquote(p
, NULL
);
3375 fp
= inc_fopen(p
, &xsl
, &xst
, true);
3378 fclose(fp
); /* Don't actually care about the file */
3380 macro_start
= nasm_malloc(sizeof(*macro_start
));
3381 macro_start
->next
= NULL
;
3382 macro_start
->text
= nasm_quote(p
, strlen(p
));
3383 macro_start
->type
= TOK_STRING
;
3384 macro_start
->a
.mac
= NULL
;
3389 * We now have a macro name, an implicit parameter count of
3390 * zero, and a string token to use as an expansion. Create
3391 * and store an SMacro.
3393 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3395 free_tlist(origline
);
3396 return DIRECTIVE_FOUND
;
3400 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3403 tline
= tline
->next
;
3405 tline
= expand_id(tline
);
3406 if (!tline
|| (tline
->type
!= TOK_ID
&&
3407 (tline
->type
!= TOK_PREPROC_ID
||
3408 tline
->text
[1] != '$'))) {
3410 "`%%strlen' expects a macro identifier as first parameter");
3411 free_tlist(origline
);
3412 return DIRECTIVE_FOUND
;
3414 ctx
= get_ctx(tline
->text
, &mname
, false);
3416 tline
= expand_smacro(tline
->next
);
3420 while (tok_type_(t
, TOK_WHITESPACE
))
3422 /* t should now point to the string */
3423 if (!tok_type_(t
, TOK_STRING
)) {
3425 "`%%strlen` requires string as second parameter");
3427 free_tlist(origline
);
3428 return DIRECTIVE_FOUND
;
3431 macro_start
= nasm_malloc(sizeof(*macro_start
));
3432 macro_start
->next
= NULL
;
3433 make_tok_num(macro_start
, nasm_unquote(t
->text
, NULL
));
3434 macro_start
->a
.mac
= NULL
;
3437 * We now have a macro name, an implicit parameter count of
3438 * zero, and a numeric token to use as an expansion. Create
3439 * and store an SMacro.
3441 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3443 free_tlist(origline
);
3444 return DIRECTIVE_FOUND
;
3447 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3450 tline
= tline
->next
;
3452 tline
= expand_id(tline
);
3453 if (!tline
|| (tline
->type
!= TOK_ID
&&
3454 (tline
->type
!= TOK_PREPROC_ID
||
3455 tline
->text
[1] != '$'))) {
3457 "`%%strcat' expects a macro identifier as first parameter");
3458 free_tlist(origline
);
3459 return DIRECTIVE_FOUND
;
3461 ctx
= get_ctx(tline
->text
, &mname
, false);
3463 tline
= expand_smacro(tline
->next
);
3467 list_for_each(t
, tline
) {
3469 case TOK_WHITESPACE
:
3472 len
+= t
->a
.len
= nasm_unquote(t
->text
, NULL
);
3475 if (!strcmp(t
->text
, ",")) /* permit comma separators */
3477 /* else fall through */
3480 "non-string passed to `%%strcat' (%d)", t
->type
);
3482 free_tlist(origline
);
3483 return DIRECTIVE_FOUND
;
3487 p
= pp
= nasm_malloc(len
);
3488 list_for_each(t
, tline
) {
3489 if (t
->type
== TOK_STRING
) {
3490 memcpy(p
, t
->text
, t
->a
.len
);
3496 * We now have a macro name, an implicit parameter count of
3497 * zero, and a numeric token to use as an expansion. Create
3498 * and store an SMacro.
3500 macro_start
= new_Token(NULL
, TOK_STRING
, NULL
, 0);
3501 macro_start
->text
= nasm_quote(pp
, len
);
3503 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3505 free_tlist(origline
);
3506 return DIRECTIVE_FOUND
;
3509 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3516 tline
= tline
->next
;
3518 tline
= expand_id(tline
);
3519 if (!tline
|| (tline
->type
!= TOK_ID
&&
3520 (tline
->type
!= TOK_PREPROC_ID
||
3521 tline
->text
[1] != '$'))) {
3523 "`%%substr' expects a macro identifier as first parameter");
3524 free_tlist(origline
);
3525 return DIRECTIVE_FOUND
;
3527 ctx
= get_ctx(tline
->text
, &mname
, false);
3529 tline
= expand_smacro(tline
->next
);
3533 while (tok_type_(t
, TOK_WHITESPACE
))
3536 /* t should now point to the string */
3537 if (t
->type
!= TOK_STRING
) {
3539 "`%%substr` requires string as second parameter");
3541 free_tlist(origline
);
3542 return DIRECTIVE_FOUND
;
3547 tokval
.t_type
= TOKEN_INVALID
;
3548 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3552 free_tlist(origline
);
3553 return DIRECTIVE_FOUND
;
3554 } else if (!is_simple(evalresult
)) {
3555 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3557 free_tlist(origline
);
3558 return DIRECTIVE_FOUND
;
3560 a1
= evalresult
->value
-1;
3562 while (tok_type_(tt
, TOK_WHITESPACE
))
3565 a2
= 1; /* Backwards compatibility: one character */
3567 tokval
.t_type
= TOKEN_INVALID
;
3568 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3572 free_tlist(origline
);
3573 return DIRECTIVE_FOUND
;
3574 } else if (!is_simple(evalresult
)) {
3575 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3577 free_tlist(origline
);
3578 return DIRECTIVE_FOUND
;
3580 a2
= evalresult
->value
;
3583 len
= nasm_unquote(t
->text
, NULL
);
3586 if (a1
+a2
> (int64_t)len
)
3589 macro_start
= nasm_malloc(sizeof(*macro_start
));
3590 macro_start
->next
= NULL
;
3591 macro_start
->text
= nasm_quote((a1
< 0) ? "" : t
->text
+a1
, a2
);
3592 macro_start
->type
= TOK_STRING
;
3593 macro_start
->a
.mac
= NULL
;
3596 * We now have a macro name, an implicit parameter count of
3597 * zero, and a numeric token to use as an expansion. Create
3598 * and store an SMacro.
3600 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3602 free_tlist(origline
);
3603 return DIRECTIVE_FOUND
;
3608 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3609 casesense
= (i
== PP_ASSIGN
);
3611 tline
= tline
->next
;
3613 tline
= expand_id(tline
);
3614 if (!tline
|| (tline
->type
!= TOK_ID
&&
3615 (tline
->type
!= TOK_PREPROC_ID
||
3616 tline
->text
[1] != '$'))) {
3618 "`%%%sassign' expects a macro identifier",
3619 (i
== PP_IASSIGN
? "i" : ""));
3620 free_tlist(origline
);
3621 return DIRECTIVE_FOUND
;
3623 ctx
= get_ctx(tline
->text
, &mname
, false);
3625 tline
= expand_smacro(tline
->next
);
3630 tokval
.t_type
= TOKEN_INVALID
;
3632 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3635 free_tlist(origline
);
3636 return DIRECTIVE_FOUND
;
3640 error(ERR_WARNING
|ERR_PASS1
,
3641 "trailing garbage after expression ignored");
3643 if (!is_simple(evalresult
)) {
3645 "non-constant value given to `%%%sassign'",
3646 (i
== PP_IASSIGN
? "i" : ""));
3647 free_tlist(origline
);
3648 return DIRECTIVE_FOUND
;
3651 macro_start
= nasm_malloc(sizeof(*macro_start
));
3652 macro_start
->next
= NULL
;
3653 make_tok_num(macro_start
, reloc_value(evalresult
));
3654 macro_start
->a
.mac
= NULL
;
3657 * We now have a macro name, an implicit parameter count of
3658 * zero, and a numeric token to use as an expansion. Create
3659 * and store an SMacro.
3661 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3662 free_tlist(origline
);
3663 return DIRECTIVE_FOUND
;
3666 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3668 * Syntax is `%line nnn[+mmm] [filename]'
3670 tline
= tline
->next
;
3672 if (!tok_type_(tline
, TOK_NUMBER
)) {
3673 error(ERR_NONFATAL
, "`%%line' expects line number");
3674 free_tlist(origline
);
3675 return DIRECTIVE_FOUND
;
3677 k
= readnum(tline
->text
, &err
);
3679 tline
= tline
->next
;
3680 if (tok_is_(tline
, "+")) {
3681 tline
= tline
->next
;
3682 if (!tok_type_(tline
, TOK_NUMBER
)) {
3683 error(ERR_NONFATAL
, "`%%line' expects line increment");
3684 free_tlist(origline
);
3685 return DIRECTIVE_FOUND
;
3687 m
= readnum(tline
->text
, &err
);
3688 tline
= tline
->next
;
3694 nasm_free(src_set_fname(detoken(tline
, false)));
3696 free_tlist(origline
);
3697 return DIRECTIVE_FOUND
;
3700 if (defining
!= NULL
) {
3701 if (defining
->type
== EXP_WHILE
) {
3702 defining
->def_depth
++;
3704 return NO_DIRECTIVE_FOUND
;
3707 if ((istk
->expansion
!= NULL
) &&
3708 (istk
->expansion
->emitting
== false)) {
3712 l
->first
= copy_Token(tline
->next
);
3713 j
= if_condition(tline
->next
, i
);
3714 tline
->next
= NULL
; /* it got freed */
3715 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
3717 ed
= new_ExpDef(EXP_WHILE
);
3720 ed
->max_depth
= DEADMAN_LIMIT
;
3721 ed
->ignoring
= ((ed
->state
== COND_IF_TRUE
) ? false : true);
3722 if (ed
->ignoring
== false) {
3725 } else if (l
!= NULL
) {
3726 delete_Token(l
->first
);
3730 ed
->prev
= defining
;
3732 free_tlist(origline
);
3733 return DIRECTIVE_FOUND
;
3736 if (defining
!= NULL
) {
3737 if (defining
->type
== EXP_WHILE
) {
3738 if (defining
->def_depth
> 0) {
3739 defining
->def_depth
--;
3740 return NO_DIRECTIVE_FOUND
;
3743 return NO_DIRECTIVE_FOUND
;
3746 if (tline
->next
!= NULL
) {
3747 error_precond(ERR_WARNING
|ERR_PASS1
,
3748 "trailing garbage after `%%endwhile' ignored");
3750 if ((defining
== NULL
) || (defining
->type
!= EXP_WHILE
)) {
3751 error(ERR_NONFATAL
, "`%%endwhile': no matching `%%while'");
3752 return DIRECTIVE_FOUND
;
3755 defining
= ed
->prev
;
3756 if (ed
->ignoring
== false) {
3757 ed
->prev
= expansions
;
3759 ei
= new_ExpInv(EXP_WHILE
, ed
);
3760 ei
->current
= ed
->line
->next
;
3761 ei
->emitting
= true;
3762 ei
->prev
= istk
->expansion
;
3763 istk
->expansion
= ei
;
3767 free_tlist(origline
);
3768 return DIRECTIVE_FOUND
;
3771 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3773 * We must search along istk->expansion until we hit a
3774 * while invocation. Then we disable the emitting state(s)
3775 * between exitwhile and endwhile.
3777 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3778 if (ei
->type
== EXP_WHILE
) {
3785 * Set all invocations leading back to the while
3786 * invocation to a non-emitting state.
3788 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3789 eei
->emitting
= false;
3791 eei
->emitting
= false;
3792 eei
->current
= NULL
;
3793 eei
->def
->cur_depth
= eei
->def
->max_depth
;
3795 error(ERR_NONFATAL
, "`%%exitwhile' not within `%%while' block");
3797 free_tlist(origline
);
3798 return DIRECTIVE_FOUND
;
3801 if (defining
!= NULL
) {
3802 if (defining
->type
== EXP_COMMENT
) {
3803 defining
->def_depth
++;
3805 return NO_DIRECTIVE_FOUND
;
3807 ed
= new_ExpDef(EXP_COMMENT
);
3808 ed
->ignoring
= true;
3809 ed
->prev
= defining
;
3811 free_tlist(origline
);
3812 return DIRECTIVE_FOUND
;
3815 if (defining
!= NULL
) {
3816 if (defining
->type
== EXP_COMMENT
) {
3817 if (defining
->def_depth
> 0) {
3818 defining
->def_depth
--;
3819 return NO_DIRECTIVE_FOUND
;
3822 return NO_DIRECTIVE_FOUND
;
3825 if ((defining
== NULL
) || (defining
->type
!= EXP_COMMENT
)) {
3826 error(ERR_NONFATAL
, "`%%endcomment': no matching `%%comment'");
3827 return DIRECTIVE_FOUND
;
3830 defining
= ed
->prev
;
3832 free_tlist(origline
);
3833 return DIRECTIVE_FOUND
;
3836 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3837 if (in_final
!= false) {
3838 error(ERR_FATAL
, "`%%final' cannot be used recursively");
3840 tline
= tline
->next
;
3842 if (tline
== NULL
) {
3843 error(ERR_NONFATAL
, "`%%final' expects at least one parameter");
3846 l
->first
= copy_Token(tline
);
3850 free_tlist(origline
);
3851 return DIRECTIVE_FOUND
;
3855 "preprocessor directive `%s' not yet implemented",
3857 return DIRECTIVE_FOUND
;
3862 * Ensure that a macro parameter contains a condition code and
3863 * nothing else. Return the condition code index if so, or -1
3866 static int find_cc(Token
* t
)
3872 return -1; /* Probably a %+ without a space */
3875 if (t
->type
!= TOK_ID
)
3879 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
3883 j
= ARRAY_SIZE(conditions
);
3886 m
= nasm_stricmp(t
->text
, conditions
[k
]);
3901 static bool paste_tokens(Token
**head
, bool handle_paste_tokens
)
3903 Token
**tail
, *t
, *tt
;
3905 bool did_paste
= false;
3908 /* Now handle token pasting... */
3911 while ((t
= *tail
) && (tt
= t
->next
)) {
3913 case TOK_WHITESPACE
:
3914 if (tt
->type
== TOK_WHITESPACE
) {
3915 /* Zap adjacent whitespace tokens */
3916 t
->next
= delete_Token(tt
);
3918 /* Do not advance paste_head here */
3929 while (tt
&& (tt
->type
== TOK_ID
|| tt
->type
== TOK_PREPROC_ID
||
3930 tt
->type
== TOK_NUMBER
|| tt
->type
== TOK_FLOAT
||
3931 tt
->type
== TOK_OTHER
)) {
3932 len
+= strlen(tt
->text
);
3937 * Now tt points to the first token after
3938 * the potential paste area...
3940 if (tt
!= t
->next
) {
3941 /* We have at least two tokens... */
3942 len
+= strlen(t
->text
);
3943 p
= tmp
= nasm_malloc(len
+1);
3947 p
= strchr(p
, '\0');
3948 t
= delete_Token(t
);
3951 t
= *tail
= tokenize(tmp
);
3958 t
->next
= tt
; /* Attach the remaining token chain */
3966 case TOK_PASTE
: /* %+ */
3967 if (handle_paste_tokens
) {
3968 /* Zap %+ and whitespace tokens to the right */
3969 while (t
&& (t
->type
== TOK_WHITESPACE
||
3970 t
->type
== TOK_PASTE
))
3971 t
= *tail
= delete_Token(t
);
3972 if (!paste_head
|| !t
)
3973 break; /* Nothing to paste with */
3977 while (tok_type_(tt
, TOK_WHITESPACE
))
3978 tt
= t
->next
= delete_Token(tt
);
3981 tmp
= nasm_strcat(t
->text
, tt
->text
);
3983 tt
= delete_Token(tt
);
3984 t
= *tail
= tokenize(tmp
);
3990 t
->next
= tt
; /* Attach the remaining token chain */
3997 /* else fall through */
4000 if (!tok_type_(t
->next
, TOK_WHITESPACE
))
4009 * expands to a list of tokens from %{x:y}
4011 static Token
*expand_mmac_params_range(ExpInv
*ei
, Token
*tline
, Token
***last
)
4013 Token
*t
= tline
, **tt
, *tm
, *head
;
4017 pos
= strchr(tline
->text
, ':');
4020 lst
= atoi(pos
+ 1);
4021 fst
= atoi(tline
->text
+ 1);
4024 * only macros params are accounted so
4025 * if someone passes %0 -- we reject such
4028 if (lst
== 0 || fst
== 0)
4031 /* the values should be sane */
4032 if ((fst
> (int)ei
->nparam
|| fst
< (-(int)ei
->nparam
)) ||
4033 (lst
> (int)ei
->nparam
|| lst
< (-(int)ei
->nparam
)))
4036 fst
= fst
< 0 ? fst
+ (int)ei
->nparam
+ 1: fst
;
4037 lst
= lst
< 0 ? lst
+ (int)ei
->nparam
+ 1: lst
;
4039 /* counted from zero */
4043 * it will be at least one token
4045 tm
= ei
->params
[(fst
+ ei
->rotate
) % ei
->nparam
];
4046 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4047 head
= t
, tt
= &t
->next
;
4049 for (i
= fst
+ 1; i
<= lst
; i
++) {
4050 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
4051 *tt
= t
, tt
= &t
->next
;
4052 j
= (i
+ ei
->rotate
) % ei
->nparam
;
4054 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4055 *tt
= t
, tt
= &t
->next
;
4058 for (i
= fst
- 1; i
>= lst
; i
--) {
4059 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
4060 *tt
= t
, tt
= &t
->next
;
4061 j
= (i
+ ei
->rotate
) % ei
->nparam
;
4063 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4064 *tt
= t
, tt
= &t
->next
;
4072 error(ERR_NONFATAL
, "`%%{%s}': macro parameters out of range",
4078 * Expand MMacro-local things: parameter references (%0, %n, %+n,
4079 * %-n) and MMacro-local identifiers (%%foo) as well as
4080 * macro indirection (%[...]) and range (%{..:..}).
4082 static Token
*expand_mmac_params(Token
* tline
)
4084 Token
*t
, *tt
, **tail
, *thead
;
4085 bool changed
= false;
4092 if (tline
->type
== TOK_PREPROC_ID
&&
4093 (((tline
->text
[1] == '+' || tline
->text
[1] == '-') && tline
->text
[2]) ||
4094 (tline
->text
[1] >= '0' && tline
->text
[1] <= '9') ||
4095 tline
->text
[1] == '%')) {
4097 int type
= 0, cc
; /* type = 0 to placate optimisers */
4104 tline
= tline
->next
;
4106 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
4107 if (ei
->type
== EXP_MMACRO
) {
4112 error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
4114 pos
= strchr(t
->text
, ':');
4116 switch (t
->text
[1]) {
4118 * We have to make a substitution of one of the
4119 * forms %1, %-1, %+1, %%foo, %0.
4122 if ((strlen(t
->text
) > 2) && (t
->text
[2] == '0')) {
4124 text
= nasm_strdup(ei
->label_text
);
4127 snprintf(tmpbuf
, sizeof(tmpbuf
), "%d", ei
->nparam
);
4128 text
= nasm_strdup(tmpbuf
);
4133 snprintf(tmpbuf
, sizeof(tmpbuf
), "..@%"PRIu64
".",
4135 text
= nasm_strcat(tmpbuf
, t
->text
+ 2);
4138 n
= atoi(t
->text
+ 2) - 1;
4139 if (n
>= ei
->nparam
)
4143 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4149 "macro parameter %d is not a condition code",
4154 if (inverse_ccs
[cc
] == -1) {
4156 "condition code `%s' is not invertible",
4160 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
4164 n
= atoi(t
->text
+ 2) - 1;
4165 if (n
>= ei
->nparam
)
4169 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4175 "macro parameter %d is not a condition code",
4180 text
= nasm_strdup(conditions
[cc
]);
4184 n
= atoi(t
->text
+ 1) - 1;
4185 if (n
>= ei
->nparam
)
4189 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4193 for (i
= 0; i
< ei
->paramlen
[n
]; i
++) {
4194 *tail
= new_Token(NULL
, tt
->type
, tt
->text
, 0);
4195 tail
= &(*tail
)->next
;
4199 text
= NULL
; /* we've done it here */
4204 * seems we have a parameters range here
4206 Token
*head
, **last
;
4207 head
= expand_mmac_params_range(ei
, t
, &last
);
4228 } else if (tline
->type
== TOK_INDIRECT
) {
4230 tline
= tline
->next
;
4231 tt
= tokenize(t
->text
);
4232 tt
= expand_mmac_params(tt
);
4233 tt
= expand_smacro(tt
);
4236 tt
->a
.mac
= NULL
; /* Necessary? */
4244 tline
= tline
->next
;
4252 paste_tokens(&thead
, false);
4258 * Expand all single-line macro calls made in the given line.
4259 * Return the expanded version of the line. The original is deemed
4260 * to be destroyed in the process. (In reality we'll just move
4261 * Tokens from input to output a lot of the time, rather than
4262 * actually bothering to destroy and replicate.)
4265 static Token
*expand_smacro(Token
* tline
)
4267 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
4268 SMacro
*head
= NULL
, *m
;
4271 unsigned int nparam
, sparam
;
4273 Token
*org_tline
= tline
;
4276 int deadman
= DEADMAN_LIMIT
;
4280 * Trick: we should avoid changing the start token pointer since it can
4281 * be contained in "next" field of other token. Because of this
4282 * we allocate a copy of first token and work with it; at the end of
4283 * routine we copy it back
4286 tline
= new_Token(org_tline
->next
, org_tline
->type
,
4287 org_tline
->text
, 0);
4288 tline
->a
.mac
= org_tline
->a
.mac
;
4289 nasm_free(org_tline
->text
);
4290 org_tline
->text
= NULL
;
4293 expanded
= true; /* Always expand %+ at least once */
4299 while (tline
) { /* main token loop */
4301 error(ERR_NONFATAL
, "interminable macro recursion");
4305 if ((mname
= tline
->text
)) {
4306 /* if this token is a local macro, look in local context */
4307 if (tline
->type
== TOK_ID
) {
4308 head
= (SMacro
*)hash_findix(&smacros
, mname
);
4309 } else if (tline
->type
== TOK_PREPROC_ID
) {
4310 ctx
= get_ctx(mname
, &mname
, true);
4311 head
= ctx
? (SMacro
*)hash_findix(&ctx
->localmac
, mname
) : NULL
;
4316 * We've hit an identifier. As in is_mmacro below, we first
4317 * check whether the identifier is a single-line macro at
4318 * all, then think about checking for parameters if
4321 list_for_each(m
, head
)
4322 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
4328 if (m
->nparam
== 0) {
4330 * Simple case: the macro is parameterless. Discard the
4331 * one token that the macro call took, and push the
4332 * expansion back on the to-do stack.
4334 if (!m
->expansion
) {
4335 if (!strcmp("__FILE__", m
->name
)) {
4338 src_get(&num
, &file
);
4339 tline
->text
= nasm_quote(file
, strlen(file
));
4340 tline
->type
= TOK_STRING
;
4344 if (!strcmp("__LINE__", m
->name
)) {
4345 nasm_free(tline
->text
);
4346 make_tok_num(tline
, src_get_linnum());
4349 if (!strcmp("__BITS__", m
->name
)) {
4350 nasm_free(tline
->text
);
4351 make_tok_num(tline
, globalbits
);
4354 tline
= delete_Token(tline
);
4359 * Complicated case: at least one macro with this name
4360 * exists and takes parameters. We must find the
4361 * parameters in the call, count them, find the SMacro
4362 * that corresponds to that form of the macro call, and
4363 * substitute for the parameters when we expand. What a
4366 /*tline = tline->next;
4367 skip_white_(tline); */
4370 while (tok_type_(t
, TOK_SMAC_END
)) {
4371 t
->a
.mac
->in_progress
= false;
4373 t
= tline
->next
= delete_Token(t
);
4376 } while (tok_type_(tline
, TOK_WHITESPACE
));
4377 if (!tok_is_(tline
, "(")) {
4379 * This macro wasn't called with parameters: ignore
4380 * the call. (Behaviour borrowed from gnu cpp.)
4389 sparam
= PARAM_DELTA
;
4390 params
= nasm_malloc(sparam
* sizeof(Token
*));
4391 params
[0] = tline
->next
;
4392 paramsize
= nasm_malloc(sparam
* sizeof(int));
4394 while (true) { /* parameter loop */
4396 * For some unusual expansions
4397 * which concatenates function call
4400 while (tok_type_(t
, TOK_SMAC_END
)) {
4401 t
->a
.mac
->in_progress
= false;
4403 t
= tline
->next
= delete_Token(t
);
4409 "macro call expects terminating `)'");
4412 if (tline
->type
== TOK_WHITESPACE
4414 if (paramsize
[nparam
])
4417 params
[nparam
] = tline
->next
;
4418 continue; /* parameter loop */
4420 if (tline
->type
== TOK_OTHER
4421 && tline
->text
[1] == 0) {
4422 char ch
= tline
->text
[0];
4423 if (ch
== ',' && !paren
&& brackets
<= 0) {
4424 if (++nparam
>= sparam
) {
4425 sparam
+= PARAM_DELTA
;
4426 params
= nasm_realloc(params
,
4427 sparam
* sizeof(Token
*));
4428 paramsize
= nasm_realloc(paramsize
,
4429 sparam
* sizeof(int));
4431 params
[nparam
] = tline
->next
;
4432 paramsize
[nparam
] = 0;
4434 continue; /* parameter loop */
4437 (brackets
> 0 || (brackets
== 0 &&
4438 !paramsize
[nparam
])))
4440 if (!(brackets
++)) {
4441 params
[nparam
] = tline
->next
;
4442 continue; /* parameter loop */
4445 if (ch
== '}' && brackets
> 0)
4446 if (--brackets
== 0) {
4448 continue; /* parameter loop */
4450 if (ch
== '(' && !brackets
)
4452 if (ch
== ')' && brackets
<= 0)
4458 error(ERR_NONFATAL
, "braces do not "
4459 "enclose all of macro parameter");
4461 paramsize
[nparam
] += white
+ 1;
4463 } /* parameter loop */
4465 while (m
&& (m
->nparam
!= nparam
||
4466 mstrcmp(m
->name
, mname
,
4470 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4471 "macro `%s' exists, "
4472 "but not taking %d parameters",
4473 mstart
->text
, nparam
);
4476 if (m
&& m
->in_progress
)
4478 if (!m
) { /* in progess or didn't find '(' or wrong nparam */
4480 * Design question: should we handle !tline, which
4481 * indicates missing ')' here, or expand those
4482 * macros anyway, which requires the (t) test a few
4486 nasm_free(paramsize
);
4490 * Expand the macro: we are placed on the last token of the
4491 * call, so that we can easily split the call from the
4492 * following tokens. We also start by pushing an SMAC_END
4493 * token for the cycle removal.
4500 tt
= new_Token(tline
, TOK_SMAC_END
, NULL
, 0);
4502 m
->in_progress
= true;
4504 list_for_each(t
, m
->expansion
) {
4505 if (t
->type
>= TOK_SMAC_PARAM
) {
4506 Token
*pcopy
= tline
, **ptail
= &pcopy
;
4510 ttt
= params
[t
->type
- TOK_SMAC_PARAM
];
4511 i
= paramsize
[t
->type
- TOK_SMAC_PARAM
];
4513 pt
= *ptail
= new_Token(tline
, ttt
->type
,
4519 } else if (t
->type
== TOK_PREPROC_Q
) {
4520 tt
= new_Token(tline
, TOK_ID
, mname
, 0);
4522 } else if (t
->type
== TOK_PREPROC_QQ
) {
4523 tt
= new_Token(tline
, TOK_ID
, m
->name
, 0);
4526 tt
= new_Token(tline
, t
->type
, t
->text
, 0);
4532 * Having done that, get rid of the macro call, and clean
4533 * up the parameters.
4536 nasm_free(paramsize
);
4539 continue; /* main token loop */
4544 if (tline
->type
== TOK_SMAC_END
) {
4545 tline
->a
.mac
->in_progress
= false;
4546 tline
= delete_Token(tline
);
4549 tline
= tline
->next
;
4557 * Now scan the entire line and look for successive TOK_IDs that resulted
4558 * after expansion (they can't be produced by tokenize()). The successive
4559 * TOK_IDs should be concatenated.
4560 * Also we look for %+ tokens and concatenate the tokens before and after
4561 * them (without white spaces in between).
4563 if (expanded
&& paste_tokens(&thead
, true)) {
4565 * If we concatenated something, *and* we had previously expanded
4566 * an actual macro, scan the lines again for macros...
4576 *org_tline
= *thead
;
4577 /* since we just gave text to org_line, don't free it */
4579 delete_Token(thead
);
4581 /* the expression expanded to empty line;
4582 we can't return NULL for some reasons
4583 we just set the line to a single WHITESPACE token. */
4584 memset(org_tline
, 0, sizeof(*org_tline
));
4585 org_tline
->text
= NULL
;
4586 org_tline
->type
= TOK_WHITESPACE
;
4595 * Similar to expand_smacro but used exclusively with macro identifiers
4596 * right before they are fetched in. The reason is that there can be
4597 * identifiers consisting of several subparts. We consider that if there
4598 * are more than one element forming the name, user wants a expansion,
4599 * otherwise it will be left as-is. Example:
4603 * the identifier %$abc will be left as-is so that the handler for %define
4604 * will suck it and define the corresponding value. Other case:
4606 * %define _%$abc cde
4608 * In this case user wants name to be expanded *before* %define starts
4609 * working, so we'll expand %$abc into something (if it has a value;
4610 * otherwise it will be left as-is) then concatenate all successive
4613 static Token
*expand_id(Token
* tline
)
4615 Token
*cur
, *oldnext
= NULL
;
4617 if (!tline
|| !tline
->next
)
4622 (cur
->next
->type
== TOK_ID
||
4623 cur
->next
->type
== TOK_PREPROC_ID
4624 || cur
->next
->type
== TOK_NUMBER
))
4627 /* If identifier consists of just one token, don't expand */
4632 oldnext
= cur
->next
; /* Detach the tail past identifier */
4633 cur
->next
= NULL
; /* so that expand_smacro stops here */
4636 tline
= expand_smacro(tline
);
4639 /* expand_smacro possibly changhed tline; re-scan for EOL */
4641 while (cur
&& cur
->next
)
4644 cur
->next
= oldnext
;
4651 * Determine whether the given line constitutes a multi-line macro
4652 * call, and return the ExpDef structure called if so. Doesn't have
4653 * to check for an initial label - that's taken care of in
4654 * expand_mmacro - but must check numbers of parameters. Guaranteed
4655 * to be called with tline->type == TOK_ID, so the putative macro
4656 * name is easy to find.
4658 static ExpDef
*is_mmacro(Token
* tline
, Token
*** params_array
)
4664 head
= (ExpDef
*) hash_findix(&expdefs
, tline
->text
);
4667 * Efficiency: first we see if any macro exists with the given
4668 * name. If not, we can return NULL immediately. _Then_ we
4669 * count the parameters, and then we look further along the
4670 * list if necessary to find the proper ExpDef.
4672 list_for_each(ed
, head
)
4673 if (!mstrcmp(ed
->name
, tline
->text
, ed
->casesense
))
4679 * OK, we have a potential macro. Count and demarcate the
4682 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
4685 * So we know how many parameters we've got. Find the ExpDef
4686 * structure that handles this number.
4689 if (ed
->nparam_min
<= nparam
4690 && (ed
->plus
|| nparam
<= ed
->nparam_max
)) {
4692 * It's right, and we can use it. Add its default
4693 * parameters to the end of our list if necessary.
4695 if (ed
->defaults
&& nparam
< ed
->nparam_min
+ ed
->ndefs
) {
4697 nasm_realloc(params
,
4698 ((ed
->nparam_min
+ ed
->ndefs
+
4699 1) * sizeof(*params
)));
4700 while (nparam
< ed
->nparam_min
+ ed
->ndefs
) {
4701 params
[nparam
] = ed
->defaults
[nparam
- ed
->nparam_min
];
4706 * If we've gone over the maximum parameter count (and
4707 * we're in Plus mode), ignore parameters beyond
4710 if (ed
->plus
&& nparam
> ed
->nparam_max
)
4711 nparam
= ed
->nparam_max
;
4713 * Then terminate the parameter list, and leave.
4715 if (!params
) { /* need this special case */
4716 params
= nasm_malloc(sizeof(*params
));
4719 params
[nparam
] = NULL
;
4720 *params_array
= params
;
4724 * This one wasn't right: look for the next one with the
4727 list_for_each(ed
, ed
->next
)
4728 if (!mstrcmp(ed
->name
, tline
->text
, ed
->casesense
))
4733 * After all that, we didn't find one with the right number of
4734 * parameters. Issue a warning, and fail to expand the macro.
4736 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4737 "macro `%s' exists, but not taking %d parameters",
4738 tline
->text
, nparam
);
4744 * Expand the multi-line macro call made by the given line, if
4745 * there is one to be expanded. If there is, push the expansion on
4746 * istk->expansion and return true. Otherwise return false.
4748 static bool expand_mmacro(Token
* tline
)
4750 Token
*label
= NULL
;
4751 int dont_prepend
= 0;
4752 Token
**params
, *t
, *mtok
;
4756 int i
, nparam
, *paramlen
;
4761 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4762 if (!tok_type_(t
, TOK_ID
) && !tok_type_(t
, TOK_PREPROC_ID
))
4765 ed
= is_mmacro(t
, ¶ms
);
4771 * We have an id which isn't a macro call. We'll assume
4772 * it might be a label; we'll also check to see if a
4773 * colon follows it. Then, if there's another id after
4774 * that lot, we'll check it again for macro-hood.
4778 if (tok_type_(t
, TOK_WHITESPACE
))
4779 last
= t
, t
= t
->next
;
4780 if (tok_is_(t
, ":")) {
4782 last
= t
, t
= t
->next
;
4783 if (tok_type_(t
, TOK_WHITESPACE
))
4784 last
= t
, t
= t
->next
;
4786 if (!tok_type_(t
, TOK_ID
) || !(ed
= is_mmacro(t
, ¶ms
)))
4794 * Fix up the parameters: this involves stripping leading and
4795 * trailing whitespace, then stripping braces if they are
4798 for (nparam
= 0; params
[nparam
]; nparam
++) ;
4799 paramlen
= nparam
? nasm_malloc(nparam
* sizeof(*paramlen
)) : NULL
;
4801 for (i
= 0; params
[i
]; i
++) {
4803 int comma
= (!ed
->plus
|| i
< nparam
- 1);
4807 if (tok_is_(t
, "{"))
4808 t
= t
->next
, brace
= true, comma
= false;
4812 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
4813 break; /* ... because we have hit a comma */
4814 if (comma
&& t
->type
== TOK_WHITESPACE
4815 && tok_is_(t
->next
, ","))
4816 break; /* ... or a space then a comma */
4817 if (brace
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "}"))
4818 break; /* ... or a brace */
4824 if (ed
->cur_depth
>= ed
->max_depth
) {
4825 if (ed
->max_depth
> 1) {
4827 "reached maximum macro recursion depth of %i for %s",
4828 ed
->max_depth
,ed
->name
);
4836 * OK, we have found a ExpDef structure representing a
4837 * previously defined mmacro. Create an expansion invocation
4838 * and point it back to the expansion definition. Substitution of
4839 * parameter tokens and macro-local tokens doesn't get done
4840 * until the single-line macro substitution process; this is
4841 * because delaying them allows us to change the semantics
4842 * later through %rotate.
4844 ei
= new_ExpInv(EXP_MMACRO
, ed
);
4845 // ei->label = label;
4846 // ei->label_text = detoken(label, false);
4847 ei
->current
= ed
->line
;
4848 ei
->emitting
= true;
4849 // ei->iline = tline;
4850 ei
->params
= params
;
4851 ei
->nparam
= nparam
;
4853 ei
->paramlen
= paramlen
;
4856 ei
->prev
= istk
->expansion
;
4857 istk
->expansion
= ei
;
4859 /***** todo: relocate %? (Q) and %?? (QQ); %00 already relocated *****/
4861 list_for_each(l, m->expansion) {
4865 l->next = istk->expansion;
4866 istk->expansion = l;
4869 list_for_each(t, ei->current->first) {
4873 tt = *tail = new_Token(NULL, TOK_ID, mname, 0);
4875 case TOK_PREPROC_QQ:
4876 tt = *tail = new_Token(NULL, TOK_ID, m->name, 0);
4878 case TOK_PREPROC_ID:
4879 if (t->text[1] == '0' && t->text[2] == '0') {
4887 tt = *tail = new_Token(NULL, x->type, x->text, 0);
4897 * Special case: detect %00 on first invocation; if found,
4898 * avoid emitting any labels that precede the mmacro call.
4899 * ed->prepend is set to -1 when %00 is detected, else 1.
4901 if (ed
->prepend
== 0) {
4902 for (l
= ed
->line
; l
!= NULL
; l
= l
->next
) {
4903 for (t
= l
->first
; t
!= NULL
; t
= t
->next
) {
4904 if ((t
->type
== TOK_PREPROC_ID
) &&
4905 (strlen(t
->text
) == 3) &&
4906 (t
->text
[1] == '0') && (t
->text
[2] == '0')) {
4911 if (dont_prepend
< 0) {
4915 ed
->prepend
= ((dont_prepend
< 0) ? -1 : 1);
4919 * If we had a label, push it on as the first line of
4920 * the macro expansion.
4922 if (label
!= NULL
) {
4923 if (ed
->prepend
< 0) {
4924 ei
->label_text
= detoken(label
, false);
4926 if (dont_prepend
== 0) {
4928 while (t
->next
!= NULL
) {
4931 t
->next
= new_Token(NULL
, TOK_OTHER
, ":", 0);
4933 Line
*l
= new_Line();
4934 l
->first
= copy_Token(label
);
4935 l
->next
= ei
->current
;
4940 list
->uplevel(ed
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
4946 /* The function that actually does the error reporting */
4947 static void verror(int severity
, const char *fmt
, va_list arg
)
4951 vsnprintf(buff
, sizeof(buff
), fmt
, arg
);
4953 if ((istk
!= NULL
) && (istk
->mmac_depth
> 0)) {
4954 ExpInv
*ei
= istk
->expansion
;
4955 int lineno
= ei
->lineno
;
4956 while (ei
!= NULL
) {
4957 if (ei
->type
== EXP_MMACRO
) {
4960 lineno
+= ei
->relno
;
4963 nasm_error(severity
, "(%s:%d) %s", ei
->def
->name
,
4966 nasm_error(severity
, "%s", buff
);
4971 * Since preprocessor always operate only on the line that didn't
4972 * arrived yet, we should always use ERR_OFFBY1.
4974 static void error(int severity
, const char *fmt
, ...)
4978 verror(severity
, fmt
, arg
);
4983 * Because %else etc are evaluated in the state context
4984 * of the previous branch, errors might get lost with error():
4985 * %if 0 ... %else trailing garbage ... %endif
4986 * So %else etc should report errors with this function.
4988 static void error_precond(int severity
, const char *fmt
, ...)
4992 /* Only ignore the error if it's really in a dead branch */
4993 if ((istk
!= NULL
) &&
4994 (istk
->expansion
!= NULL
) &&
4995 (istk
->expansion
->type
== EXP_IF
) &&
4996 (istk
->expansion
->def
->state
== COND_NEVER
))
5000 verror(severity
, fmt
, arg
);
5005 pp_reset(char *file
, int apass
, ListGen
* listgen
, StrList
**deplist
)
5010 istk
= nasm_malloc(sizeof(Include
));
5012 istk
->expansion
= NULL
;
5013 istk
->fp
= fopen(file
, "r");
5015 src_set_fname(nasm_strdup(file
));
5018 istk
->mmac_depth
= 0;
5020 error(ERR_FATAL
|ERR_NOFILE
, "unable to open input file `%s'",
5025 nested_mac_count
= 0;
5026 nested_rep_count
= 0;
5029 if (tasm_compatible_mode
) {
5030 stdmacpos
= nasm_stdmac
;
5032 stdmacpos
= nasm_stdmac_after_tasm
;
5034 any_extrastdmac
= extrastdmac
&& *extrastdmac
;
5039 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
5040 * The caller, however, will also pass in 3 for preprocess-only so
5041 * we can set __PASS__ accordingly.
5043 pass
= apass
> 2 ? 2 : apass
;
5045 dephead
= deptail
= deplist
;
5047 StrList
*sl
= nasm_malloc(strlen(file
)+1+sizeof sl
->next
);
5049 strcpy(sl
->str
, file
);
5051 deptail
= &sl
->next
;
5055 * Define the __PASS__ macro. This is defined here unlike
5056 * all the other builtins, because it is special -- it varies between
5059 t
= nasm_malloc(sizeof(*t
));
5061 make_tok_num(t
, apass
);
5063 define_smacro(NULL
, "__PASS__", true, 0, t
);
5066 static char *pp_getline(void)
5074 * Fetch a tokenized line, either from the expansion
5075 * buffer or from the input file.
5079 while (1) { /* until we get a line we can use */
5081 * Fetch a tokenized line from the expansion buffer
5083 if (istk
->expansion
!= NULL
) {
5084 ei
= istk
->expansion
;
5085 if (ei
->current
!= NULL
) {
5086 if (ei
->emitting
== false) {
5092 ei
->current
= l
->next
;
5094 tline
= copy_Token(l
->first
);
5095 if (((ei
->type
== EXP_REP
) ||
5096 (ei
->type
== EXP_MMACRO
) ||
5097 (ei
->type
== EXP_WHILE
))
5098 && (ei
->def
->nolist
== false)) {
5099 char *p
= detoken(tline
, false);
5100 list
->line(LIST_MACRO
, p
);
5103 if (ei
->linnum
> -1) {
5104 src_set_linnum(src_get_linnum() + 1);
5107 } else if ((ei
->type
== EXP_REP
) &&
5108 (ei
->def
->cur_depth
< ei
->def
->max_depth
)) {
5109 ei
->def
->cur_depth
++;
5110 ei
->current
= ei
->def
->line
;
5113 } else if ((ei
->type
== EXP_WHILE
) &&
5114 (ei
->def
->cur_depth
< ei
->def
->max_depth
)) {
5115 ei
->current
= ei
->def
->line
;
5117 tline
= copy_Token(ei
->current
->first
);
5118 int j
= if_condition(tline
, PP_WHILE
);
5120 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
5121 if (j
== COND_IF_TRUE
) {
5122 ei
->current
= ei
->current
->next
;
5123 ei
->def
->cur_depth
++;
5125 ei
->emitting
= false;
5127 ei
->def
->cur_depth
= ei
->def
->max_depth
;
5131 istk
->expansion
= ei
->prev
;
5132 ExpDef
*ed
= ei
->def
;
5134 if ((ei
->emitting
== true) &&
5135 (ed
->max_depth
== DEADMAN_LIMIT
) &&
5136 (ed
->cur_depth
== DEADMAN_LIMIT
)
5138 error(ERR_FATAL
, "runaway expansion detected, aborting");
5140 if (ed
->cur_depth
> 0) {
5142 } else if ((ed
->type
!= EXP_MMACRO
) && (ed
->type
!= EXP_IF
)) {
5143 /***** should this really be right here??? *****/
5145 Line *l = NULL, *ll = NULL;
5146 for (l = ed->line; l != NULL;) {
5147 if (l->first != NULL) {
5148 free_tlist(l->first);
5155 expansions = ed->prev;
5159 if ((ei
->type
== EXP_REP
) ||
5160 (ei
->type
== EXP_MMACRO
) ||
5161 (ei
->type
== EXP_WHILE
)) {
5162 list
->downlevel(LIST_MACRO
);
5163 if (ei
->type
== EXP_MMACRO
) {
5168 if (ei
->linnum
> -1) {
5169 src_set_linnum(ei
->linnum
);
5177 * Read in line from input and tokenize
5180 if (line
) { /* from the current input file */
5181 line
= prepreproc(line
);
5182 tline
= tokenize(line
);
5188 * The current file has ended; work down the istk
5193 if (i
->expansion
!= NULL
) {
5195 "end of file while still in an expansion");
5197 /* only set line and file name if there's a next node */
5199 src_set_linnum(i
->lineno
);
5200 nasm_free(src_set_fname(i
->fname
));
5202 if ((i
->next
== NULL
) && (finals
!= NULL
)) {
5204 ei
= new_ExpInv(EXP_FINAL
, NULL
);
5205 ei
->emitting
= true;
5206 ei
->current
= finals
;
5207 istk
->expansion
= ei
;
5212 list
->downlevel(LIST_INCLUDE
);
5215 if (finals
!= NULL
) {
5225 if (defining
== NULL
) {
5226 tline
= expand_mmac_params(tline
);
5230 * Check the line to see if it's a preprocessor directive.
5232 if (do_directive(tline
) == DIRECTIVE_FOUND
) {
5234 } else if (defining
!= NULL
) {
5236 * We're defining an expansion. We emit nothing at all,
5237 * and just shove the tokenized line on to the definition.
5239 if (defining
->ignoring
== false) {
5240 Line
*l
= new_Line();
5242 if (defining
->line
== NULL
) {
5246 defining
->last
->next
= l
;
5250 //free_tlist(tline); /***** sanity check: is this supposed to be here? *****/
5252 defining
->linecount
++;
5254 } else if ((istk
->expansion
!= NULL
) &&
5255 (istk
->expansion
->emitting
!= true)) {
5257 * We're in a non-emitting branch of an expansion.
5258 * Emit nothing at all, not even a blank line: when we
5259 * emerge from the expansion we'll give a line-number
5260 * directive so we keep our place correctly.
5265 tline
= expand_smacro(tline
);
5266 if (expand_mmacro(tline
) != true) {
5268 * De-tokenize the line again, and emit it.
5270 line
= detoken(tline
, true);
5281 static void pp_cleanup(int pass
)
5283 if (defining
!= NULL
) {
5284 error(ERR_NONFATAL
, "end of file while still defining an expansion");
5285 nasm_free(defining
); /***** todo: free everything to avoid mem leaks *****/
5288 while (cstk
!= NULL
)
5291 while (istk
!= NULL
) {
5295 nasm_free(i
->fname
);
5300 nasm_free(src_set_fname(NULL
));
5305 while ((i
= ipath
)) {
5314 void pp_include_path(char *path
)
5318 i
= nasm_malloc(sizeof(IncPath
));
5319 i
->path
= path
? nasm_strdup(path
) : NULL
;
5332 void pp_pre_include(char *fname
)
5334 Token
*inc
, *space
, *name
;
5337 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
5338 space
= new_Token(name
, TOK_WHITESPACE
, NULL
, 0);
5339 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
5347 void pp_pre_define(char *definition
)
5353 equals
= strchr(definition
, '=');
5354 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5355 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
5358 space
->next
= tokenize(definition
);
5368 void pp_pre_undefine(char *definition
)
5373 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5374 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
5375 space
->next
= tokenize(definition
);
5384 * This function is used to assist with "runtime" preprocessor
5385 * directives, e.g. pp_runtime("%define __BITS__ 64");
5387 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
5388 * PASS A VALID STRING TO THIS FUNCTION!!!!!
5391 void pp_runtime(char *definition
)
5395 def
= tokenize(definition
);
5396 if (do_directive(def
) == NO_DIRECTIVE_FOUND
)
5401 void pp_extra_stdmac(macros_t
*macros
)
5403 extrastdmac
= macros
;
5406 static void make_tok_num(Token
* tok
, int64_t val
)
5409 snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
5410 tok
->text
= nasm_strdup(numbuf
);
5411 tok
->type
= TOK_NUMBER
;