1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2011 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 */
218 bool plus
; /* is the last parameter greedy? */
219 bool nolist
; /* is this expansion listing-inhibited? */
220 Token
*dlist
; /* all defaults as one list */
221 Token
**defaults
; /* parameter default pointers */
222 int ndefs
; /* number of default parameters */
224 int prepend
; /* label prepend state */
228 int linecount
; /* number of lines within expansion */
230 int64_t def_depth
; /* current number of definition pairs deep */
231 int64_t cur_depth
; /* current number of expansions */
232 int64_t max_depth
; /* maximum number of expansions allowed */
234 int state
; /* condition state */
235 bool ignoring
; /* ignoring definition lines */
239 * Store the invocation of an expansion.
241 * The `prev' field is for the `istk->expansion` linked-list.
243 * When an expansion is being expanded, `params', `iline', `nparam',
244 * `paramlen', `rotate' and `unique' are local to the invocation.
247 ExpInv
*prev
; /* previous invocation */
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 */
261 int lineno
; /* current line number in expansion */
262 int linnum
; /* line number at invocation */
263 int relno
; /* relative line number at invocation */
264 enum pp_exp_type type
; /* expansion type */
269 * To handle an arbitrary level of file inclusion, we maintain a
270 * stack (ie linked list) of these things.
284 * Include search path. This is simply a list of strings which get
285 * prepended, in turn, to the name of an include file, in an
286 * attempt to find the file if it's not in the current directory.
294 * Conditional assembly: we maintain a separate stack of these for
295 * each level of file inclusion. (The only reason we keep the
296 * stacks separate is to ensure that a stray `%endif' in a file
297 * included from within the true branch of a `%if' won't terminate
298 * it and cause confusion: instead, rightly, it'll cause an error.)
302 * These states are for use just after %if or %elif: IF_TRUE
303 * means the condition has evaluated to truth so we are
304 * currently emitting, whereas IF_FALSE means we are not
305 * currently emitting but will start doing so if a %else comes
306 * up. In these states, all directives are admissible: %elif,
307 * %else and %endif. (And of course %if.)
309 COND_IF_TRUE
, COND_IF_FALSE
,
311 * These states come up after a %else: ELSE_TRUE means we're
312 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
313 * any %elif or %else will cause an error.
315 COND_ELSE_TRUE
, COND_ELSE_FALSE
,
317 * These states mean that we're not emitting now, and also that
318 * nothing until %endif will be emitted at all. COND_DONE is
319 * used when we've had our moment of emission
320 * and have now started seeing %elifs. COND_NEVER is used when
321 * the condition construct in question is contained within a
322 * non-emitting branch of a larger condition construct,
323 * or if there is an error.
325 COND_DONE
, COND_NEVER
327 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
330 * These defines are used as the possible return values for do_directive
332 #define NO_DIRECTIVE_FOUND 0
333 #define DIRECTIVE_FOUND 1
336 * This define sets the upper limit for smacro and expansions
338 #define DEADMAN_LIMIT (1 << 20)
341 #define REP_LIMIT ((INT64_C(1) << 62))
344 * Condition codes. Note that we use c_ prefix not C_ because C_ is
345 * used in nasm.h for the "real" condition codes. At _this_ level,
346 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
347 * ones, so we need a different enum...
349 static const char * const conditions
[] = {
350 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
351 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
352 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
355 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
356 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
357 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_RCXZ
, c_S
, c_Z
,
360 static const enum pp_conds inverse_ccs
[] = {
361 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
362 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
,
363 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, -1, c_NS
, c_NZ
366 /* For TASM compatibility we need to be able to recognise TASM compatible
367 * conditional compilation directives. Using the NASM pre-processor does
368 * not work, so we look for them specifically from the following list and
369 * then jam in the equivalent NASM directive into the input stream.
373 TM_ARG
, TM_ELIF
, TM_ELSE
, TM_ENDIF
, TM_IF
, TM_IFDEF
, TM_IFDIFI
,
374 TM_IFNDEF
, TM_INCLUDE
, TM_LOCAL
377 static const char * const tasm_directives
[] = {
378 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
379 "ifndef", "include", "local"
382 static int StackSize
= 4;
383 static char *StackPointer
= "ebp";
384 static int ArgOffset
= 8;
385 static int LocalOffset
= 0;
387 static Context
*cstk
;
388 static Include
*istk
;
389 static IncPath
*ipath
= NULL
;
391 static int pass
; /* HACK: pass 0 = generate dependencies only */
392 static StrList
**dephead
, **deptail
; /* Dependency list */
394 static uint64_t unique
; /* unique identifier numbers */
396 static Line
*predef
= NULL
;
397 static bool do_predef
;
399 static ListGen
*list
;
402 * The current set of expansion definitions we have defined.
404 static struct hash_table expdefs
;
407 * The current set of single-line macros we have defined.
409 static struct hash_table smacros
;
412 * Linked List of all active expansion definitions
414 struct ExpDef
*expansions
= NULL
;
417 * The expansion we are currently defining
419 static ExpDef
*defining
= NULL
;
421 static uint64_t nested_mac_count
;
422 static uint64_t nested_rep_count
;
425 * Linked-list of lines to preprocess, prior to cleanup
427 static Line
*finals
= NULL
;
428 static bool in_final
= false;
431 * The number of macro parameters to allocate space for at a time.
433 #define PARAM_DELTA 16
436 * The standard macro set: defined in macros.c in the array nasm_stdmac.
437 * This gives our position in the macro set, when we're processing it.
439 static macros_t
*stdmacpos
;
442 * The extra standard macros that come from the object format, if
445 static macros_t
*extrastdmac
= NULL
;
446 static bool any_extrastdmac
;
449 * Tokens are allocated in blocks to improve speed
451 #define TOKEN_BLOCKSIZE 4096
452 static Token
*freeTokens
= NULL
;
458 static Blocks blocks
= { NULL
, NULL
};
461 * Forward declarations.
463 static Token
*expand_mmac_params(Token
* tline
);
464 static Token
*expand_smacro(Token
* tline
);
465 static Token
*expand_id(Token
* tline
);
466 static Context
*get_ctx(const char *name
, const char **namep
);
467 static void make_tok_num(Token
* tok
, int64_t val
);
468 static void error(int severity
, const char *fmt
, ...);
469 static void error_precond(int severity
, const char *fmt
, ...);
470 static void *new_Block(size_t size
);
471 static void delete_Blocks(void);
472 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
473 const char *text
, int txtlen
);
474 static Token
*copy_Token(Token
* tline
);
475 static Token
*delete_Token(Token
* t
);
476 static Line
*new_Line(void);
477 static ExpDef
*new_ExpDef(int exp_type
);
478 static ExpInv
*new_ExpInv(int exp_type
, ExpDef
*ed
);
481 * Macros for safe checking of token pointers, avoid *(NULL)
483 #define tok_type_(x,t) ((x) && (x)->type == (t))
484 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
485 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
486 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
489 * A few helpers for single macros
492 /* We might be not smacro parameter at all */
493 static bool is_smacro_param(Token
*t
)
495 return t
->type
>= TOK_SMAC_PARAM
;
498 /* smacro parameters are counted in a special way */
499 static int smacro_get_param_idx(Token
*t
)
501 return t
->type
- TOK_SMAC_PARAM
;
504 /* encode smacro parameter index */
505 static int smacro_set_param_idx(Token
*t
, unsigned int index
)
507 return t
->type
= TOK_SMAC_PARAM
+ index
;
512 #define stringify(x) #x
514 #define nasm_trace(msg, ...) printf("(%s:%d): " msg "\n", __func__, __LINE__, ##__VA_ARGS__)
515 #define nasm_dump_token(t) nasm_raw_dump_token(t, __FILE__, __LINE__, __func__);
516 #define nasm_dump_stream(t) nasm_raw_dump_stream(t, __FILE__, __LINE__, __func__);
518 /* FIXME: we really need some compound type here instead of inplace code */
519 static const char *nasm_get_tok_type_str(enum pp_token_type type
)
521 #define SWITCH_TOK_NAME(type) \
523 return stringify(type)
526 SWITCH_TOK_NAME(TOK_NONE
);
527 SWITCH_TOK_NAME(TOK_WHITESPACE
);
528 SWITCH_TOK_NAME(TOK_COMMENT
);
529 SWITCH_TOK_NAME(TOK_ID
);
530 SWITCH_TOK_NAME(TOK_PREPROC_ID
);
531 SWITCH_TOK_NAME(TOK_STRING
);
532 SWITCH_TOK_NAME(TOK_NUMBER
);
533 SWITCH_TOK_NAME(TOK_FLOAT
);
534 SWITCH_TOK_NAME(TOK_SMAC_END
);
535 SWITCH_TOK_NAME(TOK_OTHER
);
536 SWITCH_TOK_NAME(TOK_INTERNAL_STRING
);
537 SWITCH_TOK_NAME(TOK_PREPROC_Q
);
538 SWITCH_TOK_NAME(TOK_PREPROC_QQ
);
539 SWITCH_TOK_NAME(TOK_PASTE
);
540 SWITCH_TOK_NAME(TOK_INDIRECT
);
541 SWITCH_TOK_NAME(TOK_SMAC_PARAM
);
542 SWITCH_TOK_NAME(TOK_MAX
);
548 static void nasm_raw_dump_token(Token
*token
, const char *file
, int line
, const char *func
)
550 printf("---[%s (%s:%d): %p]---\n", func
, file
, line
, (void *)token
);
553 list_for_each(t
, token
) {
555 printf("'%s'(%s) ", t
->text
,
556 nasm_get_tok_type_str(t
->type
));
562 static void nasm_raw_dump_stream(Token
*token
, const char *file
, int line
, const char *func
)
564 printf("---[%s (%s:%d): %p]---\n", func
, file
, line
, (void *)token
);
567 list_for_each(t
, token
)
568 printf("%s", t
->text
? t
->text
: " ");
574 #define nasm_trace(msg, ...)
575 #define nasm_dump_token(t)
576 #define nasm_dump_stream(t)
580 * nasm_unquote with error if the string contains NUL characters.
581 * If the string contains NUL characters, issue an error and return
582 * the C len, i.e. truncate at the NUL.
584 static size_t nasm_unquote_cstr(char *qstr
, enum preproc_token directive
)
586 size_t len
= nasm_unquote(qstr
, NULL
);
587 size_t clen
= strlen(qstr
);
590 error(ERR_NONFATAL
, "NUL character in `%s' directive",
591 pp_directives
[directive
]);
597 * In-place reverse a list of tokens.
599 static Token
*reverse_tokens(Token
*t
)
603 list_reverse(t
, prev
, next
);
609 * Handle TASM specific directives, which do not contain a % in
610 * front of them. We do it here because I could not find any other
611 * place to do it for the moment, and it is a hack (ideally it would
612 * be nice to be able to use the NASM pre-processor to do it).
614 static char *check_tasm_directive(char *line
)
616 int32_t i
, j
, k
, m
, len
;
617 char *p
, *q
, *oldline
, oldchar
;
619 p
= nasm_skip_spaces(line
);
621 /* Binary search for the directive name */
623 j
= ARRAY_SIZE(tasm_directives
);
624 q
= nasm_skip_word(p
);
631 m
= nasm_stricmp(p
, tasm_directives
[k
]);
633 /* We have found a directive, so jam a % in front of it
634 * so that NASM will then recognise it as one if it's own.
639 line
= nasm_malloc(len
+ 2);
641 if (k
== TM_IFDIFI
) {
643 * NASM does not recognise IFDIFI, so we convert
644 * it to %if 0. This is not used in NASM
645 * compatible code, but does need to parse for the
646 * TASM macro package.
648 strcpy(line
+ 1, "if 0");
650 memcpy(line
+ 1, p
, len
+ 1);
665 * The pre-preprocessing stage... This function translates line
666 * number indications as they emerge from GNU cpp (`# lineno "file"
667 * flags') into NASM preprocessor line number indications (`%line
670 static char *prepreproc(char *line
)
673 char *fname
, *oldline
;
675 if (line
[0] == '#' && line
[1] == ' ') {
678 lineno
= atoi(fname
);
679 fname
+= strspn(fname
, "0123456789 ");
682 fnlen
= strcspn(fname
, "\"");
683 line
= nasm_malloc(20 + fnlen
);
684 snprintf(line
, 20 + fnlen
, "%%line %d %.*s", lineno
, fnlen
, fname
);
687 if (tasm_compatible_mode
)
688 return check_tasm_directive(line
);
693 * Free a linked list of tokens.
695 static void free_tlist(Token
* list
)
698 list
= delete_Token(list
);
702 * Free a linked list of lines.
704 static void free_llist(Line
* list
)
707 list_for_each_safe(l
, tmp
, list
) {
708 free_tlist(l
->first
);
716 static void free_expdef(ExpDef
* ed
)
719 free_tlist(ed
->dlist
);
720 nasm_free(ed
->defaults
);
721 free_llist(ed
->line
);
728 static void free_expinv(ExpInv
* ei
)
731 nasm_free(ei
->label_text
);
736 * Free all currently defined macros, and free the hash tables
738 static void free_smacro_table(struct hash_table
*smt
)
742 struct hash_tbl_node
*it
= NULL
;
744 while ((s
= hash_iterate(smt
, &it
, &key
)) != NULL
) {
745 nasm_free((void *)key
);
746 list_for_each_safe(s
, tmp
, s
) {
748 free_tlist(s
->expansion
);
755 static void free_expdef_table(struct hash_table
*edt
)
759 struct hash_tbl_node
*it
= NULL
;
762 while ((ed
= hash_iterate(edt
, &it
, &key
)) != NULL
) {
763 nasm_free((void *)key
);
764 list_for_each_safe(ed
,tmp
, ed
)
770 static void free_macros(void)
772 free_smacro_table(&smacros
);
773 free_expdef_table(&expdefs
);
777 * Initialize the hash tables
779 static void init_macros(void)
781 hash_init(&smacros
, HASH_LARGE
);
782 hash_init(&expdefs
, HASH_LARGE
);
786 * Pop the context stack.
788 static void ctx_pop(void)
793 free_smacro_table(&c
->localmac
);
799 * Search for a key in the hash index; adding it if necessary
800 * (in which case we initialize the data pointer to NULL.)
803 hash_findi_add(struct hash_table
*hash
, const char *str
)
805 struct hash_insert hi
;
809 r
= hash_findi(hash
, str
, &hi
);
813 strx
= nasm_strdup(str
); /* Use a more efficient allocator here? */
814 return hash_add(&hi
, strx
, NULL
);
818 * Like hash_findi, but returns the data element rather than a pointer
819 * to it. Used only when not adding a new element, hence no third
823 hash_findix(struct hash_table
*hash
, const char *str
)
827 p
= hash_findi(hash
, str
, NULL
);
828 return p
? *p
: NULL
;
832 * read line from standard macros set,
833 * if there no more left -- return NULL
835 static char *line_from_stdmac(void)
838 const unsigned char *p
= stdmacpos
;
847 len
+= pp_directives_len
[c
- 0x80] + 1;
852 line
= nasm_malloc(len
+ 1);
854 while ((c
= *stdmacpos
++)) {
856 memcpy(q
, pp_directives
[c
- 0x80], pp_directives_len
[c
- 0x80]);
857 q
+= pp_directives_len
[c
- 0x80];
867 /* This was the last of the standard macro chain... */
869 if (any_extrastdmac
) {
870 stdmacpos
= extrastdmac
;
871 any_extrastdmac
= false;
872 } else if (do_predef
) {
875 Token
*head
, **tail
, *t
;
878 * Nasty hack: here we push the contents of
879 * `predef' on to the top-level expansion stack,
880 * since this is the most convenient way to
881 * implement the pre-include and pre-define
884 list_for_each(pd
, predef
) {
887 list_for_each(t
, pd
->first
) {
888 *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
889 tail
= &(*tail
)->next
;
894 ei
= new_ExpInv(EXP_PREDEF
, NULL
);
897 ei
->prev
= istk
->expansion
;
898 istk
->expansion
= ei
;
907 #define BUF_DELTA 512
909 * Read a line from the top file in istk, handling multiple CR/LFs
910 * at the end of the line read, and handling spurious ^Zs. Will
911 * return lines from the standard macro set if this has not already
914 static char *read_line(void)
916 char *buffer
, *p
, *q
;
917 int bufsize
, continued_count
;
920 * standart macros set (predefined) goes first
922 p
= line_from_stdmac();
927 * regular read from a file
930 buffer
= nasm_malloc(BUF_DELTA
);
934 q
= fgets(p
, bufsize
- (p
- buffer
), istk
->fp
);
938 if (p
> buffer
&& p
[-1] == '\n') {
940 * Convert backslash-CRLF line continuation sequences into
941 * nothing at all (for DOS and Windows)
943 if (((p
- 2) > buffer
) && (p
[-3] == '\\') && (p
[-2] == '\r')) {
949 * Also convert backslash-LF line continuation sequences into
950 * nothing at all (for Unix)
952 else if (((p
- 1) > buffer
) && (p
[-2] == '\\')) {
960 if (p
- buffer
> bufsize
- 10) {
961 int32_t offset
= p
- buffer
;
962 bufsize
+= BUF_DELTA
;
963 buffer
= nasm_realloc(buffer
, bufsize
);
964 p
= buffer
+ offset
; /* prevent stale-pointer problems */
968 if (!q
&& p
== buffer
) {
973 src_set_linnum(src_get_linnum() + istk
->lineinc
+
974 (continued_count
* istk
->lineinc
));
977 * Play safe: remove CRs as well as LFs, if any of either are
978 * present at the end of the line.
980 while (--p
>= buffer
&& (*p
== '\n' || *p
== '\r'))
984 * Handle spurious ^Z, which may be inserted into source files
985 * by some file transfer utilities.
987 buffer
[strcspn(buffer
, "\032")] = '\0';
989 list
->line(LIST_READ
, buffer
);
995 * Tokenize a line of text. This is a very simple process since we
996 * don't need to parse the value out of e.g. numeric tokens: we
997 * simply split one string into many.
999 static Token
*tokenize(char *line
)
1002 enum pp_token_type type
;
1004 Token
*t
, **tail
= &list
;
1005 bool verbose
= true;
1007 nasm_trace("Tokenize for '%s'", line
);
1009 if ((defining
!= NULL
) && (defining
->ignoring
== true)) {
1017 if (*p
== '+' && !nasm_isdigit(p
[1])) {
1020 } else if (nasm_isdigit(*p
) ||
1021 ((*p
== '-' || *p
== '+') && nasm_isdigit(p
[1]))) {
1025 while (nasm_isdigit(*p
));
1026 type
= TOK_PREPROC_ID
;
1027 } else if (*p
== '{') {
1029 while (*p
&& *p
!= '}') {
1036 type
= TOK_PREPROC_ID
;
1037 } else if (*p
== '[') {
1039 line
+= 2; /* Skip the leading %[ */
1041 while (lvl
&& (c
= *p
++)) {
1053 p
= nasm_skip_string(p
- 1) + 1;
1063 error(ERR_NONFATAL
, "unterminated %[ construct");
1064 type
= TOK_INDIRECT
;
1065 } else if (*p
== '?') {
1066 type
= TOK_PREPROC_Q
; /* %? */
1069 type
= TOK_PREPROC_QQ
; /* %?? */
1072 } else if (*p
== '!') {
1073 type
= TOK_PREPROC_ID
;
1078 } while (isidchar(*p
));
1079 } else if (*p
== '\'' || *p
== '\"' || *p
== '`') {
1080 p
= nasm_skip_string(p
);
1084 error(ERR_NONFATAL
|ERR_PASS1
, "unterminated %! string");
1086 /* %! without string or identifier */
1087 type
= TOK_OTHER
; /* Legacy behavior... */
1089 } else if (isidchar(*p
) ||
1090 ((*p
== '!' || *p
== '%' || *p
== '$') &&
1095 while (isidchar(*p
));
1096 type
= TOK_PREPROC_ID
;
1102 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
1105 while (*p
&& isidchar(*p
))
1107 } else if (*p
== '\'' || *p
== '"' || *p
== '`') {
1112 p
= nasm_skip_string(p
);
1116 } else if(verbose
) {
1117 error(ERR_WARNING
|ERR_PASS1
, "unterminated string");
1118 /* Handling unterminated strings by UNV */
1121 } else if (p
[0] == '$' && p
[1] == '$') {
1122 type
= TOK_OTHER
; /* TOKEN_BASE */
1124 } else if (isnumstart(*p
)) {
1125 bool is_hex
= false;
1126 bool is_float
= false;
1142 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
1144 if (*p
== '+' || *p
== '-') {
1146 * e can only be followed by +/- if it is either a
1147 * prefixed hex number or a floating-point number
1152 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
1154 } else if (c
== 'P' || c
== 'p') {
1156 if (*p
== '+' || *p
== '-')
1158 } else if (isnumchar(c
) || c
== '_')
1159 ; /* just advance */
1160 else if (c
== '.') {
1162 * we need to deal with consequences of the legacy
1163 * parser, like "1.nolist" being two tokens
1164 * (TOK_NUMBER, TOK_ID) here; at least give it
1165 * a shot for now. In the future, we probably need
1166 * a flex-based scanner with proper pattern matching
1167 * to do it as well as it can be done. Nothing in
1168 * the world is going to help the person who wants
1169 * 0x123.p16 interpreted as two tokens, though.
1175 if (nasm_isdigit(*r
) || (is_hex
&& nasm_isxdigit(*r
)) ||
1176 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
1177 (*r
== 'p' || *r
== 'P')) {
1181 break; /* Terminate the token */
1185 p
--; /* Point to first character beyond number */
1187 if (p
== line
+1 && *line
== '$') {
1188 type
= TOK_OTHER
; /* TOKEN_HERE */
1190 if (has_e
&& !is_hex
) {
1191 /* 1e13 is floating-point, but 1e13h is not */
1195 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
1197 } else if (nasm_isspace(*p
)) {
1198 type
= TOK_WHITESPACE
;
1199 p
= nasm_skip_spaces(p
);
1201 * Whitespace just before end-of-line is discarded by
1202 * pretending it's a comment; whitespace just before a
1203 * comment gets lumped into the comment.
1205 if (!*p
|| *p
== ';') {
1210 } else if (*p
== ';') {
1216 * Anything else is an operator of some kind. We check
1217 * for all the double-character operators (>>, <<, //,
1218 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1219 * else is a single-character operator.
1222 if ((p
[0] == '>' && p
[1] == '>') ||
1223 (p
[0] == '<' && p
[1] == '<') ||
1224 (p
[0] == '/' && p
[1] == '/') ||
1225 (p
[0] == '<' && p
[1] == '=') ||
1226 (p
[0] == '>' && p
[1] == '=') ||
1227 (p
[0] == '=' && p
[1] == '=') ||
1228 (p
[0] == '!' && p
[1] == '=') ||
1229 (p
[0] == '<' && p
[1] == '>') ||
1230 (p
[0] == '&' && p
[1] == '&') ||
1231 (p
[0] == '|' && p
[1] == '|') ||
1232 (p
[0] == '^' && p
[1] == '^')) {
1238 /* Handling unterminated string by UNV */
1241 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1242 t->text[p-line] = *line;
1246 if (type
!= TOK_COMMENT
) {
1247 *tail
= t
= new_Token(NULL
, type
, line
, p
- line
);
1253 nasm_dump_token(list
);
1259 * this function allocates a new managed block of memory and
1260 * returns a pointer to the block. The managed blocks are
1261 * deleted only all at once by the delete_Blocks function.
1263 static void *new_Block(size_t size
)
1265 Blocks
*b
= &blocks
;
1267 /* first, get to the end of the linked list */
1271 /* now allocate the requested chunk */
1272 b
->chunk
= nasm_malloc(size
);
1274 /* now allocate a new block for the next request */
1275 b
->next
= nasm_zalloc(sizeof(Blocks
));
1281 * this function deletes all managed blocks of memory
1283 static void delete_Blocks(void)
1285 Blocks
*a
, *b
= &blocks
;
1288 * keep in mind that the first block, pointed to by blocks
1289 * is a static and not dynamically allocated, so we don't
1293 nasm_free(b
->chunk
);
1302 * this function creates a new Token and passes a pointer to it
1303 * back to the caller. It sets the type and text elements, and
1304 * also the a.mac and next elements to NULL.
1306 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
1307 const char *text
, int txtlen
)
1313 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1314 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1315 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1316 freeTokens
[i
].next
= NULL
;
1319 freeTokens
= t
->next
;
1323 if (type
== TOK_WHITESPACE
|| !text
) {
1327 txtlen
= strlen(text
);
1328 t
->text
= nasm_malloc(txtlen
+1);
1329 memcpy(t
->text
, text
, txtlen
);
1330 t
->text
[txtlen
] = '\0';
1335 static Token
*copy_Token(Token
* tline
)
1337 Token
*t
, *tt
, *first
= NULL
, *prev
= NULL
;
1339 for (tt
= tline
; tt
!= NULL
; tt
= tt
->next
) {
1341 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1342 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1343 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1344 freeTokens
[i
].next
= NULL
;
1347 freeTokens
= t
->next
;
1349 t
->text
= tt
->text
? nasm_strdup(tt
->text
) : NULL
;
1350 t
->a
.mac
= tt
->a
.mac
;
1351 t
->a
.len
= tt
->a
.len
;
1363 static Token
*delete_Token(Token
* t
)
1365 Token
*next
= t
->next
;
1367 t
->next
= freeTokens
;
1373 * Convert a line of tokens back into text.
1374 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1375 * will be transformed into ..@ctxnum.xxx
1377 static char *detoken(Token
* tlist
, bool expand_locals
)
1384 list_for_each(t
, tlist
) {
1385 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
1390 if (*v
== '\'' || *v
== '\"' || *v
== '`') {
1391 size_t len
= nasm_unquote(v
, NULL
);
1392 size_t clen
= strlen(v
);
1395 error(ERR_NONFATAL
| ERR_PASS1
,
1396 "NUL character in %! string");
1402 char *p
= getenv(v
);
1404 error(ERR_NONFATAL
| ERR_PASS1
,
1405 "nonexistent environment variable `%s'", v
);
1408 t
->text
= nasm_strdup(p
);
1413 /* Expand local macros here and not during preprocessing */
1414 if (expand_locals
&&
1415 t
->type
== TOK_PREPROC_ID
&& t
->text
&&
1416 t
->text
[0] == '%' && t
->text
[1] == '$') {
1419 Context
*ctx
= get_ctx(t
->text
, &q
);
1422 snprintf(buffer
, sizeof(buffer
), "..@%"PRIu32
".", ctx
->number
);
1423 p
= nasm_strcat(buffer
, q
);
1429 /* Expand %? and %?? directives */
1430 if ((istk
->expansion
!= NULL
) &&
1431 ((t
->type
== TOK_PREPROC_Q
) ||
1432 (t
->type
== TOK_PREPROC_QQ
))) {
1434 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
){
1435 if (ei
->type
== EXP_MMACRO
) {
1437 if (t
->type
== TOK_PREPROC_Q
) {
1438 t
->text
= nasm_strdup(ei
->name
);
1440 t
->text
= nasm_strdup(ei
->def
->name
);
1447 if (t
->type
== TOK_WHITESPACE
)
1450 len
+= strlen(t
->text
);
1453 p
= line
= nasm_malloc(len
+ 1);
1455 list_for_each(t
, tlist
) {
1456 if (t
->type
== TOK_WHITESPACE
) {
1458 } else if (t
->text
) {
1470 * Initialize a new Line
1472 static inline Line
*new_Line(void)
1474 return (Line
*)nasm_zalloc(sizeof(Line
));
1479 * Initialize a new Expansion Definition
1481 static ExpDef
*new_ExpDef(int exp_type
)
1483 ExpDef
*ed
= (ExpDef
*)nasm_zalloc(sizeof(ExpDef
));
1484 ed
->type
= exp_type
;
1485 ed
->casesense
= true;
1486 ed
->state
= COND_NEVER
;
1493 * Initialize a new Expansion Instance
1495 static ExpInv
*new_ExpInv(int exp_type
, ExpDef
*ed
)
1497 ExpInv
*ei
= (ExpInv
*)nasm_zalloc(sizeof(ExpInv
));
1498 ei
->type
= exp_type
;
1500 ei
->unique
= ++unique
;
1502 if ((istk
->mmac_depth
< 1) &&
1503 (istk
->expansion
== NULL
) &&
1505 (ed
->type
!= EXP_MMACRO
) &&
1506 (ed
->type
!= EXP_REP
) &&
1507 (ed
->type
!= EXP_WHILE
)) {
1508 ei
->linnum
= src_get_linnum();
1509 src_set_linnum(ei
->linnum
- ed
->linecount
- 1);
1513 if ((istk
->expansion
== NULL
) ||
1514 (ei
->type
== EXP_MMACRO
)) {
1517 ei
->relno
= istk
->expansion
->lineno
;
1519 ei
->relno
-= (ed
->linecount
+ 1);
1526 * A scanner, suitable for use by the expression evaluator, which
1527 * operates on a line of Tokens. Expects a pointer to a pointer to
1528 * the first token in the line to be passed in as its private_data
1531 * FIX: This really needs to be unified with stdscan.
1533 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1535 Token
**tlineptr
= private_data
;
1537 char ourcopy
[MAX_KEYWORD
+1], *p
, *r
, *s
;
1541 *tlineptr
= tline
? tline
->next
: NULL
;
1542 } while (tline
&& (tline
->type
== TOK_WHITESPACE
||
1543 tline
->type
== TOK_COMMENT
));
1546 return tokval
->t_type
= TOKEN_EOS
;
1548 tokval
->t_charptr
= tline
->text
;
1550 if (tline
->text
[0] == '$' && !tline
->text
[1])
1551 return tokval
->t_type
= TOKEN_HERE
;
1552 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[2])
1553 return tokval
->t_type
= TOKEN_BASE
;
1555 if (tline
->type
== TOK_ID
) {
1556 p
= tokval
->t_charptr
= tline
->text
;
1558 tokval
->t_charptr
++;
1559 return tokval
->t_type
= TOKEN_ID
;
1562 for (r
= p
, s
= ourcopy
; *r
; r
++) {
1563 if (r
>= p
+MAX_KEYWORD
)
1564 return tokval
->t_type
= TOKEN_ID
; /* Not a keyword */
1565 *s
++ = nasm_tolower(*r
);
1568 /* right, so we have an identifier sitting in temp storage. now,
1569 * is it actually a register or instruction name, or what? */
1570 return nasm_token_hash(ourcopy
, tokval
);
1573 if (tline
->type
== TOK_NUMBER
) {
1575 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
1576 tokval
->t_charptr
= tline
->text
;
1578 return tokval
->t_type
= TOKEN_ERRNUM
;
1580 return tokval
->t_type
= TOKEN_NUM
;
1583 if (tline
->type
== TOK_FLOAT
) {
1584 return tokval
->t_type
= TOKEN_FLOAT
;
1587 if (tline
->type
== TOK_STRING
) {
1590 bq
= tline
->text
[0];
1591 tokval
->t_charptr
= tline
->text
;
1592 tokval
->t_inttwo
= nasm_unquote(tline
->text
, &ep
);
1594 if (ep
[0] != bq
|| ep
[1] != '\0')
1595 return tokval
->t_type
= TOKEN_ERRSTR
;
1597 return tokval
->t_type
= TOKEN_STR
;
1600 if (tline
->type
== TOK_OTHER
) {
1601 if (!strcmp(tline
->text
, "<<"))
1602 return tokval
->t_type
= TOKEN_SHL
;
1603 if (!strcmp(tline
->text
, ">>"))
1604 return tokval
->t_type
= TOKEN_SHR
;
1605 if (!strcmp(tline
->text
, "//"))
1606 return tokval
->t_type
= TOKEN_SDIV
;
1607 if (!strcmp(tline
->text
, "%%"))
1608 return tokval
->t_type
= TOKEN_SMOD
;
1609 if (!strcmp(tline
->text
, "=="))
1610 return tokval
->t_type
= TOKEN_EQ
;
1611 if (!strcmp(tline
->text
, "<>"))
1612 return tokval
->t_type
= TOKEN_NE
;
1613 if (!strcmp(tline
->text
, "!="))
1614 return tokval
->t_type
= TOKEN_NE
;
1615 if (!strcmp(tline
->text
, "<="))
1616 return tokval
->t_type
= TOKEN_LE
;
1617 if (!strcmp(tline
->text
, ">="))
1618 return tokval
->t_type
= TOKEN_GE
;
1619 if (!strcmp(tline
->text
, "&&"))
1620 return tokval
->t_type
= TOKEN_DBL_AND
;
1621 if (!strcmp(tline
->text
, "^^"))
1622 return tokval
->t_type
= TOKEN_DBL_XOR
;
1623 if (!strcmp(tline
->text
, "||"))
1624 return tokval
->t_type
= TOKEN_DBL_OR
;
1628 * We have no other options: just return the first character of
1631 return tokval
->t_type
= tline
->text
[0];
1635 * Compare a string to the name of an existing macro; this is a
1636 * simple wrapper which calls either strcmp or nasm_stricmp
1637 * depending on the value of the `casesense' parameter.
1639 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
1641 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
1645 * Compare a string to the name of an existing macro; this is a
1646 * simple wrapper which calls either strcmp or nasm_stricmp
1647 * depending on the value of the `casesense' parameter.
1649 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
1651 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
1655 * Return the Context structure associated with a %$ token. Return
1656 * NULL, having _already_ reported an error condition, if the
1657 * context stack isn't deep enough for the supplied number of $
1660 * If "namep" is non-NULL, set it to the pointer to the macro name
1661 * tail, i.e. the part beyond %$...
1663 static Context
*get_ctx(const char *name
, const char **namep
)
1671 if (!name
|| name
[0] != '%' || name
[1] != '$')
1675 error(ERR_NONFATAL
, "`%s': context stack is empty", name
);
1682 while (ctx
&& *name
== '$') {
1689 error(ERR_NONFATAL
, "`%s': context stack is only"
1690 " %d level%s deep", name
, i
, (i
== 1 ? "" : "s"));
1701 * Check to see if a file is already in a string list
1703 static bool in_list(const StrList
*list
, const char *str
)
1706 if (!strcmp(list
->str
, str
))
1714 * Open an include file. This routine must always return a valid
1715 * file pointer if it returns - it's responsible for throwing an
1716 * ERR_FATAL and bombing out completely if not. It should also try
1717 * the include path one by one until it finds the file or reaches
1718 * the end of the path.
1720 static FILE *inc_fopen(const char *file
, StrList
**dhead
, StrList
***dtail
,
1725 IncPath
*ip
= ipath
;
1726 int len
= strlen(file
);
1727 size_t prefix_len
= 0;
1731 sl
= nasm_malloc(prefix_len
+len
+1+sizeof sl
->next
);
1733 memcpy(sl
->str
, prefix
, prefix_len
);
1734 memcpy(sl
->str
+prefix_len
, file
, len
+1);
1735 fp
= fopen(sl
->str
, "r");
1736 if (fp
&& dhead
&& !in_list(*dhead
, sl
->str
)) {
1753 prefix_len
= strlen(prefix
);
1755 /* -MG given and file not found */
1756 if (dhead
&& !in_list(*dhead
, file
)) {
1757 sl
= nasm_malloc(len
+1+sizeof sl
->next
);
1759 strcpy(sl
->str
, file
);
1767 error(ERR_FATAL
, "unable to open include file `%s'", file
);
1772 * Determine if we should warn on defining a single-line macro of
1773 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1774 * return true if _any_ single-line macro of that name is defined.
1775 * Otherwise, will return true if a single-line macro with either
1776 * `nparam' or no parameters is defined.
1778 * If a macro with precisely the right number of parameters is
1779 * defined, or nparam is -1, the address of the definition structure
1780 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1781 * is NULL, no action will be taken regarding its contents, and no
1784 * Note that this is also called with nparam zero to resolve
1787 * If you already know which context macro belongs to, you can pass
1788 * the context pointer as first parameter; if you won't but name begins
1789 * with %$ the context will be automatically computed. If all_contexts
1790 * is true, macro will be searched in outer contexts as well.
1793 smacro_defined(Context
* ctx
, const char *name
, int nparam
, SMacro
** defn
,
1796 struct hash_table
*smtbl
;
1800 smtbl
= &ctx
->localmac
;
1801 } else if (name
[0] == '%' && name
[1] == '$') {
1803 ctx
= get_ctx(name
, &name
);
1805 return false; /* got to return _something_ */
1806 smtbl
= &ctx
->localmac
;
1810 m
= (SMacro
*) hash_findix(smtbl
, name
);
1813 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
1814 (nparam
<= 0 || m
->nparam
== 0 || nparam
== (int) m
->nparam
)) {
1816 if (nparam
== (int) m
->nparam
|| nparam
== -1)
1830 * Count and mark off the parameters in a multi-line macro call.
1831 * This is called both from within the multi-line macro expansion
1832 * code, and also to mark off the default parameters when provided
1833 * in a %macro definition line.
1835 static void count_mmac_params(Token
* t
, int *nparam
, Token
*** params
)
1837 int paramsize
, brace
;
1839 *nparam
= paramsize
= 0;
1842 /* +1: we need space for the final NULL */
1843 if (*nparam
+1 >= paramsize
) {
1844 paramsize
+= PARAM_DELTA
;
1845 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
1849 if (tok_is_(t
, "{"))
1851 (*params
)[(*nparam
)++] = t
;
1852 while (tok_isnt_(t
, brace
? "}" : ","))
1854 if (t
) { /* got a comma/brace */
1858 * Now we've found the closing brace, look further
1862 if (tok_isnt_(t
, ",")) {
1864 "braces do not enclose all of macro parameter");
1865 while (tok_isnt_(t
, ","))
1869 t
= t
->next
; /* eat the comma */
1876 * Determine whether one of the various `if' conditions is true or
1879 * We must free the tline we get passed.
1881 static bool if_condition(Token
* tline
, enum preproc_token ct
)
1883 enum pp_conditional i
= PP_COND(ct
);
1885 Token
*t
, *tt
, **tptr
, *origline
;
1886 struct tokenval tokval
;
1888 enum pp_token_type needtype
;
1895 j
= false; /* have we matched yet? */
1900 if (tline
->type
!= TOK_ID
) {
1902 "`%s' expects context identifiers", pp_directives
[ct
]);
1903 free_tlist(origline
);
1906 if (cstk
&& cstk
->name
&& !nasm_stricmp(tline
->text
, cstk
->name
))
1908 tline
= tline
->next
;
1913 j
= false; /* have we matched yet? */
1916 if (!tline
|| (tline
->type
!= TOK_ID
&&
1917 (tline
->type
!= TOK_PREPROC_ID
||
1918 tline
->text
[1] != '$'))) {
1920 "`%s' expects macro identifiers", pp_directives
[ct
]);
1923 if (smacro_defined(NULL
, tline
->text
, 0, NULL
, true))
1925 tline
= tline
->next
;
1930 tline
= expand_smacro(tline
);
1931 j
= false; /* have we matched yet? */
1934 if (!tline
|| (tline
->type
!= TOK_ID
&&
1935 tline
->type
!= TOK_STRING
&&
1936 (tline
->type
!= TOK_PREPROC_ID
||
1937 tline
->text
[1] != '!'))) {
1939 "`%s' expects environment variable names",
1944 if (tline
->type
== TOK_PREPROC_ID
)
1945 p
+= 2; /* Skip leading %! */
1946 if (*p
== '\'' || *p
== '\"' || *p
== '`')
1947 nasm_unquote_cstr(p
, ct
);
1950 tline
= tline
->next
;
1956 tline
= expand_smacro(tline
);
1958 while (tok_isnt_(tt
, ","))
1962 "`%s' expects two comma-separated arguments",
1967 j
= true; /* assume equality unless proved not */
1968 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1969 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1970 error(ERR_NONFATAL
, "`%s': more than one comma on line",
1974 if (t
->type
== TOK_WHITESPACE
) {
1978 if (tt
->type
== TOK_WHITESPACE
) {
1982 if (tt
->type
!= t
->type
) {
1983 j
= false; /* found mismatching tokens */
1986 /* When comparing strings, need to unquote them first */
1987 if (t
->type
== TOK_STRING
) {
1988 size_t l1
= nasm_unquote(t
->text
, NULL
);
1989 size_t l2
= nasm_unquote(tt
->text
, NULL
);
1995 if (mmemcmp(t
->text
, tt
->text
, l1
, i
== PPC_IFIDN
)) {
1999 } else if (mstrcmp(tt
->text
, t
->text
, i
== PPC_IFIDN
) != 0) {
2000 j
= false; /* found mismatching tokens */
2007 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
2008 j
= false; /* trailing gunk on one end or other */
2014 ExpDef searching
, *ed
;
2017 tline
= expand_id(tline
);
2018 if (!tok_type_(tline
, TOK_ID
)) {
2020 "`%s' expects a macro name", pp_directives
[ct
]);
2023 memset(&searching
, 0, sizeof(searching
));
2024 searching
.name
= nasm_strdup(tline
->text
);
2025 searching
.casesense
= true;
2026 searching
.nparam_max
= INT_MAX
;
2027 tline
= expand_smacro(tline
->next
);
2030 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2032 "`%s' expects a parameter count or nothing",
2035 searching
.nparam_min
= searching
.nparam_max
=
2036 readnum(tline
->text
, &j
);
2039 "unable to parse parameter count `%s'",
2042 if (tline
&& tok_is_(tline
->next
, "-")) {
2043 tline
= tline
->next
->next
;
2044 if (tok_is_(tline
, "*"))
2045 searching
.nparam_max
= INT_MAX
;
2046 else if (!tok_type_(tline
, TOK_NUMBER
))
2048 "`%s' expects a parameter count after `-'",
2051 searching
.nparam_max
= readnum(tline
->text
, &j
);
2054 "unable to parse parameter count `%s'",
2056 if (searching
.nparam_min
> searching
.nparam_max
)
2058 "minimum parameter count exceeds maximum");
2061 if (tline
&& tok_is_(tline
->next
, "+")) {
2062 tline
= tline
->next
;
2063 searching
.plus
= true;
2065 ed
= (ExpDef
*) hash_findix(&expdefs
, searching
.name
);
2066 while (ed
!= NULL
) {
2067 if (!strcmp(ed
->name
, searching
.name
) &&
2068 (ed
->nparam_min
<= searching
.nparam_max
|| searching
.plus
) &&
2069 (searching
.nparam_min
<= ed
->nparam_max
|| ed
->plus
)) {
2075 if (tline
&& tline
->next
)
2076 error(ERR_WARNING
|ERR_PASS1
,
2077 "trailing garbage after %%ifmacro ignored");
2078 nasm_free(searching
.name
);
2087 needtype
= TOK_NUMBER
;
2090 needtype
= TOK_STRING
;
2094 t
= tline
= expand_smacro(tline
);
2096 while (tok_type_(t
, TOK_WHITESPACE
) ||
2097 (needtype
== TOK_NUMBER
&&
2098 tok_type_(t
, TOK_OTHER
) &&
2099 (t
->text
[0] == '-' || t
->text
[0] == '+') &&
2103 j
= tok_type_(t
, needtype
);
2107 t
= tline
= expand_smacro(tline
);
2108 while (tok_type_(t
, TOK_WHITESPACE
))
2113 t
= t
->next
; /* Skip the actual token */
2114 while (tok_type_(t
, TOK_WHITESPACE
))
2116 j
= !t
; /* Should be nothing left */
2121 t
= tline
= expand_smacro(tline
);
2122 while (tok_type_(t
, TOK_WHITESPACE
))
2125 j
= !t
; /* Should be empty */
2129 t
= tline
= expand_smacro(tline
);
2131 tokval
.t_type
= TOKEN_INVALID
;
2132 evalresult
= evaluate(ppscan
, tptr
, &tokval
,
2133 NULL
, pass
| CRITICAL
, error
, NULL
);
2137 error(ERR_WARNING
|ERR_PASS1
,
2138 "trailing garbage after expression ignored");
2139 if (!is_simple(evalresult
)) {
2141 "non-constant value given to `%s'", pp_directives
[ct
]);
2144 j
= reloc_value(evalresult
) != 0;
2149 "preprocessor directive `%s' not yet implemented",
2154 free_tlist(origline
);
2155 return j
^ PP_NEGATIVE(ct
);
2158 free_tlist(origline
);
2163 * Common code for defining an smacro
2165 static bool define_smacro(Context
*ctx
, const char *mname
, bool casesense
,
2166 int nparam
, Token
*expansion
)
2168 SMacro
*smac
, **smhead
;
2169 struct hash_table
*smtbl
;
2171 if (smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
)) {
2173 error(ERR_WARNING
|ERR_PASS1
,
2174 "single-line macro `%s' defined both with and"
2175 " without parameters", mname
);
2177 * Some instances of the old code considered this a failure,
2178 * some others didn't. What is the right thing to do here?
2180 free_tlist(expansion
);
2181 return false; /* Failure */
2184 * We're redefining, so we have to take over an
2185 * existing SMacro structure. This means freeing
2186 * what was already in it.
2188 nasm_free(smac
->name
);
2189 free_tlist(smac
->expansion
);
2192 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2193 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
2194 smac
= nasm_zalloc(sizeof(SMacro
));
2195 smac
->next
= *smhead
;
2198 smac
->name
= nasm_strdup(mname
);
2199 smac
->casesense
= casesense
;
2200 smac
->nparam
= nparam
;
2201 smac
->expansion
= expansion
;
2202 smac
->in_progress
= false;
2203 return true; /* Success */
2207 * Undefine an smacro
2209 static void undef_smacro(Context
*ctx
, const char *mname
)
2211 SMacro
**smhead
, *s
, **sp
;
2212 struct hash_table
*smtbl
;
2214 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2215 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
2219 * We now have a macro name... go hunt for it.
2222 while ((s
= *sp
) != NULL
) {
2223 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
2226 free_tlist(s
->expansion
);
2236 * Parse a mmacro specification.
2238 static bool parse_mmacro_spec(Token
*tline
, ExpDef
*def
, const char *directive
)
2242 tline
= tline
->next
;
2244 tline
= expand_id(tline
);
2245 if (!tok_type_(tline
, TOK_ID
)) {
2246 error(ERR_NONFATAL
, "`%s' expects a macro name", directive
);
2250 def
->name
= nasm_strdup(tline
->text
);
2252 def
->nolist
= false;
2253 // def->in_progress = 0;
2254 // def->rep_nest = NULL;
2255 def
->nparam_min
= 0;
2256 def
->nparam_max
= 0;
2258 tline
= expand_smacro(tline
->next
);
2260 if (!tok_type_(tline
, TOK_NUMBER
)) {
2261 error(ERR_NONFATAL
, "`%s' expects a parameter count", directive
);
2263 def
->nparam_min
= def
->nparam_max
=
2264 readnum(tline
->text
, &err
);
2267 "unable to parse parameter count `%s'", tline
->text
);
2269 if (tline
&& tok_is_(tline
->next
, "-")) {
2270 tline
= tline
->next
->next
;
2271 if (tok_is_(tline
, "*")) {
2272 def
->nparam_max
= INT_MAX
;
2273 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2275 "`%s' expects a parameter count after `-'", directive
);
2277 def
->nparam_max
= readnum(tline
->text
, &err
);
2279 error(ERR_NONFATAL
, "unable to parse parameter count `%s'",
2282 if (def
->nparam_min
> def
->nparam_max
) {
2283 error(ERR_NONFATAL
, "minimum parameter count exceeds maximum");
2287 if (tline
&& tok_is_(tline
->next
, "+")) {
2288 tline
= tline
->next
;
2291 if (tline
&& tok_type_(tline
->next
, TOK_ID
) &&
2292 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
2293 tline
= tline
->next
;
2298 * Handle default parameters.
2300 if (tline
&& tline
->next
) {
2301 def
->dlist
= tline
->next
;
2303 count_mmac_params(def
->dlist
, &def
->ndefs
, &def
->defaults
);
2306 def
->defaults
= NULL
;
2310 if (def
->defaults
&& def
->ndefs
> def
->nparam_max
- def
->nparam_min
&&
2312 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MDP
,
2313 "too many default macro parameters");
2320 * Decode a size directive
2322 static int parse_size(const char *str
) {
2323 static const char *size_names
[] =
2324 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2325 static const int sizes
[] =
2326 { 0, 1, 4, 16, 8, 10, 2, 32 };
2328 return sizes
[bsii(str
, size_names
, ARRAY_SIZE(size_names
))+1];
2332 * find and process preprocessor directive in passed line
2333 * Find out if a line contains a preprocessor directive, and deal
2336 * If a directive _is_ found, it is the responsibility of this routine
2337 * (and not the caller) to free_tlist() the line.
2339 * @param tline a pointer to the current tokeninzed line linked list
2340 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2343 static int do_directive(Token
* tline
)
2345 enum preproc_token i
;
2358 Token
*t
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
2359 struct tokenval tokval
;
2361 ExpDef
*ed
, *eed
, **edhead
;
2370 if (!tline
|| !tok_type_(tline
, TOK_PREPROC_ID
) ||
2371 (tline
->text
[1] == '%' || tline
->text
[1] == '$'
2372 || tline
->text
[1] == '!'))
2373 return NO_DIRECTIVE_FOUND
;
2375 i
= pp_token_hash(tline
->text
);
2379 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2380 error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2382 return NO_DIRECTIVE_FOUND
; /* didn't get it */
2385 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2386 /* Directive to tell NASM what the default stack size is. The
2387 * default is for a 16-bit stack, and this can be overriden with
2390 tline
= tline
->next
;
2391 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2392 tline
= tline
->next
;
2393 if (!tline
|| tline
->type
!= TOK_ID
) {
2394 error(ERR_NONFATAL
, "`%%stacksize' missing size parameter");
2395 free_tlist(origline
);
2396 return DIRECTIVE_FOUND
;
2398 if (nasm_stricmp(tline
->text
, "flat") == 0) {
2399 /* All subsequent ARG directives are for a 32-bit stack */
2401 StackPointer
= "ebp";
2404 } else if (nasm_stricmp(tline
->text
, "flat64") == 0) {
2405 /* All subsequent ARG directives are for a 64-bit stack */
2407 StackPointer
= "rbp";
2410 } else if (nasm_stricmp(tline
->text
, "large") == 0) {
2411 /* All subsequent ARG directives are for a 16-bit stack,
2412 * far function call.
2415 StackPointer
= "bp";
2418 } else if (nasm_stricmp(tline
->text
, "small") == 0) {
2419 /* All subsequent ARG directives are for a 16-bit stack,
2420 * far function call. We don't support near functions.
2423 StackPointer
= "bp";
2427 error(ERR_NONFATAL
, "`%%stacksize' invalid size type");
2428 free_tlist(origline
);
2429 return DIRECTIVE_FOUND
;
2431 free_tlist(origline
);
2432 return DIRECTIVE_FOUND
;
2435 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2436 /* TASM like ARG directive to define arguments to functions, in
2437 * the following form:
2439 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2443 char *arg
, directive
[256];
2444 int size
= StackSize
;
2446 /* Find the argument name */
2447 tline
= tline
->next
;
2448 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2449 tline
= tline
->next
;
2450 if (!tline
|| tline
->type
!= TOK_ID
) {
2451 error(ERR_NONFATAL
, "`%%arg' missing argument parameter");
2452 free_tlist(origline
);
2453 return DIRECTIVE_FOUND
;
2457 /* Find the argument size type */
2458 tline
= tline
->next
;
2459 if (!tline
|| tline
->type
!= TOK_OTHER
2460 || tline
->text
[0] != ':') {
2462 "Syntax error processing `%%arg' directive");
2463 free_tlist(origline
);
2464 return DIRECTIVE_FOUND
;
2466 tline
= tline
->next
;
2467 if (!tline
|| tline
->type
!= TOK_ID
) {
2468 error(ERR_NONFATAL
, "`%%arg' missing size type parameter");
2469 free_tlist(origline
);
2470 return DIRECTIVE_FOUND
;
2473 /* Allow macro expansion of type parameter */
2474 tt
= tokenize(tline
->text
);
2475 tt
= expand_smacro(tt
);
2476 size
= parse_size(tt
->text
);
2479 "Invalid size type for `%%arg' missing directive");
2481 free_tlist(origline
);
2482 return DIRECTIVE_FOUND
;
2486 /* Round up to even stack slots */
2487 size
= ALIGN(size
, StackSize
);
2489 /* Now define the macro for the argument */
2490 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
2491 arg
, StackPointer
, offset
);
2492 do_directive(tokenize(directive
));
2495 /* Move to the next argument in the list */
2496 tline
= tline
->next
;
2497 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2498 tline
= tline
->next
;
2499 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2501 free_tlist(origline
);
2502 return DIRECTIVE_FOUND
;
2505 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2506 /* TASM like LOCAL directive to define local variables for a
2507 * function, in the following form:
2509 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2511 * The '= LocalSize' at the end is ignored by NASM, but is
2512 * required by TASM to define the local parameter size (and used
2513 * by the TASM macro package).
2515 offset
= LocalOffset
;
2517 char *local
, directive
[256];
2518 int size
= StackSize
;
2520 /* Find the argument name */
2521 tline
= tline
->next
;
2522 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2523 tline
= tline
->next
;
2524 if (!tline
|| tline
->type
!= TOK_ID
) {
2526 "`%%local' missing argument parameter");
2527 free_tlist(origline
);
2528 return DIRECTIVE_FOUND
;
2530 local
= tline
->text
;
2532 /* Find the argument size type */
2533 tline
= tline
->next
;
2534 if (!tline
|| tline
->type
!= TOK_OTHER
2535 || tline
->text
[0] != ':') {
2537 "Syntax error processing `%%local' directive");
2538 free_tlist(origline
);
2539 return DIRECTIVE_FOUND
;
2541 tline
= tline
->next
;
2542 if (!tline
|| tline
->type
!= TOK_ID
) {
2544 "`%%local' missing size type parameter");
2545 free_tlist(origline
);
2546 return DIRECTIVE_FOUND
;
2549 /* Allow macro expansion of type parameter */
2550 tt
= tokenize(tline
->text
);
2551 tt
= expand_smacro(tt
);
2552 size
= parse_size(tt
->text
);
2555 "Invalid size type for `%%local' missing directive");
2557 free_tlist(origline
);
2558 return DIRECTIVE_FOUND
;
2562 /* Round up to even stack slots */
2563 size
= ALIGN(size
, StackSize
);
2565 offset
+= size
; /* Negative offset, increment before */
2567 /* Now define the macro for the argument */
2568 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
2569 local
, StackPointer
, offset
);
2570 do_directive(tokenize(directive
));
2572 /* Now define the assign to setup the enter_c macro correctly */
2573 snprintf(directive
, sizeof(directive
),
2574 "%%assign %%$localsize %%$localsize+%d", size
);
2575 do_directive(tokenize(directive
));
2577 /* Move to the next argument in the list */
2578 tline
= tline
->next
;
2579 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2580 tline
= tline
->next
;
2581 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2582 LocalOffset
= offset
;
2583 free_tlist(origline
);
2584 return DIRECTIVE_FOUND
;
2587 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2589 error(ERR_WARNING
|ERR_PASS1
,
2590 "trailing garbage after `%%clear' ignored");
2593 free_tlist(origline
);
2594 return DIRECTIVE_FOUND
;
2597 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2598 t
= tline
->next
= expand_smacro(tline
->next
);
2600 if (!t
|| (t
->type
!= TOK_STRING
&&
2601 t
->type
!= TOK_INTERNAL_STRING
)) {
2602 error(ERR_NONFATAL
, "`%%depend' expects a file name");
2603 free_tlist(origline
);
2604 return DIRECTIVE_FOUND
; /* but we did _something_ */
2607 error(ERR_WARNING
|ERR_PASS1
,
2608 "trailing garbage after `%%depend' ignored");
2610 if (t
->type
!= TOK_INTERNAL_STRING
)
2611 nasm_unquote_cstr(p
, i
);
2612 if (dephead
&& !in_list(*dephead
, p
)) {
2613 StrList
*sl
= nasm_malloc(strlen(p
)+1+sizeof sl
->next
);
2617 deptail
= &sl
->next
;
2619 free_tlist(origline
);
2620 return DIRECTIVE_FOUND
;
2623 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2624 t
= tline
->next
= expand_smacro(tline
->next
);
2627 if (!t
|| (t
->type
!= TOK_STRING
&&
2628 t
->type
!= TOK_INTERNAL_STRING
)) {
2629 error(ERR_NONFATAL
, "`%%include' expects a file name");
2630 free_tlist(origline
);
2631 return DIRECTIVE_FOUND
; /* but we did _something_ */
2634 error(ERR_WARNING
|ERR_PASS1
,
2635 "trailing garbage after `%%include' ignored");
2637 if (t
->type
!= TOK_INTERNAL_STRING
)
2638 nasm_unquote_cstr(p
, i
);
2639 inc
= nasm_zalloc(sizeof(Include
));
2641 inc
->fp
= inc_fopen(p
, dephead
, &deptail
, pass
== 0);
2643 /* -MG given but file not found */
2646 inc
->fname
= src_set_fname(nasm_strdup(p
));
2647 inc
->lineno
= src_set_linnum(0);
2649 inc
->expansion
= NULL
;
2651 list
->uplevel(LIST_INCLUDE
);
2653 free_tlist(origline
);
2654 return DIRECTIVE_FOUND
;
2657 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2659 static macros_t
*use_pkg
;
2660 const char *pkg_macro
= NULL
;
2662 tline
= tline
->next
;
2664 tline
= expand_id(tline
);
2666 if (!tline
|| (tline
->type
!= TOK_STRING
&&
2667 tline
->type
!= TOK_INTERNAL_STRING
&&
2668 tline
->type
!= TOK_ID
)) {
2669 error(ERR_NONFATAL
, "`%%use' expects a package name");
2670 free_tlist(origline
);
2671 return DIRECTIVE_FOUND
; /* but we did _something_ */
2674 error(ERR_WARNING
|ERR_PASS1
,
2675 "trailing garbage after `%%use' ignored");
2676 if (tline
->type
== TOK_STRING
)
2677 nasm_unquote_cstr(tline
->text
, i
);
2678 use_pkg
= nasm_stdmac_find_package(tline
->text
);
2680 error(ERR_NONFATAL
, "unknown `%%use' package: %s", tline
->text
);
2682 pkg_macro
= (char *)use_pkg
+ 1; /* The first string will be <%define>__USE_*__ */
2683 if (use_pkg
&& ! smacro_defined(NULL
, pkg_macro
, 0, NULL
, true)) {
2684 /* Not already included, go ahead and include it */
2685 stdmacpos
= use_pkg
;
2687 free_tlist(origline
);
2688 return DIRECTIVE_FOUND
;
2693 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2694 tline
= tline
->next
;
2696 tline
= expand_id(tline
);
2698 if (!tok_type_(tline
, TOK_ID
)) {
2699 error(ERR_NONFATAL
, "`%s' expects a context identifier",
2701 free_tlist(origline
);
2702 return DIRECTIVE_FOUND
; /* but we did _something_ */
2705 error(ERR_WARNING
|ERR_PASS1
,
2706 "trailing garbage after `%s' ignored",
2708 p
= nasm_strdup(tline
->text
);
2710 p
= NULL
; /* Anonymous */
2714 ctx
= nasm_zalloc(sizeof(Context
));
2716 hash_init(&ctx
->localmac
, HASH_SMALL
);
2718 ctx
->number
= unique
++;
2723 error(ERR_NONFATAL
, "`%s': context stack is empty",
2725 } else if (i
== PP_POP
) {
2726 if (p
&& (!cstk
->name
|| nasm_stricmp(p
, cstk
->name
)))
2727 error(ERR_NONFATAL
, "`%%pop' in wrong context: %s, "
2729 cstk
->name
? cstk
->name
: "anonymous", p
);
2734 nasm_free(cstk
->name
);
2740 free_tlist(origline
);
2741 return DIRECTIVE_FOUND
;
2743 severity
= ERR_FATAL
;
2746 severity
= ERR_NONFATAL
;
2749 severity
= ERR_WARNING
|ERR_WARN_USER
;
2753 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2755 /* Only error out if this is the final pass */
2756 if (pass
!= 2 && i
!= PP_FATAL
)
2757 return DIRECTIVE_FOUND
;
2759 tline
->next
= expand_smacro(tline
->next
);
2760 tline
= tline
->next
;
2762 t
= tline
? tline
->next
: NULL
;
2764 if (tok_type_(tline
, TOK_STRING
) && !t
) {
2765 /* The line contains only a quoted string */
2767 nasm_unquote(p
, NULL
); /* Ignore NUL character truncation */
2768 error(severity
, "%s", p
);
2770 /* Not a quoted string, or more than a quoted string */
2771 p
= detoken(tline
, false);
2772 error(severity
, "%s", p
);
2775 free_tlist(origline
);
2776 return DIRECTIVE_FOUND
;
2780 if (defining
!= NULL
) {
2781 if (defining
->type
== EXP_IF
) {
2782 defining
->def_depth
++;
2784 return NO_DIRECTIVE_FOUND
;
2786 if ((istk
->expansion
!= NULL
) &&
2787 (istk
->expansion
->emitting
== false)) {
2790 j
= if_condition(tline
->next
, i
);
2791 tline
->next
= NULL
; /* it got freed */
2792 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
2794 ed
= new_ExpDef(EXP_IF
);
2796 ed
->ignoring
= ((ed
->state
== COND_IF_TRUE
) ? false : true);
2797 ed
->prev
= defining
;
2799 free_tlist(origline
);
2800 return DIRECTIVE_FOUND
;
2803 if (defining
!= NULL
) {
2804 if ((defining
->type
!= EXP_IF
) || (defining
->def_depth
> 0)) {
2805 return NO_DIRECTIVE_FOUND
;
2808 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2809 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2811 switch (defining
->state
) {
2813 defining
->state
= COND_DONE
;
2814 defining
->ignoring
= true;
2819 defining
->ignoring
= true;
2822 case COND_ELSE_TRUE
:
2823 case COND_ELSE_FALSE
:
2824 error_precond(ERR_WARNING
|ERR_PASS1
,
2825 "`%%elif' after `%%else' ignored");
2826 defining
->state
= COND_NEVER
;
2827 defining
->ignoring
= true;
2832 * IMPORTANT: In the case of %if, we will already have
2833 * called expand_mmac_params(); however, if we're
2834 * processing an %elif we must have been in a
2835 * non-emitting mode, which would have inhibited
2836 * the normal invocation of expand_mmac_params().
2837 * Therefore, we have to do it explicitly here.
2839 j
= if_condition(expand_mmac_params(tline
->next
), i
);
2840 tline
->next
= NULL
; /* it got freed */
2842 j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2843 defining
->ignoring
= ((defining
->state
== COND_IF_TRUE
) ? false : true);
2846 free_tlist(origline
);
2847 return DIRECTIVE_FOUND
;
2850 if (defining
!= NULL
) {
2851 if ((defining
->type
!= EXP_IF
) || (defining
->def_depth
> 0)) {
2852 return NO_DIRECTIVE_FOUND
;
2856 error_precond(ERR_WARNING
|ERR_PASS1
,
2857 "trailing garbage after `%%else' ignored");
2858 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2859 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2861 switch (defining
->state
) {
2864 defining
->state
= COND_ELSE_FALSE
;
2865 defining
->ignoring
= true;
2869 defining
->ignoring
= true;
2873 defining
->state
= COND_ELSE_TRUE
;
2874 defining
->ignoring
= false;
2877 case COND_ELSE_TRUE
:
2878 case COND_ELSE_FALSE
:
2879 error_precond(ERR_WARNING
|ERR_PASS1
,
2880 "`%%else' after `%%else' ignored.");
2881 defining
->state
= COND_NEVER
;
2882 defining
->ignoring
= true;
2885 free_tlist(origline
);
2886 return DIRECTIVE_FOUND
;
2889 if (defining
!= NULL
) {
2890 if (defining
->type
== EXP_IF
) {
2891 if (defining
->def_depth
> 0) {
2892 defining
->def_depth
--;
2893 return NO_DIRECTIVE_FOUND
;
2896 return NO_DIRECTIVE_FOUND
;
2900 error_precond(ERR_WARNING
|ERR_PASS1
,
2901 "trailing garbage after `%%endif' ignored");
2902 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2903 error(ERR_NONFATAL
, "`%%endif': no matching `%%if'");
2904 return DIRECTIVE_FOUND
;
2907 defining
= ed
->prev
;
2908 ed
->prev
= expansions
;
2910 ei
= new_ExpInv(EXP_IF
, ed
);
2911 ei
->current
= ed
->line
;
2912 ei
->emitting
= true;
2913 ei
->prev
= istk
->expansion
;
2914 istk
->expansion
= ei
;
2915 free_tlist(origline
);
2916 return DIRECTIVE_FOUND
;
2922 if (defining
!= NULL
) {
2923 if (defining
->type
== EXP_MMACRO
) {
2924 defining
->def_depth
++;
2926 return NO_DIRECTIVE_FOUND
;
2928 ed
= new_ExpDef(EXP_MMACRO
);
2930 (i
== PP_RMACRO
) || (i
== PP_IRMACRO
) ? DEADMAN_LIMIT
: 0;
2931 ed
->casesense
= (i
== PP_MACRO
) || (i
== PP_RMACRO
);
2932 if (!parse_mmacro_spec(tline
, ed
, pp_directives
[i
])) {
2935 return DIRECTIVE_FOUND
;
2939 ed
->max_depth
= (ed
->max_depth
+ 1);
2940 ed
->ignoring
= false;
2941 ed
->prev
= defining
;
2944 eed
= (ExpDef
*) hash_findix(&expdefs
, ed
->name
);
2946 if (!strcmp(eed
->name
, ed
->name
) &&
2947 (eed
->nparam_min
<= ed
->nparam_max
|| ed
->plus
) &&
2948 (ed
->nparam_min
<= eed
->nparam_max
|| eed
->plus
)) {
2949 error(ERR_WARNING
|ERR_PASS1
,
2950 "redefining multi-line macro `%s'", ed
->name
);
2951 return DIRECTIVE_FOUND
;
2955 free_tlist(origline
);
2956 return DIRECTIVE_FOUND
;
2960 if (defining
!= NULL
) {
2961 if (defining
->type
== EXP_MMACRO
) {
2962 if (defining
->def_depth
> 0) {
2963 defining
->def_depth
--;
2964 return NO_DIRECTIVE_FOUND
;
2967 return NO_DIRECTIVE_FOUND
;
2970 if (!(defining
) || (defining
->type
!= EXP_MMACRO
)) {
2971 error(ERR_NONFATAL
, "`%s': not defining a macro", tline
->text
);
2972 return DIRECTIVE_FOUND
;
2974 edhead
= (ExpDef
**) hash_findi_add(&expdefs
, defining
->name
);
2975 defining
->next
= *edhead
;
2978 defining
= ed
->prev
;
2979 ed
->prev
= expansions
;
2982 free_tlist(origline
);
2983 return DIRECTIVE_FOUND
;
2986 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2988 * We must search along istk->expansion until we hit a
2989 * macro invocation. Then we disable the emitting state(s)
2990 * between exitmacro and endmacro.
2992 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
2993 if(ei
->type
== EXP_MMACRO
) {
3000 * Set all invocations leading back to the macro
3001 * invocation to a non-emitting state.
3003 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3004 eei
->emitting
= false;
3006 eei
->emitting
= false;
3008 error(ERR_NONFATAL
, "`%%exitmacro' not within `%%macro' block");
3010 free_tlist(origline
);
3011 return DIRECTIVE_FOUND
;
3015 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3020 spec
.casesense
= (i
== PP_UNMACRO
);
3021 if (!parse_mmacro_spec(tline
, &spec
, pp_directives
[i
])) {
3022 return DIRECTIVE_FOUND
;
3024 ed_p
= (ExpDef
**) hash_findi(&expdefs
, spec
.name
, NULL
);
3025 while (ed_p
&& *ed_p
) {
3027 if (ed
->casesense
== spec
.casesense
&&
3028 !mstrcmp(ed
->name
, spec
.name
, spec
.casesense
) &&
3029 ed
->nparam_min
== spec
.nparam_min
&&
3030 ed
->nparam_max
== spec
.nparam_max
&&
3031 ed
->plus
== spec
.plus
) {
3032 if (ed
->cur_depth
> 0) {
3033 error(ERR_NONFATAL
, "`%s' ignored on active macro",
3044 free_tlist(origline
);
3045 free_tlist(spec
.dlist
);
3046 return DIRECTIVE_FOUND
;
3050 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3051 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
3052 tline
= tline
->next
;
3054 free_tlist(origline
);
3055 error(ERR_NONFATAL
, "`%%rotate' missing rotate count");
3056 return DIRECTIVE_FOUND
;
3058 t
= expand_smacro(tline
->next
);
3060 free_tlist(origline
);
3063 tokval
.t_type
= TOKEN_INVALID
;
3065 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3068 return DIRECTIVE_FOUND
;
3070 error(ERR_WARNING
|ERR_PASS1
,
3071 "trailing garbage after expression ignored");
3072 if (!is_simple(evalresult
)) {
3073 error(ERR_NONFATAL
, "non-constant value given to `%%rotate'");
3074 return DIRECTIVE_FOUND
;
3076 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3077 if (ei
->type
== EXP_MMACRO
) {
3082 error(ERR_NONFATAL
, "`%%rotate' invoked outside a macro call");
3083 } else if (ei
->nparam
== 0) {
3085 "`%%rotate' invoked within macro without parameters");
3087 int rotate
= ei
->rotate
+ reloc_value(evalresult
);
3089 rotate
%= (int)ei
->nparam
;
3091 rotate
+= ei
->nparam
;
3092 ei
->rotate
= rotate
;
3094 return DIRECTIVE_FOUND
;
3097 if (defining
!= NULL
) {
3098 if (defining
->type
== EXP_REP
) {
3099 defining
->def_depth
++;
3101 return NO_DIRECTIVE_FOUND
;
3105 tline
= tline
->next
;
3106 } while (tok_type_(tline
, TOK_WHITESPACE
));
3108 if (tok_type_(tline
, TOK_ID
) &&
3109 nasm_stricmp(tline
->text
, ".nolist") == 0) {
3112 tline
= tline
->next
;
3113 } while (tok_type_(tline
, TOK_WHITESPACE
));
3117 t
= expand_smacro(tline
);
3119 tokval
.t_type
= TOKEN_INVALID
;
3121 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3123 free_tlist(origline
);
3124 return DIRECTIVE_FOUND
;
3127 error(ERR_WARNING
|ERR_PASS1
,
3128 "trailing garbage after expression ignored");
3129 if (!is_simple(evalresult
)) {
3130 error(ERR_NONFATAL
, "non-constant value given to `%%rep'");
3131 return DIRECTIVE_FOUND
;
3133 count
= reloc_value(evalresult
);
3134 if (count
>= REP_LIMIT
) {
3135 error(ERR_NONFATAL
, "`%%rep' value exceeds limit");
3140 error(ERR_NONFATAL
, "`%%rep' expects a repeat count");
3143 free_tlist(origline
);
3144 ed
= new_ExpDef(EXP_REP
);
3145 ed
->nolist
= nolist
;
3148 ed
->max_depth
= (count
- 1);
3149 ed
->ignoring
= false;
3150 ed
->prev
= defining
;
3152 return DIRECTIVE_FOUND
;
3155 if (defining
!= NULL
) {
3156 if (defining
->type
== EXP_REP
) {
3157 if (defining
->def_depth
> 0) {
3158 defining
->def_depth
--;
3159 return NO_DIRECTIVE_FOUND
;
3162 return NO_DIRECTIVE_FOUND
;
3165 if ((defining
== NULL
) || (defining
->type
!= EXP_REP
)) {
3166 error(ERR_NONFATAL
, "`%%endrep': no matching `%%rep'");
3167 return DIRECTIVE_FOUND
;
3171 * Now we have a "macro" defined - although it has no name
3172 * and we won't be entering it in the hash tables - we must
3173 * push a macro-end marker for it on to istk->expansion.
3174 * After that, it will take care of propagating itself (a
3175 * macro-end marker line for a macro which is really a %rep
3176 * block will cause the macro to be re-expanded, complete
3177 * with another macro-end marker to ensure the process
3178 * continues) until the whole expansion is forcibly removed
3179 * from istk->expansion by a %exitrep.
3182 defining
= ed
->prev
;
3183 ed
->prev
= expansions
;
3185 ei
= new_ExpInv(EXP_REP
, ed
);
3186 ei
->current
= ed
->line
;
3187 ei
->emitting
= ((ed
->max_depth
> 0) ? true : false);
3188 list
->uplevel(ed
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
3189 ei
->prev
= istk
->expansion
;
3190 istk
->expansion
= ei
;
3191 free_tlist(origline
);
3192 return DIRECTIVE_FOUND
;
3195 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3197 * We must search along istk->expansion until we hit a
3198 * rep invocation. Then we disable the emitting state(s)
3199 * between exitrep and endrep.
3201 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3202 if (ei
->type
== EXP_REP
) {
3209 * Set all invocations leading back to the rep
3210 * invocation to a non-emitting state.
3212 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3213 eei
->emitting
= false;
3215 eei
->emitting
= false;
3216 eei
->current
= NULL
;
3217 eei
->def
->cur_depth
= eei
->def
->max_depth
;
3219 error(ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
3221 free_tlist(origline
);
3222 return DIRECTIVE_FOUND
;
3228 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3229 casesense
= (i
== PP_DEFINE
|| i
== PP_XDEFINE
);
3231 tline
= tline
->next
;
3233 tline
= expand_id(tline
);
3234 if (!tline
|| (tline
->type
!= TOK_ID
&&
3235 (tline
->type
!= TOK_PREPROC_ID
||
3236 tline
->text
[1] != '$'))) {
3237 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3239 free_tlist(origline
);
3240 return DIRECTIVE_FOUND
;
3243 ctx
= get_ctx(tline
->text
, &mname
);
3245 param_start
= tline
= tline
->next
;
3248 /* Expand the macro definition now for %xdefine and %ixdefine */
3249 if ((i
== PP_XDEFINE
) || (i
== PP_IXDEFINE
))
3250 tline
= expand_smacro(tline
);
3252 if (tok_is_(tline
, "(")) {
3254 * This macro has parameters.
3257 tline
= tline
->next
;
3261 error(ERR_NONFATAL
, "parameter identifier expected");
3262 free_tlist(origline
);
3263 return DIRECTIVE_FOUND
;
3265 if (tline
->type
!= TOK_ID
) {
3267 "`%s': parameter identifier expected",
3269 free_tlist(origline
);
3270 return DIRECTIVE_FOUND
;
3273 smacro_set_param_idx(tline
, nparam
);
3276 tline
= tline
->next
;
3278 if (tok_is_(tline
, ",")) {
3279 tline
= tline
->next
;
3281 if (!tok_is_(tline
, ")")) {
3283 "`)' expected to terminate macro template");
3284 free_tlist(origline
);
3285 return DIRECTIVE_FOUND
;
3291 tline
= tline
->next
;
3293 if (tok_type_(tline
, TOK_WHITESPACE
))
3294 last
= tline
, tline
= tline
->next
;
3299 if (t
->type
== TOK_ID
) {
3300 list_for_each(tt
, param_start
)
3301 if (is_smacro_param(tt
) &&
3302 !strcmp(tt
->text
, t
->text
))
3306 t
->next
= macro_start
;
3311 * Good. We now have a macro name, a parameter count, and a
3312 * token list (in reverse order) for an expansion. We ought
3313 * to be OK just to create an SMacro, store it, and let
3314 * free_tlist have the rest of the line (which we have
3315 * carefully re-terminated after chopping off the expansion
3318 define_smacro(ctx
, mname
, casesense
, nparam
, macro_start
);
3319 free_tlist(origline
);
3320 return DIRECTIVE_FOUND
;
3323 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3324 tline
= tline
->next
;
3326 tline
= expand_id(tline
);
3327 if (!tline
|| (tline
->type
!= TOK_ID
&&
3328 (tline
->type
!= TOK_PREPROC_ID
||
3329 tline
->text
[1] != '$'))) {
3330 error(ERR_NONFATAL
, "`%%undef' expects a macro identifier");
3331 free_tlist(origline
);
3332 return DIRECTIVE_FOUND
;
3335 error(ERR_WARNING
|ERR_PASS1
,
3336 "trailing garbage after macro name ignored");
3339 /* Find the context that symbol belongs to */
3340 ctx
= get_ctx(tline
->text
, &mname
);
3341 undef_smacro(ctx
, mname
);
3342 free_tlist(origline
);
3343 return DIRECTIVE_FOUND
;
3347 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3348 casesense
= (i
== PP_DEFSTR
);
3350 tline
= tline
->next
;
3352 tline
= expand_id(tline
);
3353 if (!tline
|| (tline
->type
!= TOK_ID
&&
3354 (tline
->type
!= TOK_PREPROC_ID
||
3355 tline
->text
[1] != '$'))) {
3356 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3358 free_tlist(origline
);
3359 return DIRECTIVE_FOUND
;
3362 ctx
= get_ctx(tline
->text
, &mname
);
3364 tline
= expand_smacro(tline
->next
);
3367 while (tok_type_(tline
, TOK_WHITESPACE
))
3368 tline
= delete_Token(tline
);
3370 p
= detoken(tline
, false);
3371 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3372 macro_start
->text
= nasm_quote(p
, strlen(p
));
3373 macro_start
->type
= TOK_STRING
;
3377 * We now have a macro name, an implicit parameter count of
3378 * zero, and a string token to use as an expansion. Create
3379 * and store an SMacro.
3381 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3382 free_tlist(origline
);
3383 return DIRECTIVE_FOUND
;
3387 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3388 casesense
= (i
== PP_DEFTOK
);
3390 tline
= tline
->next
;
3392 tline
= expand_id(tline
);
3393 if (!tline
|| (tline
->type
!= TOK_ID
&&
3394 (tline
->type
!= TOK_PREPROC_ID
||
3395 tline
->text
[1] != '$'))) {
3397 "`%s' expects a macro identifier as first parameter",
3399 free_tlist(origline
);
3400 return DIRECTIVE_FOUND
;
3402 ctx
= get_ctx(tline
->text
, &mname
);
3404 tline
= expand_smacro(tline
->next
);
3408 while (tok_type_(t
, TOK_WHITESPACE
))
3410 /* t should now point to the string */
3411 if (!tok_type_(t
, TOK_STRING
)) {
3413 "`%s` requires string as second parameter",
3416 free_tlist(origline
);
3417 return DIRECTIVE_FOUND
;
3421 * Convert the string to a token stream. Note that smacros
3422 * are stored with the token stream reversed, so we have to
3423 * reverse the output of tokenize().
3425 nasm_unquote_cstr(t
->text
, i
);
3426 macro_start
= reverse_tokens(tokenize(t
->text
));
3429 * We now have a macro name, an implicit parameter count of
3430 * zero, and a numeric token to use as an expansion. Create
3431 * and store an SMacro.
3433 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3435 free_tlist(origline
);
3436 return DIRECTIVE_FOUND
;
3439 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3442 StrList
*xsl
= NULL
;
3443 StrList
**xst
= &xsl
;
3447 tline
= tline
->next
;
3449 tline
= expand_id(tline
);
3450 if (!tline
|| (tline
->type
!= TOK_ID
&&
3451 (tline
->type
!= TOK_PREPROC_ID
||
3452 tline
->text
[1] != '$'))) {
3454 "`%%pathsearch' expects a macro identifier as first parameter");
3455 free_tlist(origline
);
3456 return DIRECTIVE_FOUND
;
3458 ctx
= get_ctx(tline
->text
, &mname
);
3460 tline
= expand_smacro(tline
->next
);
3464 while (tok_type_(t
, TOK_WHITESPACE
))
3467 if (!t
|| (t
->type
!= TOK_STRING
&&
3468 t
->type
!= TOK_INTERNAL_STRING
)) {
3469 error(ERR_NONFATAL
, "`%%pathsearch' expects a file name");
3471 free_tlist(origline
);
3472 return DIRECTIVE_FOUND
; /* but we did _something_ */
3475 error(ERR_WARNING
|ERR_PASS1
,
3476 "trailing garbage after `%%pathsearch' ignored");
3478 if (t
->type
!= TOK_INTERNAL_STRING
)
3479 nasm_unquote(p
, NULL
);
3481 fp
= inc_fopen(p
, &xsl
, &xst
, true);
3484 fclose(fp
); /* Don't actually care about the file */
3486 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3487 macro_start
->text
= nasm_quote(p
, strlen(p
));
3488 macro_start
->type
= TOK_STRING
;
3492 * We now have a macro name, an implicit parameter count of
3493 * zero, and a string token to use as an expansion. Create
3494 * and store an SMacro.
3496 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3498 free_tlist(origline
);
3499 return DIRECTIVE_FOUND
;
3503 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3506 tline
= tline
->next
;
3508 tline
= expand_id(tline
);
3509 if (!tline
|| (tline
->type
!= TOK_ID
&&
3510 (tline
->type
!= TOK_PREPROC_ID
||
3511 tline
->text
[1] != '$'))) {
3513 "`%%strlen' expects a macro identifier as first parameter");
3514 free_tlist(origline
);
3515 return DIRECTIVE_FOUND
;
3517 ctx
= get_ctx(tline
->text
, &mname
);
3519 tline
= expand_smacro(tline
->next
);
3523 while (tok_type_(t
, TOK_WHITESPACE
))
3525 /* t should now point to the string */
3526 if (!tok_type_(t
, TOK_STRING
)) {
3528 "`%%strlen` requires string as second parameter");
3530 free_tlist(origline
);
3531 return DIRECTIVE_FOUND
;
3534 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3535 make_tok_num(macro_start
, nasm_unquote(t
->text
, NULL
));
3538 * We now have a macro name, an implicit parameter count of
3539 * zero, and a numeric token to use as an expansion. Create
3540 * and store an SMacro.
3542 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3544 free_tlist(origline
);
3545 return DIRECTIVE_FOUND
;
3548 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3551 tline
= tline
->next
;
3553 tline
= expand_id(tline
);
3554 if (!tline
|| (tline
->type
!= TOK_ID
&&
3555 (tline
->type
!= TOK_PREPROC_ID
||
3556 tline
->text
[1] != '$'))) {
3558 "`%%strcat' expects a macro identifier as first parameter");
3559 free_tlist(origline
);
3560 return DIRECTIVE_FOUND
;
3562 ctx
= get_ctx(tline
->text
, &mname
);
3564 tline
= expand_smacro(tline
->next
);
3568 list_for_each(t
, tline
) {
3570 case TOK_WHITESPACE
:
3573 len
+= t
->a
.len
= nasm_unquote(t
->text
, NULL
);
3576 if (!strcmp(t
->text
, ",")) /* permit comma separators */
3578 /* else fall through */
3581 "non-string passed to `%%strcat' (%d)", t
->type
);
3583 free_tlist(origline
);
3584 return DIRECTIVE_FOUND
;
3588 p
= pp
= nasm_malloc(len
);
3589 list_for_each(t
, tline
) {
3590 if (t
->type
== TOK_STRING
) {
3591 memcpy(p
, t
->text
, t
->a
.len
);
3597 * We now have a macro name, an implicit parameter count of
3598 * zero, and a numeric token to use as an expansion. Create
3599 * and store an SMacro.
3601 macro_start
= new_Token(NULL
, TOK_STRING
, NULL
, 0);
3602 macro_start
->text
= nasm_quote(pp
, len
);
3604 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3606 free_tlist(origline
);
3607 return DIRECTIVE_FOUND
;
3610 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3612 int64_t start
, count
;
3617 tline
= tline
->next
;
3619 tline
= expand_id(tline
);
3620 if (!tline
|| (tline
->type
!= TOK_ID
&&
3621 (tline
->type
!= TOK_PREPROC_ID
||
3622 tline
->text
[1] != '$'))) {
3624 "`%%substr' expects a macro identifier as first parameter");
3625 free_tlist(origline
);
3626 return DIRECTIVE_FOUND
;
3628 ctx
= get_ctx(tline
->text
, &mname
);
3630 tline
= expand_smacro(tline
->next
);
3633 if (tline
) /* skip expanded id */
3635 while (tok_type_(t
, TOK_WHITESPACE
))
3638 /* t should now point to the string */
3639 if (!tok_type_(t
, TOK_STRING
)) {
3641 "`%%substr` requires string as second parameter");
3643 free_tlist(origline
);
3644 return DIRECTIVE_FOUND
;
3649 tokval
.t_type
= TOKEN_INVALID
;
3650 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3654 free_tlist(origline
);
3655 return DIRECTIVE_FOUND
;
3656 } else if (!is_simple(evalresult
)) {
3657 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3659 free_tlist(origline
);
3660 return DIRECTIVE_FOUND
;
3662 start
= evalresult
->value
- 1;
3664 while (tok_type_(tt
, TOK_WHITESPACE
))
3667 count
= 1; /* Backwards compatibility: one character */
3669 tokval
.t_type
= TOKEN_INVALID
;
3670 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3674 free_tlist(origline
);
3675 return DIRECTIVE_FOUND
;
3676 } else if (!is_simple(evalresult
)) {
3677 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3679 free_tlist(origline
);
3680 return DIRECTIVE_FOUND
;
3682 count
= evalresult
->value
;
3685 len
= nasm_unquote(t
->text
, NULL
);
3686 /* make start and count being in range */
3690 count
= len
+ count
+ 1 - start
;
3691 if (start
+ count
> (int64_t)len
)
3692 count
= len
- start
;
3693 if (!len
|| count
< 0 || start
>=(int64_t)len
)
3694 start
= -1, count
= 0; /* empty string */
3696 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3697 macro_start
->text
= nasm_quote((start
< 0) ? "" : t
->text
+ start
, count
);
3698 macro_start
->type
= TOK_STRING
;
3701 * We now have a macro name, an implicit parameter count of
3702 * zero, and a numeric token to use as an expansion. Create
3703 * and store an SMacro.
3705 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3707 free_tlist(origline
);
3708 return DIRECTIVE_FOUND
;
3713 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3714 casesense
= (i
== PP_ASSIGN
);
3716 tline
= tline
->next
;
3718 tline
= expand_id(tline
);
3719 if (!tline
|| (tline
->type
!= TOK_ID
&&
3720 (tline
->type
!= TOK_PREPROC_ID
||
3721 tline
->text
[1] != '$'))) {
3723 "`%%%sassign' expects a macro identifier",
3724 (i
== PP_IASSIGN
? "i" : ""));
3725 free_tlist(origline
);
3726 return DIRECTIVE_FOUND
;
3728 ctx
= get_ctx(tline
->text
, &mname
);
3730 tline
= expand_smacro(tline
->next
);
3735 tokval
.t_type
= TOKEN_INVALID
;
3737 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3740 free_tlist(origline
);
3741 return DIRECTIVE_FOUND
;
3745 error(ERR_WARNING
|ERR_PASS1
,
3746 "trailing garbage after expression ignored");
3748 if (!is_simple(evalresult
)) {
3750 "non-constant value given to `%%%sassign'",
3751 (i
== PP_IASSIGN
? "i" : ""));
3752 free_tlist(origline
);
3753 return DIRECTIVE_FOUND
;
3756 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3757 make_tok_num(macro_start
, reloc_value(evalresult
));
3760 * We now have a macro name, an implicit parameter count of
3761 * zero, and a numeric token to use as an expansion. Create
3762 * and store an SMacro.
3764 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3765 free_tlist(origline
);
3766 return DIRECTIVE_FOUND
;
3769 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3771 * Syntax is `%line nnn[+mmm] [filename]'
3773 tline
= tline
->next
;
3775 if (!tok_type_(tline
, TOK_NUMBER
)) {
3776 error(ERR_NONFATAL
, "`%%line' expects line number");
3777 free_tlist(origline
);
3778 return DIRECTIVE_FOUND
;
3780 k
= readnum(tline
->text
, &err
);
3782 tline
= tline
->next
;
3783 if (tok_is_(tline
, "+")) {
3784 tline
= tline
->next
;
3785 if (!tok_type_(tline
, TOK_NUMBER
)) {
3786 error(ERR_NONFATAL
, "`%%line' expects line increment");
3787 free_tlist(origline
);
3788 return DIRECTIVE_FOUND
;
3790 m
= readnum(tline
->text
, &err
);
3791 tline
= tline
->next
;
3797 nasm_free(src_set_fname(detoken(tline
, false)));
3799 free_tlist(origline
);
3800 return DIRECTIVE_FOUND
;
3803 if (defining
!= NULL
) {
3804 if (defining
->type
== EXP_WHILE
) {
3805 defining
->def_depth
++;
3807 return NO_DIRECTIVE_FOUND
;
3810 if ((istk
->expansion
!= NULL
) &&
3811 (istk
->expansion
->emitting
== false)) {
3815 l
->first
= copy_Token(tline
->next
);
3816 j
= if_condition(tline
->next
, i
);
3817 tline
->next
= NULL
; /* it got freed */
3818 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
3820 ed
= new_ExpDef(EXP_WHILE
);
3823 ed
->max_depth
= DEADMAN_LIMIT
;
3824 ed
->ignoring
= ((ed
->state
== COND_IF_TRUE
) ? false : true);
3825 if (ed
->ignoring
== false) {
3828 } else if (l
!= NULL
) {
3829 delete_Token(l
->first
);
3833 ed
->prev
= defining
;
3835 free_tlist(origline
);
3836 return DIRECTIVE_FOUND
;
3839 if (defining
!= NULL
) {
3840 if (defining
->type
== EXP_WHILE
) {
3841 if (defining
->def_depth
> 0) {
3842 defining
->def_depth
--;
3843 return NO_DIRECTIVE_FOUND
;
3846 return NO_DIRECTIVE_FOUND
;
3849 if (tline
->next
!= NULL
) {
3850 error_precond(ERR_WARNING
|ERR_PASS1
,
3851 "trailing garbage after `%%endwhile' ignored");
3853 if ((defining
== NULL
) || (defining
->type
!= EXP_WHILE
)) {
3854 error(ERR_NONFATAL
, "`%%endwhile': no matching `%%while'");
3855 return DIRECTIVE_FOUND
;
3858 defining
= ed
->prev
;
3859 if (ed
->ignoring
== false) {
3860 ed
->prev
= expansions
;
3862 ei
= new_ExpInv(EXP_WHILE
, ed
);
3863 ei
->current
= ed
->line
->next
;
3864 ei
->emitting
= true;
3865 ei
->prev
= istk
->expansion
;
3866 istk
->expansion
= ei
;
3870 free_tlist(origline
);
3871 return DIRECTIVE_FOUND
;
3874 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3876 * We must search along istk->expansion until we hit a
3877 * while invocation. Then we disable the emitting state(s)
3878 * between exitwhile and endwhile.
3880 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3881 if (ei
->type
== EXP_WHILE
) {
3888 * Set all invocations leading back to the while
3889 * invocation to a non-emitting state.
3891 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3892 eei
->emitting
= false;
3894 eei
->emitting
= false;
3895 eei
->current
= NULL
;
3896 eei
->def
->cur_depth
= eei
->def
->max_depth
;
3898 error(ERR_NONFATAL
, "`%%exitwhile' not within `%%while' block");
3900 free_tlist(origline
);
3901 return DIRECTIVE_FOUND
;
3904 if (defining
!= NULL
) {
3905 if (defining
->type
== EXP_COMMENT
) {
3906 defining
->def_depth
++;
3908 return NO_DIRECTIVE_FOUND
;
3910 ed
= new_ExpDef(EXP_COMMENT
);
3911 ed
->ignoring
= true;
3912 ed
->prev
= defining
;
3914 free_tlist(origline
);
3915 return DIRECTIVE_FOUND
;
3918 if (defining
!= NULL
) {
3919 if (defining
->type
== EXP_COMMENT
) {
3920 if (defining
->def_depth
> 0) {
3921 defining
->def_depth
--;
3922 return NO_DIRECTIVE_FOUND
;
3925 return NO_DIRECTIVE_FOUND
;
3928 if ((defining
== NULL
) || (defining
->type
!= EXP_COMMENT
)) {
3929 error(ERR_NONFATAL
, "`%%endcomment': no matching `%%comment'");
3930 return DIRECTIVE_FOUND
;
3933 defining
= ed
->prev
;
3935 free_tlist(origline
);
3936 return DIRECTIVE_FOUND
;
3939 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3940 if (in_final
!= false) {
3941 error(ERR_FATAL
, "`%%final' cannot be used recursively");
3943 tline
= tline
->next
;
3945 if (tline
== NULL
) {
3946 error(ERR_NONFATAL
, "`%%final' expects at least one parameter");
3949 l
->first
= copy_Token(tline
);
3953 free_tlist(origline
);
3954 return DIRECTIVE_FOUND
;
3958 "preprocessor directive `%s' not yet implemented",
3960 return DIRECTIVE_FOUND
;
3965 * Ensure that a macro parameter contains a condition code and
3966 * nothing else. Return the condition code index if so, or -1
3969 static int find_cc(Token
* t
)
3975 return -1; /* Probably a %+ without a space */
3978 if (t
->type
!= TOK_ID
)
3982 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
3986 j
= ARRAY_SIZE(conditions
);
3989 m
= nasm_stricmp(t
->text
, conditions
[k
]);
4004 static bool paste_tokens(Token
**head
, const struct tokseq_match
*m
,
4005 int mnum
, bool handle_paste_tokens
)
4007 Token
**tail
, *t
, *tt
;
4009 bool did_paste
= false;
4013 /* Now handle token pasting... */
4016 while ((t
= *tail
) && (tt
= t
->next
)) {
4018 case TOK_WHITESPACE
:
4019 if (tt
->type
== TOK_WHITESPACE
) {
4020 /* Zap adjacent whitespace tokens */
4021 t
->next
= delete_Token(tt
);
4023 /* Do not advance paste_head here */
4027 case TOK_PASTE
: /* %+ */
4028 if (handle_paste_tokens
) {
4029 /* Zap %+ and whitespace tokens to the right */
4030 while (t
&& (t
->type
== TOK_WHITESPACE
||
4031 t
->type
== TOK_PASTE
))
4032 t
= *tail
= delete_Token(t
);
4033 if (!paste_head
|| !t
)
4034 break; /* Nothing to paste with */
4038 while (tok_type_(tt
, TOK_WHITESPACE
))
4039 tt
= t
->next
= delete_Token(tt
);
4041 tmp
= nasm_strcat(t
->text
, tt
->text
);
4043 tt
= delete_Token(tt
);
4044 t
= *tail
= tokenize(tmp
);
4050 t
->next
= tt
; /* Attach the remaining token chain */
4057 /* else fall through */
4060 * Concatenation of tokens might look nontrivial
4061 * but in real it's pretty simple -- the caller
4062 * prepares the masks of token types to be concatenated
4063 * and we simply find matched sequences and slip
4066 for (i
= 0; i
< mnum
; i
++) {
4067 if (PP_CONCAT_MASK(t
->type
) & m
[i
].mask_head
) {
4071 while (tt
&& (PP_CONCAT_MASK(tt
->type
) & m
[i
].mask_tail
)) {
4072 len
+= strlen(tt
->text
);
4076 nasm_dump_token(tt
);
4079 * Now tt points to the first token after
4080 * the potential paste area...
4082 if (tt
!= t
->next
) {
4083 /* We have at least two tokens... */
4084 len
+= strlen(t
->text
);
4085 p
= tmp
= nasm_malloc(len
+1);
4088 p
= strchr(p
, '\0');
4089 t
= delete_Token(t
);
4091 t
= *tail
= tokenize(tmp
);
4097 t
->next
= tt
; /* Attach the remaining token chain */
4105 if (i
>= mnum
) { /* no match */
4107 if (!tok_type_(t
->next
, TOK_WHITESPACE
))
4117 * expands to a list of tokens from %{x:y}
4119 static Token
*expand_mmac_params_range(ExpInv
*ei
, Token
*tline
, Token
***last
)
4121 Token
*t
= tline
, **tt
, *tm
, *head
;
4125 pos
= strchr(tline
->text
, ':');
4128 lst
= atoi(pos
+ 1);
4129 fst
= atoi(tline
->text
+ 1);
4132 * only macros params are accounted so
4133 * if someone passes %0 -- we reject such
4136 if (lst
== 0 || fst
== 0)
4139 /* the values should be sane */
4140 if ((fst
> (int)ei
->nparam
|| fst
< (-(int)ei
->nparam
)) ||
4141 (lst
> (int)ei
->nparam
|| lst
< (-(int)ei
->nparam
)))
4144 fst
= fst
< 0 ? fst
+ (int)ei
->nparam
+ 1: fst
;
4145 lst
= lst
< 0 ? lst
+ (int)ei
->nparam
+ 1: lst
;
4147 /* counted from zero */
4151 * it will be at least one token
4153 tm
= ei
->params
[(fst
+ ei
->rotate
) % ei
->nparam
];
4154 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4155 head
= t
, tt
= &t
->next
;
4157 for (i
= fst
+ 1; i
<= lst
; i
++) {
4158 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
4159 *tt
= t
, tt
= &t
->next
;
4160 j
= (i
+ ei
->rotate
) % ei
->nparam
;
4162 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4163 *tt
= t
, tt
= &t
->next
;
4166 for (i
= fst
- 1; i
>= lst
; i
--) {
4167 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
4168 *tt
= t
, tt
= &t
->next
;
4169 j
= (i
+ ei
->rotate
) % ei
->nparam
;
4171 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4172 *tt
= t
, tt
= &t
->next
;
4180 error(ERR_NONFATAL
, "`%%{%s}': macro parameters out of range",
4186 * Expand MMacro-local things: parameter references (%0, %n, %+n,
4187 * %-n) and MMacro-local identifiers (%%foo) as well as
4188 * macro indirection (%[...]) and range (%{..:..}).
4190 static Token
*expand_mmac_params(Token
* tline
)
4192 Token
*t
, *tt
, **tail
, *thead
;
4193 bool changed
= false;
4199 nasm_dump_stream(tline
);
4202 if (tline
->type
== TOK_PREPROC_ID
&&
4203 (((tline
->text
[1] == '+' || tline
->text
[1] == '-') && tline
->text
[2]) ||
4204 (tline
->text
[1] >= '0' && tline
->text
[1] <= '9') ||
4205 tline
->text
[1] == '%')) {
4207 int type
= 0, cc
; /* type = 0 to placate optimisers */
4214 tline
= tline
->next
;
4216 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
4217 if (ei
->type
== EXP_MMACRO
) {
4222 error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
4224 pos
= strchr(t
->text
, ':');
4226 switch (t
->text
[1]) {
4228 * We have to make a substitution of one of the
4229 * forms %1, %-1, %+1, %%foo, %0.
4232 if ((strlen(t
->text
) > 2) && (t
->text
[2] == '0')) {
4234 text
= nasm_strdup(ei
->label_text
);
4237 snprintf(tmpbuf
, sizeof(tmpbuf
), "%d", ei
->nparam
);
4238 text
= nasm_strdup(tmpbuf
);
4243 snprintf(tmpbuf
, sizeof(tmpbuf
), "..@%"PRIu64
".",
4245 text
= nasm_strcat(tmpbuf
, t
->text
+ 2);
4248 n
= atoi(t
->text
+ 2) - 1;
4249 if (n
>= ei
->nparam
)
4253 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4259 "macro parameter %d is not a condition code",
4264 if (inverse_ccs
[cc
] == -1) {
4266 "condition code `%s' is not invertible",
4270 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
4274 n
= atoi(t
->text
+ 2) - 1;
4275 if (n
>= ei
->nparam
)
4279 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4285 "macro parameter %d is not a condition code",
4290 text
= nasm_strdup(conditions
[cc
]);
4294 n
= atoi(t
->text
+ 1) - 1;
4295 if (n
>= ei
->nparam
)
4299 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4303 for (i
= 0; i
< ei
->paramlen
[n
]; i
++) {
4304 *tail
= new_Token(NULL
, tt
->type
, tt
->text
, 0);
4305 tail
= &(*tail
)->next
;
4309 text
= NULL
; /* we've done it here */
4314 * seems we have a parameters range here
4316 Token
*head
, **last
;
4317 head
= expand_mmac_params_range(ei
, t
, &last
);
4338 } else if (tline
->type
== TOK_INDIRECT
) {
4340 tline
= tline
->next
;
4341 tt
= tokenize(t
->text
);
4342 tt
= expand_mmac_params(tt
);
4343 tt
= expand_smacro(tt
);
4346 tt
->a
.mac
= NULL
; /* Necessary? */
4354 tline
= tline
->next
;
4362 const struct tokseq_match t
[] = {
4364 PP_CONCAT_MASK(TOK_ID
) |
4365 PP_CONCAT_MASK(TOK_FLOAT
), /* head */
4366 PP_CONCAT_MASK(TOK_ID
) |
4367 PP_CONCAT_MASK(TOK_NUMBER
) |
4368 PP_CONCAT_MASK(TOK_FLOAT
) |
4369 PP_CONCAT_MASK(TOK_OTHER
) /* tail */
4372 PP_CONCAT_MASK(TOK_NUMBER
), /* head */
4373 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4376 paste_tokens(&thead
, t
, ARRAY_SIZE(t
), false);
4379 nasm_dump_token(thead
);
4385 * Expand all single-line macro calls made in the given line.
4386 * Return the expanded version of the line. The original is deemed
4387 * to be destroyed in the process. (In reality we'll just move
4388 * Tokens from input to output a lot of the time, rather than
4389 * actually bothering to destroy and replicate.)
4392 static Token
*expand_smacro(Token
* tline
)
4394 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
4395 SMacro
*head
= NULL
, *m
;
4398 unsigned int nparam
, sparam
;
4400 Token
*org_tline
= tline
;
4403 int deadman
= DEADMAN_LIMIT
;
4407 * Trick: we should avoid changing the start token pointer since it can
4408 * be contained in "next" field of other token. Because of this
4409 * we allocate a copy of first token and work with it; at the end of
4410 * routine we copy it back
4413 tline
= new_Token(org_tline
->next
, org_tline
->type
,
4414 org_tline
->text
, 0);
4415 tline
->a
.mac
= org_tline
->a
.mac
;
4416 nasm_free(org_tline
->text
);
4417 org_tline
->text
= NULL
;
4420 expanded
= true; /* Always expand %+ at least once */
4426 while (tline
) { /* main token loop */
4428 error(ERR_NONFATAL
, "interminable macro recursion");
4432 if ((mname
= tline
->text
)) {
4433 /* if this token is a local macro, look in local context */
4434 if (tline
->type
== TOK_ID
) {
4435 head
= (SMacro
*)hash_findix(&smacros
, mname
);
4436 } else if (tline
->type
== TOK_PREPROC_ID
) {
4437 ctx
= get_ctx(mname
, &mname
);
4438 head
= ctx
? (SMacro
*)hash_findix(&ctx
->localmac
, mname
) : NULL
;
4443 * We've hit an identifier. As in is_mmacro below, we first
4444 * check whether the identifier is a single-line macro at
4445 * all, then think about checking for parameters if
4448 list_for_each(m
, head
)
4449 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
4455 if (m
->nparam
== 0) {
4457 * Simple case: the macro is parameterless. Discard the
4458 * one token that the macro call took, and push the
4459 * expansion back on the to-do stack.
4461 if (!m
->expansion
) {
4462 if (!strcmp("__FILE__", m
->name
)) {
4465 src_get(&num
, &file
);
4466 tline
->text
= nasm_quote(file
, strlen(file
));
4467 tline
->type
= TOK_STRING
;
4471 if (!strcmp("__LINE__", m
->name
)) {
4472 nasm_free(tline
->text
);
4473 make_tok_num(tline
, src_get_linnum());
4476 if (!strcmp("__BITS__", m
->name
)) {
4477 nasm_free(tline
->text
);
4478 make_tok_num(tline
, globalbits
);
4481 tline
= delete_Token(tline
);
4486 * Complicated case: at least one macro with this name
4487 * exists and takes parameters. We must find the
4488 * parameters in the call, count them, find the SMacro
4489 * that corresponds to that form of the macro call, and
4490 * substitute for the parameters when we expand. What a
4493 /*tline = tline->next;
4494 skip_white_(tline); */
4497 while (tok_type_(t
, TOK_SMAC_END
)) {
4498 t
->a
.mac
->in_progress
= false;
4500 t
= tline
->next
= delete_Token(t
);
4503 } while (tok_type_(tline
, TOK_WHITESPACE
));
4504 if (!tok_is_(tline
, "(")) {
4506 * This macro wasn't called with parameters: ignore
4507 * the call. (Behaviour borrowed from gnu cpp.)
4516 sparam
= PARAM_DELTA
;
4517 params
= nasm_malloc(sparam
* sizeof(Token
*));
4518 params
[0] = tline
->next
;
4519 paramsize
= nasm_malloc(sparam
* sizeof(int));
4521 while (true) { /* parameter loop */
4523 * For some unusual expansions
4524 * which concatenates function call
4527 while (tok_type_(t
, TOK_SMAC_END
)) {
4528 t
->a
.mac
->in_progress
= false;
4530 t
= tline
->next
= delete_Token(t
);
4536 "macro call expects terminating `)'");
4539 if (tline
->type
== TOK_WHITESPACE
4541 if (paramsize
[nparam
])
4544 params
[nparam
] = tline
->next
;
4545 continue; /* parameter loop */
4547 if (tline
->type
== TOK_OTHER
4548 && tline
->text
[1] == 0) {
4549 char ch
= tline
->text
[0];
4550 if (ch
== ',' && !paren
&& brackets
<= 0) {
4551 if (++nparam
>= sparam
) {
4552 sparam
+= PARAM_DELTA
;
4553 params
= nasm_realloc(params
,
4554 sparam
* sizeof(Token
*));
4555 paramsize
= nasm_realloc(paramsize
,
4556 sparam
* sizeof(int));
4558 params
[nparam
] = tline
->next
;
4559 paramsize
[nparam
] = 0;
4561 continue; /* parameter loop */
4564 (brackets
> 0 || (brackets
== 0 &&
4565 !paramsize
[nparam
])))
4567 if (!(brackets
++)) {
4568 params
[nparam
] = tline
->next
;
4569 continue; /* parameter loop */
4572 if (ch
== '}' && brackets
> 0)
4573 if (--brackets
== 0) {
4575 continue; /* parameter loop */
4577 if (ch
== '(' && !brackets
)
4579 if (ch
== ')' && brackets
<= 0)
4585 error(ERR_NONFATAL
, "braces do not "
4586 "enclose all of macro parameter");
4588 paramsize
[nparam
] += white
+ 1;
4590 } /* parameter loop */
4592 while (m
&& (m
->nparam
!= nparam
||
4593 mstrcmp(m
->name
, mname
,
4597 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4598 "macro `%s' exists, "
4599 "but not taking %d parameters",
4600 mstart
->text
, nparam
);
4603 if (m
&& m
->in_progress
)
4605 if (!m
) { /* in progess or didn't find '(' or wrong nparam */
4607 * Design question: should we handle !tline, which
4608 * indicates missing ')' here, or expand those
4609 * macros anyway, which requires the (t) test a few
4613 nasm_free(paramsize
);
4617 * Expand the macro: we are placed on the last token of the
4618 * call, so that we can easily split the call from the
4619 * following tokens. We also start by pushing an SMAC_END
4620 * token for the cycle removal.
4627 tt
= new_Token(tline
, TOK_SMAC_END
, NULL
, 0);
4629 m
->in_progress
= true;
4631 list_for_each(t
, m
->expansion
) {
4632 if (is_smacro_param(t
)) {
4633 Token
*pcopy
= tline
, **ptail
= &pcopy
;
4637 idx
= smacro_get_param_idx(t
);
4641 * We need smacro paramters appended.
4643 for (i
= paramsize
[idx
]; i
> 0; i
--) {
4644 *ptail
= new_Token(tline
, ttt
->type
, ttt
->text
, 0);
4645 ptail
= &(*ptail
)->next
;
4650 } else if (t
->type
== TOK_PREPROC_Q
) {
4651 tt
= new_Token(tline
, TOK_ID
, mname
, 0);
4653 } else if (t
->type
== TOK_PREPROC_QQ
) {
4654 tt
= new_Token(tline
, TOK_ID
, m
->name
, 0);
4657 tt
= new_Token(tline
, t
->type
, t
->text
, 0);
4663 * Having done that, get rid of the macro call, and clean
4664 * up the parameters.
4667 nasm_free(paramsize
);
4670 continue; /* main token loop */
4675 if (tline
->type
== TOK_SMAC_END
) {
4676 tline
->a
.mac
->in_progress
= false;
4677 tline
= delete_Token(tline
);
4680 tline
= tline
->next
;
4688 * Now scan the entire line and look for successive TOK_IDs that resulted
4689 * after expansion (they can't be produced by tokenize()). The successive
4690 * TOK_IDs should be concatenated.
4691 * Also we look for %+ tokens and concatenate the tokens before and after
4692 * them (without white spaces in between).
4695 const struct tokseq_match t
[] = {
4697 PP_CONCAT_MASK(TOK_ID
) |
4698 PP_CONCAT_MASK(TOK_PREPROC_ID
), /* head */
4699 PP_CONCAT_MASK(TOK_ID
) |
4700 PP_CONCAT_MASK(TOK_PREPROC_ID
) |
4701 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4704 if (paste_tokens(&thead
, t
, ARRAY_SIZE(t
), true)) {
4706 * If we concatenated something, *and* we had previously expanded
4707 * an actual macro, scan the lines again for macros...
4718 *org_tline
= *thead
;
4719 /* since we just gave text to org_line, don't free it */
4721 delete_Token(thead
);
4723 /* the expression expanded to empty line;
4724 we can't return NULL for some reasons
4725 we just set the line to a single WHITESPACE token. */
4726 memset(org_tline
, 0, sizeof(*org_tline
));
4727 org_tline
->text
= NULL
;
4728 org_tline
->type
= TOK_WHITESPACE
;
4737 * Similar to expand_smacro but used exclusively with macro identifiers
4738 * right before they are fetched in. The reason is that there can be
4739 * identifiers consisting of several subparts. We consider that if there
4740 * are more than one element forming the name, user wants a expansion,
4741 * otherwise it will be left as-is. Example:
4745 * the identifier %$abc will be left as-is so that the handler for %define
4746 * will suck it and define the corresponding value. Other case:
4748 * %define _%$abc cde
4750 * In this case user wants name to be expanded *before* %define starts
4751 * working, so we'll expand %$abc into something (if it has a value;
4752 * otherwise it will be left as-is) then concatenate all successive
4755 static Token
*expand_id(Token
* tline
)
4757 Token
*cur
, *oldnext
= NULL
;
4759 if (!tline
|| !tline
->next
)
4764 (cur
->next
->type
== TOK_ID
||
4765 cur
->next
->type
== TOK_PREPROC_ID
||
4766 cur
->next
->type
== TOK_NUMBER
))
4769 /* If identifier consists of just one token, don't expand */
4774 oldnext
= cur
->next
; /* Detach the tail past identifier */
4775 cur
->next
= NULL
; /* so that expand_smacro stops here */
4778 tline
= expand_smacro(tline
);
4781 /* expand_smacro possibly changhed tline; re-scan for EOL */
4783 while (cur
&& cur
->next
)
4786 cur
->next
= oldnext
;
4793 * Determine whether the given line constitutes a multi-line macro
4794 * call, and return the ExpDef structure called if so. Doesn't have
4795 * to check for an initial label - that's taken care of in
4796 * expand_mmacro - but must check numbers of parameters. Guaranteed
4797 * to be called with tline->type == TOK_ID, so the putative macro
4798 * name is easy to find.
4800 static ExpDef
*is_mmacro(Token
* tline
, Token
*** params_array
)
4806 head
= (ExpDef
*) hash_findix(&expdefs
, tline
->text
);
4809 * Efficiency: first we see if any macro exists with the given
4810 * name. If not, we can return NULL immediately. _Then_ we
4811 * count the parameters, and then we look further along the
4812 * list if necessary to find the proper ExpDef.
4814 list_for_each(ed
, head
)
4815 if (!mstrcmp(ed
->name
, tline
->text
, ed
->casesense
))
4821 * OK, we have a potential macro. Count and demarcate the
4824 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
4827 * So we know how many parameters we've got. Find the ExpDef
4828 * structure that handles this number.
4831 if (ed
->nparam_min
<= nparam
4832 && (ed
->plus
|| nparam
<= ed
->nparam_max
)) {
4834 * It's right, and we can use it. Add its default
4835 * parameters to the end of our list if necessary.
4837 if (ed
->defaults
&& nparam
< ed
->nparam_min
+ ed
->ndefs
) {
4839 nasm_realloc(params
,
4840 ((ed
->nparam_min
+ ed
->ndefs
+
4841 1) * sizeof(*params
)));
4842 while (nparam
< ed
->nparam_min
+ ed
->ndefs
) {
4843 params
[nparam
] = ed
->defaults
[nparam
- ed
->nparam_min
];
4848 * If we've gone over the maximum parameter count (and
4849 * we're in Plus mode), ignore parameters beyond
4852 if (ed
->plus
&& nparam
> ed
->nparam_max
)
4853 nparam
= ed
->nparam_max
;
4855 * Then terminate the parameter list, and leave.
4857 if (!params
) { /* need this special case */
4858 params
= nasm_malloc(sizeof(*params
));
4861 params
[nparam
] = NULL
;
4862 *params_array
= params
;
4866 * This one wasn't right: look for the next one with the
4869 list_for_each(ed
, ed
->next
)
4870 if (!mstrcmp(ed
->name
, tline
->text
, ed
->casesense
))
4875 * After all that, we didn't find one with the right number of
4876 * parameters. Issue a warning, and fail to expand the macro.
4878 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4879 "macro `%s' exists, but not taking %d parameters",
4880 tline
->text
, nparam
);
4886 * Expand the multi-line macro call made by the given line, if
4887 * there is one to be expanded. If there is, push the expansion on
4888 * istk->expansion and return true. Otherwise return false.
4890 static bool expand_mmacro(Token
* tline
)
4892 Token
*label
= NULL
;
4893 int dont_prepend
= 0;
4898 int i
, nparam
, *paramlen
;
4903 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4904 if (!tok_type_(t
, TOK_ID
) && !tok_type_(t
, TOK_PREPROC_ID
))
4906 ed
= is_mmacro(t
, ¶ms
);
4912 * We have an id which isn't a macro call. We'll assume
4913 * it might be a label; we'll also check to see if a
4914 * colon follows it. Then, if there's another id after
4915 * that lot, we'll check it again for macro-hood.
4919 if (tok_type_(t
, TOK_WHITESPACE
))
4920 last
= t
, t
= t
->next
;
4921 if (tok_is_(t
, ":")) {
4923 last
= t
, t
= t
->next
;
4924 if (tok_type_(t
, TOK_WHITESPACE
))
4925 last
= t
, t
= t
->next
;
4927 if (!tok_type_(t
, TOK_ID
) || !(ed
= is_mmacro(t
, ¶ms
)))
4935 * Fix up the parameters: this involves stripping leading and
4936 * trailing whitespace, then stripping braces if they are
4939 for (nparam
= 0; params
[nparam
]; nparam
++) ;
4940 paramlen
= nparam
? nasm_malloc(nparam
* sizeof(*paramlen
)) : NULL
;
4942 for (i
= 0; params
[i
]; i
++) {
4944 int comma
= (!ed
->plus
|| i
< nparam
- 1);
4948 if (tok_is_(t
, "{"))
4949 t
= t
->next
, brace
= true, comma
= false;
4953 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
4954 break; /* ... because we have hit a comma */
4955 if (comma
&& t
->type
== TOK_WHITESPACE
4956 && tok_is_(t
->next
, ","))
4957 break; /* ... or a space then a comma */
4958 if (brace
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "}"))
4959 break; /* ... or a brace */
4965 if (ed
->cur_depth
>= ed
->max_depth
) {
4966 if (ed
->max_depth
> 1) {
4968 "reached maximum macro recursion depth of %i for %s",
4969 ed
->max_depth
,ed
->name
);
4977 * OK, we have found a ExpDef structure representing a
4978 * previously defined mmacro. Create an expansion invocation
4979 * and point it back to the expansion definition. Substitution of
4980 * parameter tokens and macro-local tokens doesn't get done
4981 * until the single-line macro substitution process; this is
4982 * because delaying them allows us to change the semantics
4983 * later through %rotate.
4985 ei
= new_ExpInv(EXP_MMACRO
, ed
);
4986 ei
->name
= nasm_strdup(mname
);
4987 //ei->label = label;
4988 //ei->label_text = detoken(label, false);
4989 ei
->current
= ed
->line
;
4990 ei
->emitting
= true;
4991 //ei->iline = tline;
4992 ei
->params
= params
;
4993 ei
->nparam
= nparam
;
4995 ei
->paramlen
= paramlen
;
4998 ei
->prev
= istk
->expansion
;
4999 istk
->expansion
= ei
;
5002 * Special case: detect %00 on first invocation; if found,
5003 * avoid emitting any labels that precede the mmacro call.
5004 * ed->prepend is set to -1 when %00 is detected, else 1.
5006 if (ed
->prepend
== 0) {
5007 for (l
= ed
->line
; l
!= NULL
; l
= l
->next
) {
5008 for (t
= l
->first
; t
!= NULL
; t
= t
->next
) {
5009 if ((t
->type
== TOK_PREPROC_ID
) &&
5010 (strlen(t
->text
) == 3) &&
5011 (t
->text
[1] == '0') && (t
->text
[2] == '0')) {
5016 if (dont_prepend
< 0) {
5020 ed
->prepend
= ((dont_prepend
< 0) ? -1 : 1);
5024 * If we had a label, push it on as the first line of
5025 * the macro expansion.
5027 if (label
!= NULL
) {
5028 if (ed
->prepend
< 0) {
5029 ei
->label_text
= detoken(label
, false);
5031 if (dont_prepend
== 0) {
5033 while (t
->next
!= NULL
) {
5036 t
->next
= new_Token(NULL
, TOK_OTHER
, ":", 0);
5039 l
->first
= copy_Token(label
);
5040 l
->next
= ei
->current
;
5045 list
->uplevel(ed
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
5051 /* The function that actually does the error reporting */
5052 static void verror(int severity
, const char *fmt
, va_list arg
)
5056 vsnprintf(buff
, sizeof(buff
), fmt
, arg
);
5058 if (istk
&& istk
->mmac_depth
> 0) {
5059 ExpInv
*ei
= istk
->expansion
;
5060 int lineno
= ei
->lineno
;
5062 if (ei
->type
== EXP_MMACRO
)
5064 lineno
+= ei
->relno
;
5067 nasm_error(severity
, "(%s:%d) %s", ei
->def
->name
,
5070 nasm_error(severity
, "%s", buff
);
5074 * Since preprocessor always operate only on the line that didn't
5075 * arrived yet, we should always use ERR_OFFBY1.
5077 static void error(int severity
, const char *fmt
, ...)
5081 verror(severity
, fmt
, arg
);
5086 * Because %else etc are evaluated in the state context
5087 * of the previous branch, errors might get lost with error():
5088 * %if 0 ... %else trailing garbage ... %endif
5089 * So %else etc should report errors with this function.
5091 static void error_precond(int severity
, const char *fmt
, ...)
5095 /* Only ignore the error if it's really in a dead branch */
5096 if ((istk
!= NULL
) &&
5097 (istk
->expansion
!= NULL
) &&
5098 (istk
->expansion
->type
== EXP_IF
) &&
5099 (istk
->expansion
->def
->state
== COND_NEVER
))
5103 verror(severity
, fmt
, arg
);
5108 pp_reset(char *file
, int apass
, ListGen
* listgen
, StrList
**deplist
)
5113 istk
= nasm_zalloc(sizeof(Include
));
5114 istk
->fp
= fopen(file
, "r");
5115 src_set_fname(nasm_strdup(file
));
5119 error(ERR_FATAL
|ERR_NOFILE
, "unable to open input file `%s'",
5124 nested_mac_count
= 0;
5125 nested_rep_count
= 0;
5128 if (tasm_compatible_mode
) {
5129 stdmacpos
= nasm_stdmac
;
5131 stdmacpos
= nasm_stdmac_after_tasm
;
5133 any_extrastdmac
= extrastdmac
&& *extrastdmac
;
5138 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
5139 * The caller, however, will also pass in 3 for preprocess-only so
5140 * we can set __PASS__ accordingly.
5142 pass
= apass
> 2 ? 2 : apass
;
5144 dephead
= deptail
= deplist
;
5146 StrList
*sl
= nasm_malloc(strlen(file
)+1+sizeof sl
->next
);
5148 strcpy(sl
->str
, file
);
5150 deptail
= &sl
->next
;
5154 * Define the __PASS__ macro. This is defined here unlike
5155 * all the other builtins, because it is special -- it varies between
5158 t
= nasm_zalloc(sizeof(*t
));
5159 make_tok_num(t
, apass
);
5160 define_smacro(NULL
, "__PASS__", true, 0, t
);
5163 static char *pp_getline(void)
5174 * Fetch a tokenized line, either from the expansion
5175 * buffer or from the input file.
5179 while (1) { /* until we get a line we can use */
5181 * Fetch a tokenized line from the expansion buffer
5183 if (istk
->expansion
!= NULL
) {
5184 ei
= istk
->expansion
;
5185 if (ei
->current
!= NULL
) {
5186 if (ei
->emitting
== false) {
5191 ei
->current
= l
->next
;
5193 tline
= copy_Token(l
->first
);
5194 if (((ei
->type
== EXP_REP
) ||
5195 (ei
->type
== EXP_MMACRO
) ||
5196 (ei
->type
== EXP_WHILE
))
5197 && (ei
->def
->nolist
== false)) {
5198 char *p
= detoken(tline
, false);
5199 list
->line(LIST_MACRO
, p
);
5202 if (ei
->linnum
> -1) {
5203 src_set_linnum(src_get_linnum() + 1);
5206 } else if ((ei
->type
== EXP_REP
) &&
5207 (ei
->def
->cur_depth
< ei
->def
->max_depth
)) {
5208 ei
->def
->cur_depth
++;
5209 ei
->current
= ei
->def
->line
;
5212 } else if ((ei
->type
== EXP_WHILE
) &&
5213 (ei
->def
->cur_depth
< ei
->def
->max_depth
)) {
5214 ei
->current
= ei
->def
->line
;
5216 tline
= copy_Token(ei
->current
->first
);
5217 j
= if_condition(tline
, PP_WHILE
);
5219 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
5220 if (j
== COND_IF_TRUE
) {
5221 ei
->current
= ei
->current
->next
;
5222 ei
->def
->cur_depth
++;
5224 ei
->emitting
= false;
5226 ei
->def
->cur_depth
= ei
->def
->max_depth
;
5230 istk
->expansion
= ei
->prev
;
5233 if ((ei
->emitting
== true) &&
5234 (ed
->max_depth
== DEADMAN_LIMIT
) &&
5235 (ed
->cur_depth
== DEADMAN_LIMIT
)
5237 error(ERR_FATAL
, "runaway expansion detected, aborting");
5239 if (ed
->cur_depth
> 0) {
5241 } else if (ed
->type
!= EXP_MMACRO
) {
5242 expansions
= ed
->prev
;
5245 if ((ei
->type
== EXP_REP
) ||
5246 (ei
->type
== EXP_MMACRO
) ||
5247 (ei
->type
== EXP_WHILE
)) {
5248 list
->downlevel(LIST_MACRO
);
5249 if (ei
->type
== EXP_MMACRO
) {
5254 if (ei
->linnum
> -1) {
5255 src_set_linnum(ei
->linnum
);
5263 * Read in line from input and tokenize
5266 if (line
) { /* from the current input file */
5267 line
= prepreproc(line
);
5268 tline
= tokenize(line
);
5274 * The current file has ended; work down the istk
5279 if (i
->expansion
!= NULL
) {
5281 "end of file while still in an expansion");
5283 /* only set line and file name if there's a next node */
5285 src_set_linnum(i
->lineno
);
5286 nasm_free(src_set_fname(nasm_strdup(i
->fname
)));
5288 if ((i
->next
== NULL
) && (finals
!= NULL
)) {
5290 ei
= new_ExpInv(EXP_FINAL
, NULL
);
5291 ei
->emitting
= true;
5292 ei
->current
= finals
;
5293 istk
->expansion
= ei
;
5298 list
->downlevel(LIST_INCLUDE
);
5301 if (finals
!= NULL
) {
5311 if (defining
== NULL
) {
5312 tline
= expand_mmac_params(tline
);
5316 * Check the line to see if it's a preprocessor directive.
5318 if (do_directive(tline
) == DIRECTIVE_FOUND
) {
5320 } else if (defining
!= NULL
) {
5322 * We're defining an expansion. We emit nothing at all,
5323 * and just shove the tokenized line on to the definition.
5325 if (defining
->ignoring
== false) {
5326 Line
*l
= new_Line();
5328 if (defining
->line
== NULL
) {
5332 defining
->last
->next
= l
;
5338 defining
->linecount
++;
5340 } else if ((istk
->expansion
!= NULL
) &&
5341 (istk
->expansion
->emitting
!= true)) {
5343 * We're in a non-emitting branch of an expansion.
5344 * Emit nothing at all, not even a blank line: when we
5345 * emerge from the expansion we'll give a line-number
5346 * directive so we keep our place correctly.
5351 tline
= expand_smacro(tline
);
5352 if (expand_mmacro(tline
) != true) {
5354 * De-tokenize the line again, and emit it.
5356 line
= detoken(tline
, true);
5367 static void pp_cleanup(int pass
)
5369 if (defining
!= NULL
) {
5370 error(ERR_NONFATAL
, "end of file while still defining an expansion");
5371 while (defining
!= NULL
) {
5372 ExpDef
*ed
= defining
;
5373 defining
= ed
->prev
;
5378 while (cstk
!= NULL
)
5381 while (istk
!= NULL
) {
5385 nasm_free(i
->fname
);
5386 while (i
->expansion
!= NULL
) {
5387 ExpInv
*ei
= i
->expansion
;
5388 i
->expansion
= ei
->prev
;
5395 nasm_free(src_set_fname(NULL
));
5400 while ((i
= ipath
)) {
5408 void pp_include_path(char *path
)
5410 IncPath
*i
= nasm_zalloc(sizeof(IncPath
));
5413 i
->path
= nasm_strdup(path
);
5425 void pp_pre_include(char *fname
)
5427 Token
*inc
, *space
, *name
;
5430 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
5431 space
= new_Token(name
, TOK_WHITESPACE
, NULL
, 0);
5432 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
5440 void pp_pre_define(char *definition
)
5446 equals
= strchr(definition
, '=');
5447 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5448 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
5451 space
->next
= tokenize(definition
);
5461 void pp_pre_undefine(char *definition
)
5466 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5467 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
5468 space
->next
= tokenize(definition
);
5477 * This function is used to assist with "runtime" preprocessor
5478 * directives, e.g. pp_runtime("%define __BITS__ 64");
5480 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
5481 * PASS A VALID STRING TO THIS FUNCTION!!!!!
5484 void pp_runtime(char *definition
)
5488 def
= tokenize(definition
);
5489 if (do_directive(def
) == NO_DIRECTIVE_FOUND
)
5494 void pp_extra_stdmac(macros_t
*macros
)
5496 extrastdmac
= macros
;
5499 static void make_tok_num(Token
* tok
, int64_t val
)
5502 snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
5503 tok
->text
= nasm_strdup(numbuf
);
5504 tok
->type
= TOK_NUMBER
;
5507 struct preproc_ops nasmpp
= {