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 */
157 #define PP_CONCAT_MASK(x) (1 << (x))
159 struct tokseq_match
{
168 SMacro
*mac
; /* associated macro for TOK_SMAC_END */
169 size_t len
; /* scratch length field */
170 } a
; /* Auxiliary data */
171 enum pp_token_type type
;
175 * Expansion definitions are stored as a linked list of
176 * these, which is essentially a container to allow several linked
179 * Note that in this module, linked lists are treated as stacks
180 * wherever possible. For this reason, Lines are _pushed_ on to the
181 * `last' field in ExpDef structures, so that the linked list,
182 * if walked, would emit the expansion lines in the proper order.
193 EXP_NONE
= 0, EXP_PREDEF
,
196 EXP_COMMENT
, EXP_FINAL
,
197 EXP_MAX
= INT_MAX
/* Keep compiler from reducing the range */
201 * Store the definition of an expansion, in which is any
202 * preprocessor directive that has an ending pair.
204 * This design allows for arbitrary expansion/recursion depth,
205 * upto the DEADMAN_LIMIT.
207 * The `next' field is used for storing ExpDef in hash tables; the
208 * `prev' field is for the global `expansions` linked-list.
211 ExpDef
*prev
; /* previous definition */
212 ExpDef
*next
; /* next in hash table */
213 enum pp_exp_type type
; /* expansion type */
214 char *name
; /* definition name */
215 int nparam_min
, nparam_max
;
217 bool plus
; /* is the last parameter greedy? */
218 bool nolist
; /* is this expansion listing-inhibited? */
219 Token
*dlist
; /* all defaults as one list */
220 Token
**defaults
; /* parameter default pointers */
221 int ndefs
; /* number of default parameters */
223 int prepend
; /* label prepend state */
227 int linecount
; /* number of lines within expansion */
229 int64_t def_depth
; /* current number of definition pairs deep */
230 int64_t cur_depth
; /* current number of expansions */
231 int64_t max_depth
; /* maximum number of expansions allowed */
233 int state
; /* condition state */
234 bool ignoring
; /* ignoring definition lines */
238 * Store the invocation of an expansion.
240 * The `prev' field is for the `istk->expansion` linked-list.
242 * When an expansion is being expanded, `params', `iline', `nparam',
243 * `paramlen', `rotate' and `unique' are local to the invocation.
246 ExpInv
*prev
; /* previous invocation */
247 enum pp_exp_type type
; /* expansion type */
248 ExpDef
*def
; /* pointer to expansion definition */
249 char *name
; /* invocation name */
250 Line
*label
; /* pointer to label */
251 char *label_text
; /* pointer to label text */
252 Line
*current
; /* pointer to current line in invocation */
254 Token
**params
; /* actual parameters */
255 Token
*iline
; /* invocation line */
256 unsigned int nparam
, rotate
;
261 int lineno
; /* current line number in expansion */
262 int linnum
; /* line number at invocation */
263 int relno
; /* relative line number at invocation */
267 * To handle an arbitrary level of file inclusion, we maintain a
268 * stack (ie linked list) of these things.
281 * Include search path. This is simply a list of strings which get
282 * prepended, in turn, to the name of an include file, in an
283 * attempt to find the file if it's not in the current directory.
291 * Conditional assembly: we maintain a separate stack of these for
292 * each level of file inclusion. (The only reason we keep the
293 * stacks separate is to ensure that a stray `%endif' in a file
294 * included from within the true branch of a `%if' won't terminate
295 * it and cause confusion: instead, rightly, it'll cause an error.)
299 * These states are for use just after %if or %elif: IF_TRUE
300 * means the condition has evaluated to truth so we are
301 * currently emitting, whereas IF_FALSE means we are not
302 * currently emitting but will start doing so if a %else comes
303 * up. In these states, all directives are admissible: %elif,
304 * %else and %endif. (And of course %if.)
306 COND_IF_TRUE
, COND_IF_FALSE
,
308 * These states come up after a %else: ELSE_TRUE means we're
309 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
310 * any %elif or %else will cause an error.
312 COND_ELSE_TRUE
, COND_ELSE_FALSE
,
314 * These states mean that we're not emitting now, and also that
315 * nothing until %endif will be emitted at all. COND_DONE is
316 * used when we've had our moment of emission
317 * and have now started seeing %elifs. COND_NEVER is used when
318 * the condition construct in question is contained within a
319 * non-emitting branch of a larger condition construct,
320 * or if there is an error.
322 COND_DONE
, COND_NEVER
324 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
327 * These defines are used as the possible return values for do_directive
329 #define NO_DIRECTIVE_FOUND 0
330 #define DIRECTIVE_FOUND 1
333 * This define sets the upper limit for smacro and expansions
335 #define DEADMAN_LIMIT (1 << 20)
338 #define REP_LIMIT ((INT64_C(1) << 62))
341 * Condition codes. Note that we use c_ prefix not C_ because C_ is
342 * used in nasm.h for the "real" condition codes. At _this_ level,
343 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
344 * ones, so we need a different enum...
346 static const char * const conditions
[] = {
347 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
348 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
349 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
352 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
353 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
354 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_RCXZ
, c_S
, c_Z
,
357 static const enum pp_conds inverse_ccs
[] = {
358 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
359 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
,
360 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, -1, c_NS
, c_NZ
363 /* For TASM compatibility we need to be able to recognise TASM compatible
364 * conditional compilation directives. Using the NASM pre-processor does
365 * not work, so we look for them specifically from the following list and
366 * then jam in the equivalent NASM directive into the input stream.
370 TM_ARG
, TM_ELIF
, TM_ELSE
, TM_ENDIF
, TM_IF
, TM_IFDEF
, TM_IFDIFI
,
371 TM_IFNDEF
, TM_INCLUDE
, TM_LOCAL
374 static const char * const tasm_directives
[] = {
375 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
376 "ifndef", "include", "local"
379 static int StackSize
= 4;
380 static char *StackPointer
= "ebp";
381 static int ArgOffset
= 8;
382 static int LocalOffset
= 0;
384 static Context
*cstk
;
385 static Include
*istk
;
386 static IncPath
*ipath
= NULL
;
388 static int pass
; /* HACK: pass 0 = generate dependencies only */
389 static StrList
**dephead
, **deptail
; /* Dependency list */
391 static uint64_t unique
; /* unique identifier numbers */
393 static Line
*predef
= NULL
;
394 static bool do_predef
;
396 static ListGen
*list
;
399 * The current set of expansion definitions we have defined.
401 static struct hash_table expdefs
;
404 * The current set of single-line macros we have defined.
406 static struct hash_table smacros
;
409 * Linked List of all active expansion definitions
411 struct ExpDef
*expansions
= NULL
;
414 * The expansion we are currently defining
416 static ExpDef
*defining
= NULL
;
418 static uint64_t nested_mac_count
;
419 static uint64_t nested_rep_count
;
422 * Linked-list of lines to preprocess, prior to cleanup
424 static Line
*finals
= NULL
;
425 static bool in_final
= false;
428 * The number of macro parameters to allocate space for at a time.
430 #define PARAM_DELTA 16
433 * The standard macro set: defined in macros.c in the array nasm_stdmac.
434 * This gives our position in the macro set, when we're processing it.
436 static macros_t
*stdmacpos
;
439 * The extra standard macros that come from the object format, if
442 static macros_t
*extrastdmac
= NULL
;
443 static bool any_extrastdmac
;
446 * Tokens are allocated in blocks to improve speed
448 #define TOKEN_BLOCKSIZE 4096
449 static Token
*freeTokens
= NULL
;
455 static Blocks blocks
= { NULL
, NULL
};
458 * Forward declarations.
460 static Token
*expand_mmac_params(Token
* tline
);
461 static Token
*expand_smacro(Token
* tline
);
462 static Token
*expand_id(Token
* tline
);
463 static Context
*get_ctx(const char *name
, const char **namep
,
465 static void make_tok_num(Token
* tok
, int64_t val
);
466 static void error(int severity
, const char *fmt
, ...);
467 static void error_precond(int severity
, const char *fmt
, ...);
468 static void *new_Block(size_t size
);
469 static void delete_Blocks(void);
470 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
471 const char *text
, int txtlen
);
472 static Token
*copy_Token(Token
* tline
);
473 static Token
*delete_Token(Token
* t
);
474 static Line
*new_Line(void);
475 static ExpDef
*new_ExpDef(int exp_type
);
476 static ExpInv
*new_ExpInv(int exp_type
, ExpDef
*ed
);
479 * Macros for safe checking of token pointers, avoid *(NULL)
481 #define tok_type_(x,t) ((x) && (x)->type == (t))
482 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
483 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
484 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
488 #define dump_token(t) raw_dump_token(t, __FILE__, __LINE__, __func__);
489 static void raw_dump_token(Token
*token
, const char *file
, int line
, const char *func
)
491 printf("---[%s (%s:%d): %p]---\n", func
, file
, line
, (void *)token
);
494 list_for_each(t
, token
) {
496 printf("'%s' ", t
->text
);
505 * nasm_unquote with error if the string contains NUL characters.
506 * If the string contains NUL characters, issue an error and return
507 * the C len, i.e. truncate at the NUL.
509 static size_t nasm_unquote_cstr(char *qstr
, enum preproc_token directive
)
511 size_t len
= nasm_unquote(qstr
, NULL
);
512 size_t clen
= strlen(qstr
);
515 error(ERR_NONFATAL
, "NUL character in `%s' directive",
516 pp_directives
[directive
]);
522 * In-place reverse a list of tokens.
524 static Token
*reverse_tokens(Token
*t
)
540 * Handle TASM specific directives, which do not contain a % in
541 * front of them. We do it here because I could not find any other
542 * place to do it for the moment, and it is a hack (ideally it would
543 * be nice to be able to use the NASM pre-processor to do it).
545 static char *check_tasm_directive(char *line
)
547 int32_t i
, j
, k
, m
, len
;
548 char *p
, *q
, *oldline
, oldchar
;
550 p
= nasm_skip_spaces(line
);
552 /* Binary search for the directive name */
554 j
= ARRAY_SIZE(tasm_directives
);
555 q
= nasm_skip_word(p
);
562 m
= nasm_stricmp(p
, tasm_directives
[k
]);
564 /* We have found a directive, so jam a % in front of it
565 * so that NASM will then recognise it as one if it's own.
570 line
= nasm_malloc(len
+ 2);
572 if (k
== TM_IFDIFI
) {
574 * NASM does not recognise IFDIFI, so we convert
575 * it to %if 0. This is not used in NASM
576 * compatible code, but does need to parse for the
577 * TASM macro package.
579 strcpy(line
+ 1, "if 0");
581 memcpy(line
+ 1, p
, len
+ 1);
596 * The pre-preprocessing stage... This function translates line
597 * number indications as they emerge from GNU cpp (`# lineno "file"
598 * flags') into NASM preprocessor line number indications (`%line
601 static char *prepreproc(char *line
)
604 char *fname
, *oldline
;
606 if (line
[0] == '#' && line
[1] == ' ') {
609 lineno
= atoi(fname
);
610 fname
+= strspn(fname
, "0123456789 ");
613 fnlen
= strcspn(fname
, "\"");
614 line
= nasm_malloc(20 + fnlen
);
615 snprintf(line
, 20 + fnlen
, "%%line %d %.*s", lineno
, fnlen
, fname
);
618 if (tasm_compatible_mode
)
619 return check_tasm_directive(line
);
624 * Free a linked list of tokens.
626 static void free_tlist(Token
* list
)
629 list
= delete_Token(list
);
633 * Free a linked list of lines.
635 static void free_llist(Line
* list
)
638 list_for_each_safe(l
, tmp
, list
) {
639 free_tlist(l
->first
);
647 static void free_expdef(ExpDef
* ed
)
650 free_tlist(ed
->dlist
);
651 nasm_free(ed
->defaults
);
652 free_llist(ed
->line
);
659 static void free_expinv(ExpInv
* ei
)
661 if (ei
->name
!= NULL
)
663 if (ei
->label_text
!= NULL
)
664 nasm_free(ei
->label_text
);
669 * Free all currently defined macros, and free the hash tables
671 static void free_smacro_table(struct hash_table
*smt
)
675 struct hash_tbl_node
*it
= NULL
;
677 while ((s
= hash_iterate(smt
, &it
, &key
)) != NULL
) {
678 nasm_free((void *)key
);
679 list_for_each_safe(s
, tmp
, s
) {
681 free_tlist(s
->expansion
);
688 static void free_expdef_table(struct hash_table
*edt
)
692 struct hash_tbl_node
*it
= NULL
;
695 while ((ed
= hash_iterate(edt
, &it
, &key
)) != NULL
) {
696 nasm_free((void *)key
);
697 list_for_each_safe(ed
,tmp
, ed
)
703 static void free_macros(void)
705 free_smacro_table(&smacros
);
706 free_expdef_table(&expdefs
);
710 * Initialize the hash tables
712 static void init_macros(void)
714 hash_init(&smacros
, HASH_LARGE
);
715 hash_init(&expdefs
, HASH_LARGE
);
719 * Pop the context stack.
721 static void ctx_pop(void)
726 free_smacro_table(&c
->localmac
);
732 * Search for a key in the hash index; adding it if necessary
733 * (in which case we initialize the data pointer to NULL.)
736 hash_findi_add(struct hash_table
*hash
, const char *str
)
738 struct hash_insert hi
;
742 r
= hash_findi(hash
, str
, &hi
);
746 strx
= nasm_strdup(str
); /* Use a more efficient allocator here? */
747 return hash_add(&hi
, strx
, NULL
);
751 * Like hash_findi, but returns the data element rather than a pointer
752 * to it. Used only when not adding a new element, hence no third
756 hash_findix(struct hash_table
*hash
, const char *str
)
760 p
= hash_findi(hash
, str
, NULL
);
761 return p
? *p
: NULL
;
765 * read line from standard macros set,
766 * if there no more left -- return NULL
768 static char *line_from_stdmac(void)
771 const unsigned char *p
= stdmacpos
;
780 len
+= pp_directives_len
[c
- 0x80] + 1;
785 line
= nasm_malloc(len
+ 1);
787 while ((c
= *stdmacpos
++)) {
789 memcpy(q
, pp_directives
[c
- 0x80], pp_directives_len
[c
- 0x80]);
790 q
+= pp_directives_len
[c
- 0x80];
800 /* This was the last of the standard macro chain... */
802 if (any_extrastdmac
) {
803 stdmacpos
= extrastdmac
;
804 any_extrastdmac
= false;
805 } else if (do_predef
) {
808 Token
*head
, **tail
, *t
;
811 * Nasty hack: here we push the contents of
812 * `predef' on to the top-level expansion stack,
813 * since this is the most convenient way to
814 * implement the pre-include and pre-define
817 list_for_each(pd
, predef
) {
820 list_for_each(t
, pd
->first
) {
821 *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
822 tail
= &(*tail
)->next
;
827 ei
= new_ExpInv(EXP_PREDEF
, NULL
);
830 ei
->prev
= istk
->expansion
;
831 istk
->expansion
= ei
;
840 #define BUF_DELTA 512
842 * Read a line from the top file in istk, handling multiple CR/LFs
843 * at the end of the line read, and handling spurious ^Zs. Will
844 * return lines from the standard macro set if this has not already
847 static char *read_line(void)
849 char *buffer
, *p
, *q
;
850 int bufsize
, continued_count
;
853 * standart macros set (predefined) goes first
855 p
= line_from_stdmac();
860 * regular read from a file
863 buffer
= nasm_malloc(BUF_DELTA
);
867 q
= fgets(p
, bufsize
- (p
- buffer
), istk
->fp
);
871 if (p
> buffer
&& p
[-1] == '\n') {
873 * Convert backslash-CRLF line continuation sequences into
874 * nothing at all (for DOS and Windows)
876 if (((p
- 2) > buffer
) && (p
[-3] == '\\') && (p
[-2] == '\r')) {
882 * Also convert backslash-LF line continuation sequences into
883 * nothing at all (for Unix)
885 else if (((p
- 1) > buffer
) && (p
[-2] == '\\')) {
893 if (p
- buffer
> bufsize
- 10) {
894 int32_t offset
= p
- buffer
;
895 bufsize
+= BUF_DELTA
;
896 buffer
= nasm_realloc(buffer
, bufsize
);
897 p
= buffer
+ offset
; /* prevent stale-pointer problems */
901 if (!q
&& p
== buffer
) {
906 src_set_linnum(src_get_linnum() + istk
->lineinc
+
907 (continued_count
* istk
->lineinc
));
910 * Play safe: remove CRs as well as LFs, if any of either are
911 * present at the end of the line.
913 while (--p
>= buffer
&& (*p
== '\n' || *p
== '\r'))
917 * Handle spurious ^Z, which may be inserted into source files
918 * by some file transfer utilities.
920 buffer
[strcspn(buffer
, "\032")] = '\0';
922 list
->line(LIST_READ
, buffer
);
928 * Tokenize a line of text. This is a very simple process since we
929 * don't need to parse the value out of e.g. numeric tokens: we
930 * simply split one string into many.
932 static Token
*tokenize(char *line
)
935 enum pp_token_type type
;
937 Token
*t
, **tail
= &list
;
940 if ((defining
!= NULL
) && (defining
->ignoring
== true)) {
948 if (*p
== '+' && !nasm_isdigit(p
[1])) {
951 } else if (nasm_isdigit(*p
) ||
952 ((*p
== '-' || *p
== '+') && nasm_isdigit(p
[1]))) {
956 while (nasm_isdigit(*p
));
957 type
= TOK_PREPROC_ID
;
958 } else if (*p
== '{') {
960 while (*p
&& *p
!= '}') {
967 type
= TOK_PREPROC_ID
;
968 } else if (*p
== '[') {
970 line
+= 2; /* Skip the leading %[ */
972 while (lvl
&& (c
= *p
++)) {
984 p
= nasm_skip_string(p
- 1) + 1;
994 error(ERR_NONFATAL
, "unterminated %[ construct");
996 } else if (*p
== '?') {
997 type
= TOK_PREPROC_Q
; /* %? */
1000 type
= TOK_PREPROC_QQ
; /* %?? */
1003 } else if (*p
== '!') {
1004 type
= TOK_PREPROC_ID
;
1009 } while (isidchar(*p
));
1010 } else if (*p
== '\'' || *p
== '\"' || *p
== '`') {
1011 p
= nasm_skip_string(p
);
1015 error(ERR_NONFATAL
|ERR_PASS1
, "unterminated %! string");
1017 /* %! without string or identifier */
1018 type
= TOK_OTHER
; /* Legacy behavior... */
1020 } else if (isidchar(*p
) ||
1021 ((*p
== '!' || *p
== '%' || *p
== '$') &&
1026 while (isidchar(*p
));
1027 type
= TOK_PREPROC_ID
;
1033 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
1036 while (*p
&& isidchar(*p
))
1038 } else if (*p
== '\'' || *p
== '"' || *p
== '`') {
1043 p
= nasm_skip_string(p
);
1047 } else if(verbose
) {
1048 error(ERR_WARNING
|ERR_PASS1
, "unterminated string");
1049 /* Handling unterminated strings by UNV */
1052 } else if (p
[0] == '$' && p
[1] == '$') {
1053 type
= TOK_OTHER
; /* TOKEN_BASE */
1055 } else if (isnumstart(*p
)) {
1056 bool is_hex
= false;
1057 bool is_float
= false;
1073 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
1075 if (*p
== '+' || *p
== '-') {
1077 * e can only be followed by +/- if it is either a
1078 * prefixed hex number or a floating-point number
1083 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
1085 } else if (c
== 'P' || c
== 'p') {
1087 if (*p
== '+' || *p
== '-')
1089 } else if (isnumchar(c
) || c
== '_')
1090 ; /* just advance */
1091 else if (c
== '.') {
1093 * we need to deal with consequences of the legacy
1094 * parser, like "1.nolist" being two tokens
1095 * (TOK_NUMBER, TOK_ID) here; at least give it
1096 * a shot for now. In the future, we probably need
1097 * a flex-based scanner with proper pattern matching
1098 * to do it as well as it can be done. Nothing in
1099 * the world is going to help the person who wants
1100 * 0x123.p16 interpreted as two tokens, though.
1106 if (nasm_isdigit(*r
) || (is_hex
&& nasm_isxdigit(*r
)) ||
1107 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
1108 (*r
== 'p' || *r
== 'P')) {
1112 break; /* Terminate the token */
1116 p
--; /* Point to first character beyond number */
1118 if (p
== line
+1 && *line
== '$') {
1119 type
= TOK_OTHER
; /* TOKEN_HERE */
1121 if (has_e
&& !is_hex
) {
1122 /* 1e13 is floating-point, but 1e13h is not */
1126 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
1128 } else if (nasm_isspace(*p
)) {
1129 type
= TOK_WHITESPACE
;
1130 p
= nasm_skip_spaces(p
);
1132 * Whitespace just before end-of-line is discarded by
1133 * pretending it's a comment; whitespace just before a
1134 * comment gets lumped into the comment.
1136 if (!*p
|| *p
== ';') {
1141 } else if (*p
== ';') {
1147 * Anything else is an operator of some kind. We check
1148 * for all the double-character operators (>>, <<, //,
1149 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1150 * else is a single-character operator.
1153 if ((p
[0] == '>' && p
[1] == '>') ||
1154 (p
[0] == '<' && p
[1] == '<') ||
1155 (p
[0] == '/' && p
[1] == '/') ||
1156 (p
[0] == '<' && p
[1] == '=') ||
1157 (p
[0] == '>' && p
[1] == '=') ||
1158 (p
[0] == '=' && p
[1] == '=') ||
1159 (p
[0] == '!' && p
[1] == '=') ||
1160 (p
[0] == '<' && p
[1] == '>') ||
1161 (p
[0] == '&' && p
[1] == '&') ||
1162 (p
[0] == '|' && p
[1] == '|') ||
1163 (p
[0] == '^' && p
[1] == '^')) {
1169 /* Handling unterminated string by UNV */
1172 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1173 t->text[p-line] = *line;
1177 if (type
!= TOK_COMMENT
) {
1178 *tail
= t
= new_Token(NULL
, type
, line
, p
- line
);
1187 * this function allocates a new managed block of memory and
1188 * returns a pointer to the block. The managed blocks are
1189 * deleted only all at once by the delete_Blocks function.
1191 static void *new_Block(size_t size
)
1193 Blocks
*b
= &blocks
;
1195 /* first, get to the end of the linked list */
1198 /* now allocate the requested chunk */
1199 b
->chunk
= nasm_malloc(size
);
1201 /* now allocate a new block for the next request */
1202 b
->next
= nasm_malloc(sizeof(Blocks
));
1203 /* and initialize the contents of the new block */
1204 b
->next
->next
= NULL
;
1205 b
->next
->chunk
= NULL
;
1210 * this function deletes all managed blocks of memory
1212 static void delete_Blocks(void)
1214 Blocks
*a
, *b
= &blocks
;
1217 * keep in mind that the first block, pointed to by blocks
1218 * is a static and not dynamically allocated, so we don't
1223 nasm_free(b
->chunk
);
1232 * this function creates a new Token and passes a pointer to it
1233 * back to the caller. It sets the type and text elements, and
1234 * also the a.mac and next elements to NULL.
1236 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
1237 const char *text
, int txtlen
)
1243 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1244 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1245 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1246 freeTokens
[i
].next
= NULL
;
1249 freeTokens
= t
->next
;
1253 if (type
== TOK_WHITESPACE
|| !text
) {
1257 txtlen
= strlen(text
);
1258 t
->text
= nasm_malloc(txtlen
+1);
1259 memcpy(t
->text
, text
, txtlen
);
1260 t
->text
[txtlen
] = '\0';
1265 static Token
*copy_Token(Token
* tline
)
1267 Token
*t
, *tt
, *first
= NULL
, *prev
= NULL
;
1269 for (tt
= tline
; tt
!= NULL
; tt
= tt
->next
) {
1271 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1272 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1273 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1274 freeTokens
[i
].next
= NULL
;
1277 freeTokens
= t
->next
;
1279 t
->text
= tt
->text
? nasm_strdup(tt
->text
) : NULL
;
1280 t
->a
.mac
= tt
->a
.mac
;
1281 t
->a
.len
= tt
->a
.len
;
1293 static Token
*delete_Token(Token
* t
)
1295 Token
*next
= t
->next
;
1297 t
->next
= freeTokens
;
1303 * Convert a line of tokens back into text.
1304 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1305 * will be transformed into ..@ctxnum.xxx
1307 static char *detoken(Token
* tlist
, bool expand_locals
)
1314 list_for_each(t
, tlist
) {
1315 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
1320 if (*v
== '\'' || *v
== '\"' || *v
== '`') {
1321 size_t len
= nasm_unquote(v
, NULL
);
1322 size_t clen
= strlen(v
);
1325 error(ERR_NONFATAL
| ERR_PASS1
,
1326 "NUL character in %! string");
1332 char *p
= getenv(v
);
1334 error(ERR_NONFATAL
| ERR_PASS1
,
1335 "nonexistent environment variable `%s'", v
);
1338 t
->text
= nasm_strdup(p
);
1343 /* Expand local macros here and not during preprocessing */
1344 if (expand_locals
&&
1345 t
->type
== TOK_PREPROC_ID
&& t
->text
&&
1346 t
->text
[0] == '%' && t
->text
[1] == '$') {
1349 Context
*ctx
= get_ctx(t
->text
, &q
, false);
1352 snprintf(buffer
, sizeof(buffer
), "..@%"PRIu32
".", ctx
->number
);
1353 p
= nasm_strcat(buffer
, q
);
1359 /* Expand %? and %?? directives */
1360 if ((istk
->expansion
!= NULL
) &&
1361 ((t
->type
== TOK_PREPROC_Q
) ||
1362 (t
->type
== TOK_PREPROC_QQ
))) {
1364 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
){
1365 if (ei
->type
== EXP_MMACRO
) {
1367 if (t
->type
== TOK_PREPROC_Q
) {
1368 t
->text
= nasm_strdup(ei
->name
);
1370 t
->text
= nasm_strdup(ei
->def
->name
);
1377 if (t
->type
== TOK_WHITESPACE
)
1380 len
+= strlen(t
->text
);
1383 p
= line
= nasm_malloc(len
+ 1);
1385 list_for_each(t
, tlist
) {
1386 if (t
->type
== TOK_WHITESPACE
) {
1388 } else if (t
->text
) {
1400 * Initialize a new Line
1402 static inline Line
*new_Line(void)
1404 Line
*l
= nasm_malloc(sizeof(Line
));
1412 * Initialize a new Expansion Definition
1414 static ExpDef
*new_ExpDef(int exp_type
)
1416 ExpDef
*ed
= (ExpDef
*)nasm_zalloc(sizeof(ExpDef
));
1417 ed
->type
= exp_type
;
1418 ed
->casesense
= true;
1419 ed
->state
= COND_NEVER
;
1426 * Initialize a new Expansion Instance
1428 static ExpInv
*new_ExpInv(int exp_type
, ExpDef
*ed
)
1430 ExpInv
*ei
= (ExpInv
*)nasm_zalloc(sizeof(ExpInv
));
1431 ei
->type
= exp_type
;
1433 ei
->unique
= ++unique
;
1435 if ((istk
->mmac_depth
< 1) &&
1436 (istk
->expansion
== NULL
) &&
1438 (ed
->type
!= EXP_MMACRO
) &&
1439 (ed
->type
!= EXP_REP
) &&
1440 (ed
->type
!= EXP_WHILE
)) {
1441 ei
->linnum
= src_get_linnum();
1442 src_set_linnum(ei
->linnum
- ed
->linecount
- 1);
1446 if ((istk
->expansion
== NULL
) ||
1447 (ei
->type
== EXP_MMACRO
)) {
1450 ei
->relno
= istk
->expansion
->lineno
;
1452 ei
->relno
-= (ed
->linecount
+ 1);
1459 * A scanner, suitable for use by the expression evaluator, which
1460 * operates on a line of Tokens. Expects a pointer to a pointer to
1461 * the first token in the line to be passed in as its private_data
1464 * FIX: This really needs to be unified with stdscan.
1466 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1468 Token
**tlineptr
= private_data
;
1470 char ourcopy
[MAX_KEYWORD
+1], *p
, *r
, *s
;
1474 *tlineptr
= tline
? tline
->next
: NULL
;
1475 } while (tline
&& (tline
->type
== TOK_WHITESPACE
||
1476 tline
->type
== TOK_COMMENT
));
1479 return tokval
->t_type
= TOKEN_EOS
;
1481 tokval
->t_charptr
= tline
->text
;
1483 if (tline
->text
[0] == '$' && !tline
->text
[1])
1484 return tokval
->t_type
= TOKEN_HERE
;
1485 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[2])
1486 return tokval
->t_type
= TOKEN_BASE
;
1488 if (tline
->type
== TOK_ID
) {
1489 p
= tokval
->t_charptr
= tline
->text
;
1491 tokval
->t_charptr
++;
1492 return tokval
->t_type
= TOKEN_ID
;
1495 for (r
= p
, s
= ourcopy
; *r
; r
++) {
1496 if (r
>= p
+MAX_KEYWORD
)
1497 return tokval
->t_type
= TOKEN_ID
; /* Not a keyword */
1498 *s
++ = nasm_tolower(*r
);
1501 /* right, so we have an identifier sitting in temp storage. now,
1502 * is it actually a register or instruction name, or what? */
1503 return nasm_token_hash(ourcopy
, tokval
);
1506 if (tline
->type
== TOK_NUMBER
) {
1508 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
1509 tokval
->t_charptr
= tline
->text
;
1511 return tokval
->t_type
= TOKEN_ERRNUM
;
1513 return tokval
->t_type
= TOKEN_NUM
;
1516 if (tline
->type
== TOK_FLOAT
) {
1517 return tokval
->t_type
= TOKEN_FLOAT
;
1520 if (tline
->type
== TOK_STRING
) {
1523 bq
= tline
->text
[0];
1524 tokval
->t_charptr
= tline
->text
;
1525 tokval
->t_inttwo
= nasm_unquote(tline
->text
, &ep
);
1527 if (ep
[0] != bq
|| ep
[1] != '\0')
1528 return tokval
->t_type
= TOKEN_ERRSTR
;
1530 return tokval
->t_type
= TOKEN_STR
;
1533 if (tline
->type
== TOK_OTHER
) {
1534 if (!strcmp(tline
->text
, "<<"))
1535 return tokval
->t_type
= TOKEN_SHL
;
1536 if (!strcmp(tline
->text
, ">>"))
1537 return tokval
->t_type
= TOKEN_SHR
;
1538 if (!strcmp(tline
->text
, "//"))
1539 return tokval
->t_type
= TOKEN_SDIV
;
1540 if (!strcmp(tline
->text
, "%%"))
1541 return tokval
->t_type
= TOKEN_SMOD
;
1542 if (!strcmp(tline
->text
, "=="))
1543 return tokval
->t_type
= TOKEN_EQ
;
1544 if (!strcmp(tline
->text
, "<>"))
1545 return tokval
->t_type
= TOKEN_NE
;
1546 if (!strcmp(tline
->text
, "!="))
1547 return tokval
->t_type
= TOKEN_NE
;
1548 if (!strcmp(tline
->text
, "<="))
1549 return tokval
->t_type
= TOKEN_LE
;
1550 if (!strcmp(tline
->text
, ">="))
1551 return tokval
->t_type
= TOKEN_GE
;
1552 if (!strcmp(tline
->text
, "&&"))
1553 return tokval
->t_type
= TOKEN_DBL_AND
;
1554 if (!strcmp(tline
->text
, "^^"))
1555 return tokval
->t_type
= TOKEN_DBL_XOR
;
1556 if (!strcmp(tline
->text
, "||"))
1557 return tokval
->t_type
= TOKEN_DBL_OR
;
1561 * We have no other options: just return the first character of
1564 return tokval
->t_type
= tline
->text
[0];
1568 * Compare a string to the name of an existing macro; this is a
1569 * simple wrapper which calls either strcmp or nasm_stricmp
1570 * depending on the value of the `casesense' parameter.
1572 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
1574 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
1578 * Compare a string to the name of an existing macro; this is a
1579 * simple wrapper which calls either strcmp or nasm_stricmp
1580 * depending on the value of the `casesense' parameter.
1582 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
1584 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
1588 * Return the Context structure associated with a %$ token. Return
1589 * NULL, having _already_ reported an error condition, if the
1590 * context stack isn't deep enough for the supplied number of $
1592 * If all_contexts == true, contexts that enclose current are
1593 * also scanned for such smacro, until it is found; if not -
1594 * only the context that directly results from the number of $'s
1595 * in variable's name.
1597 * If "namep" is non-NULL, set it to the pointer to the macro name
1598 * tail, i.e. the part beyond %$...
1600 static Context
*get_ctx(const char *name
, const char **namep
,
1610 if (!name
|| name
[0] != '%' || name
[1] != '$')
1614 error(ERR_NONFATAL
, "`%s': context stack is empty", name
);
1621 while (ctx
&& *name
== '$') {
1627 error(ERR_NONFATAL
, "`%s': context stack is only"
1628 " %d level%s deep", name
, i
, (i
== 1 ? "" : "s"));
1639 /* Search for this smacro in found context */
1640 m
= hash_findix(&ctx
->localmac
, name
);
1642 if (!mstrcmp(m
->name
, name
, m
->casesense
))
1653 * Check to see if a file is already in a string list
1655 static bool in_list(const StrList
*list
, const char *str
)
1658 if (!strcmp(list
->str
, str
))
1666 * Open an include file. This routine must always return a valid
1667 * file pointer if it returns - it's responsible for throwing an
1668 * ERR_FATAL and bombing out completely if not. It should also try
1669 * the include path one by one until it finds the file or reaches
1670 * the end of the path.
1672 static FILE *inc_fopen(const char *file
, StrList
**dhead
, StrList
***dtail
,
1677 IncPath
*ip
= ipath
;
1678 int len
= strlen(file
);
1679 size_t prefix_len
= 0;
1683 sl
= nasm_malloc(prefix_len
+len
+1+sizeof sl
->next
);
1685 memcpy(sl
->str
, prefix
, prefix_len
);
1686 memcpy(sl
->str
+prefix_len
, file
, len
+1);
1687 fp
= fopen(sl
->str
, "r");
1688 if (fp
&& dhead
&& !in_list(*dhead
, sl
->str
)) {
1705 prefix_len
= strlen(prefix
);
1707 /* -MG given and file not found */
1708 if (dhead
&& !in_list(*dhead
, file
)) {
1709 sl
= nasm_malloc(len
+1+sizeof sl
->next
);
1711 strcpy(sl
->str
, file
);
1719 error(ERR_FATAL
, "unable to open include file `%s'", file
);
1724 * Determine if we should warn on defining a single-line macro of
1725 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1726 * return true if _any_ single-line macro of that name is defined.
1727 * Otherwise, will return true if a single-line macro with either
1728 * `nparam' or no parameters is defined.
1730 * If a macro with precisely the right number of parameters is
1731 * defined, or nparam is -1, the address of the definition structure
1732 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1733 * is NULL, no action will be taken regarding its contents, and no
1736 * Note that this is also called with nparam zero to resolve
1739 * If you already know which context macro belongs to, you can pass
1740 * the context pointer as first parameter; if you won't but name begins
1741 * with %$ the context will be automatically computed. If all_contexts
1742 * is true, macro will be searched in outer contexts as well.
1745 smacro_defined(Context
* ctx
, const char *name
, int nparam
, SMacro
** defn
,
1748 struct hash_table
*smtbl
;
1752 smtbl
= &ctx
->localmac
;
1753 } else if (name
[0] == '%' && name
[1] == '$') {
1755 ctx
= get_ctx(name
, &name
, false);
1757 return false; /* got to return _something_ */
1758 smtbl
= &ctx
->localmac
;
1762 m
= (SMacro
*) hash_findix(smtbl
, name
);
1765 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
1766 (nparam
<= 0 || m
->nparam
== 0 || nparam
== (int) m
->nparam
)) {
1768 if (nparam
== (int) m
->nparam
|| nparam
== -1)
1782 * Count and mark off the parameters in a multi-line macro call.
1783 * This is called both from within the multi-line macro expansion
1784 * code, and also to mark off the default parameters when provided
1785 * in a %macro definition line.
1787 static void count_mmac_params(Token
* t
, int *nparam
, Token
*** params
)
1789 int paramsize
, brace
;
1791 *nparam
= paramsize
= 0;
1794 /* +1: we need space for the final NULL */
1795 if (*nparam
+1 >= paramsize
) {
1796 paramsize
+= PARAM_DELTA
;
1797 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
1801 if (tok_is_(t
, "{"))
1803 (*params
)[(*nparam
)++] = t
;
1804 while (tok_isnt_(t
, brace
? "}" : ","))
1806 if (t
) { /* got a comma/brace */
1810 * Now we've found the closing brace, look further
1814 if (tok_isnt_(t
, ",")) {
1816 "braces do not enclose all of macro parameter");
1817 while (tok_isnt_(t
, ","))
1821 t
= t
->next
; /* eat the comma */
1828 * Determine whether one of the various `if' conditions is true or
1831 * We must free the tline we get passed.
1833 static bool if_condition(Token
* tline
, enum preproc_token ct
)
1835 enum pp_conditional i
= PP_COND(ct
);
1837 Token
*t
, *tt
, **tptr
, *origline
;
1838 struct tokenval tokval
;
1840 enum pp_token_type needtype
;
1847 j
= false; /* have we matched yet? */
1852 if (tline
->type
!= TOK_ID
) {
1854 "`%s' expects context identifiers", pp_directives
[ct
]);
1855 free_tlist(origline
);
1858 if (cstk
&& cstk
->name
&& !nasm_stricmp(tline
->text
, cstk
->name
))
1860 tline
= tline
->next
;
1865 j
= false; /* have we matched yet? */
1868 if (!tline
|| (tline
->type
!= TOK_ID
&&
1869 (tline
->type
!= TOK_PREPROC_ID
||
1870 tline
->text
[1] != '$'))) {
1872 "`%s' expects macro identifiers", pp_directives
[ct
]);
1875 if (smacro_defined(NULL
, tline
->text
, 0, NULL
, true))
1877 tline
= tline
->next
;
1882 tline
= expand_smacro(tline
);
1883 j
= false; /* have we matched yet? */
1886 if (!tline
|| (tline
->type
!= TOK_ID
&&
1887 tline
->type
!= TOK_STRING
&&
1888 (tline
->type
!= TOK_PREPROC_ID
||
1889 tline
->text
[1] != '!'))) {
1891 "`%s' expects environment variable names",
1896 if (tline
->type
== TOK_PREPROC_ID
)
1897 p
+= 2; /* Skip leading %! */
1898 if (*p
== '\'' || *p
== '\"' || *p
== '`')
1899 nasm_unquote_cstr(p
, ct
);
1902 tline
= tline
->next
;
1908 tline
= expand_smacro(tline
);
1910 while (tok_isnt_(tt
, ","))
1914 "`%s' expects two comma-separated arguments",
1919 j
= true; /* assume equality unless proved not */
1920 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1921 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1922 error(ERR_NONFATAL
, "`%s': more than one comma on line",
1926 if (t
->type
== TOK_WHITESPACE
) {
1930 if (tt
->type
== TOK_WHITESPACE
) {
1934 if (tt
->type
!= t
->type
) {
1935 j
= false; /* found mismatching tokens */
1938 /* When comparing strings, need to unquote them first */
1939 if (t
->type
== TOK_STRING
) {
1940 size_t l1
= nasm_unquote(t
->text
, NULL
);
1941 size_t l2
= nasm_unquote(tt
->text
, NULL
);
1947 if (mmemcmp(t
->text
, tt
->text
, l1
, i
== PPC_IFIDN
)) {
1951 } else if (mstrcmp(tt
->text
, t
->text
, i
== PPC_IFIDN
) != 0) {
1952 j
= false; /* found mismatching tokens */
1959 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
1960 j
= false; /* trailing gunk on one end or other */
1966 ExpDef searching
, *ed
;
1969 tline
= expand_id(tline
);
1970 if (!tok_type_(tline
, TOK_ID
)) {
1972 "`%s' expects a macro name", pp_directives
[ct
]);
1975 memset(&searching
, 0, sizeof(searching
));
1976 searching
.name
= nasm_strdup(tline
->text
);
1977 searching
.casesense
= true;
1978 searching
.nparam_max
= INT_MAX
;
1979 tline
= expand_smacro(tline
->next
);
1982 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
1984 "`%s' expects a parameter count or nothing",
1987 searching
.nparam_min
= searching
.nparam_max
=
1988 readnum(tline
->text
, &j
);
1991 "unable to parse parameter count `%s'",
1994 if (tline
&& tok_is_(tline
->next
, "-")) {
1995 tline
= tline
->next
->next
;
1996 if (tok_is_(tline
, "*"))
1997 searching
.nparam_max
= INT_MAX
;
1998 else if (!tok_type_(tline
, TOK_NUMBER
))
2000 "`%s' expects a parameter count after `-'",
2003 searching
.nparam_max
= readnum(tline
->text
, &j
);
2006 "unable to parse parameter count `%s'",
2008 if (searching
.nparam_min
> searching
.nparam_max
)
2010 "minimum parameter count exceeds maximum");
2013 if (tline
&& tok_is_(tline
->next
, "+")) {
2014 tline
= tline
->next
;
2015 searching
.plus
= true;
2017 ed
= (ExpDef
*) hash_findix(&expdefs
, searching
.name
);
2018 while (ed
!= NULL
) {
2019 if (!strcmp(ed
->name
, searching
.name
) &&
2020 (ed
->nparam_min
<= searching
.nparam_max
|| searching
.plus
) &&
2021 (searching
.nparam_min
<= ed
->nparam_max
|| ed
->plus
)) {
2027 if (tline
&& tline
->next
)
2028 error(ERR_WARNING
|ERR_PASS1
,
2029 "trailing garbage after %%ifmacro ignored");
2030 nasm_free(searching
.name
);
2039 needtype
= TOK_NUMBER
;
2042 needtype
= TOK_STRING
;
2046 t
= tline
= expand_smacro(tline
);
2048 while (tok_type_(t
, TOK_WHITESPACE
) ||
2049 (needtype
== TOK_NUMBER
&&
2050 tok_type_(t
, TOK_OTHER
) &&
2051 (t
->text
[0] == '-' || t
->text
[0] == '+') &&
2055 j
= tok_type_(t
, needtype
);
2059 t
= tline
= expand_smacro(tline
);
2060 while (tok_type_(t
, TOK_WHITESPACE
))
2065 t
= t
->next
; /* Skip the actual token */
2066 while (tok_type_(t
, TOK_WHITESPACE
))
2068 j
= !t
; /* Should be nothing left */
2073 t
= tline
= expand_smacro(tline
);
2074 while (tok_type_(t
, TOK_WHITESPACE
))
2077 j
= !t
; /* Should be empty */
2081 t
= tline
= expand_smacro(tline
);
2083 tokval
.t_type
= TOKEN_INVALID
;
2084 evalresult
= evaluate(ppscan
, tptr
, &tokval
,
2085 NULL
, pass
| CRITICAL
, error
, NULL
);
2089 error(ERR_WARNING
|ERR_PASS1
,
2090 "trailing garbage after expression ignored");
2091 if (!is_simple(evalresult
)) {
2093 "non-constant value given to `%s'", pp_directives
[ct
]);
2096 j
= reloc_value(evalresult
) != 0;
2101 "preprocessor directive `%s' not yet implemented",
2106 free_tlist(origline
);
2107 return j
^ PP_NEGATIVE(ct
);
2110 free_tlist(origline
);
2115 * Common code for defining an smacro
2117 static bool define_smacro(Context
*ctx
, const char *mname
, bool casesense
,
2118 int nparam
, Token
*expansion
)
2120 SMacro
*smac
, **smhead
;
2121 struct hash_table
*smtbl
;
2123 if (smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
)) {
2125 error(ERR_WARNING
|ERR_PASS1
,
2126 "single-line macro `%s' defined both with and"
2127 " without parameters", mname
);
2129 * Some instances of the old code considered this a failure,
2130 * some others didn't. What is the right thing to do here?
2132 free_tlist(expansion
);
2133 return false; /* Failure */
2136 * We're redefining, so we have to take over an
2137 * existing SMacro structure. This means freeing
2138 * what was already in it.
2140 nasm_free(smac
->name
);
2141 free_tlist(smac
->expansion
);
2144 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2145 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
2146 smac
= nasm_zalloc(sizeof(SMacro
));
2147 smac
->next
= *smhead
;
2150 smac
->name
= nasm_strdup(mname
);
2151 smac
->casesense
= casesense
;
2152 smac
->nparam
= nparam
;
2153 smac
->expansion
= expansion
;
2154 smac
->in_progress
= false;
2155 return true; /* Success */
2159 * Undefine an smacro
2161 static void undef_smacro(Context
*ctx
, const char *mname
)
2163 SMacro
**smhead
, *s
, **sp
;
2164 struct hash_table
*smtbl
;
2166 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2167 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
2171 * We now have a macro name... go hunt for it.
2174 while ((s
= *sp
) != NULL
) {
2175 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
2178 free_tlist(s
->expansion
);
2188 * Parse a mmacro specification.
2190 static bool parse_mmacro_spec(Token
*tline
, ExpDef
*def
, const char *directive
)
2194 tline
= tline
->next
;
2196 tline
= expand_id(tline
);
2197 if (!tok_type_(tline
, TOK_ID
)) {
2198 error(ERR_NONFATAL
, "`%s' expects a macro name", directive
);
2202 def
->name
= nasm_strdup(tline
->text
);
2204 def
->nolist
= false;
2205 // def->in_progress = 0;
2206 // def->rep_nest = NULL;
2207 def
->nparam_min
= 0;
2208 def
->nparam_max
= 0;
2210 tline
= expand_smacro(tline
->next
);
2212 if (!tok_type_(tline
, TOK_NUMBER
)) {
2213 error(ERR_NONFATAL
, "`%s' expects a parameter count", directive
);
2215 def
->nparam_min
= def
->nparam_max
=
2216 readnum(tline
->text
, &err
);
2219 "unable to parse parameter count `%s'", tline
->text
);
2221 if (tline
&& tok_is_(tline
->next
, "-")) {
2222 tline
= tline
->next
->next
;
2223 if (tok_is_(tline
, "*")) {
2224 def
->nparam_max
= INT_MAX
;
2225 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2227 "`%s' expects a parameter count after `-'", directive
);
2229 def
->nparam_max
= readnum(tline
->text
, &err
);
2231 error(ERR_NONFATAL
, "unable to parse parameter count `%s'",
2234 if (def
->nparam_min
> def
->nparam_max
) {
2235 error(ERR_NONFATAL
, "minimum parameter count exceeds maximum");
2239 if (tline
&& tok_is_(tline
->next
, "+")) {
2240 tline
= tline
->next
;
2243 if (tline
&& tok_type_(tline
->next
, TOK_ID
) &&
2244 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
2245 tline
= tline
->next
;
2250 * Handle default parameters.
2252 if (tline
&& tline
->next
) {
2253 def
->dlist
= tline
->next
;
2255 count_mmac_params(def
->dlist
, &def
->ndefs
, &def
->defaults
);
2258 def
->defaults
= NULL
;
2262 if (def
->defaults
&& def
->ndefs
> def
->nparam_max
- def
->nparam_min
&&
2264 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MDP
,
2265 "too many default macro parameters");
2272 * Decode a size directive
2274 static int parse_size(const char *str
) {
2275 static const char *size_names
[] =
2276 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2277 static const int sizes
[] =
2278 { 0, 1, 4, 16, 8, 10, 2, 32 };
2280 return sizes
[bsii(str
, size_names
, ARRAY_SIZE(size_names
))+1];
2284 * find and process preprocessor directive in passed line
2285 * Find out if a line contains a preprocessor directive, and deal
2288 * If a directive _is_ found, it is the responsibility of this routine
2289 * (and not the caller) to free_tlist() the line.
2291 * @param tline a pointer to the current tokeninzed line linked list
2292 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2295 static int do_directive(Token
* tline
)
2297 enum preproc_token i
;
2310 Token
*t
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
2311 struct tokenval tokval
;
2313 ExpDef
*ed
, *eed
, **edhead
;
2322 if (!tline
|| !tok_type_(tline
, TOK_PREPROC_ID
) ||
2323 (tline
->text
[1] == '%' || tline
->text
[1] == '$'
2324 || tline
->text
[1] == '!'))
2325 return NO_DIRECTIVE_FOUND
;
2327 i
= pp_token_hash(tline
->text
);
2331 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2332 error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2334 return NO_DIRECTIVE_FOUND
; /* didn't get it */
2337 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2338 /* Directive to tell NASM what the default stack size is. The
2339 * default is for a 16-bit stack, and this can be overriden with
2342 tline
= tline
->next
;
2343 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2344 tline
= tline
->next
;
2345 if (!tline
|| tline
->type
!= TOK_ID
) {
2346 error(ERR_NONFATAL
, "`%%stacksize' missing size parameter");
2347 free_tlist(origline
);
2348 return DIRECTIVE_FOUND
;
2350 if (nasm_stricmp(tline
->text
, "flat") == 0) {
2351 /* All subsequent ARG directives are for a 32-bit stack */
2353 StackPointer
= "ebp";
2356 } else if (nasm_stricmp(tline
->text
, "flat64") == 0) {
2357 /* All subsequent ARG directives are for a 64-bit stack */
2359 StackPointer
= "rbp";
2362 } else if (nasm_stricmp(tline
->text
, "large") == 0) {
2363 /* All subsequent ARG directives are for a 16-bit stack,
2364 * far function call.
2367 StackPointer
= "bp";
2370 } else if (nasm_stricmp(tline
->text
, "small") == 0) {
2371 /* All subsequent ARG directives are for a 16-bit stack,
2372 * far function call. We don't support near functions.
2375 StackPointer
= "bp";
2379 error(ERR_NONFATAL
, "`%%stacksize' invalid size type");
2380 free_tlist(origline
);
2381 return DIRECTIVE_FOUND
;
2383 free_tlist(origline
);
2384 return DIRECTIVE_FOUND
;
2387 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2388 /* TASM like ARG directive to define arguments to functions, in
2389 * the following form:
2391 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2395 char *arg
, directive
[256];
2396 int size
= StackSize
;
2398 /* Find the argument name */
2399 tline
= tline
->next
;
2400 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2401 tline
= tline
->next
;
2402 if (!tline
|| tline
->type
!= TOK_ID
) {
2403 error(ERR_NONFATAL
, "`%%arg' missing argument parameter");
2404 free_tlist(origline
);
2405 return DIRECTIVE_FOUND
;
2409 /* Find the argument size type */
2410 tline
= tline
->next
;
2411 if (!tline
|| tline
->type
!= TOK_OTHER
2412 || tline
->text
[0] != ':') {
2414 "Syntax error processing `%%arg' directive");
2415 free_tlist(origline
);
2416 return DIRECTIVE_FOUND
;
2418 tline
= tline
->next
;
2419 if (!tline
|| tline
->type
!= TOK_ID
) {
2420 error(ERR_NONFATAL
, "`%%arg' missing size type parameter");
2421 free_tlist(origline
);
2422 return DIRECTIVE_FOUND
;
2425 /* Allow macro expansion of type parameter */
2426 tt
= tokenize(tline
->text
);
2427 tt
= expand_smacro(tt
);
2428 size
= parse_size(tt
->text
);
2431 "Invalid size type for `%%arg' missing directive");
2433 free_tlist(origline
);
2434 return DIRECTIVE_FOUND
;
2438 /* Round up to even stack slots */
2439 size
= ALIGN(size
, StackSize
);
2441 /* Now define the macro for the argument */
2442 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
2443 arg
, StackPointer
, offset
);
2444 do_directive(tokenize(directive
));
2447 /* Move to the next argument in the list */
2448 tline
= tline
->next
;
2449 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2450 tline
= tline
->next
;
2451 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2453 free_tlist(origline
);
2454 return DIRECTIVE_FOUND
;
2457 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2458 /* TASM like LOCAL directive to define local variables for a
2459 * function, in the following form:
2461 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2463 * The '= LocalSize' at the end is ignored by NASM, but is
2464 * required by TASM to define the local parameter size (and used
2465 * by the TASM macro package).
2467 offset
= LocalOffset
;
2469 char *local
, directive
[256];
2470 int size
= StackSize
;
2472 /* Find the argument name */
2473 tline
= tline
->next
;
2474 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2475 tline
= tline
->next
;
2476 if (!tline
|| tline
->type
!= TOK_ID
) {
2478 "`%%local' missing argument parameter");
2479 free_tlist(origline
);
2480 return DIRECTIVE_FOUND
;
2482 local
= tline
->text
;
2484 /* Find the argument size type */
2485 tline
= tline
->next
;
2486 if (!tline
|| tline
->type
!= TOK_OTHER
2487 || tline
->text
[0] != ':') {
2489 "Syntax error processing `%%local' directive");
2490 free_tlist(origline
);
2491 return DIRECTIVE_FOUND
;
2493 tline
= tline
->next
;
2494 if (!tline
|| tline
->type
!= TOK_ID
) {
2496 "`%%local' missing size type parameter");
2497 free_tlist(origline
);
2498 return DIRECTIVE_FOUND
;
2501 /* Allow macro expansion of type parameter */
2502 tt
= tokenize(tline
->text
);
2503 tt
= expand_smacro(tt
);
2504 size
= parse_size(tt
->text
);
2507 "Invalid size type for `%%local' missing directive");
2509 free_tlist(origline
);
2510 return DIRECTIVE_FOUND
;
2514 /* Round up to even stack slots */
2515 size
= ALIGN(size
, StackSize
);
2517 offset
+= size
; /* Negative offset, increment before */
2519 /* Now define the macro for the argument */
2520 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
2521 local
, StackPointer
, offset
);
2522 do_directive(tokenize(directive
));
2524 /* Now define the assign to setup the enter_c macro correctly */
2525 snprintf(directive
, sizeof(directive
),
2526 "%%assign %%$localsize %%$localsize+%d", size
);
2527 do_directive(tokenize(directive
));
2529 /* Move to the next argument in the list */
2530 tline
= tline
->next
;
2531 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2532 tline
= tline
->next
;
2533 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2534 LocalOffset
= offset
;
2535 free_tlist(origline
);
2536 return DIRECTIVE_FOUND
;
2539 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2541 error(ERR_WARNING
|ERR_PASS1
,
2542 "trailing garbage after `%%clear' ignored");
2545 free_tlist(origline
);
2546 return DIRECTIVE_FOUND
;
2549 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2550 t
= tline
->next
= expand_smacro(tline
->next
);
2552 if (!t
|| (t
->type
!= TOK_STRING
&&
2553 t
->type
!= TOK_INTERNAL_STRING
)) {
2554 error(ERR_NONFATAL
, "`%%depend' expects a file name");
2555 free_tlist(origline
);
2556 return DIRECTIVE_FOUND
; /* but we did _something_ */
2559 error(ERR_WARNING
|ERR_PASS1
,
2560 "trailing garbage after `%%depend' ignored");
2562 if (t
->type
!= TOK_INTERNAL_STRING
)
2563 nasm_unquote_cstr(p
, i
);
2564 if (dephead
&& !in_list(*dephead
, p
)) {
2565 StrList
*sl
= nasm_malloc(strlen(p
)+1+sizeof sl
->next
);
2569 deptail
= &sl
->next
;
2571 free_tlist(origline
);
2572 return DIRECTIVE_FOUND
;
2575 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2576 t
= tline
->next
= expand_smacro(tline
->next
);
2579 if (!t
|| (t
->type
!= TOK_STRING
&&
2580 t
->type
!= TOK_INTERNAL_STRING
)) {
2581 error(ERR_NONFATAL
, "`%%include' expects a file name");
2582 free_tlist(origline
);
2583 return DIRECTIVE_FOUND
; /* but we did _something_ */
2586 error(ERR_WARNING
|ERR_PASS1
,
2587 "trailing garbage after `%%include' ignored");
2589 if (t
->type
!= TOK_INTERNAL_STRING
)
2590 nasm_unquote_cstr(p
, i
);
2591 inc
= nasm_zalloc(sizeof(Include
));
2593 inc
->fp
= inc_fopen(p
, dephead
, &deptail
, pass
== 0);
2595 /* -MG given but file not found */
2598 inc
->fname
= src_set_fname(nasm_strdup(p
));
2599 inc
->lineno
= src_set_linnum(0);
2601 inc
->expansion
= NULL
;
2603 list
->uplevel(LIST_INCLUDE
);
2605 free_tlist(origline
);
2606 return DIRECTIVE_FOUND
;
2609 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2611 static macros_t
*use_pkg
;
2612 const char *pkg_macro
= NULL
;
2614 tline
= tline
->next
;
2616 tline
= expand_id(tline
);
2618 if (!tline
|| (tline
->type
!= TOK_STRING
&&
2619 tline
->type
!= TOK_INTERNAL_STRING
&&
2620 tline
->type
!= TOK_ID
)) {
2621 error(ERR_NONFATAL
, "`%%use' expects a package name");
2622 free_tlist(origline
);
2623 return DIRECTIVE_FOUND
; /* but we did _something_ */
2626 error(ERR_WARNING
|ERR_PASS1
,
2627 "trailing garbage after `%%use' ignored");
2628 if (tline
->type
== TOK_STRING
)
2629 nasm_unquote_cstr(tline
->text
, i
);
2630 use_pkg
= nasm_stdmac_find_package(tline
->text
);
2632 error(ERR_NONFATAL
, "unknown `%%use' package: %s", tline
->text
);
2634 pkg_macro
= (char *)use_pkg
+ 1; /* The first string will be <%define>__USE_*__ */
2635 if (use_pkg
&& ! smacro_defined(NULL
, pkg_macro
, 0, NULL
, true)) {
2636 /* Not already included, go ahead and include it */
2637 stdmacpos
= use_pkg
;
2639 free_tlist(origline
);
2640 return DIRECTIVE_FOUND
;
2645 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2646 tline
= tline
->next
;
2648 tline
= expand_id(tline
);
2650 if (!tok_type_(tline
, TOK_ID
)) {
2651 error(ERR_NONFATAL
, "`%s' expects a context identifier",
2653 free_tlist(origline
);
2654 return DIRECTIVE_FOUND
; /* but we did _something_ */
2657 error(ERR_WARNING
|ERR_PASS1
,
2658 "trailing garbage after `%s' ignored",
2660 p
= nasm_strdup(tline
->text
);
2662 p
= NULL
; /* Anonymous */
2666 ctx
= nasm_zalloc(sizeof(Context
));
2668 hash_init(&ctx
->localmac
, HASH_SMALL
);
2670 ctx
->number
= unique
++;
2675 error(ERR_NONFATAL
, "`%s': context stack is empty",
2677 } else if (i
== PP_POP
) {
2678 if (p
&& (!cstk
->name
|| nasm_stricmp(p
, cstk
->name
)))
2679 error(ERR_NONFATAL
, "`%%pop' in wrong context: %s, "
2681 cstk
->name
? cstk
->name
: "anonymous", p
);
2686 nasm_free(cstk
->name
);
2692 free_tlist(origline
);
2693 return DIRECTIVE_FOUND
;
2695 severity
= ERR_FATAL
;
2698 severity
= ERR_NONFATAL
;
2701 severity
= ERR_WARNING
|ERR_WARN_USER
;
2705 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2707 /* Only error out if this is the final pass */
2708 if (pass
!= 2 && i
!= PP_FATAL
)
2709 return DIRECTIVE_FOUND
;
2711 tline
->next
= expand_smacro(tline
->next
);
2712 tline
= tline
->next
;
2714 t
= tline
? tline
->next
: NULL
;
2716 if (tok_type_(tline
, TOK_STRING
) && !t
) {
2717 /* The line contains only a quoted string */
2719 nasm_unquote(p
, NULL
); /* Ignore NUL character truncation */
2720 error(severity
, "%s", p
);
2722 /* Not a quoted string, or more than a quoted string */
2723 p
= detoken(tline
, false);
2724 error(severity
, "%s", p
);
2727 free_tlist(origline
);
2728 return DIRECTIVE_FOUND
;
2732 if (defining
!= NULL
) {
2733 if (defining
->type
== EXP_IF
) {
2734 defining
->def_depth
++;
2736 return NO_DIRECTIVE_FOUND
;
2738 if ((istk
->expansion
!= NULL
) &&
2739 (istk
->expansion
->emitting
== false)) {
2742 j
= if_condition(tline
->next
, i
);
2743 tline
->next
= NULL
; /* it got freed */
2744 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
2746 ed
= new_ExpDef(EXP_IF
);
2752 ed
->ignoring
= ((ed
->state
== COND_IF_TRUE
) ? false : true);
2753 ed
->prev
= defining
;
2755 free_tlist(origline
);
2756 return DIRECTIVE_FOUND
;
2759 if (defining
!= NULL
) {
2760 if ((defining
->type
!= EXP_IF
) || (defining
->def_depth
> 0)) {
2761 return NO_DIRECTIVE_FOUND
;
2764 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2765 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2767 switch (defining
->state
) {
2769 defining
->state
= COND_DONE
;
2770 defining
->ignoring
= true;
2775 defining
->ignoring
= true;
2778 case COND_ELSE_TRUE
:
2779 case COND_ELSE_FALSE
:
2780 error_precond(ERR_WARNING
|ERR_PASS1
,
2781 "`%%elif' after `%%else' ignored");
2782 defining
->state
= COND_NEVER
;
2783 defining
->ignoring
= true;
2788 * IMPORTANT: In the case of %if, we will already have
2789 * called expand_mmac_params(); however, if we're
2790 * processing an %elif we must have been in a
2791 * non-emitting mode, which would have inhibited
2792 * the normal invocation of expand_mmac_params().
2793 * Therefore, we have to do it explicitly here.
2795 j
= if_condition(expand_mmac_params(tline
->next
), i
);
2796 tline
->next
= NULL
; /* it got freed */
2798 j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2799 defining
->ignoring
= ((defining
->state
== COND_IF_TRUE
) ? false : true);
2802 free_tlist(origline
);
2803 return DIRECTIVE_FOUND
;
2806 if (defining
!= NULL
) {
2807 if ((defining
->type
!= EXP_IF
) || (defining
->def_depth
> 0)) {
2808 return NO_DIRECTIVE_FOUND
;
2812 error_precond(ERR_WARNING
|ERR_PASS1
,
2813 "trailing garbage after `%%else' ignored");
2814 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2815 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2817 switch (defining
->state
) {
2820 defining
->state
= COND_ELSE_FALSE
;
2821 defining
->ignoring
= true;
2825 defining
->ignoring
= true;
2829 defining
->state
= COND_ELSE_TRUE
;
2830 defining
->ignoring
= false;
2833 case COND_ELSE_TRUE
:
2834 case COND_ELSE_FALSE
:
2835 error_precond(ERR_WARNING
|ERR_PASS1
,
2836 "`%%else' after `%%else' ignored.");
2837 defining
->state
= COND_NEVER
;
2838 defining
->ignoring
= true;
2841 free_tlist(origline
);
2842 return DIRECTIVE_FOUND
;
2845 if (defining
!= NULL
) {
2846 if (defining
->type
== EXP_IF
) {
2847 if (defining
->def_depth
> 0) {
2848 defining
->def_depth
--;
2849 return NO_DIRECTIVE_FOUND
;
2852 return NO_DIRECTIVE_FOUND
;
2856 error_precond(ERR_WARNING
|ERR_PASS1
,
2857 "trailing garbage after `%%endif' ignored");
2858 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2859 error(ERR_NONFATAL
, "`%%endif': no matching `%%if'");
2860 return DIRECTIVE_FOUND
;
2863 defining
= ed
->prev
;
2864 ed
->prev
= expansions
;
2866 ei
= new_ExpInv(EXP_IF
, ed
);
2867 ei
->current
= ed
->line
;
2868 ei
->emitting
= true;
2869 ei
->prev
= istk
->expansion
;
2870 istk
->expansion
= ei
;
2871 free_tlist(origline
);
2872 return DIRECTIVE_FOUND
;
2878 if (defining
!= NULL
) {
2879 if (defining
->type
== EXP_MMACRO
) {
2880 defining
->def_depth
++;
2882 return NO_DIRECTIVE_FOUND
;
2884 ed
= new_ExpDef(EXP_MMACRO
);
2886 (i
== PP_RMACRO
) || (i
== PP_IRMACRO
) ? DEADMAN_LIMIT
: 0;
2887 ed
->casesense
= (i
== PP_MACRO
) || (i
== PP_RMACRO
);
2888 if (!parse_mmacro_spec(tline
, ed
, pp_directives
[i
])) {
2891 return DIRECTIVE_FOUND
;
2895 ed
->max_depth
= (ed
->max_depth
+ 1);
2896 ed
->ignoring
= false;
2897 ed
->prev
= defining
;
2900 eed
= (ExpDef
*) hash_findix(&expdefs
, ed
->name
);
2902 if (!strcmp(eed
->name
, ed
->name
) &&
2903 (eed
->nparam_min
<= ed
->nparam_max
|| ed
->plus
) &&
2904 (ed
->nparam_min
<= eed
->nparam_max
|| eed
->plus
)) {
2905 error(ERR_WARNING
|ERR_PASS1
,
2906 "redefining multi-line macro `%s'", ed
->name
);
2907 return DIRECTIVE_FOUND
;
2911 free_tlist(origline
);
2912 return DIRECTIVE_FOUND
;
2916 if (defining
!= NULL
) {
2917 if (defining
->type
== EXP_MMACRO
) {
2918 if (defining
->def_depth
> 0) {
2919 defining
->def_depth
--;
2920 return NO_DIRECTIVE_FOUND
;
2923 return NO_DIRECTIVE_FOUND
;
2926 if (!(defining
) || (defining
->type
!= EXP_MMACRO
)) {
2927 error(ERR_NONFATAL
, "`%s': not defining a macro", tline
->text
);
2928 return DIRECTIVE_FOUND
;
2930 edhead
= (ExpDef
**) hash_findi_add(&expdefs
, defining
->name
);
2931 defining
->next
= *edhead
;
2934 defining
= ed
->prev
;
2935 ed
->prev
= expansions
;
2938 free_tlist(origline
);
2939 return DIRECTIVE_FOUND
;
2942 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2944 * We must search along istk->expansion until we hit a
2945 * macro invocation. Then we disable the emitting state(s)
2946 * between exitmacro and endmacro.
2948 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
2949 if(ei
->type
== EXP_MMACRO
) {
2956 * Set all invocations leading back to the macro
2957 * invocation to a non-emitting state.
2959 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
2960 eei
->emitting
= false;
2962 eei
->emitting
= false;
2964 error(ERR_NONFATAL
, "`%%exitmacro' not within `%%macro' block");
2966 free_tlist(origline
);
2967 return DIRECTIVE_FOUND
;
2971 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2976 spec
.casesense
= (i
== PP_UNMACRO
);
2977 if (!parse_mmacro_spec(tline
, &spec
, pp_directives
[i
])) {
2978 return DIRECTIVE_FOUND
;
2980 ed_p
= (ExpDef
**) hash_findi(&expdefs
, spec
.name
, NULL
);
2981 while (ed_p
&& *ed_p
) {
2983 if (ed
->casesense
== spec
.casesense
&&
2984 !mstrcmp(ed
->name
, spec
.name
, spec
.casesense
) &&
2985 ed
->nparam_min
== spec
.nparam_min
&&
2986 ed
->nparam_max
== spec
.nparam_max
&&
2987 ed
->plus
== spec
.plus
) {
2988 if (ed
->cur_depth
> 0) {
2989 error(ERR_NONFATAL
, "`%s' ignored on active macro",
3000 free_tlist(origline
);
3001 free_tlist(spec
.dlist
);
3002 return DIRECTIVE_FOUND
;
3006 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3007 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
3008 tline
= tline
->next
;
3010 free_tlist(origline
);
3011 error(ERR_NONFATAL
, "`%%rotate' missing rotate count");
3012 return DIRECTIVE_FOUND
;
3014 t
= expand_smacro(tline
->next
);
3016 free_tlist(origline
);
3019 tokval
.t_type
= TOKEN_INVALID
;
3021 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3024 return DIRECTIVE_FOUND
;
3026 error(ERR_WARNING
|ERR_PASS1
,
3027 "trailing garbage after expression ignored");
3028 if (!is_simple(evalresult
)) {
3029 error(ERR_NONFATAL
, "non-constant value given to `%%rotate'");
3030 return DIRECTIVE_FOUND
;
3032 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3033 if (ei
->type
== EXP_MMACRO
) {
3038 error(ERR_NONFATAL
, "`%%rotate' invoked outside a macro call");
3039 } else if (ei
->nparam
== 0) {
3041 "`%%rotate' invoked within macro without parameters");
3043 int rotate
= ei
->rotate
+ reloc_value(evalresult
);
3045 rotate
%= (int)ei
->nparam
;
3047 rotate
+= ei
->nparam
;
3048 ei
->rotate
= rotate
;
3050 return DIRECTIVE_FOUND
;
3053 if (defining
!= NULL
) {
3054 if (defining
->type
== EXP_REP
) {
3055 defining
->def_depth
++;
3057 return NO_DIRECTIVE_FOUND
;
3061 tline
= tline
->next
;
3062 } while (tok_type_(tline
, TOK_WHITESPACE
));
3064 if (tok_type_(tline
, TOK_ID
) &&
3065 nasm_stricmp(tline
->text
, ".nolist") == 0) {
3068 tline
= tline
->next
;
3069 } while (tok_type_(tline
, TOK_WHITESPACE
));
3073 t
= expand_smacro(tline
);
3075 tokval
.t_type
= TOKEN_INVALID
;
3077 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3079 free_tlist(origline
);
3080 return DIRECTIVE_FOUND
;
3083 error(ERR_WARNING
|ERR_PASS1
,
3084 "trailing garbage after expression ignored");
3085 if (!is_simple(evalresult
)) {
3086 error(ERR_NONFATAL
, "non-constant value given to `%%rep'");
3087 return DIRECTIVE_FOUND
;
3089 count
= reloc_value(evalresult
);
3090 if (count
>= REP_LIMIT
) {
3091 error(ERR_NONFATAL
, "`%%rep' value exceeds limit");
3096 error(ERR_NONFATAL
, "`%%rep' expects a repeat count");
3099 free_tlist(origline
);
3100 ed
= new_ExpDef(EXP_REP
);
3101 ed
->nolist
= nolist
;
3104 ed
->max_depth
= (count
- 1);
3105 ed
->ignoring
= false;
3106 ed
->prev
= defining
;
3108 return DIRECTIVE_FOUND
;
3111 if (defining
!= NULL
) {
3112 if (defining
->type
== EXP_REP
) {
3113 if (defining
->def_depth
> 0) {
3114 defining
->def_depth
--;
3115 return NO_DIRECTIVE_FOUND
;
3118 return NO_DIRECTIVE_FOUND
;
3121 if ((defining
== NULL
) || (defining
->type
!= EXP_REP
)) {
3122 error(ERR_NONFATAL
, "`%%endrep': no matching `%%rep'");
3123 return DIRECTIVE_FOUND
;
3127 * Now we have a "macro" defined - although it has no name
3128 * and we won't be entering it in the hash tables - we must
3129 * push a macro-end marker for it on to istk->expansion.
3130 * After that, it will take care of propagating itself (a
3131 * macro-end marker line for a macro which is really a %rep
3132 * block will cause the macro to be re-expanded, complete
3133 * with another macro-end marker to ensure the process
3134 * continues) until the whole expansion is forcibly removed
3135 * from istk->expansion by a %exitrep.
3138 defining
= ed
->prev
;
3139 ed
->prev
= expansions
;
3141 ei
= new_ExpInv(EXP_REP
, ed
);
3142 ei
->current
= ed
->line
;
3143 ei
->emitting
= ((ed
->max_depth
> 0) ? true : false);
3144 list
->uplevel(ed
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
3145 ei
->prev
= istk
->expansion
;
3146 istk
->expansion
= ei
;
3147 free_tlist(origline
);
3148 return DIRECTIVE_FOUND
;
3151 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3153 * We must search along istk->expansion until we hit a
3154 * rep invocation. Then we disable the emitting state(s)
3155 * between exitrep and endrep.
3157 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3158 if (ei
->type
== EXP_REP
) {
3165 * Set all invocations leading back to the rep
3166 * invocation to a non-emitting state.
3168 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3169 eei
->emitting
= false;
3171 eei
->emitting
= false;
3172 eei
->current
= NULL
;
3173 eei
->def
->cur_depth
= eei
->def
->max_depth
;
3175 error(ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
3177 free_tlist(origline
);
3178 return DIRECTIVE_FOUND
;
3184 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3185 casesense
= (i
== PP_DEFINE
|| i
== PP_XDEFINE
);
3187 tline
= tline
->next
;
3189 tline
= expand_id(tline
);
3190 if (!tline
|| (tline
->type
!= TOK_ID
&&
3191 (tline
->type
!= TOK_PREPROC_ID
||
3192 tline
->text
[1] != '$'))) {
3193 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3195 free_tlist(origline
);
3196 return DIRECTIVE_FOUND
;
3199 ctx
= get_ctx(tline
->text
, &mname
, false);
3201 param_start
= tline
= tline
->next
;
3204 /* Expand the macro definition now for %xdefine and %ixdefine */
3205 if ((i
== PP_XDEFINE
) || (i
== PP_IXDEFINE
))
3206 tline
= expand_smacro(tline
);
3208 if (tok_is_(tline
, "(")) {
3210 * This macro has parameters.
3213 tline
= tline
->next
;
3217 error(ERR_NONFATAL
, "parameter identifier expected");
3218 free_tlist(origline
);
3219 return DIRECTIVE_FOUND
;
3221 if (tline
->type
!= TOK_ID
) {
3223 "`%s': parameter identifier expected",
3225 free_tlist(origline
);
3226 return DIRECTIVE_FOUND
;
3228 tline
->type
= TOK_SMAC_PARAM
+ nparam
++;
3229 tline
= tline
->next
;
3231 if (tok_is_(tline
, ",")) {
3232 tline
= tline
->next
;
3234 if (!tok_is_(tline
, ")")) {
3236 "`)' expected to terminate macro template");
3237 free_tlist(origline
);
3238 return DIRECTIVE_FOUND
;
3244 tline
= tline
->next
;
3246 if (tok_type_(tline
, TOK_WHITESPACE
))
3247 last
= tline
, tline
= tline
->next
;
3252 if (t
->type
== TOK_ID
) {
3253 list_for_each(tt
, param_start
)
3254 if (tt
->type
>= TOK_SMAC_PARAM
&&
3255 !strcmp(tt
->text
, t
->text
))
3259 t
->next
= macro_start
;
3264 * Good. We now have a macro name, a parameter count, and a
3265 * token list (in reverse order) for an expansion. We ought
3266 * to be OK just to create an SMacro, store it, and let
3267 * free_tlist have the rest of the line (which we have
3268 * carefully re-terminated after chopping off the expansion
3271 define_smacro(ctx
, mname
, casesense
, nparam
, macro_start
);
3272 free_tlist(origline
);
3273 return DIRECTIVE_FOUND
;
3276 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3277 tline
= tline
->next
;
3279 tline
= expand_id(tline
);
3280 if (!tline
|| (tline
->type
!= TOK_ID
&&
3281 (tline
->type
!= TOK_PREPROC_ID
||
3282 tline
->text
[1] != '$'))) {
3283 error(ERR_NONFATAL
, "`%%undef' expects a macro identifier");
3284 free_tlist(origline
);
3285 return DIRECTIVE_FOUND
;
3288 error(ERR_WARNING
|ERR_PASS1
,
3289 "trailing garbage after macro name ignored");
3292 /* Find the context that symbol belongs to */
3293 ctx
= get_ctx(tline
->text
, &mname
, false);
3294 undef_smacro(ctx
, mname
);
3295 free_tlist(origline
);
3296 return DIRECTIVE_FOUND
;
3300 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3301 casesense
= (i
== PP_DEFSTR
);
3303 tline
= tline
->next
;
3305 tline
= expand_id(tline
);
3306 if (!tline
|| (tline
->type
!= TOK_ID
&&
3307 (tline
->type
!= TOK_PREPROC_ID
||
3308 tline
->text
[1] != '$'))) {
3309 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3311 free_tlist(origline
);
3312 return DIRECTIVE_FOUND
;
3315 ctx
= get_ctx(tline
->text
, &mname
, false);
3317 tline
= expand_smacro(tline
->next
);
3320 while (tok_type_(tline
, TOK_WHITESPACE
))
3321 tline
= delete_Token(tline
);
3323 p
= detoken(tline
, false);
3324 macro_start
= nasm_malloc(sizeof(*macro_start
));
3325 macro_start
->next
= NULL
;
3326 macro_start
->text
= nasm_quote(p
, strlen(p
));
3327 macro_start
->type
= TOK_STRING
;
3328 macro_start
->a
.mac
= NULL
;
3332 * We now have a macro name, an implicit parameter count of
3333 * zero, and a string token to use as an expansion. Create
3334 * and store an SMacro.
3336 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3337 free_tlist(origline
);
3338 return DIRECTIVE_FOUND
;
3342 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3343 casesense
= (i
== PP_DEFTOK
);
3345 tline
= tline
->next
;
3347 tline
= expand_id(tline
);
3348 if (!tline
|| (tline
->type
!= TOK_ID
&&
3349 (tline
->type
!= TOK_PREPROC_ID
||
3350 tline
->text
[1] != '$'))) {
3352 "`%s' expects a macro identifier as first parameter",
3354 free_tlist(origline
);
3355 return DIRECTIVE_FOUND
;
3357 ctx
= get_ctx(tline
->text
, &mname
, false);
3359 tline
= expand_smacro(tline
->next
);
3363 while (tok_type_(t
, TOK_WHITESPACE
))
3365 /* t should now point to the string */
3366 if (!tok_type_(t
, TOK_STRING
)) {
3368 "`%s` requires string as second parameter",
3371 free_tlist(origline
);
3372 return DIRECTIVE_FOUND
;
3376 * Convert the string to a token stream. Note that smacros
3377 * are stored with the token stream reversed, so we have to
3378 * reverse the output of tokenize().
3380 nasm_unquote_cstr(t
->text
, i
);
3381 macro_start
= reverse_tokens(tokenize(t
->text
));
3384 * We now have a macro name, an implicit parameter count of
3385 * zero, and a numeric token to use as an expansion. Create
3386 * and store an SMacro.
3388 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3390 free_tlist(origline
);
3391 return DIRECTIVE_FOUND
;
3394 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3397 StrList
*xsl
= NULL
;
3398 StrList
**xst
= &xsl
;
3402 tline
= tline
->next
;
3404 tline
= expand_id(tline
);
3405 if (!tline
|| (tline
->type
!= TOK_ID
&&
3406 (tline
->type
!= TOK_PREPROC_ID
||
3407 tline
->text
[1] != '$'))) {
3409 "`%%pathsearch' expects a macro identifier as first parameter");
3410 free_tlist(origline
);
3411 return DIRECTIVE_FOUND
;
3413 ctx
= get_ctx(tline
->text
, &mname
, false);
3415 tline
= expand_smacro(tline
->next
);
3419 while (tok_type_(t
, TOK_WHITESPACE
))
3422 if (!t
|| (t
->type
!= TOK_STRING
&&
3423 t
->type
!= TOK_INTERNAL_STRING
)) {
3424 error(ERR_NONFATAL
, "`%%pathsearch' expects a file name");
3426 free_tlist(origline
);
3427 return DIRECTIVE_FOUND
; /* but we did _something_ */
3430 error(ERR_WARNING
|ERR_PASS1
,
3431 "trailing garbage after `%%pathsearch' ignored");
3433 if (t
->type
!= TOK_INTERNAL_STRING
)
3434 nasm_unquote(p
, NULL
);
3436 fp
= inc_fopen(p
, &xsl
, &xst
, true);
3439 fclose(fp
); /* Don't actually care about the file */
3441 macro_start
= nasm_malloc(sizeof(*macro_start
));
3442 macro_start
->next
= NULL
;
3443 macro_start
->text
= nasm_quote(p
, strlen(p
));
3444 macro_start
->type
= TOK_STRING
;
3445 macro_start
->a
.mac
= NULL
;
3450 * We now have a macro name, an implicit parameter count of
3451 * zero, and a string token to use as an expansion. Create
3452 * and store an SMacro.
3454 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3456 free_tlist(origline
);
3457 return DIRECTIVE_FOUND
;
3461 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3464 tline
= tline
->next
;
3466 tline
= expand_id(tline
);
3467 if (!tline
|| (tline
->type
!= TOK_ID
&&
3468 (tline
->type
!= TOK_PREPROC_ID
||
3469 tline
->text
[1] != '$'))) {
3471 "`%%strlen' expects a macro identifier as first parameter");
3472 free_tlist(origline
);
3473 return DIRECTIVE_FOUND
;
3475 ctx
= get_ctx(tline
->text
, &mname
, false);
3477 tline
= expand_smacro(tline
->next
);
3481 while (tok_type_(t
, TOK_WHITESPACE
))
3483 /* t should now point to the string */
3484 if (!tok_type_(t
, TOK_STRING
)) {
3486 "`%%strlen` requires string as second parameter");
3488 free_tlist(origline
);
3489 return DIRECTIVE_FOUND
;
3492 macro_start
= nasm_malloc(sizeof(*macro_start
));
3493 macro_start
->next
= NULL
;
3494 make_tok_num(macro_start
, nasm_unquote(t
->text
, NULL
));
3495 macro_start
->a
.mac
= NULL
;
3498 * We now have a macro name, an implicit parameter count of
3499 * zero, and a numeric token to use as an expansion. Create
3500 * and store an SMacro.
3502 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3504 free_tlist(origline
);
3505 return DIRECTIVE_FOUND
;
3508 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3511 tline
= tline
->next
;
3513 tline
= expand_id(tline
);
3514 if (!tline
|| (tline
->type
!= TOK_ID
&&
3515 (tline
->type
!= TOK_PREPROC_ID
||
3516 tline
->text
[1] != '$'))) {
3518 "`%%strcat' expects a macro identifier as first parameter");
3519 free_tlist(origline
);
3520 return DIRECTIVE_FOUND
;
3522 ctx
= get_ctx(tline
->text
, &mname
, false);
3524 tline
= expand_smacro(tline
->next
);
3528 list_for_each(t
, tline
) {
3530 case TOK_WHITESPACE
:
3533 len
+= t
->a
.len
= nasm_unquote(t
->text
, NULL
);
3536 if (!strcmp(t
->text
, ",")) /* permit comma separators */
3538 /* else fall through */
3541 "non-string passed to `%%strcat' (%d)", t
->type
);
3543 free_tlist(origline
);
3544 return DIRECTIVE_FOUND
;
3548 p
= pp
= nasm_malloc(len
);
3549 list_for_each(t
, tline
) {
3550 if (t
->type
== TOK_STRING
) {
3551 memcpy(p
, t
->text
, t
->a
.len
);
3557 * We now have a macro name, an implicit parameter count of
3558 * zero, and a numeric token to use as an expansion. Create
3559 * and store an SMacro.
3561 macro_start
= new_Token(NULL
, TOK_STRING
, NULL
, 0);
3562 macro_start
->text
= nasm_quote(pp
, len
);
3564 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3566 free_tlist(origline
);
3567 return DIRECTIVE_FOUND
;
3570 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3572 int64_t start
, count
;
3577 tline
= tline
->next
;
3579 tline
= expand_id(tline
);
3580 if (!tline
|| (tline
->type
!= TOK_ID
&&
3581 (tline
->type
!= TOK_PREPROC_ID
||
3582 tline
->text
[1] != '$'))) {
3584 "`%%substr' expects a macro identifier as first parameter");
3585 free_tlist(origline
);
3586 return DIRECTIVE_FOUND
;
3588 ctx
= get_ctx(tline
->text
, &mname
, false);
3590 tline
= expand_smacro(tline
->next
);
3593 if (tline
) /* skip expanded id */
3595 while (tok_type_(t
, TOK_WHITESPACE
))
3598 /* t should now point to the string */
3599 if (!tok_type_(t
, TOK_STRING
)) {
3601 "`%%substr` requires string as second parameter");
3603 free_tlist(origline
);
3604 return DIRECTIVE_FOUND
;
3609 tokval
.t_type
= TOKEN_INVALID
;
3610 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3614 free_tlist(origline
);
3615 return DIRECTIVE_FOUND
;
3616 } else if (!is_simple(evalresult
)) {
3617 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3619 free_tlist(origline
);
3620 return DIRECTIVE_FOUND
;
3622 start
= evalresult
->value
- 1;
3624 while (tok_type_(tt
, TOK_WHITESPACE
))
3627 count
= 1; /* Backwards compatibility: one character */
3629 tokval
.t_type
= TOKEN_INVALID
;
3630 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3634 free_tlist(origline
);
3635 return DIRECTIVE_FOUND
;
3636 } else if (!is_simple(evalresult
)) {
3637 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3639 free_tlist(origline
);
3640 return DIRECTIVE_FOUND
;
3642 count
= evalresult
->value
;
3645 len
= nasm_unquote(t
->text
, NULL
);
3646 /* make start and count being in range */
3650 count
= len
+ count
+ 1 - start
;
3651 if (start
+ count
> (int64_t)len
)
3652 count
= len
- start
;
3653 if (!len
|| count
< 0 || start
>=(int64_t)len
)
3654 start
= -1, count
= 0; /* empty string */
3656 macro_start
= nasm_malloc(sizeof(*macro_start
));
3657 macro_start
->next
= NULL
;
3658 macro_start
->text
= nasm_quote((start
< 0) ? "" : t
->text
+ start
, count
);
3659 macro_start
->type
= TOK_STRING
;
3660 macro_start
->a
.mac
= NULL
;
3663 * We now have a macro name, an implicit parameter count of
3664 * zero, and a numeric token to use as an expansion. Create
3665 * and store an SMacro.
3667 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3669 free_tlist(origline
);
3670 return DIRECTIVE_FOUND
;
3675 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3676 casesense
= (i
== PP_ASSIGN
);
3678 tline
= tline
->next
;
3680 tline
= expand_id(tline
);
3681 if (!tline
|| (tline
->type
!= TOK_ID
&&
3682 (tline
->type
!= TOK_PREPROC_ID
||
3683 tline
->text
[1] != '$'))) {
3685 "`%%%sassign' expects a macro identifier",
3686 (i
== PP_IASSIGN
? "i" : ""));
3687 free_tlist(origline
);
3688 return DIRECTIVE_FOUND
;
3690 ctx
= get_ctx(tline
->text
, &mname
, false);
3692 tline
= expand_smacro(tline
->next
);
3697 tokval
.t_type
= TOKEN_INVALID
;
3699 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3702 free_tlist(origline
);
3703 return DIRECTIVE_FOUND
;
3707 error(ERR_WARNING
|ERR_PASS1
,
3708 "trailing garbage after expression ignored");
3710 if (!is_simple(evalresult
)) {
3712 "non-constant value given to `%%%sassign'",
3713 (i
== PP_IASSIGN
? "i" : ""));
3714 free_tlist(origline
);
3715 return DIRECTIVE_FOUND
;
3718 macro_start
= nasm_malloc(sizeof(*macro_start
));
3719 macro_start
->next
= NULL
;
3720 make_tok_num(macro_start
, reloc_value(evalresult
));
3721 macro_start
->a
.mac
= NULL
;
3724 * We now have a macro name, an implicit parameter count of
3725 * zero, and a numeric token to use as an expansion. Create
3726 * and store an SMacro.
3728 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3729 free_tlist(origline
);
3730 return DIRECTIVE_FOUND
;
3733 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3735 * Syntax is `%line nnn[+mmm] [filename]'
3737 tline
= tline
->next
;
3739 if (!tok_type_(tline
, TOK_NUMBER
)) {
3740 error(ERR_NONFATAL
, "`%%line' expects line number");
3741 free_tlist(origline
);
3742 return DIRECTIVE_FOUND
;
3744 k
= readnum(tline
->text
, &err
);
3746 tline
= tline
->next
;
3747 if (tok_is_(tline
, "+")) {
3748 tline
= tline
->next
;
3749 if (!tok_type_(tline
, TOK_NUMBER
)) {
3750 error(ERR_NONFATAL
, "`%%line' expects line increment");
3751 free_tlist(origline
);
3752 return DIRECTIVE_FOUND
;
3754 m
= readnum(tline
->text
, &err
);
3755 tline
= tline
->next
;
3761 nasm_free(src_set_fname(detoken(tline
, false)));
3763 free_tlist(origline
);
3764 return DIRECTIVE_FOUND
;
3767 if (defining
!= NULL
) {
3768 if (defining
->type
== EXP_WHILE
) {
3769 defining
->def_depth
++;
3771 return NO_DIRECTIVE_FOUND
;
3774 if ((istk
->expansion
!= NULL
) &&
3775 (istk
->expansion
->emitting
== false)) {
3779 l
->first
= copy_Token(tline
->next
);
3780 j
= if_condition(tline
->next
, i
);
3781 tline
->next
= NULL
; /* it got freed */
3782 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
3784 ed
= new_ExpDef(EXP_WHILE
);
3787 ed
->max_depth
= DEADMAN_LIMIT
;
3788 ed
->ignoring
= ((ed
->state
== COND_IF_TRUE
) ? false : true);
3789 if (ed
->ignoring
== false) {
3792 } else if (l
!= NULL
) {
3793 delete_Token(l
->first
);
3797 ed
->prev
= defining
;
3799 free_tlist(origline
);
3800 return DIRECTIVE_FOUND
;
3803 if (defining
!= NULL
) {
3804 if (defining
->type
== EXP_WHILE
) {
3805 if (defining
->def_depth
> 0) {
3806 defining
->def_depth
--;
3807 return NO_DIRECTIVE_FOUND
;
3810 return NO_DIRECTIVE_FOUND
;
3813 if (tline
->next
!= NULL
) {
3814 error_precond(ERR_WARNING
|ERR_PASS1
,
3815 "trailing garbage after `%%endwhile' ignored");
3817 if ((defining
== NULL
) || (defining
->type
!= EXP_WHILE
)) {
3818 error(ERR_NONFATAL
, "`%%endwhile': no matching `%%while'");
3819 return DIRECTIVE_FOUND
;
3822 defining
= ed
->prev
;
3823 if (ed
->ignoring
== false) {
3824 ed
->prev
= expansions
;
3826 ei
= new_ExpInv(EXP_WHILE
, ed
);
3827 ei
->current
= ed
->line
->next
;
3828 ei
->emitting
= true;
3829 ei
->prev
= istk
->expansion
;
3830 istk
->expansion
= ei
;
3834 free_tlist(origline
);
3835 return DIRECTIVE_FOUND
;
3838 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3840 * We must search along istk->expansion until we hit a
3841 * while invocation. Then we disable the emitting state(s)
3842 * between exitwhile and endwhile.
3844 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3845 if (ei
->type
== EXP_WHILE
) {
3852 * Set all invocations leading back to the while
3853 * invocation to a non-emitting state.
3855 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3856 eei
->emitting
= false;
3858 eei
->emitting
= false;
3859 eei
->current
= NULL
;
3860 eei
->def
->cur_depth
= eei
->def
->max_depth
;
3862 error(ERR_NONFATAL
, "`%%exitwhile' not within `%%while' block");
3864 free_tlist(origline
);
3865 return DIRECTIVE_FOUND
;
3868 if (defining
!= NULL
) {
3869 if (defining
->type
== EXP_COMMENT
) {
3870 defining
->def_depth
++;
3872 return NO_DIRECTIVE_FOUND
;
3874 ed
= new_ExpDef(EXP_COMMENT
);
3875 ed
->ignoring
= true;
3876 ed
->prev
= defining
;
3878 free_tlist(origline
);
3879 return DIRECTIVE_FOUND
;
3882 if (defining
!= NULL
) {
3883 if (defining
->type
== EXP_COMMENT
) {
3884 if (defining
->def_depth
> 0) {
3885 defining
->def_depth
--;
3886 return NO_DIRECTIVE_FOUND
;
3889 return NO_DIRECTIVE_FOUND
;
3892 if ((defining
== NULL
) || (defining
->type
!= EXP_COMMENT
)) {
3893 error(ERR_NONFATAL
, "`%%endcomment': no matching `%%comment'");
3894 return DIRECTIVE_FOUND
;
3897 defining
= ed
->prev
;
3899 free_tlist(origline
);
3900 return DIRECTIVE_FOUND
;
3903 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3904 if (in_final
!= false) {
3905 error(ERR_FATAL
, "`%%final' cannot be used recursively");
3907 tline
= tline
->next
;
3909 if (tline
== NULL
) {
3910 error(ERR_NONFATAL
, "`%%final' expects at least one parameter");
3913 l
->first
= copy_Token(tline
);
3917 free_tlist(origline
);
3918 return DIRECTIVE_FOUND
;
3922 "preprocessor directive `%s' not yet implemented",
3924 return DIRECTIVE_FOUND
;
3929 * Ensure that a macro parameter contains a condition code and
3930 * nothing else. Return the condition code index if so, or -1
3933 static int find_cc(Token
* t
)
3939 return -1; /* Probably a %+ without a space */
3942 if (t
->type
!= TOK_ID
)
3946 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
3950 j
= ARRAY_SIZE(conditions
);
3953 m
= nasm_stricmp(t
->text
, conditions
[k
]);
3968 static bool paste_tokens(Token
**head
, const struct tokseq_match
*m
,
3969 int mnum
, bool handle_paste_tokens
)
3971 Token
**tail
, *t
, *tt
;
3973 bool did_paste
= false;
3977 /* Now handle token pasting... */
3980 while ((t
= *tail
) && (tt
= t
->next
)) {
3982 case TOK_WHITESPACE
:
3983 if (tt
->type
== TOK_WHITESPACE
) {
3984 /* Zap adjacent whitespace tokens */
3985 t
->next
= delete_Token(tt
);
3987 /* Do not advance paste_head here */
3991 case TOK_PASTE
: /* %+ */
3992 if (handle_paste_tokens
) {
3993 /* Zap %+ and whitespace tokens to the right */
3994 while (t
&& (t
->type
== TOK_WHITESPACE
||
3995 t
->type
== TOK_PASTE
))
3996 t
= *tail
= delete_Token(t
);
3997 if (!paste_head
|| !t
)
3998 break; /* Nothing to paste with */
4002 while (tok_type_(tt
, TOK_WHITESPACE
))
4003 tt
= t
->next
= delete_Token(tt
);
4005 tmp
= nasm_strcat(t
->text
, tt
->text
);
4007 tt
= delete_Token(tt
);
4008 t
= *tail
= tokenize(tmp
);
4014 t
->next
= tt
; /* Attach the remaining token chain */
4021 /* else fall through */
4024 * Concatenation of tokens might look nontrivial
4025 * but in real it's pretty simple -- the caller
4026 * prepares the masks of token types to be concatenated
4027 * and we simply find matched sequences and slip
4030 for (i
= 0; i
< mnum
; i
++) {
4031 if (PP_CONCAT_MASK(t
->type
) & m
[i
].mask_head
) {
4035 while (tt
&& (PP_CONCAT_MASK(tt
->type
) & m
[i
].mask_tail
)) {
4036 len
+= strlen(tt
->text
);
4041 * Now tt points to the first token after
4042 * the potential paste area...
4044 if (tt
!= t
->next
) {
4045 /* We have at least two tokens... */
4046 len
+= strlen(t
->text
);
4047 p
= tmp
= nasm_malloc(len
+1);
4050 p
= strchr(p
, '\0');
4051 t
= delete_Token(t
);
4053 t
= *tail
= tokenize(tmp
);
4059 t
->next
= tt
; /* Attach the remaining token chain */
4067 if (i
>= mnum
) { /* no match */
4069 if (!tok_type_(t
->next
, TOK_WHITESPACE
))
4079 * expands to a list of tokens from %{x:y}
4081 static Token
*expand_mmac_params_range(ExpInv
*ei
, Token
*tline
, Token
***last
)
4083 Token
*t
= tline
, **tt
, *tm
, *head
;
4087 pos
= strchr(tline
->text
, ':');
4090 lst
= atoi(pos
+ 1);
4091 fst
= atoi(tline
->text
+ 1);
4094 * only macros params are accounted so
4095 * if someone passes %0 -- we reject such
4098 if (lst
== 0 || fst
== 0)
4101 /* the values should be sane */
4102 if ((fst
> (int)ei
->nparam
|| fst
< (-(int)ei
->nparam
)) ||
4103 (lst
> (int)ei
->nparam
|| lst
< (-(int)ei
->nparam
)))
4106 fst
= fst
< 0 ? fst
+ (int)ei
->nparam
+ 1: fst
;
4107 lst
= lst
< 0 ? lst
+ (int)ei
->nparam
+ 1: lst
;
4109 /* counted from zero */
4113 * it will be at least one token
4115 tm
= ei
->params
[(fst
+ ei
->rotate
) % ei
->nparam
];
4116 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4117 head
= t
, tt
= &t
->next
;
4119 for (i
= fst
+ 1; i
<= lst
; i
++) {
4120 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
4121 *tt
= t
, tt
= &t
->next
;
4122 j
= (i
+ ei
->rotate
) % ei
->nparam
;
4124 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4125 *tt
= t
, tt
= &t
->next
;
4128 for (i
= fst
- 1; i
>= lst
; i
--) {
4129 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
4130 *tt
= t
, tt
= &t
->next
;
4131 j
= (i
+ ei
->rotate
) % ei
->nparam
;
4133 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4134 *tt
= t
, tt
= &t
->next
;
4142 error(ERR_NONFATAL
, "`%%{%s}': macro parameters out of range",
4148 * Expand MMacro-local things: parameter references (%0, %n, %+n,
4149 * %-n) and MMacro-local identifiers (%%foo) as well as
4150 * macro indirection (%[...]) and range (%{..:..}).
4152 static Token
*expand_mmac_params(Token
* tline
)
4154 Token
*t
, *tt
, **tail
, *thead
;
4155 bool changed
= false;
4162 if (tline
->type
== TOK_PREPROC_ID
&&
4163 (((tline
->text
[1] == '+' || tline
->text
[1] == '-') && tline
->text
[2]) ||
4164 (tline
->text
[1] >= '0' && tline
->text
[1] <= '9') ||
4165 tline
->text
[1] == '%')) {
4167 int type
= 0, cc
; /* type = 0 to placate optimisers */
4174 tline
= tline
->next
;
4176 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
4177 if (ei
->type
== EXP_MMACRO
) {
4182 error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
4184 pos
= strchr(t
->text
, ':');
4186 switch (t
->text
[1]) {
4188 * We have to make a substitution of one of the
4189 * forms %1, %-1, %+1, %%foo, %0.
4192 if ((strlen(t
->text
) > 2) && (t
->text
[2] == '0')) {
4194 text
= nasm_strdup(ei
->label_text
);
4197 snprintf(tmpbuf
, sizeof(tmpbuf
), "%d", ei
->nparam
);
4198 text
= nasm_strdup(tmpbuf
);
4203 snprintf(tmpbuf
, sizeof(tmpbuf
), "..@%"PRIu64
".",
4205 text
= nasm_strcat(tmpbuf
, t
->text
+ 2);
4208 n
= atoi(t
->text
+ 2) - 1;
4209 if (n
>= ei
->nparam
)
4213 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4219 "macro parameter %d is not a condition code",
4224 if (inverse_ccs
[cc
] == -1) {
4226 "condition code `%s' is not invertible",
4230 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
4234 n
= atoi(t
->text
+ 2) - 1;
4235 if (n
>= ei
->nparam
)
4239 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4245 "macro parameter %d is not a condition code",
4250 text
= nasm_strdup(conditions
[cc
]);
4254 n
= atoi(t
->text
+ 1) - 1;
4255 if (n
>= ei
->nparam
)
4259 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4263 for (i
= 0; i
< ei
->paramlen
[n
]; i
++) {
4264 *tail
= new_Token(NULL
, tt
->type
, tt
->text
, 0);
4265 tail
= &(*tail
)->next
;
4269 text
= NULL
; /* we've done it here */
4274 * seems we have a parameters range here
4276 Token
*head
, **last
;
4277 head
= expand_mmac_params_range(ei
, t
, &last
);
4298 } else if (tline
->type
== TOK_INDIRECT
) {
4300 tline
= tline
->next
;
4301 tt
= tokenize(t
->text
);
4302 tt
= expand_mmac_params(tt
);
4303 tt
= expand_smacro(tt
);
4306 tt
->a
.mac
= NULL
; /* Necessary? */
4314 tline
= tline
->next
;
4322 const struct tokseq_match t
[] = {
4324 PP_CONCAT_MASK(TOK_ID
) |
4325 PP_CONCAT_MASK(TOK_FLOAT
), /* head */
4326 PP_CONCAT_MASK(TOK_ID
) |
4327 PP_CONCAT_MASK(TOK_NUMBER
) |
4328 PP_CONCAT_MASK(TOK_FLOAT
) |
4329 PP_CONCAT_MASK(TOK_OTHER
) /* tail */
4332 PP_CONCAT_MASK(TOK_NUMBER
), /* head */
4333 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4336 paste_tokens(&thead
, t
, ARRAY_SIZE(t
), false);
4343 * Expand all single-line macro calls made in the given line.
4344 * Return the expanded version of the line. The original is deemed
4345 * to be destroyed in the process. (In reality we'll just move
4346 * Tokens from input to output a lot of the time, rather than
4347 * actually bothering to destroy and replicate.)
4350 static Token
*expand_smacro(Token
* tline
)
4352 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
4353 SMacro
*head
= NULL
, *m
;
4356 unsigned int nparam
, sparam
;
4358 Token
*org_tline
= tline
;
4361 int deadman
= DEADMAN_LIMIT
;
4365 * Trick: we should avoid changing the start token pointer since it can
4366 * be contained in "next" field of other token. Because of this
4367 * we allocate a copy of first token and work with it; at the end of
4368 * routine we copy it back
4371 tline
= new_Token(org_tline
->next
, org_tline
->type
,
4372 org_tline
->text
, 0);
4373 tline
->a
.mac
= org_tline
->a
.mac
;
4374 nasm_free(org_tline
->text
);
4375 org_tline
->text
= NULL
;
4378 expanded
= true; /* Always expand %+ at least once */
4384 while (tline
) { /* main token loop */
4386 error(ERR_NONFATAL
, "interminable macro recursion");
4390 if ((mname
= tline
->text
)) {
4391 /* if this token is a local macro, look in local context */
4392 if (tline
->type
== TOK_ID
) {
4393 head
= (SMacro
*)hash_findix(&smacros
, mname
);
4394 } else if (tline
->type
== TOK_PREPROC_ID
) {
4395 ctx
= get_ctx(mname
, &mname
, false);
4396 head
= ctx
? (SMacro
*)hash_findix(&ctx
->localmac
, mname
) : NULL
;
4401 * We've hit an identifier. As in is_mmacro below, we first
4402 * check whether the identifier is a single-line macro at
4403 * all, then think about checking for parameters if
4406 list_for_each(m
, head
)
4407 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
4413 if (m
->nparam
== 0) {
4415 * Simple case: the macro is parameterless. Discard the
4416 * one token that the macro call took, and push the
4417 * expansion back on the to-do stack.
4419 if (!m
->expansion
) {
4420 if (!strcmp("__FILE__", m
->name
)) {
4423 src_get(&num
, &file
);
4424 tline
->text
= nasm_quote(file
, strlen(file
));
4425 tline
->type
= TOK_STRING
;
4429 if (!strcmp("__LINE__", m
->name
)) {
4430 nasm_free(tline
->text
);
4431 make_tok_num(tline
, src_get_linnum());
4434 if (!strcmp("__BITS__", m
->name
)) {
4435 nasm_free(tline
->text
);
4436 make_tok_num(tline
, globalbits
);
4439 tline
= delete_Token(tline
);
4444 * Complicated case: at least one macro with this name
4445 * exists and takes parameters. We must find the
4446 * parameters in the call, count them, find the SMacro
4447 * that corresponds to that form of the macro call, and
4448 * substitute for the parameters when we expand. What a
4451 /*tline = tline->next;
4452 skip_white_(tline); */
4455 while (tok_type_(t
, TOK_SMAC_END
)) {
4456 t
->a
.mac
->in_progress
= false;
4458 t
= tline
->next
= delete_Token(t
);
4461 } while (tok_type_(tline
, TOK_WHITESPACE
));
4462 if (!tok_is_(tline
, "(")) {
4464 * This macro wasn't called with parameters: ignore
4465 * the call. (Behaviour borrowed from gnu cpp.)
4474 sparam
= PARAM_DELTA
;
4475 params
= nasm_malloc(sparam
* sizeof(Token
*));
4476 params
[0] = tline
->next
;
4477 paramsize
= nasm_malloc(sparam
* sizeof(int));
4479 while (true) { /* parameter loop */
4481 * For some unusual expansions
4482 * which concatenates function call
4485 while (tok_type_(t
, TOK_SMAC_END
)) {
4486 t
->a
.mac
->in_progress
= false;
4488 t
= tline
->next
= delete_Token(t
);
4494 "macro call expects terminating `)'");
4497 if (tline
->type
== TOK_WHITESPACE
4499 if (paramsize
[nparam
])
4502 params
[nparam
] = tline
->next
;
4503 continue; /* parameter loop */
4505 if (tline
->type
== TOK_OTHER
4506 && tline
->text
[1] == 0) {
4507 char ch
= tline
->text
[0];
4508 if (ch
== ',' && !paren
&& brackets
<= 0) {
4509 if (++nparam
>= sparam
) {
4510 sparam
+= PARAM_DELTA
;
4511 params
= nasm_realloc(params
,
4512 sparam
* sizeof(Token
*));
4513 paramsize
= nasm_realloc(paramsize
,
4514 sparam
* sizeof(int));
4516 params
[nparam
] = tline
->next
;
4517 paramsize
[nparam
] = 0;
4519 continue; /* parameter loop */
4522 (brackets
> 0 || (brackets
== 0 &&
4523 !paramsize
[nparam
])))
4525 if (!(brackets
++)) {
4526 params
[nparam
] = tline
->next
;
4527 continue; /* parameter loop */
4530 if (ch
== '}' && brackets
> 0)
4531 if (--brackets
== 0) {
4533 continue; /* parameter loop */
4535 if (ch
== '(' && !brackets
)
4537 if (ch
== ')' && brackets
<= 0)
4543 error(ERR_NONFATAL
, "braces do not "
4544 "enclose all of macro parameter");
4546 paramsize
[nparam
] += white
+ 1;
4548 } /* parameter loop */
4550 while (m
&& (m
->nparam
!= nparam
||
4551 mstrcmp(m
->name
, mname
,
4555 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4556 "macro `%s' exists, "
4557 "but not taking %d parameters",
4558 mstart
->text
, nparam
);
4561 if (m
&& m
->in_progress
)
4563 if (!m
) { /* in progess or didn't find '(' or wrong nparam */
4565 * Design question: should we handle !tline, which
4566 * indicates missing ')' here, or expand those
4567 * macros anyway, which requires the (t) test a few
4571 nasm_free(paramsize
);
4575 * Expand the macro: we are placed on the last token of the
4576 * call, so that we can easily split the call from the
4577 * following tokens. We also start by pushing an SMAC_END
4578 * token for the cycle removal.
4585 tt
= new_Token(tline
, TOK_SMAC_END
, NULL
, 0);
4587 m
->in_progress
= true;
4589 list_for_each(t
, m
->expansion
) {
4590 if (t
->type
>= TOK_SMAC_PARAM
) {
4591 Token
*pcopy
= tline
, **ptail
= &pcopy
;
4595 ttt
= params
[t
->type
- TOK_SMAC_PARAM
];
4596 i
= paramsize
[t
->type
- TOK_SMAC_PARAM
];
4598 pt
= *ptail
= new_Token(tline
, ttt
->type
,
4604 } else if (t
->type
== TOK_PREPROC_Q
) {
4605 tt
= new_Token(tline
, TOK_ID
, mname
, 0);
4607 } else if (t
->type
== TOK_PREPROC_QQ
) {
4608 tt
= new_Token(tline
, TOK_ID
, m
->name
, 0);
4611 tt
= new_Token(tline
, t
->type
, t
->text
, 0);
4617 * Having done that, get rid of the macro call, and clean
4618 * up the parameters.
4621 nasm_free(paramsize
);
4624 continue; /* main token loop */
4629 if (tline
->type
== TOK_SMAC_END
) {
4630 tline
->a
.mac
->in_progress
= false;
4631 tline
= delete_Token(tline
);
4634 tline
= tline
->next
;
4642 * Now scan the entire line and look for successive TOK_IDs that resulted
4643 * after expansion (they can't be produced by tokenize()). The successive
4644 * TOK_IDs should be concatenated.
4645 * Also we look for %+ tokens and concatenate the tokens before and after
4646 * them (without white spaces in between).
4649 const struct tokseq_match t
[] = {
4651 PP_CONCAT_MASK(TOK_ID
) |
4652 PP_CONCAT_MASK(TOK_PREPROC_ID
), /* head */
4653 PP_CONCAT_MASK(TOK_ID
) |
4654 PP_CONCAT_MASK(TOK_PREPROC_ID
) |
4655 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4658 if (paste_tokens(&thead
, t
, ARRAY_SIZE(t
), true)) {
4660 * If we concatenated something, *and* we had previously expanded
4661 * an actual macro, scan the lines again for macros...
4672 *org_tline
= *thead
;
4673 /* since we just gave text to org_line, don't free it */
4675 delete_Token(thead
);
4677 /* the expression expanded to empty line;
4678 we can't return NULL for some reasons
4679 we just set the line to a single WHITESPACE token. */
4680 memset(org_tline
, 0, sizeof(*org_tline
));
4681 org_tline
->text
= NULL
;
4682 org_tline
->type
= TOK_WHITESPACE
;
4691 * Similar to expand_smacro but used exclusively with macro identifiers
4692 * right before they are fetched in. The reason is that there can be
4693 * identifiers consisting of several subparts. We consider that if there
4694 * are more than one element forming the name, user wants a expansion,
4695 * otherwise it will be left as-is. Example:
4699 * the identifier %$abc will be left as-is so that the handler for %define
4700 * will suck it and define the corresponding value. Other case:
4702 * %define _%$abc cde
4704 * In this case user wants name to be expanded *before* %define starts
4705 * working, so we'll expand %$abc into something (if it has a value;
4706 * otherwise it will be left as-is) then concatenate all successive
4709 static Token
*expand_id(Token
* tline
)
4711 Token
*cur
, *oldnext
= NULL
;
4713 if (!tline
|| !tline
->next
)
4718 (cur
->next
->type
== TOK_ID
||
4719 cur
->next
->type
== TOK_PREPROC_ID
4720 || cur
->next
->type
== TOK_NUMBER
))
4723 /* If identifier consists of just one token, don't expand */
4728 oldnext
= cur
->next
; /* Detach the tail past identifier */
4729 cur
->next
= NULL
; /* so that expand_smacro stops here */
4732 tline
= expand_smacro(tline
);
4735 /* expand_smacro possibly changhed tline; re-scan for EOL */
4737 while (cur
&& cur
->next
)
4740 cur
->next
= oldnext
;
4747 * Determine whether the given line constitutes a multi-line macro
4748 * call, and return the ExpDef structure called if so. Doesn't have
4749 * to check for an initial label - that's taken care of in
4750 * expand_mmacro - but must check numbers of parameters. Guaranteed
4751 * to be called with tline->type == TOK_ID, so the putative macro
4752 * name is easy to find.
4754 static ExpDef
*is_mmacro(Token
* tline
, Token
*** params_array
)
4760 head
= (ExpDef
*) hash_findix(&expdefs
, tline
->text
);
4763 * Efficiency: first we see if any macro exists with the given
4764 * name. If not, we can return NULL immediately. _Then_ we
4765 * count the parameters, and then we look further along the
4766 * list if necessary to find the proper ExpDef.
4768 list_for_each(ed
, head
)
4769 if (!mstrcmp(ed
->name
, tline
->text
, ed
->casesense
))
4775 * OK, we have a potential macro. Count and demarcate the
4778 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
4781 * So we know how many parameters we've got. Find the ExpDef
4782 * structure that handles this number.
4785 if (ed
->nparam_min
<= nparam
4786 && (ed
->plus
|| nparam
<= ed
->nparam_max
)) {
4788 * It's right, and we can use it. Add its default
4789 * parameters to the end of our list if necessary.
4791 if (ed
->defaults
&& nparam
< ed
->nparam_min
+ ed
->ndefs
) {
4793 nasm_realloc(params
,
4794 ((ed
->nparam_min
+ ed
->ndefs
+
4795 1) * sizeof(*params
)));
4796 while (nparam
< ed
->nparam_min
+ ed
->ndefs
) {
4797 params
[nparam
] = ed
->defaults
[nparam
- ed
->nparam_min
];
4802 * If we've gone over the maximum parameter count (and
4803 * we're in Plus mode), ignore parameters beyond
4806 if (ed
->plus
&& nparam
> ed
->nparam_max
)
4807 nparam
= ed
->nparam_max
;
4809 * Then terminate the parameter list, and leave.
4811 if (!params
) { /* need this special case */
4812 params
= nasm_malloc(sizeof(*params
));
4815 params
[nparam
] = NULL
;
4816 *params_array
= params
;
4820 * This one wasn't right: look for the next one with the
4823 list_for_each(ed
, ed
->next
)
4824 if (!mstrcmp(ed
->name
, tline
->text
, ed
->casesense
))
4829 * After all that, we didn't find one with the right number of
4830 * parameters. Issue a warning, and fail to expand the macro.
4832 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4833 "macro `%s' exists, but not taking %d parameters",
4834 tline
->text
, nparam
);
4840 * Expand the multi-line macro call made by the given line, if
4841 * there is one to be expanded. If there is, push the expansion on
4842 * istk->expansion and return true. Otherwise return false.
4844 static bool expand_mmacro(Token
* tline
)
4846 Token
*label
= NULL
;
4847 int dont_prepend
= 0;
4848 Token
**params
, *t
, *mtok
;
4852 int i
, nparam
, *paramlen
;
4857 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4858 if (!tok_type_(t
, TOK_ID
) && !tok_type_(t
, TOK_PREPROC_ID
))
4861 ed
= is_mmacro(t
, ¶ms
);
4867 * We have an id which isn't a macro call. We'll assume
4868 * it might be a label; we'll also check to see if a
4869 * colon follows it. Then, if there's another id after
4870 * that lot, we'll check it again for macro-hood.
4874 if (tok_type_(t
, TOK_WHITESPACE
))
4875 last
= t
, t
= t
->next
;
4876 if (tok_is_(t
, ":")) {
4878 last
= t
, t
= t
->next
;
4879 if (tok_type_(t
, TOK_WHITESPACE
))
4880 last
= t
, t
= t
->next
;
4882 if (!tok_type_(t
, TOK_ID
) || !(ed
= is_mmacro(t
, ¶ms
)))
4890 * Fix up the parameters: this involves stripping leading and
4891 * trailing whitespace, then stripping braces if they are
4894 for (nparam
= 0; params
[nparam
]; nparam
++) ;
4895 paramlen
= nparam
? nasm_malloc(nparam
* sizeof(*paramlen
)) : NULL
;
4897 for (i
= 0; params
[i
]; i
++) {
4899 int comma
= (!ed
->plus
|| i
< nparam
- 1);
4903 if (tok_is_(t
, "{"))
4904 t
= t
->next
, brace
= true, comma
= false;
4908 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
4909 break; /* ... because we have hit a comma */
4910 if (comma
&& t
->type
== TOK_WHITESPACE
4911 && tok_is_(t
->next
, ","))
4912 break; /* ... or a space then a comma */
4913 if (brace
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "}"))
4914 break; /* ... or a brace */
4920 if (ed
->cur_depth
>= ed
->max_depth
) {
4921 if (ed
->max_depth
> 1) {
4923 "reached maximum macro recursion depth of %i for %s",
4924 ed
->max_depth
,ed
->name
);
4932 * OK, we have found a ExpDef structure representing a
4933 * previously defined mmacro. Create an expansion invocation
4934 * and point it back to the expansion definition. Substitution of
4935 * parameter tokens and macro-local tokens doesn't get done
4936 * until the single-line macro substitution process; this is
4937 * because delaying them allows us to change the semantics
4938 * later through %rotate.
4940 ei
= new_ExpInv(EXP_MMACRO
, ed
);
4941 ei
->name
= nasm_strdup(mname
);
4942 //ei->label = label;
4943 //ei->label_text = detoken(label, false);
4944 ei
->current
= ed
->line
;
4945 ei
->emitting
= true;
4946 //ei->iline = tline;
4947 ei
->params
= params
;
4948 ei
->nparam
= nparam
;
4950 ei
->paramlen
= paramlen
;
4953 ei
->prev
= istk
->expansion
;
4954 istk
->expansion
= ei
;
4957 * Special case: detect %00 on first invocation; if found,
4958 * avoid emitting any labels that precede the mmacro call.
4959 * ed->prepend is set to -1 when %00 is detected, else 1.
4961 if (ed
->prepend
== 0) {
4962 for (l
= ed
->line
; l
!= NULL
; l
= l
->next
) {
4963 for (t
= l
->first
; t
!= NULL
; t
= t
->next
) {
4964 if ((t
->type
== TOK_PREPROC_ID
) &&
4965 (strlen(t
->text
) == 3) &&
4966 (t
->text
[1] == '0') && (t
->text
[2] == '0')) {
4971 if (dont_prepend
< 0) {
4975 ed
->prepend
= ((dont_prepend
< 0) ? -1 : 1);
4979 * If we had a label, push it on as the first line of
4980 * the macro expansion.
4982 if (label
!= NULL
) {
4983 if (ed
->prepend
< 0) {
4984 ei
->label_text
= detoken(label
, false);
4986 if (dont_prepend
== 0) {
4988 while (t
->next
!= NULL
) {
4991 t
->next
= new_Token(NULL
, TOK_OTHER
, ":", 0);
4994 l
->first
= copy_Token(label
);
4995 l
->next
= ei
->current
;
5000 list
->uplevel(ed
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
5006 /* The function that actually does the error reporting */
5007 static void verror(int severity
, const char *fmt
, va_list arg
)
5011 vsnprintf(buff
, sizeof(buff
), fmt
, arg
);
5013 if (istk
&& istk
->mmac_depth
> 0) {
5014 ExpInv
*ei
= istk
->expansion
;
5015 int lineno
= ei
->lineno
;
5017 if (ei
->type
== EXP_MMACRO
)
5019 lineno
+= ei
->relno
;
5022 nasm_error(severity
, "(%s:%d) %s", ei
->def
->name
,
5025 nasm_error(severity
, "%s", buff
);
5029 * Since preprocessor always operate only on the line that didn't
5030 * arrived yet, we should always use ERR_OFFBY1.
5032 static void error(int severity
, const char *fmt
, ...)
5036 verror(severity
, fmt
, arg
);
5041 * Because %else etc are evaluated in the state context
5042 * of the previous branch, errors might get lost with error():
5043 * %if 0 ... %else trailing garbage ... %endif
5044 * So %else etc should report errors with this function.
5046 static void error_precond(int severity
, const char *fmt
, ...)
5050 /* Only ignore the error if it's really in a dead branch */
5051 if ((istk
!= NULL
) &&
5052 (istk
->expansion
!= NULL
) &&
5053 (istk
->expansion
->type
== EXP_IF
) &&
5054 (istk
->expansion
->def
->state
== COND_NEVER
))
5058 verror(severity
, fmt
, arg
);
5063 pp_reset(char *file
, int apass
, ListGen
* listgen
, StrList
**deplist
)
5068 istk
= nasm_malloc(sizeof(Include
));
5070 istk
->expansion
= NULL
;
5071 istk
->fp
= fopen(file
, "r");
5073 src_set_fname(nasm_strdup(file
));
5076 istk
->mmac_depth
= 0;
5078 error(ERR_FATAL
|ERR_NOFILE
, "unable to open input file `%s'",
5083 nested_mac_count
= 0;
5084 nested_rep_count
= 0;
5087 if (tasm_compatible_mode
) {
5088 stdmacpos
= nasm_stdmac
;
5090 stdmacpos
= nasm_stdmac_after_tasm
;
5092 any_extrastdmac
= extrastdmac
&& *extrastdmac
;
5097 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
5098 * The caller, however, will also pass in 3 for preprocess-only so
5099 * we can set __PASS__ accordingly.
5101 pass
= apass
> 2 ? 2 : apass
;
5103 dephead
= deptail
= deplist
;
5105 StrList
*sl
= nasm_malloc(strlen(file
)+1+sizeof sl
->next
);
5107 strcpy(sl
->str
, file
);
5109 deptail
= &sl
->next
;
5113 * Define the __PASS__ macro. This is defined here unlike
5114 * all the other builtins, because it is special -- it varies between
5117 t
= nasm_malloc(sizeof(*t
));
5119 make_tok_num(t
, apass
);
5121 define_smacro(NULL
, "__PASS__", true, 0, t
);
5124 static char *pp_getline(void)
5135 * Fetch a tokenized line, either from the expansion
5136 * buffer or from the input file.
5140 while (1) { /* until we get a line we can use */
5142 * Fetch a tokenized line from the expansion buffer
5144 if (istk
->expansion
!= NULL
) {
5145 ei
= istk
->expansion
;
5146 if (ei
->current
!= NULL
) {
5147 if (ei
->emitting
== false) {
5152 ei
->current
= l
->next
;
5154 tline
= copy_Token(l
->first
);
5155 if (((ei
->type
== EXP_REP
) ||
5156 (ei
->type
== EXP_MMACRO
) ||
5157 (ei
->type
== EXP_WHILE
))
5158 && (ei
->def
->nolist
== false)) {
5159 char *p
= detoken(tline
, false);
5160 list
->line(LIST_MACRO
, p
);
5163 if (ei
->linnum
> -1) {
5164 src_set_linnum(src_get_linnum() + 1);
5167 } else if ((ei
->type
== EXP_REP
) &&
5168 (ei
->def
->cur_depth
< ei
->def
->max_depth
)) {
5169 ei
->def
->cur_depth
++;
5170 ei
->current
= ei
->def
->line
;
5173 } else if ((ei
->type
== EXP_WHILE
) &&
5174 (ei
->def
->cur_depth
< ei
->def
->max_depth
)) {
5175 ei
->current
= ei
->def
->line
;
5177 tline
= copy_Token(ei
->current
->first
);
5178 j
= if_condition(tline
, PP_WHILE
);
5180 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
5181 if (j
== COND_IF_TRUE
) {
5182 ei
->current
= ei
->current
->next
;
5183 ei
->def
->cur_depth
++;
5185 ei
->emitting
= false;
5187 ei
->def
->cur_depth
= ei
->def
->max_depth
;
5191 istk
->expansion
= ei
->prev
;
5194 if ((ei
->emitting
== true) &&
5195 (ed
->max_depth
== DEADMAN_LIMIT
) &&
5196 (ed
->cur_depth
== DEADMAN_LIMIT
)
5198 error(ERR_FATAL
, "runaway expansion detected, aborting");
5200 if (ed
->cur_depth
> 0) {
5202 } else if (ed
->type
!= EXP_MMACRO
) {
5203 expansions
= ed
->prev
;
5206 if ((ei
->type
== EXP_REP
) ||
5207 (ei
->type
== EXP_MMACRO
) ||
5208 (ei
->type
== EXP_WHILE
)) {
5209 list
->downlevel(LIST_MACRO
);
5210 if (ei
->type
== EXP_MMACRO
) {
5215 if (ei
->linnum
> -1) {
5216 src_set_linnum(ei
->linnum
);
5224 * Read in line from input and tokenize
5227 if (line
) { /* from the current input file */
5228 line
= prepreproc(line
);
5229 tline
= tokenize(line
);
5235 * The current file has ended; work down the istk
5240 if (i
->expansion
!= NULL
) {
5242 "end of file while still in an expansion");
5244 /* only set line and file name if there's a next node */
5246 src_set_linnum(i
->lineno
);
5247 nasm_free(src_set_fname(i
->fname
));
5249 if ((i
->next
== NULL
) && (finals
!= NULL
)) {
5251 ei
= new_ExpInv(EXP_FINAL
, NULL
);
5252 ei
->emitting
= true;
5253 ei
->current
= finals
;
5254 istk
->expansion
= ei
;
5259 list
->downlevel(LIST_INCLUDE
);
5262 if (finals
!= NULL
) {
5272 if (defining
== NULL
) {
5273 tline
= expand_mmac_params(tline
);
5277 * Check the line to see if it's a preprocessor directive.
5279 if (do_directive(tline
) == DIRECTIVE_FOUND
) {
5281 } else if (defining
!= NULL
) {
5283 * We're defining an expansion. We emit nothing at all,
5284 * and just shove the tokenized line on to the definition.
5286 if (defining
->ignoring
== false) {
5287 Line
*l
= new_Line();
5289 if (defining
->line
== NULL
) {
5293 defining
->last
->next
= l
;
5299 defining
->linecount
++;
5301 } else if ((istk
->expansion
!= NULL
) &&
5302 (istk
->expansion
->emitting
!= true)) {
5304 * We're in a non-emitting branch of an expansion.
5305 * Emit nothing at all, not even a blank line: when we
5306 * emerge from the expansion we'll give a line-number
5307 * directive so we keep our place correctly.
5312 tline
= expand_smacro(tline
);
5313 if (expand_mmacro(tline
) != true) {
5315 * De-tokenize the line again, and emit it.
5317 line
= detoken(tline
, true);
5328 static void pp_cleanup(int pass
)
5330 if (defining
!= NULL
) {
5331 error(ERR_NONFATAL
, "end of file while still defining an expansion");
5332 while (defining
!= NULL
) {
5333 ExpDef
*ed
= defining
;
5334 defining
= ed
->prev
;
5339 while (cstk
!= NULL
)
5342 while (istk
!= NULL
) {
5346 nasm_free(i
->fname
);
5348 while (i
->expansion
!= NULL
) {
5349 ExpInv
*ei
= i
->expansion
;
5350 i
->expansion
= ei
->prev
;
5356 nasm_free(src_set_fname(NULL
));
5361 while ((i
= ipath
)) {
5370 void pp_include_path(char *path
)
5374 i
= nasm_malloc(sizeof(IncPath
));
5375 i
->path
= path
? nasm_strdup(path
) : NULL
;
5388 void pp_pre_include(char *fname
)
5390 Token
*inc
, *space
, *name
;
5393 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
5394 space
= new_Token(name
, TOK_WHITESPACE
, NULL
, 0);
5395 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
5403 void pp_pre_define(char *definition
)
5409 equals
= strchr(definition
, '=');
5410 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5411 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
5414 space
->next
= tokenize(definition
);
5424 void pp_pre_undefine(char *definition
)
5429 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5430 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
5431 space
->next
= tokenize(definition
);
5440 * This function is used to assist with "runtime" preprocessor
5441 * directives, e.g. pp_runtime("%define __BITS__ 64");
5443 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
5444 * PASS A VALID STRING TO THIS FUNCTION!!!!!
5447 void pp_runtime(char *definition
)
5451 def
= tokenize(definition
);
5452 if (do_directive(def
) == NO_DIRECTIVE_FOUND
)
5457 void pp_extra_stdmac(macros_t
*macros
)
5459 extrastdmac
= macros
;
5462 static void make_tok_num(Token
* tok
, int64_t val
)
5465 snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
5466 tok
->text
= nasm_strdup(numbuf
);
5467 tok
->type
= TOK_NUMBER
;