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 */
215 int nparam_min
, nparam_max
;
217 bool plus
; /* is the last parameter greedy? */
218 bool nolist
; /* is this expansion listing-inhibited? */
219 Token
*dlist
; /* all defaults as one list */
220 Token
**defaults
; /* parameter default pointers */
221 int ndefs
; /* number of default parameters */
223 int prepend
; /* label prepend state */
227 int linecount
; /* number of lines within expansion */
229 int64_t def_depth
; /* current number of definition pairs deep */
230 int64_t cur_depth
; /* current number of expansions */
231 int64_t max_depth
; /* maximum number of expansions allowed */
233 int state
; /* condition state */
234 bool ignoring
; /* ignoring definition lines */
238 * Store the invocation of an expansion.
240 * The `prev' field is for the `istk->expansion` linked-list.
242 * When an expansion is being expanded, `params', `iline', `nparam',
243 * `paramlen', `rotate' and `unique' are local to the invocation.
246 ExpInv
*prev
; /* previous invocation */
247 ExpDef
*def
; /* pointer to expansion definition */
248 char *name
; /* invocation name */
249 Line
*label
; /* pointer to label */
250 char *label_text
; /* pointer to label text */
251 Line
*current
; /* pointer to current line in invocation */
253 Token
**params
; /* actual parameters */
254 Token
*iline
; /* invocation line */
260 int lineno
; /* current line number in expansion */
261 int linnum
; /* line number at invocation */
262 int relno
; /* relative line number at invocation */
263 enum pp_exp_type type
; /* expansion type */
268 * To handle an arbitrary level of file inclusion, we maintain a
269 * stack (ie linked list) of these things.
282 * Include search path. This is simply a list of strings which get
283 * prepended, in turn, to the name of an include file, in an
284 * attempt to find the file if it's not in the current directory.
292 * Conditional assembly: we maintain a separate stack of these for
293 * each level of file inclusion. (The only reason we keep the
294 * stacks separate is to ensure that a stray `%endif' in a file
295 * included from within the true branch of a `%if' won't terminate
296 * it and cause confusion: instead, rightly, it'll cause an error.)
300 * These states are for use just after %if or %elif: IF_TRUE
301 * means the condition has evaluated to truth so we are
302 * currently emitting, whereas IF_FALSE means we are not
303 * currently emitting but will start doing so if a %else comes
304 * up. In these states, all directives are admissible: %elif,
305 * %else and %endif. (And of course %if.)
307 COND_IF_TRUE
, COND_IF_FALSE
,
309 * These states come up after a %else: ELSE_TRUE means we're
310 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
311 * any %elif or %else will cause an error.
313 COND_ELSE_TRUE
, COND_ELSE_FALSE
,
315 * These states mean that we're not emitting now, and also that
316 * nothing until %endif will be emitted at all. COND_DONE is
317 * used when we've had our moment of emission
318 * and have now started seeing %elifs. COND_NEVER is used when
319 * the condition construct in question is contained within a
320 * non-emitting branch of a larger condition construct,
321 * or if there is an error.
323 COND_DONE
, COND_NEVER
325 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
328 * These defines are used as the possible return values for do_directive
330 #define NO_DIRECTIVE_FOUND 0
331 #define DIRECTIVE_FOUND 1
334 * This define sets the upper limit for smacro and expansions
336 #define DEADMAN_LIMIT (1 << 20)
339 #define REP_LIMIT ((INT64_C(1) << 62))
342 * Condition codes. Note that we use c_ prefix not C_ because C_ is
343 * used in nasm.h for the "real" condition codes. At _this_ level,
344 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
345 * ones, so we need a different enum...
347 static const char * const conditions
[] = {
348 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
349 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
350 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
353 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
354 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
355 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_RCXZ
, c_S
, c_Z
,
358 static const enum pp_conds inverse_ccs
[] = {
359 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
360 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
,
361 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, -1, c_NS
, c_NZ
364 /* For TASM compatibility we need to be able to recognise TASM compatible
365 * conditional compilation directives. Using the NASM pre-processor does
366 * not work, so we look for them specifically from the following list and
367 * then jam in the equivalent NASM directive into the input stream.
371 TM_ARG
, TM_ELIF
, TM_ELSE
, TM_ENDIF
, TM_IF
, TM_IFDEF
, TM_IFDIFI
,
372 TM_IFNDEF
, TM_INCLUDE
, TM_LOCAL
375 static const char * const tasm_directives
[] = {
376 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
377 "ifndef", "include", "local"
380 static int StackSize
= 4;
381 static char *StackPointer
= "ebp";
382 static int ArgOffset
= 8;
383 static int LocalOffset
= 0;
385 static Context
*cstk
;
386 static Include
*istk
;
387 static IncPath
*ipath
= NULL
;
389 static int pass
; /* HACK: pass 0 = generate dependencies only */
390 static StrList
**dephead
, **deptail
; /* Dependency list */
392 static uint64_t unique
; /* unique identifier numbers */
394 static Line
*predef
= NULL
;
395 static bool do_predef
;
397 static ListGen
*list
;
400 * The current set of expansion definitions we have defined.
402 static struct hash_table expdefs
;
405 * The current set of single-line macros we have defined.
407 static struct hash_table smacros
;
410 * Linked List of all active expansion definitions
412 struct ExpDef
*expansions
= NULL
;
415 * The expansion we are currently defining
417 static ExpDef
*defining
= NULL
;
419 static uint64_t nested_mac_count
;
420 static uint64_t nested_rep_count
;
423 * Linked-list of lines to preprocess, prior to cleanup
425 static Line
*finals
= NULL
;
426 static bool in_final
= false;
429 * The number of macro parameters to allocate space for at a time.
431 #define PARAM_DELTA 16
434 * The standard macro set: defined in macros.c in the array nasm_stdmac.
435 * This gives our position in the macro set, when we're processing it.
437 static macros_t
*stdmacpos
;
440 * The extra standard macros that come from the object format, if
443 static macros_t
*extrastdmac
= NULL
;
444 static bool any_extrastdmac
;
447 * Tokens are allocated in blocks to improve speed
449 #define TOKEN_BLOCKSIZE 4096
450 static Token
*freeTokens
= NULL
;
456 static Blocks blocks
= { NULL
, NULL
};
459 * Forward declarations.
461 static Token
*expand_mmac_params(Token
* tline
);
462 static Token
*expand_smacro(Token
* tline
);
463 static Token
*expand_id(Token
* tline
);
464 static Context
*get_ctx(const char *name
, const char **namep
);
465 static void make_tok_num(Token
* tok
, int64_t val
);
466 static void error(int severity
, const char *fmt
, ...);
467 static void error_precond(int severity
, const char *fmt
, ...);
468 static void *new_Block(size_t size
);
469 static void delete_Blocks(void);
470 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
471 const char *text
, int txtlen
);
472 static Token
*copy_Token(Token
* tline
);
473 static Token
*delete_Token(Token
* t
);
474 static Line
*new_Line(void);
475 static ExpDef
*new_ExpDef(int exp_type
);
476 static ExpInv
*new_ExpInv(int exp_type
, ExpDef
*ed
);
479 * Macros for safe checking of token pointers, avoid *(NULL)
481 #define tok_type_(x,t) ((x) && (x)->type == (t))
482 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
483 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
484 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
487 * A few helpers for single macros
490 /* We might be not smacro parameter at all */
491 static bool is_smacro_param(Token
*t
)
493 return t
->type
>= TOK_SMAC_PARAM
;
496 /* smacro parameters are counted in a special way */
497 static int smacro_get_param_idx(Token
*t
)
499 return t
->type
- TOK_SMAC_PARAM
;
502 /* encode smacro parameter index */
503 static int smacro_set_param_idx(Token
*t
, unsigned int index
)
505 return t
->type
= TOK_SMAC_PARAM
+ index
;
510 #define stringify(x) #x
512 #define nasm_trace(msg, ...) printf("(%s:%d): " msg "\n", __func__, __LINE__, ##__VA_ARGS__)
513 #define nasm_dump_token(t) nasm_raw_dump_token(t, __FILE__, __LINE__, __func__);
514 #define nasm_dump_stream(t) nasm_raw_dump_stream(t, __FILE__, __LINE__, __func__);
516 /* FIXME: we really need some compound type here instead of inplace code */
517 static const char *nasm_get_tok_type_str(enum pp_token_type type
)
519 #define SWITCH_TOK_NAME(type) \
521 return stringify(type)
524 SWITCH_TOK_NAME(TOK_NONE
);
525 SWITCH_TOK_NAME(TOK_WHITESPACE
);
526 SWITCH_TOK_NAME(TOK_COMMENT
);
527 SWITCH_TOK_NAME(TOK_ID
);
528 SWITCH_TOK_NAME(TOK_PREPROC_ID
);
529 SWITCH_TOK_NAME(TOK_STRING
);
530 SWITCH_TOK_NAME(TOK_NUMBER
);
531 SWITCH_TOK_NAME(TOK_FLOAT
);
532 SWITCH_TOK_NAME(TOK_SMAC_END
);
533 SWITCH_TOK_NAME(TOK_OTHER
);
534 SWITCH_TOK_NAME(TOK_INTERNAL_STRING
);
535 SWITCH_TOK_NAME(TOK_PREPROC_Q
);
536 SWITCH_TOK_NAME(TOK_PREPROC_QQ
);
537 SWITCH_TOK_NAME(TOK_PASTE
);
538 SWITCH_TOK_NAME(TOK_INDIRECT
);
539 SWITCH_TOK_NAME(TOK_SMAC_PARAM
);
540 SWITCH_TOK_NAME(TOK_MAX
);
546 static void nasm_raw_dump_token(Token
*token
, const char *file
, int line
, const char *func
)
548 printf("---[%s (%s:%d): %p]---\n", func
, file
, line
, (void *)token
);
551 list_for_each(t
, token
) {
553 printf("'%s'(%s) ", t
->text
,
554 nasm_get_tok_type_str(t
->type
));
560 static void nasm_raw_dump_stream(Token
*token
, const char *file
, int line
, const char *func
)
562 printf("---[%s (%s:%d): %p]---\n", func
, file
, line
, (void *)token
);
565 list_for_each(t
, token
)
566 printf("%s", t
->text
? t
->text
: " ");
572 #define nasm_trace(msg, ...)
573 #define nasm_dump_token(t)
574 #define nasm_dump_stream(t)
578 * nasm_unquote with error if the string contains NUL characters.
579 * If the string contains NUL characters, issue an error and return
580 * the C len, i.e. truncate at the NUL.
582 static size_t nasm_unquote_cstr(char *qstr
, enum preproc_token directive
)
584 size_t len
= nasm_unquote(qstr
, NULL
);
585 size_t clen
= strlen(qstr
);
588 error(ERR_NONFATAL
, "NUL character in `%s' directive",
589 pp_directives
[directive
]);
595 * In-place reverse a list of tokens.
597 static Token
*reverse_tokens(Token
*t
)
601 list_reverse(t
, prev
, next
);
607 * Handle TASM specific directives, which do not contain a % in
608 * front of them. We do it here because I could not find any other
609 * place to do it for the moment, and it is a hack (ideally it would
610 * be nice to be able to use the NASM pre-processor to do it).
612 static char *check_tasm_directive(char *line
)
614 int32_t i
, j
, k
, m
, len
;
615 char *p
, *q
, *oldline
, oldchar
;
617 p
= nasm_skip_spaces(line
);
619 /* Binary search for the directive name */
621 j
= ARRAY_SIZE(tasm_directives
);
622 q
= nasm_skip_word(p
);
629 m
= nasm_stricmp(p
, tasm_directives
[k
]);
631 /* We have found a directive, so jam a % in front of it
632 * so that NASM will then recognise it as one if it's own.
637 line
= nasm_malloc(len
+ 2);
639 if (k
== TM_IFDIFI
) {
641 * NASM does not recognise IFDIFI, so we convert
642 * it to %if 0. This is not used in NASM
643 * compatible code, but does need to parse for the
644 * TASM macro package.
646 strcpy(line
+ 1, "if 0");
648 memcpy(line
+ 1, p
, len
+ 1);
663 * The pre-preprocessing stage... This function translates line
664 * number indications as they emerge from GNU cpp (`# lineno "file"
665 * flags') into NASM preprocessor line number indications (`%line
668 static char *prepreproc(char *line
)
671 char *fname
, *oldline
;
673 if (line
[0] == '#' && line
[1] == ' ') {
676 lineno
= atoi(fname
);
677 fname
+= strspn(fname
, "0123456789 ");
680 fnlen
= strcspn(fname
, "\"");
681 line
= nasm_malloc(20 + fnlen
);
682 snprintf(line
, 20 + fnlen
, "%%line %d %.*s", lineno
, fnlen
, fname
);
685 if (tasm_compatible_mode
)
686 return check_tasm_directive(line
);
691 * Free a linked list of tokens.
693 static void free_tlist(Token
* list
)
696 list
= delete_Token(list
);
700 * Free a linked list of lines.
702 static void free_llist(Line
* list
)
705 list_for_each_safe(l
, tmp
, list
) {
706 free_tlist(l
->first
);
714 static void free_expdef(ExpDef
* ed
)
717 free_tlist(ed
->dlist
);
718 nasm_free(ed
->defaults
);
719 free_llist(ed
->line
);
726 static void free_expinv(ExpInv
* ei
)
729 nasm_free(ei
->label_text
);
734 * Free all currently defined macros, and free the hash tables
736 static void free_smacro_table(struct hash_table
*smt
)
740 struct hash_tbl_node
*it
= NULL
;
742 while ((s
= hash_iterate(smt
, &it
, &key
)) != NULL
) {
743 nasm_free((void *)key
);
744 list_for_each_safe(s
, tmp
, s
) {
746 free_tlist(s
->expansion
);
753 static void free_expdef_table(struct hash_table
*edt
)
757 struct hash_tbl_node
*it
= NULL
;
760 while ((ed
= hash_iterate(edt
, &it
, &key
)) != NULL
) {
761 nasm_free((void *)key
);
762 list_for_each_safe(ed
,tmp
, ed
)
768 static void free_macros(void)
770 free_smacro_table(&smacros
);
771 free_expdef_table(&expdefs
);
775 * Initialize the hash tables
777 static void init_macros(void)
779 hash_init(&smacros
, HASH_LARGE
);
780 hash_init(&expdefs
, HASH_LARGE
);
784 * Pop the context stack.
786 static void ctx_pop(void)
791 free_smacro_table(&c
->localmac
);
797 * Search for a key in the hash index; adding it if necessary
798 * (in which case we initialize the data pointer to NULL.)
801 hash_findi_add(struct hash_table
*hash
, const char *str
)
803 struct hash_insert hi
;
807 r
= hash_findi(hash
, str
, &hi
);
811 strx
= nasm_strdup(str
); /* Use a more efficient allocator here? */
812 return hash_add(&hi
, strx
, NULL
);
816 * Like hash_findi, but returns the data element rather than a pointer
817 * to it. Used only when not adding a new element, hence no third
821 hash_findix(struct hash_table
*hash
, const char *str
)
825 p
= hash_findi(hash
, str
, NULL
);
826 return p
? *p
: NULL
;
830 * read line from standard macros set,
831 * if there no more left -- return NULL
833 static char *line_from_stdmac(void)
836 const unsigned char *p
= stdmacpos
;
845 len
+= pp_directives_len
[c
- 0x80] + 1;
850 line
= nasm_malloc(len
+ 1);
852 while ((c
= *stdmacpos
++)) {
854 memcpy(q
, pp_directives
[c
- 0x80], pp_directives_len
[c
- 0x80]);
855 q
+= pp_directives_len
[c
- 0x80];
865 /* This was the last of the standard macro chain... */
867 if (any_extrastdmac
) {
868 stdmacpos
= extrastdmac
;
869 any_extrastdmac
= false;
870 } else if (do_predef
) {
873 Token
*head
, **tail
, *t
;
876 * Nasty hack: here we push the contents of
877 * `predef' on to the top-level expansion stack,
878 * since this is the most convenient way to
879 * implement the pre-include and pre-define
882 list_for_each(pd
, predef
) {
885 list_for_each(t
, pd
->first
) {
886 *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
887 tail
= &(*tail
)->next
;
892 ei
= new_ExpInv(EXP_PREDEF
, NULL
);
895 ei
->prev
= istk
->expansion
;
896 istk
->expansion
= ei
;
905 #define BUF_DELTA 512
907 * Read a line from the top file in istk, handling multiple CR/LFs
908 * at the end of the line read, and handling spurious ^Zs. Will
909 * return lines from the standard macro set if this has not already
912 static char *read_line(void)
914 char *buffer
, *p
, *q
;
915 int bufsize
, continued_count
;
918 * standart macros set (predefined) goes first
920 p
= line_from_stdmac();
925 * regular read from a file
928 buffer
= nasm_malloc(BUF_DELTA
);
932 q
= fgets(p
, bufsize
- (p
- buffer
), istk
->fp
);
936 if (p
> buffer
&& p
[-1] == '\n') {
938 * Convert backslash-CRLF line continuation sequences into
939 * nothing at all (for DOS and Windows)
941 if (((p
- 2) > buffer
) && (p
[-3] == '\\') && (p
[-2] == '\r')) {
947 * Also convert backslash-LF line continuation sequences into
948 * nothing at all (for Unix)
950 else if (((p
- 1) > buffer
) && (p
[-2] == '\\')) {
958 if (p
- buffer
> bufsize
- 10) {
959 int32_t offset
= p
- buffer
;
960 bufsize
+= BUF_DELTA
;
961 buffer
= nasm_realloc(buffer
, bufsize
);
962 p
= buffer
+ offset
; /* prevent stale-pointer problems */
966 if (!q
&& p
== buffer
) {
971 src_set_linnum(src_get_linnum() + istk
->lineinc
+
972 (continued_count
* istk
->lineinc
));
975 * Play safe: remove CRs as well as LFs, if any of either are
976 * present at the end of the line.
978 while (--p
>= buffer
&& (*p
== '\n' || *p
== '\r'))
982 * Handle spurious ^Z, which may be inserted into source files
983 * by some file transfer utilities.
985 buffer
[strcspn(buffer
, "\032")] = '\0';
987 list
->line(LIST_READ
, buffer
);
993 * Tokenize a line of text. This is a very simple process since we
994 * don't need to parse the value out of e.g. numeric tokens: we
995 * simply split one string into many.
997 static Token
*tokenize(char *line
)
1000 enum pp_token_type type
;
1002 Token
*t
, **tail
= &list
;
1003 bool verbose
= true;
1005 nasm_trace("Tokenize for '%s'", line
);
1007 if ((defining
!= NULL
) && (defining
->ignoring
== true)) {
1015 if (*p
== '+' && !nasm_isdigit(p
[1])) {
1018 } else if (nasm_isdigit(*p
) ||
1019 ((*p
== '-' || *p
== '+') && nasm_isdigit(p
[1]))) {
1023 while (nasm_isdigit(*p
));
1024 type
= TOK_PREPROC_ID
;
1025 } else if (*p
== '{') {
1027 while (*p
&& *p
!= '}') {
1034 type
= TOK_PREPROC_ID
;
1035 } else if (*p
== '[') {
1037 line
+= 2; /* Skip the leading %[ */
1039 while (lvl
&& (c
= *p
++)) {
1051 p
= nasm_skip_string(p
- 1) + 1;
1061 error(ERR_NONFATAL
, "unterminated %[ construct");
1062 type
= TOK_INDIRECT
;
1063 } else if (*p
== '?') {
1064 type
= TOK_PREPROC_Q
; /* %? */
1067 type
= TOK_PREPROC_QQ
; /* %?? */
1070 } else if (*p
== '!') {
1071 type
= TOK_PREPROC_ID
;
1076 } while (isidchar(*p
));
1077 } else if (*p
== '\'' || *p
== '\"' || *p
== '`') {
1078 p
= nasm_skip_string(p
);
1082 error(ERR_NONFATAL
|ERR_PASS1
, "unterminated %! string");
1084 /* %! without string or identifier */
1085 type
= TOK_OTHER
; /* Legacy behavior... */
1087 } else if (isidchar(*p
) ||
1088 ((*p
== '!' || *p
== '%' || *p
== '$') &&
1093 while (isidchar(*p
));
1094 type
= TOK_PREPROC_ID
;
1100 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
1103 while (*p
&& isidchar(*p
))
1105 } else if (*p
== '\'' || *p
== '"' || *p
== '`') {
1110 p
= nasm_skip_string(p
);
1114 } else if(verbose
) {
1115 error(ERR_WARNING
|ERR_PASS1
, "unterminated string");
1116 /* Handling unterminated strings by UNV */
1119 } else if (p
[0] == '$' && p
[1] == '$') {
1120 type
= TOK_OTHER
; /* TOKEN_BASE */
1122 } else if (isnumstart(*p
)) {
1123 bool is_hex
= false;
1124 bool is_float
= false;
1140 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
1142 if (*p
== '+' || *p
== '-') {
1144 * e can only be followed by +/- if it is either a
1145 * prefixed hex number or a floating-point number
1150 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
1152 } else if (c
== 'P' || c
== 'p') {
1154 if (*p
== '+' || *p
== '-')
1156 } else if (isnumchar(c
) || c
== '_')
1157 ; /* just advance */
1158 else if (c
== '.') {
1160 * we need to deal with consequences of the legacy
1161 * parser, like "1.nolist" being two tokens
1162 * (TOK_NUMBER, TOK_ID) here; at least give it
1163 * a shot for now. In the future, we probably need
1164 * a flex-based scanner with proper pattern matching
1165 * to do it as well as it can be done. Nothing in
1166 * the world is going to help the person who wants
1167 * 0x123.p16 interpreted as two tokens, though.
1173 if (nasm_isdigit(*r
) || (is_hex
&& nasm_isxdigit(*r
)) ||
1174 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
1175 (*r
== 'p' || *r
== 'P')) {
1179 break; /* Terminate the token */
1183 p
--; /* Point to first character beyond number */
1185 if (p
== line
+1 && *line
== '$') {
1186 type
= TOK_OTHER
; /* TOKEN_HERE */
1188 if (has_e
&& !is_hex
) {
1189 /* 1e13 is floating-point, but 1e13h is not */
1193 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
1195 } else if (nasm_isspace(*p
)) {
1196 type
= TOK_WHITESPACE
;
1197 p
= nasm_skip_spaces(p
);
1199 * Whitespace just before end-of-line is discarded by
1200 * pretending it's a comment; whitespace just before a
1201 * comment gets lumped into the comment.
1203 if (!*p
|| *p
== ';') {
1208 } else if (*p
== ';') {
1214 * Anything else is an operator of some kind. We check
1215 * for all the double-character operators (>>, <<, //,
1216 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1217 * else is a single-character operator.
1220 if ((p
[0] == '>' && p
[1] == '>') ||
1221 (p
[0] == '<' && p
[1] == '<') ||
1222 (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] == '^')) {
1236 /* Handling unterminated string by UNV */
1239 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1240 t->text[p-line] = *line;
1244 if (type
!= TOK_COMMENT
) {
1245 *tail
= t
= new_Token(NULL
, type
, line
, p
- line
);
1251 nasm_dump_token(list
);
1257 * this function allocates a new managed block of memory and
1258 * returns a pointer to the block. The managed blocks are
1259 * deleted only all at once by the delete_Blocks function.
1261 static void *new_Block(size_t size
)
1263 Blocks
*b
= &blocks
;
1265 /* first, get to the end of the linked list */
1269 /* now allocate the requested chunk */
1270 b
->chunk
= nasm_malloc(size
);
1272 /* now allocate a new block for the next request */
1273 b
->next
= nasm_zalloc(sizeof(Blocks
));
1279 * this function deletes all managed blocks of memory
1281 static void delete_Blocks(void)
1283 Blocks
*a
, *b
= &blocks
;
1286 * keep in mind that the first block, pointed to by blocks
1287 * is a static and not dynamically allocated, so we don't
1291 nasm_free(b
->chunk
);
1300 * this function creates a new Token and passes a pointer to it
1301 * back to the caller. It sets the type and text elements, and
1302 * also the a.mac and next elements to NULL.
1304 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
1305 const char *text
, int txtlen
)
1311 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1312 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1313 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1314 freeTokens
[i
].next
= NULL
;
1317 freeTokens
= t
->next
;
1321 if (type
== TOK_WHITESPACE
|| !text
) {
1325 txtlen
= strlen(text
);
1326 t
->text
= nasm_malloc(txtlen
+1);
1327 memcpy(t
->text
, text
, txtlen
);
1328 t
->text
[txtlen
] = '\0';
1333 static Token
*copy_Token(Token
* tline
)
1335 Token
*t
, *tt
, *first
= NULL
, *prev
= NULL
;
1337 for (tt
= tline
; tt
!= NULL
; tt
= tt
->next
) {
1339 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1340 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1341 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1342 freeTokens
[i
].next
= NULL
;
1345 freeTokens
= t
->next
;
1347 t
->text
= tt
->text
? nasm_strdup(tt
->text
) : NULL
;
1348 t
->a
.mac
= tt
->a
.mac
;
1349 t
->a
.len
= tt
->a
.len
;
1361 static Token
*delete_Token(Token
* t
)
1363 Token
*next
= t
->next
;
1365 t
->next
= freeTokens
;
1371 * Convert a line of tokens back into text.
1372 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1373 * will be transformed into ..@ctxnum.xxx
1375 static char *detoken(Token
* tlist
, bool expand_locals
)
1382 list_for_each(t
, tlist
) {
1383 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
1388 if (*v
== '\'' || *v
== '\"' || *v
== '`') {
1389 size_t len
= nasm_unquote(v
, NULL
);
1390 size_t clen
= strlen(v
);
1393 error(ERR_NONFATAL
| ERR_PASS1
,
1394 "NUL character in %! string");
1400 char *p
= getenv(v
);
1402 error(ERR_NONFATAL
| ERR_PASS1
,
1403 "nonexistent environment variable `%s'", v
);
1406 t
->text
= nasm_strdup(p
);
1411 /* Expand local macros here and not during preprocessing */
1412 if (expand_locals
&&
1413 t
->type
== TOK_PREPROC_ID
&& t
->text
&&
1414 t
->text
[0] == '%' && t
->text
[1] == '$') {
1417 Context
*ctx
= get_ctx(t
->text
, &q
);
1420 snprintf(buffer
, sizeof(buffer
), "..@%"PRIu32
".", ctx
->number
);
1421 p
= nasm_strcat(buffer
, q
);
1427 /* Expand %? and %?? directives */
1428 if ((istk
->expansion
!= NULL
) &&
1429 ((t
->type
== TOK_PREPROC_Q
) ||
1430 (t
->type
== TOK_PREPROC_QQ
))) {
1432 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
){
1433 if (ei
->type
== EXP_MMACRO
) {
1435 if (t
->type
== TOK_PREPROC_Q
) {
1436 t
->text
= nasm_strdup(ei
->name
);
1438 t
->text
= nasm_strdup(ei
->def
->name
);
1445 if (t
->type
== TOK_WHITESPACE
)
1448 len
+= strlen(t
->text
);
1451 p
= line
= nasm_malloc(len
+ 1);
1453 list_for_each(t
, tlist
) {
1454 if (t
->type
== TOK_WHITESPACE
) {
1456 } else if (t
->text
) {
1468 * Initialize a new Line
1470 static inline Line
*new_Line(void)
1472 return (Line
*)nasm_zalloc(sizeof(Line
));
1477 * Initialize a new Expansion Definition
1479 static ExpDef
*new_ExpDef(int exp_type
)
1481 ExpDef
*ed
= (ExpDef
*)nasm_zalloc(sizeof(ExpDef
));
1482 ed
->type
= exp_type
;
1483 ed
->casesense
= true;
1484 ed
->state
= COND_NEVER
;
1491 * Initialize a new Expansion Instance
1493 static ExpInv
*new_ExpInv(int exp_type
, ExpDef
*ed
)
1495 ExpInv
*ei
= (ExpInv
*)nasm_zalloc(sizeof(ExpInv
));
1496 ei
->type
= exp_type
;
1498 ei
->unique
= ++unique
;
1500 if ((istk
->mmac_depth
< 1) &&
1501 (istk
->expansion
== NULL
) &&
1503 (ed
->type
!= EXP_MMACRO
) &&
1504 (ed
->type
!= EXP_REP
) &&
1505 (ed
->type
!= EXP_WHILE
)) {
1506 ei
->linnum
= src_get_linnum();
1507 src_set_linnum(ei
->linnum
- ed
->linecount
- 1);
1511 if ((istk
->expansion
== NULL
) ||
1512 (ei
->type
== EXP_MMACRO
)) {
1515 ei
->relno
= istk
->expansion
->lineno
;
1517 ei
->relno
-= (ed
->linecount
+ 1);
1524 * A scanner, suitable for use by the expression evaluator, which
1525 * operates on a line of Tokens. Expects a pointer to a pointer to
1526 * the first token in the line to be passed in as its private_data
1529 * FIX: This really needs to be unified with stdscan.
1531 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1533 Token
**tlineptr
= private_data
;
1535 char ourcopy
[MAX_KEYWORD
+1], *p
, *r
, *s
;
1539 *tlineptr
= tline
? tline
->next
: NULL
;
1540 } while (tline
&& (tline
->type
== TOK_WHITESPACE
||
1541 tline
->type
== TOK_COMMENT
));
1544 return tokval
->t_type
= TOKEN_EOS
;
1546 tokval
->t_charptr
= tline
->text
;
1548 if (tline
->text
[0] == '$' && !tline
->text
[1])
1549 return tokval
->t_type
= TOKEN_HERE
;
1550 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[2])
1551 return tokval
->t_type
= TOKEN_BASE
;
1553 if (tline
->type
== TOK_ID
) {
1554 p
= tokval
->t_charptr
= tline
->text
;
1556 tokval
->t_charptr
++;
1557 return tokval
->t_type
= TOKEN_ID
;
1560 for (r
= p
, s
= ourcopy
; *r
; r
++) {
1561 if (r
>= p
+MAX_KEYWORD
)
1562 return tokval
->t_type
= TOKEN_ID
; /* Not a keyword */
1563 *s
++ = nasm_tolower(*r
);
1566 /* right, so we have an identifier sitting in temp storage. now,
1567 * is it actually a register or instruction name, or what? */
1568 return nasm_token_hash(ourcopy
, tokval
);
1571 if (tline
->type
== TOK_NUMBER
) {
1573 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
1574 tokval
->t_charptr
= tline
->text
;
1576 return tokval
->t_type
= TOKEN_ERRNUM
;
1578 return tokval
->t_type
= TOKEN_NUM
;
1581 if (tline
->type
== TOK_FLOAT
) {
1582 return tokval
->t_type
= TOKEN_FLOAT
;
1585 if (tline
->type
== TOK_STRING
) {
1588 bq
= tline
->text
[0];
1589 tokval
->t_charptr
= tline
->text
;
1590 tokval
->t_inttwo
= nasm_unquote(tline
->text
, &ep
);
1592 if (ep
[0] != bq
|| ep
[1] != '\0')
1593 return tokval
->t_type
= TOKEN_ERRSTR
;
1595 return tokval
->t_type
= TOKEN_STR
;
1598 if (tline
->type
== TOK_OTHER
) {
1599 if (!strcmp(tline
->text
, "<<"))
1600 return tokval
->t_type
= TOKEN_SHL
;
1601 if (!strcmp(tline
->text
, ">>"))
1602 return tokval
->t_type
= TOKEN_SHR
;
1603 if (!strcmp(tline
->text
, "//"))
1604 return tokval
->t_type
= TOKEN_SDIV
;
1605 if (!strcmp(tline
->text
, "%%"))
1606 return tokval
->t_type
= TOKEN_SMOD
;
1607 if (!strcmp(tline
->text
, "=="))
1608 return tokval
->t_type
= TOKEN_EQ
;
1609 if (!strcmp(tline
->text
, "<>"))
1610 return tokval
->t_type
= TOKEN_NE
;
1611 if (!strcmp(tline
->text
, "!="))
1612 return tokval
->t_type
= TOKEN_NE
;
1613 if (!strcmp(tline
->text
, "<="))
1614 return tokval
->t_type
= TOKEN_LE
;
1615 if (!strcmp(tline
->text
, ">="))
1616 return tokval
->t_type
= TOKEN_GE
;
1617 if (!strcmp(tline
->text
, "&&"))
1618 return tokval
->t_type
= TOKEN_DBL_AND
;
1619 if (!strcmp(tline
->text
, "^^"))
1620 return tokval
->t_type
= TOKEN_DBL_XOR
;
1621 if (!strcmp(tline
->text
, "||"))
1622 return tokval
->t_type
= TOKEN_DBL_OR
;
1626 * We have no other options: just return the first character of
1629 return tokval
->t_type
= tline
->text
[0];
1633 * Compare a string to the name of an existing macro; this is a
1634 * simple wrapper which calls either strcmp or nasm_stricmp
1635 * depending on the value of the `casesense' parameter.
1637 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
1639 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
1643 * Compare a string to the name of an existing macro; this is a
1644 * simple wrapper which calls either strcmp or nasm_stricmp
1645 * depending on the value of the `casesense' parameter.
1647 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
1649 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
1653 * Return the Context structure associated with a %$ token. Return
1654 * NULL, having _already_ reported an error condition, if the
1655 * context stack isn't deep enough for the supplied number of $
1658 * If "namep" is non-NULL, set it to the pointer to the macro name
1659 * tail, i.e. the part beyond %$...
1661 static Context
*get_ctx(const char *name
, const char **namep
)
1669 if (!name
|| name
[0] != '%' || name
[1] != '$')
1673 error(ERR_NONFATAL
, "`%s': context stack is empty", name
);
1680 while (ctx
&& *name
== '$') {
1687 error(ERR_NONFATAL
, "`%s': context stack is only"
1688 " %d level%s deep", name
, i
, (i
== 1 ? "" : "s"));
1699 * Check to see if a file is already in a string list
1701 static bool in_list(const StrList
*list
, const char *str
)
1704 if (!strcmp(list
->str
, str
))
1712 * Open an include file. This routine must always return a valid
1713 * file pointer if it returns - it's responsible for throwing an
1714 * ERR_FATAL and bombing out completely if not. It should also try
1715 * the include path one by one until it finds the file or reaches
1716 * the end of the path.
1718 static FILE *inc_fopen(const char *file
, StrList
**dhead
, StrList
***dtail
,
1723 IncPath
*ip
= ipath
;
1724 int len
= strlen(file
);
1725 size_t prefix_len
= 0;
1729 sl
= nasm_malloc(prefix_len
+len
+1+sizeof sl
->next
);
1731 memcpy(sl
->str
, prefix
, prefix_len
);
1732 memcpy(sl
->str
+prefix_len
, file
, len
+1);
1733 fp
= fopen(sl
->str
, "r");
1734 if (fp
&& dhead
&& !in_list(*dhead
, sl
->str
)) {
1751 prefix_len
= strlen(prefix
);
1753 /* -MG given and file not found */
1754 if (dhead
&& !in_list(*dhead
, file
)) {
1755 sl
= nasm_malloc(len
+1+sizeof sl
->next
);
1757 strcpy(sl
->str
, file
);
1765 error(ERR_FATAL
, "unable to open include file `%s'", file
);
1770 * Determine if we should warn on defining a single-line macro of
1771 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1772 * return true if _any_ single-line macro of that name is defined.
1773 * Otherwise, will return true if a single-line macro with either
1774 * `nparam' or no parameters is defined.
1776 * If a macro with precisely the right number of parameters is
1777 * defined, or nparam is -1, the address of the definition structure
1778 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1779 * is NULL, no action will be taken regarding its contents, and no
1782 * Note that this is also called with nparam zero to resolve
1785 * If you already know which context macro belongs to, you can pass
1786 * the context pointer as first parameter; if you won't but name begins
1787 * with %$ the context will be automatically computed. If all_contexts
1788 * is true, macro will be searched in outer contexts as well.
1791 smacro_defined(Context
* ctx
, const char *name
, int nparam
, SMacro
** defn
,
1794 struct hash_table
*smtbl
;
1798 smtbl
= &ctx
->localmac
;
1799 } else if (name
[0] == '%' && name
[1] == '$') {
1801 ctx
= get_ctx(name
, &name
);
1803 return false; /* got to return _something_ */
1804 smtbl
= &ctx
->localmac
;
1808 m
= (SMacro
*) hash_findix(smtbl
, name
);
1811 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
1812 (nparam
<= 0 || m
->nparam
== 0 || nparam
== (int) m
->nparam
)) {
1814 if (nparam
== (int) m
->nparam
|| nparam
== -1)
1828 * Count and mark off the parameters in a multi-line macro call.
1829 * This is called both from within the multi-line macro expansion
1830 * code, and also to mark off the default parameters when provided
1831 * in a %macro definition line.
1833 static void count_mmac_params(Token
* t
, int *nparam
, Token
*** params
)
1835 int paramsize
, brace
;
1837 *nparam
= paramsize
= 0;
1840 /* +1: we need space for the final NULL */
1841 if (*nparam
+1 >= paramsize
) {
1842 paramsize
+= PARAM_DELTA
;
1843 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
1847 if (tok_is_(t
, "{"))
1849 (*params
)[(*nparam
)++] = t
;
1850 while (tok_isnt_(t
, brace
? "}" : ","))
1852 if (t
) { /* got a comma/brace */
1856 * Now we've found the closing brace, look further
1860 if (tok_isnt_(t
, ",")) {
1862 "braces do not enclose all of macro parameter");
1863 while (tok_isnt_(t
, ","))
1867 t
= t
->next
; /* eat the comma */
1874 * Determine whether one of the various `if' conditions is true or
1877 * We must free the tline we get passed.
1879 static bool if_condition(Token
* tline
, enum preproc_token ct
)
1881 enum pp_conditional i
= PP_COND(ct
);
1883 Token
*t
, *tt
, **tptr
, *origline
;
1884 struct tokenval tokval
;
1886 enum pp_token_type needtype
;
1893 j
= false; /* have we matched yet? */
1898 if (tline
->type
!= TOK_ID
) {
1900 "`%s' expects context identifiers", pp_directives
[ct
]);
1901 free_tlist(origline
);
1904 if (cstk
&& cstk
->name
&& !nasm_stricmp(tline
->text
, cstk
->name
))
1906 tline
= tline
->next
;
1911 j
= false; /* have we matched yet? */
1914 if (!tline
|| (tline
->type
!= TOK_ID
&&
1915 (tline
->type
!= TOK_PREPROC_ID
||
1916 tline
->text
[1] != '$'))) {
1918 "`%s' expects macro identifiers", pp_directives
[ct
]);
1921 if (smacro_defined(NULL
, tline
->text
, 0, NULL
, true))
1923 tline
= tline
->next
;
1928 tline
= expand_smacro(tline
);
1929 j
= false; /* have we matched yet? */
1932 if (!tline
|| (tline
->type
!= TOK_ID
&&
1933 tline
->type
!= TOK_STRING
&&
1934 (tline
->type
!= TOK_PREPROC_ID
||
1935 tline
->text
[1] != '!'))) {
1937 "`%s' expects environment variable names",
1942 if (tline
->type
== TOK_PREPROC_ID
)
1943 p
+= 2; /* Skip leading %! */
1944 if (*p
== '\'' || *p
== '\"' || *p
== '`')
1945 nasm_unquote_cstr(p
, ct
);
1948 tline
= tline
->next
;
1954 tline
= expand_smacro(tline
);
1956 while (tok_isnt_(tt
, ","))
1960 "`%s' expects two comma-separated arguments",
1965 j
= true; /* assume equality unless proved not */
1966 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1967 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1968 error(ERR_NONFATAL
, "`%s': more than one comma on line",
1972 if (t
->type
== TOK_WHITESPACE
) {
1976 if (tt
->type
== TOK_WHITESPACE
) {
1980 if (tt
->type
!= t
->type
) {
1981 j
= false; /* found mismatching tokens */
1984 /* When comparing strings, need to unquote them first */
1985 if (t
->type
== TOK_STRING
) {
1986 size_t l1
= nasm_unquote(t
->text
, NULL
);
1987 size_t l2
= nasm_unquote(tt
->text
, NULL
);
1993 if (mmemcmp(t
->text
, tt
->text
, l1
, i
== PPC_IFIDN
)) {
1997 } else if (mstrcmp(tt
->text
, t
->text
, i
== PPC_IFIDN
) != 0) {
1998 j
= false; /* found mismatching tokens */
2005 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
2006 j
= false; /* trailing gunk on one end or other */
2012 ExpDef searching
, *ed
;
2015 tline
= expand_id(tline
);
2016 if (!tok_type_(tline
, TOK_ID
)) {
2018 "`%s' expects a macro name", pp_directives
[ct
]);
2021 memset(&searching
, 0, sizeof(searching
));
2022 searching
.name
= nasm_strdup(tline
->text
);
2023 searching
.casesense
= true;
2024 searching
.nparam_max
= INT_MAX
;
2025 tline
= expand_smacro(tline
->next
);
2028 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2030 "`%s' expects a parameter count or nothing",
2033 searching
.nparam_min
= searching
.nparam_max
=
2034 readnum(tline
->text
, &j
);
2037 "unable to parse parameter count `%s'",
2040 if (tline
&& tok_is_(tline
->next
, "-")) {
2041 tline
= tline
->next
->next
;
2042 if (tok_is_(tline
, "*"))
2043 searching
.nparam_max
= INT_MAX
;
2044 else if (!tok_type_(tline
, TOK_NUMBER
))
2046 "`%s' expects a parameter count after `-'",
2049 searching
.nparam_max
= readnum(tline
->text
, &j
);
2052 "unable to parse parameter count `%s'",
2054 if (searching
.nparam_min
> searching
.nparam_max
)
2056 "minimum parameter count exceeds maximum");
2059 if (tline
&& tok_is_(tline
->next
, "+")) {
2060 tline
= tline
->next
;
2061 searching
.plus
= true;
2063 ed
= (ExpDef
*) hash_findix(&expdefs
, searching
.name
);
2064 while (ed
!= NULL
) {
2065 if (!strcmp(ed
->name
, searching
.name
) &&
2066 (ed
->nparam_min
<= searching
.nparam_max
|| searching
.plus
) &&
2067 (searching
.nparam_min
<= ed
->nparam_max
|| ed
->plus
)) {
2073 if (tline
&& tline
->next
)
2074 error(ERR_WARNING
|ERR_PASS1
,
2075 "trailing garbage after %%ifmacro ignored");
2076 nasm_free(searching
.name
);
2085 needtype
= TOK_NUMBER
;
2088 needtype
= TOK_STRING
;
2092 t
= tline
= expand_smacro(tline
);
2094 while (tok_type_(t
, TOK_WHITESPACE
) ||
2095 (needtype
== TOK_NUMBER
&&
2096 tok_type_(t
, TOK_OTHER
) &&
2097 (t
->text
[0] == '-' || t
->text
[0] == '+') &&
2101 j
= tok_type_(t
, needtype
);
2105 t
= tline
= expand_smacro(tline
);
2106 while (tok_type_(t
, TOK_WHITESPACE
))
2111 t
= t
->next
; /* Skip the actual token */
2112 while (tok_type_(t
, TOK_WHITESPACE
))
2114 j
= !t
; /* Should be nothing left */
2119 t
= tline
= expand_smacro(tline
);
2120 while (tok_type_(t
, TOK_WHITESPACE
))
2123 j
= !t
; /* Should be empty */
2127 t
= tline
= expand_smacro(tline
);
2129 tokval
.t_type
= TOKEN_INVALID
;
2130 evalresult
= evaluate(ppscan
, tptr
, &tokval
,
2131 NULL
, pass
| CRITICAL
, error
, NULL
);
2135 error(ERR_WARNING
|ERR_PASS1
,
2136 "trailing garbage after expression ignored");
2137 if (!is_simple(evalresult
)) {
2139 "non-constant value given to `%s'", pp_directives
[ct
]);
2142 j
= reloc_value(evalresult
) != 0;
2147 "preprocessor directive `%s' not yet implemented",
2152 free_tlist(origline
);
2153 return j
^ PP_NEGATIVE(ct
);
2156 free_tlist(origline
);
2161 * Common code for defining an smacro
2163 static bool define_smacro(Context
*ctx
, const char *mname
, bool casesense
,
2164 int nparam
, Token
*expansion
)
2166 SMacro
*smac
, **smhead
;
2167 struct hash_table
*smtbl
;
2169 if (smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
)) {
2171 error(ERR_WARNING
|ERR_PASS1
,
2172 "single-line macro `%s' defined both with and"
2173 " without parameters", mname
);
2175 * Some instances of the old code considered this a failure,
2176 * some others didn't. What is the right thing to do here?
2178 free_tlist(expansion
);
2179 return false; /* Failure */
2182 * We're redefining, so we have to take over an
2183 * existing SMacro structure. This means freeing
2184 * what was already in it.
2186 nasm_free(smac
->name
);
2187 free_tlist(smac
->expansion
);
2190 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2191 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
2192 smac
= nasm_zalloc(sizeof(SMacro
));
2193 smac
->next
= *smhead
;
2196 smac
->name
= nasm_strdup(mname
);
2197 smac
->casesense
= casesense
;
2198 smac
->nparam
= nparam
;
2199 smac
->expansion
= expansion
;
2200 smac
->in_progress
= false;
2201 return true; /* Success */
2205 * Undefine an smacro
2207 static void undef_smacro(Context
*ctx
, const char *mname
)
2209 SMacro
**smhead
, *s
, **sp
;
2210 struct hash_table
*smtbl
;
2212 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2213 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
2217 * We now have a macro name... go hunt for it.
2220 while ((s
= *sp
) != NULL
) {
2221 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
2224 free_tlist(s
->expansion
);
2234 * Parse a mmacro specification.
2236 static bool parse_mmacro_spec(Token
*tline
, ExpDef
*def
, const char *directive
)
2240 tline
= tline
->next
;
2242 tline
= expand_id(tline
);
2243 if (!tok_type_(tline
, TOK_ID
)) {
2244 error(ERR_NONFATAL
, "`%s' expects a macro name", directive
);
2248 def
->name
= nasm_strdup(tline
->text
);
2250 def
->nolist
= false;
2251 // def->in_progress = 0;
2252 // def->rep_nest = NULL;
2253 def
->nparam_min
= 0;
2254 def
->nparam_max
= 0;
2256 tline
= expand_smacro(tline
->next
);
2258 if (!tok_type_(tline
, TOK_NUMBER
)) {
2259 error(ERR_NONFATAL
, "`%s' expects a parameter count", directive
);
2261 def
->nparam_min
= def
->nparam_max
=
2262 readnum(tline
->text
, &err
);
2265 "unable to parse parameter count `%s'", tline
->text
);
2267 if (tline
&& tok_is_(tline
->next
, "-")) {
2268 tline
= tline
->next
->next
;
2269 if (tok_is_(tline
, "*")) {
2270 def
->nparam_max
= INT_MAX
;
2271 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2273 "`%s' expects a parameter count after `-'", directive
);
2275 def
->nparam_max
= readnum(tline
->text
, &err
);
2277 error(ERR_NONFATAL
, "unable to parse parameter count `%s'",
2280 if (def
->nparam_min
> def
->nparam_max
) {
2281 error(ERR_NONFATAL
, "minimum parameter count exceeds maximum");
2285 if (tline
&& tok_is_(tline
->next
, "+")) {
2286 tline
= tline
->next
;
2289 if (tline
&& tok_type_(tline
->next
, TOK_ID
) &&
2290 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
2291 tline
= tline
->next
;
2296 * Handle default parameters.
2298 if (tline
&& tline
->next
) {
2299 def
->dlist
= tline
->next
;
2301 count_mmac_params(def
->dlist
, &def
->ndefs
, &def
->defaults
);
2304 def
->defaults
= NULL
;
2308 if (def
->defaults
&& def
->ndefs
> def
->nparam_max
- def
->nparam_min
&&
2310 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MDP
,
2311 "too many default macro parameters");
2318 * Decode a size directive
2320 static int parse_size(const char *str
) {
2321 static const char *size_names
[] =
2322 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2323 static const int sizes
[] =
2324 { 0, 1, 4, 16, 8, 10, 2, 32 };
2326 return sizes
[bsii(str
, size_names
, ARRAY_SIZE(size_names
))+1];
2330 * find and process preprocessor directive in passed line
2331 * Find out if a line contains a preprocessor directive, and deal
2334 * If a directive _is_ found, it is the responsibility of this routine
2335 * (and not the caller) to free_tlist() the line.
2337 * @param tline a pointer to the current tokeninzed line linked list
2338 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2341 static int do_directive(Token
* tline
)
2343 enum preproc_token i
;
2356 Token
*t
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
2357 struct tokenval tokval
;
2359 ExpDef
*ed
, *eed
, **edhead
;
2368 if (!tline
|| !tok_type_(tline
, TOK_PREPROC_ID
) ||
2369 (tline
->text
[1] == '%' || tline
->text
[1] == '$'
2370 || tline
->text
[1] == '!'))
2371 return NO_DIRECTIVE_FOUND
;
2373 i
= pp_token_hash(tline
->text
);
2377 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2378 error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2380 return NO_DIRECTIVE_FOUND
; /* didn't get it */
2383 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2384 /* Directive to tell NASM what the default stack size is. The
2385 * default is for a 16-bit stack, and this can be overriden with
2388 tline
= tline
->next
;
2389 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2390 tline
= tline
->next
;
2391 if (!tline
|| tline
->type
!= TOK_ID
) {
2392 error(ERR_NONFATAL
, "`%%stacksize' missing size parameter");
2393 free_tlist(origline
);
2394 return DIRECTIVE_FOUND
;
2396 if (nasm_stricmp(tline
->text
, "flat") == 0) {
2397 /* All subsequent ARG directives are for a 32-bit stack */
2399 StackPointer
= "ebp";
2402 } else if (nasm_stricmp(tline
->text
, "flat64") == 0) {
2403 /* All subsequent ARG directives are for a 64-bit stack */
2405 StackPointer
= "rbp";
2408 } else if (nasm_stricmp(tline
->text
, "large") == 0) {
2409 /* All subsequent ARG directives are for a 16-bit stack,
2410 * far function call.
2413 StackPointer
= "bp";
2416 } else if (nasm_stricmp(tline
->text
, "small") == 0) {
2417 /* All subsequent ARG directives are for a 16-bit stack,
2418 * far function call. We don't support near functions.
2421 StackPointer
= "bp";
2425 error(ERR_NONFATAL
, "`%%stacksize' invalid size type");
2426 free_tlist(origline
);
2427 return DIRECTIVE_FOUND
;
2429 free_tlist(origline
);
2430 return DIRECTIVE_FOUND
;
2433 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2434 /* TASM like ARG directive to define arguments to functions, in
2435 * the following form:
2437 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2441 char *arg
, directive
[256];
2442 int size
= StackSize
;
2444 /* Find the argument name */
2445 tline
= tline
->next
;
2446 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2447 tline
= tline
->next
;
2448 if (!tline
|| tline
->type
!= TOK_ID
) {
2449 error(ERR_NONFATAL
, "`%%arg' missing argument parameter");
2450 free_tlist(origline
);
2451 return DIRECTIVE_FOUND
;
2455 /* Find the argument size type */
2456 tline
= tline
->next
;
2457 if (!tline
|| tline
->type
!= TOK_OTHER
2458 || tline
->text
[0] != ':') {
2460 "Syntax error processing `%%arg' directive");
2461 free_tlist(origline
);
2462 return DIRECTIVE_FOUND
;
2464 tline
= tline
->next
;
2465 if (!tline
|| tline
->type
!= TOK_ID
) {
2466 error(ERR_NONFATAL
, "`%%arg' missing size type parameter");
2467 free_tlist(origline
);
2468 return DIRECTIVE_FOUND
;
2471 /* Allow macro expansion of type parameter */
2472 tt
= tokenize(tline
->text
);
2473 tt
= expand_smacro(tt
);
2474 size
= parse_size(tt
->text
);
2477 "Invalid size type for `%%arg' missing directive");
2479 free_tlist(origline
);
2480 return DIRECTIVE_FOUND
;
2484 /* Round up to even stack slots */
2485 size
= ALIGN(size
, StackSize
);
2487 /* Now define the macro for the argument */
2488 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
2489 arg
, StackPointer
, offset
);
2490 do_directive(tokenize(directive
));
2493 /* Move to the next argument in the list */
2494 tline
= tline
->next
;
2495 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2496 tline
= tline
->next
;
2497 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2499 free_tlist(origline
);
2500 return DIRECTIVE_FOUND
;
2503 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2504 /* TASM like LOCAL directive to define local variables for a
2505 * function, in the following form:
2507 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2509 * The '= LocalSize' at the end is ignored by NASM, but is
2510 * required by TASM to define the local parameter size (and used
2511 * by the TASM macro package).
2513 offset
= LocalOffset
;
2515 char *local
, directive
[256];
2516 int size
= StackSize
;
2518 /* Find the argument name */
2519 tline
= tline
->next
;
2520 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2521 tline
= tline
->next
;
2522 if (!tline
|| tline
->type
!= TOK_ID
) {
2524 "`%%local' missing argument parameter");
2525 free_tlist(origline
);
2526 return DIRECTIVE_FOUND
;
2528 local
= tline
->text
;
2530 /* Find the argument size type */
2531 tline
= tline
->next
;
2532 if (!tline
|| tline
->type
!= TOK_OTHER
2533 || tline
->text
[0] != ':') {
2535 "Syntax error processing `%%local' directive");
2536 free_tlist(origline
);
2537 return DIRECTIVE_FOUND
;
2539 tline
= tline
->next
;
2540 if (!tline
|| tline
->type
!= TOK_ID
) {
2542 "`%%local' missing size type parameter");
2543 free_tlist(origline
);
2544 return DIRECTIVE_FOUND
;
2547 /* Allow macro expansion of type parameter */
2548 tt
= tokenize(tline
->text
);
2549 tt
= expand_smacro(tt
);
2550 size
= parse_size(tt
->text
);
2553 "Invalid size type for `%%local' missing directive");
2555 free_tlist(origline
);
2556 return DIRECTIVE_FOUND
;
2560 /* Round up to even stack slots */
2561 size
= ALIGN(size
, StackSize
);
2563 offset
+= size
; /* Negative offset, increment before */
2565 /* Now define the macro for the argument */
2566 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
2567 local
, StackPointer
, offset
);
2568 do_directive(tokenize(directive
));
2570 /* Now define the assign to setup the enter_c macro correctly */
2571 snprintf(directive
, sizeof(directive
),
2572 "%%assign %%$localsize %%$localsize+%d", size
);
2573 do_directive(tokenize(directive
));
2575 /* Move to the next argument in the list */
2576 tline
= tline
->next
;
2577 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2578 tline
= tline
->next
;
2579 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2580 LocalOffset
= offset
;
2581 free_tlist(origline
);
2582 return DIRECTIVE_FOUND
;
2585 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2587 error(ERR_WARNING
|ERR_PASS1
,
2588 "trailing garbage after `%%clear' ignored");
2591 free_tlist(origline
);
2592 return DIRECTIVE_FOUND
;
2595 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2596 t
= tline
->next
= expand_smacro(tline
->next
);
2598 if (!t
|| (t
->type
!= TOK_STRING
&&
2599 t
->type
!= TOK_INTERNAL_STRING
)) {
2600 error(ERR_NONFATAL
, "`%%depend' expects a file name");
2601 free_tlist(origline
);
2602 return DIRECTIVE_FOUND
; /* but we did _something_ */
2605 error(ERR_WARNING
|ERR_PASS1
,
2606 "trailing garbage after `%%depend' ignored");
2608 if (t
->type
!= TOK_INTERNAL_STRING
)
2609 nasm_unquote_cstr(p
, i
);
2610 if (dephead
&& !in_list(*dephead
, p
)) {
2611 StrList
*sl
= nasm_malloc(strlen(p
)+1+sizeof sl
->next
);
2615 deptail
= &sl
->next
;
2617 free_tlist(origline
);
2618 return DIRECTIVE_FOUND
;
2621 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2622 t
= tline
->next
= expand_smacro(tline
->next
);
2625 if (!t
|| (t
->type
!= TOK_STRING
&&
2626 t
->type
!= TOK_INTERNAL_STRING
)) {
2627 error(ERR_NONFATAL
, "`%%include' expects a file name");
2628 free_tlist(origline
);
2629 return DIRECTIVE_FOUND
; /* but we did _something_ */
2632 error(ERR_WARNING
|ERR_PASS1
,
2633 "trailing garbage after `%%include' ignored");
2635 if (t
->type
!= TOK_INTERNAL_STRING
)
2636 nasm_unquote_cstr(p
, i
);
2637 inc
= nasm_zalloc(sizeof(Include
));
2639 inc
->fp
= inc_fopen(p
, dephead
, &deptail
, pass
== 0);
2641 /* -MG given but file not found */
2644 inc
->fname
= src_set_fname(nasm_strdup(p
));
2645 inc
->lineno
= src_set_linnum(0);
2647 inc
->expansion
= NULL
;
2649 list
->uplevel(LIST_INCLUDE
);
2651 free_tlist(origline
);
2652 return DIRECTIVE_FOUND
;
2655 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2657 static macros_t
*use_pkg
;
2658 const char *pkg_macro
= NULL
;
2660 tline
= tline
->next
;
2662 tline
= expand_id(tline
);
2664 if (!tline
|| (tline
->type
!= TOK_STRING
&&
2665 tline
->type
!= TOK_INTERNAL_STRING
&&
2666 tline
->type
!= TOK_ID
)) {
2667 error(ERR_NONFATAL
, "`%%use' expects a package name");
2668 free_tlist(origline
);
2669 return DIRECTIVE_FOUND
; /* but we did _something_ */
2672 error(ERR_WARNING
|ERR_PASS1
,
2673 "trailing garbage after `%%use' ignored");
2674 if (tline
->type
== TOK_STRING
)
2675 nasm_unquote_cstr(tline
->text
, i
);
2676 use_pkg
= nasm_stdmac_find_package(tline
->text
);
2678 error(ERR_NONFATAL
, "unknown `%%use' package: %s", tline
->text
);
2680 pkg_macro
= (char *)use_pkg
+ 1; /* The first string will be <%define>__USE_*__ */
2681 if (use_pkg
&& ! smacro_defined(NULL
, pkg_macro
, 0, NULL
, true)) {
2682 /* Not already included, go ahead and include it */
2683 stdmacpos
= use_pkg
;
2685 free_tlist(origline
);
2686 return DIRECTIVE_FOUND
;
2691 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2692 tline
= tline
->next
;
2694 tline
= expand_id(tline
);
2696 if (!tok_type_(tline
, TOK_ID
)) {
2697 error(ERR_NONFATAL
, "`%s' expects a context identifier",
2699 free_tlist(origline
);
2700 return DIRECTIVE_FOUND
; /* but we did _something_ */
2703 error(ERR_WARNING
|ERR_PASS1
,
2704 "trailing garbage after `%s' ignored",
2706 p
= nasm_strdup(tline
->text
);
2708 p
= NULL
; /* Anonymous */
2712 ctx
= nasm_zalloc(sizeof(Context
));
2714 hash_init(&ctx
->localmac
, HASH_SMALL
);
2716 ctx
->number
= unique
++;
2721 error(ERR_NONFATAL
, "`%s': context stack is empty",
2723 } else if (i
== PP_POP
) {
2724 if (p
&& (!cstk
->name
|| nasm_stricmp(p
, cstk
->name
)))
2725 error(ERR_NONFATAL
, "`%%pop' in wrong context: %s, "
2727 cstk
->name
? cstk
->name
: "anonymous", p
);
2732 nasm_free(cstk
->name
);
2738 free_tlist(origline
);
2739 return DIRECTIVE_FOUND
;
2741 severity
= ERR_FATAL
;
2744 severity
= ERR_NONFATAL
;
2747 severity
= ERR_WARNING
|ERR_WARN_USER
;
2751 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2753 /* Only error out if this is the final pass */
2754 if (pass
!= 2 && i
!= PP_FATAL
)
2755 return DIRECTIVE_FOUND
;
2757 tline
->next
= expand_smacro(tline
->next
);
2758 tline
= tline
->next
;
2760 t
= tline
? tline
->next
: NULL
;
2762 if (tok_type_(tline
, TOK_STRING
) && !t
) {
2763 /* The line contains only a quoted string */
2765 nasm_unquote(p
, NULL
); /* Ignore NUL character truncation */
2766 error(severity
, "%s", p
);
2768 /* Not a quoted string, or more than a quoted string */
2769 p
= detoken(tline
, false);
2770 error(severity
, "%s", p
);
2773 free_tlist(origline
);
2774 return DIRECTIVE_FOUND
;
2778 if (defining
!= NULL
) {
2779 if (defining
->type
== EXP_IF
) {
2780 defining
->def_depth
++;
2782 return NO_DIRECTIVE_FOUND
;
2784 if ((istk
->expansion
!= NULL
) &&
2785 (istk
->expansion
->emitting
== false)) {
2788 j
= if_condition(tline
->next
, i
);
2789 tline
->next
= NULL
; /* it got freed */
2790 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
2792 ed
= new_ExpDef(EXP_IF
);
2794 ed
->ignoring
= ((ed
->state
== COND_IF_TRUE
) ? false : true);
2795 ed
->prev
= defining
;
2797 free_tlist(origline
);
2798 return DIRECTIVE_FOUND
;
2801 if (defining
!= NULL
) {
2802 if ((defining
->type
!= EXP_IF
) || (defining
->def_depth
> 0)) {
2803 return NO_DIRECTIVE_FOUND
;
2806 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2807 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2809 switch (defining
->state
) {
2811 defining
->state
= COND_DONE
;
2812 defining
->ignoring
= true;
2817 defining
->ignoring
= true;
2820 case COND_ELSE_TRUE
:
2821 case COND_ELSE_FALSE
:
2822 error_precond(ERR_WARNING
|ERR_PASS1
,
2823 "`%%elif' after `%%else' ignored");
2824 defining
->state
= COND_NEVER
;
2825 defining
->ignoring
= true;
2830 * IMPORTANT: In the case of %if, we will already have
2831 * called expand_mmac_params(); however, if we're
2832 * processing an %elif we must have been in a
2833 * non-emitting mode, which would have inhibited
2834 * the normal invocation of expand_mmac_params().
2835 * Therefore, we have to do it explicitly here.
2837 j
= if_condition(expand_mmac_params(tline
->next
), i
);
2838 tline
->next
= NULL
; /* it got freed */
2840 j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2841 defining
->ignoring
= ((defining
->state
== COND_IF_TRUE
) ? false : true);
2844 free_tlist(origline
);
2845 return DIRECTIVE_FOUND
;
2848 if (defining
!= NULL
) {
2849 if ((defining
->type
!= EXP_IF
) || (defining
->def_depth
> 0)) {
2850 return NO_DIRECTIVE_FOUND
;
2854 error_precond(ERR_WARNING
|ERR_PASS1
,
2855 "trailing garbage after `%%else' ignored");
2856 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2857 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2859 switch (defining
->state
) {
2862 defining
->state
= COND_ELSE_FALSE
;
2863 defining
->ignoring
= true;
2867 defining
->ignoring
= true;
2871 defining
->state
= COND_ELSE_TRUE
;
2872 defining
->ignoring
= false;
2875 case COND_ELSE_TRUE
:
2876 case COND_ELSE_FALSE
:
2877 error_precond(ERR_WARNING
|ERR_PASS1
,
2878 "`%%else' after `%%else' ignored.");
2879 defining
->state
= COND_NEVER
;
2880 defining
->ignoring
= true;
2883 free_tlist(origline
);
2884 return DIRECTIVE_FOUND
;
2887 if (defining
!= NULL
) {
2888 if (defining
->type
== EXP_IF
) {
2889 if (defining
->def_depth
> 0) {
2890 defining
->def_depth
--;
2891 return NO_DIRECTIVE_FOUND
;
2894 return NO_DIRECTIVE_FOUND
;
2898 error_precond(ERR_WARNING
|ERR_PASS1
,
2899 "trailing garbage after `%%endif' ignored");
2900 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2901 error(ERR_NONFATAL
, "`%%endif': no matching `%%if'");
2902 return DIRECTIVE_FOUND
;
2905 defining
= ed
->prev
;
2906 ed
->prev
= expansions
;
2908 ei
= new_ExpInv(EXP_IF
, ed
);
2909 ei
->current
= ed
->line
;
2910 ei
->emitting
= true;
2911 ei
->prev
= istk
->expansion
;
2912 istk
->expansion
= ei
;
2913 free_tlist(origline
);
2914 return DIRECTIVE_FOUND
;
2920 if (defining
!= NULL
) {
2921 if (defining
->type
== EXP_MMACRO
) {
2922 defining
->def_depth
++;
2924 return NO_DIRECTIVE_FOUND
;
2926 ed
= new_ExpDef(EXP_MMACRO
);
2928 (i
== PP_RMACRO
) || (i
== PP_IRMACRO
) ? DEADMAN_LIMIT
: 0;
2929 ed
->casesense
= (i
== PP_MACRO
) || (i
== PP_RMACRO
);
2930 if (!parse_mmacro_spec(tline
, ed
, pp_directives
[i
])) {
2933 return DIRECTIVE_FOUND
;
2937 ed
->max_depth
= (ed
->max_depth
+ 1);
2938 ed
->ignoring
= false;
2939 ed
->prev
= defining
;
2942 eed
= (ExpDef
*) hash_findix(&expdefs
, ed
->name
);
2944 if (!strcmp(eed
->name
, ed
->name
) &&
2945 (eed
->nparam_min
<= ed
->nparam_max
|| ed
->plus
) &&
2946 (ed
->nparam_min
<= eed
->nparam_max
|| eed
->plus
)) {
2947 error(ERR_WARNING
|ERR_PASS1
,
2948 "redefining multi-line macro `%s'", ed
->name
);
2949 return DIRECTIVE_FOUND
;
2953 free_tlist(origline
);
2954 return DIRECTIVE_FOUND
;
2958 if (defining
!= NULL
) {
2959 if (defining
->type
== EXP_MMACRO
) {
2960 if (defining
->def_depth
> 0) {
2961 defining
->def_depth
--;
2962 return NO_DIRECTIVE_FOUND
;
2965 return NO_DIRECTIVE_FOUND
;
2968 if (!(defining
) || (defining
->type
!= EXP_MMACRO
)) {
2969 error(ERR_NONFATAL
, "`%s': not defining a macro", tline
->text
);
2970 return DIRECTIVE_FOUND
;
2972 edhead
= (ExpDef
**) hash_findi_add(&expdefs
, defining
->name
);
2973 defining
->next
= *edhead
;
2976 defining
= ed
->prev
;
2977 ed
->prev
= expansions
;
2980 free_tlist(origline
);
2981 return DIRECTIVE_FOUND
;
2984 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2986 * We must search along istk->expansion until we hit a
2987 * macro invocation. Then we disable the emitting state(s)
2988 * between exitmacro and endmacro.
2990 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
2991 if(ei
->type
== EXP_MMACRO
) {
2998 * Set all invocations leading back to the macro
2999 * invocation to a non-emitting state.
3001 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3002 eei
->emitting
= false;
3004 eei
->emitting
= false;
3006 error(ERR_NONFATAL
, "`%%exitmacro' not within `%%macro' block");
3008 free_tlist(origline
);
3009 return DIRECTIVE_FOUND
;
3013 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3018 spec
.casesense
= (i
== PP_UNMACRO
);
3019 if (!parse_mmacro_spec(tline
, &spec
, pp_directives
[i
])) {
3020 return DIRECTIVE_FOUND
;
3022 ed_p
= (ExpDef
**) hash_findi(&expdefs
, spec
.name
, NULL
);
3023 while (ed_p
&& *ed_p
) {
3025 if (ed
->casesense
== spec
.casesense
&&
3026 !mstrcmp(ed
->name
, spec
.name
, spec
.casesense
) &&
3027 ed
->nparam_min
== spec
.nparam_min
&&
3028 ed
->nparam_max
== spec
.nparam_max
&&
3029 ed
->plus
== spec
.plus
) {
3030 if (ed
->cur_depth
> 0) {
3031 error(ERR_NONFATAL
, "`%s' ignored on active macro",
3042 free_tlist(origline
);
3043 free_tlist(spec
.dlist
);
3044 return DIRECTIVE_FOUND
;
3048 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3049 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
3050 tline
= tline
->next
;
3052 free_tlist(origline
);
3053 error(ERR_NONFATAL
, "`%%rotate' missing rotate count");
3054 return DIRECTIVE_FOUND
;
3056 t
= expand_smacro(tline
->next
);
3058 free_tlist(origline
);
3061 tokval
.t_type
= TOKEN_INVALID
;
3063 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3066 return DIRECTIVE_FOUND
;
3068 error(ERR_WARNING
|ERR_PASS1
,
3069 "trailing garbage after expression ignored");
3070 if (!is_simple(evalresult
)) {
3071 error(ERR_NONFATAL
, "non-constant value given to `%%rotate'");
3072 return DIRECTIVE_FOUND
;
3074 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3075 if (ei
->type
== EXP_MMACRO
) {
3080 error(ERR_NONFATAL
, "`%%rotate' invoked outside a macro call");
3081 } else if (ei
->nparam
== 0) {
3083 "`%%rotate' invoked within macro without parameters");
3085 int rotate
= ei
->rotate
+ reloc_value(evalresult
);
3087 rotate
%= (int)ei
->nparam
;
3089 rotate
+= ei
->nparam
;
3090 ei
->rotate
= rotate
;
3092 return DIRECTIVE_FOUND
;
3095 if (defining
!= NULL
) {
3096 if (defining
->type
== EXP_REP
) {
3097 defining
->def_depth
++;
3099 return NO_DIRECTIVE_FOUND
;
3103 tline
= tline
->next
;
3104 } while (tok_type_(tline
, TOK_WHITESPACE
));
3106 if (tok_type_(tline
, TOK_ID
) &&
3107 nasm_stricmp(tline
->text
, ".nolist") == 0) {
3110 tline
= tline
->next
;
3111 } while (tok_type_(tline
, TOK_WHITESPACE
));
3115 t
= expand_smacro(tline
);
3117 tokval
.t_type
= TOKEN_INVALID
;
3119 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3121 free_tlist(origline
);
3122 return DIRECTIVE_FOUND
;
3125 error(ERR_WARNING
|ERR_PASS1
,
3126 "trailing garbage after expression ignored");
3127 if (!is_simple(evalresult
)) {
3128 error(ERR_NONFATAL
, "non-constant value given to `%%rep'");
3129 return DIRECTIVE_FOUND
;
3131 count
= reloc_value(evalresult
);
3132 if (count
>= REP_LIMIT
) {
3133 error(ERR_NONFATAL
, "`%%rep' value exceeds limit");
3138 error(ERR_NONFATAL
, "`%%rep' expects a repeat count");
3141 free_tlist(origline
);
3142 ed
= new_ExpDef(EXP_REP
);
3143 ed
->nolist
= nolist
;
3146 ed
->max_depth
= (count
- 1);
3147 ed
->ignoring
= false;
3148 ed
->prev
= defining
;
3150 return DIRECTIVE_FOUND
;
3153 if (defining
!= NULL
) {
3154 if (defining
->type
== EXP_REP
) {
3155 if (defining
->def_depth
> 0) {
3156 defining
->def_depth
--;
3157 return NO_DIRECTIVE_FOUND
;
3160 return NO_DIRECTIVE_FOUND
;
3163 if ((defining
== NULL
) || (defining
->type
!= EXP_REP
)) {
3164 error(ERR_NONFATAL
, "`%%endrep': no matching `%%rep'");
3165 return DIRECTIVE_FOUND
;
3169 * Now we have a "macro" defined - although it has no name
3170 * and we won't be entering it in the hash tables - we must
3171 * push a macro-end marker for it on to istk->expansion.
3172 * After that, it will take care of propagating itself (a
3173 * macro-end marker line for a macro which is really a %rep
3174 * block will cause the macro to be re-expanded, complete
3175 * with another macro-end marker to ensure the process
3176 * continues) until the whole expansion is forcibly removed
3177 * from istk->expansion by a %exitrep.
3180 defining
= ed
->prev
;
3181 ed
->prev
= expansions
;
3183 ei
= new_ExpInv(EXP_REP
, ed
);
3184 ei
->current
= ed
->line
;
3185 ei
->emitting
= ((ed
->max_depth
> 0) ? true : false);
3186 list
->uplevel(ed
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
3187 ei
->prev
= istk
->expansion
;
3188 istk
->expansion
= ei
;
3189 free_tlist(origline
);
3190 return DIRECTIVE_FOUND
;
3193 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3195 * We must search along istk->expansion until we hit a
3196 * rep invocation. Then we disable the emitting state(s)
3197 * between exitrep and endrep.
3199 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3200 if (ei
->type
== EXP_REP
) {
3207 * Set all invocations leading back to the rep
3208 * invocation to a non-emitting state.
3210 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3211 eei
->emitting
= false;
3213 eei
->emitting
= false;
3214 eei
->current
= NULL
;
3215 eei
->def
->cur_depth
= eei
->def
->max_depth
;
3217 error(ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
3219 free_tlist(origline
);
3220 return DIRECTIVE_FOUND
;
3226 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3227 casesense
= (i
== PP_DEFINE
|| i
== PP_XDEFINE
);
3229 tline
= tline
->next
;
3231 tline
= expand_id(tline
);
3232 if (!tline
|| (tline
->type
!= TOK_ID
&&
3233 (tline
->type
!= TOK_PREPROC_ID
||
3234 tline
->text
[1] != '$'))) {
3235 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3237 free_tlist(origline
);
3238 return DIRECTIVE_FOUND
;
3241 ctx
= get_ctx(tline
->text
, &mname
);
3243 param_start
= tline
= tline
->next
;
3246 /* Expand the macro definition now for %xdefine and %ixdefine */
3247 if ((i
== PP_XDEFINE
) || (i
== PP_IXDEFINE
))
3248 tline
= expand_smacro(tline
);
3250 if (tok_is_(tline
, "(")) {
3252 * This macro has parameters.
3255 tline
= tline
->next
;
3259 error(ERR_NONFATAL
, "parameter identifier expected");
3260 free_tlist(origline
);
3261 return DIRECTIVE_FOUND
;
3263 if (tline
->type
!= TOK_ID
) {
3265 "`%s': parameter identifier expected",
3267 free_tlist(origline
);
3268 return DIRECTIVE_FOUND
;
3271 smacro_set_param_idx(tline
, nparam
);
3274 tline
= tline
->next
;
3276 if (tok_is_(tline
, ",")) {
3277 tline
= tline
->next
;
3279 if (!tok_is_(tline
, ")")) {
3281 "`)' expected to terminate macro template");
3282 free_tlist(origline
);
3283 return DIRECTIVE_FOUND
;
3289 tline
= tline
->next
;
3291 if (tok_type_(tline
, TOK_WHITESPACE
))
3292 last
= tline
, tline
= tline
->next
;
3297 if (t
->type
== TOK_ID
) {
3298 list_for_each(tt
, param_start
)
3299 if (is_smacro_param(tt
) &&
3300 !strcmp(tt
->text
, t
->text
))
3304 t
->next
= macro_start
;
3309 * Good. We now have a macro name, a parameter count, and a
3310 * token list (in reverse order) for an expansion. We ought
3311 * to be OK just to create an SMacro, store it, and let
3312 * free_tlist have the rest of the line (which we have
3313 * carefully re-terminated after chopping off the expansion
3316 define_smacro(ctx
, mname
, casesense
, nparam
, macro_start
);
3317 free_tlist(origline
);
3318 return DIRECTIVE_FOUND
;
3321 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3322 tline
= tline
->next
;
3324 tline
= expand_id(tline
);
3325 if (!tline
|| (tline
->type
!= TOK_ID
&&
3326 (tline
->type
!= TOK_PREPROC_ID
||
3327 tline
->text
[1] != '$'))) {
3328 error(ERR_NONFATAL
, "`%%undef' expects a macro identifier");
3329 free_tlist(origline
);
3330 return DIRECTIVE_FOUND
;
3333 error(ERR_WARNING
|ERR_PASS1
,
3334 "trailing garbage after macro name ignored");
3337 /* Find the context that symbol belongs to */
3338 ctx
= get_ctx(tline
->text
, &mname
);
3339 undef_smacro(ctx
, mname
);
3340 free_tlist(origline
);
3341 return DIRECTIVE_FOUND
;
3345 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3346 casesense
= (i
== PP_DEFSTR
);
3348 tline
= tline
->next
;
3350 tline
= expand_id(tline
);
3351 if (!tline
|| (tline
->type
!= TOK_ID
&&
3352 (tline
->type
!= TOK_PREPROC_ID
||
3353 tline
->text
[1] != '$'))) {
3354 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3356 free_tlist(origline
);
3357 return DIRECTIVE_FOUND
;
3360 ctx
= get_ctx(tline
->text
, &mname
);
3362 tline
= expand_smacro(tline
->next
);
3365 while (tok_type_(tline
, TOK_WHITESPACE
))
3366 tline
= delete_Token(tline
);
3368 p
= detoken(tline
, false);
3369 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3370 macro_start
->text
= nasm_quote(p
, strlen(p
));
3371 macro_start
->type
= TOK_STRING
;
3375 * We now have a macro name, an implicit parameter count of
3376 * zero, and a string token to use as an expansion. Create
3377 * and store an SMacro.
3379 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3380 free_tlist(origline
);
3381 return DIRECTIVE_FOUND
;
3385 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3386 casesense
= (i
== PP_DEFTOK
);
3388 tline
= tline
->next
;
3390 tline
= expand_id(tline
);
3391 if (!tline
|| (tline
->type
!= TOK_ID
&&
3392 (tline
->type
!= TOK_PREPROC_ID
||
3393 tline
->text
[1] != '$'))) {
3395 "`%s' expects a macro identifier as first parameter",
3397 free_tlist(origline
);
3398 return DIRECTIVE_FOUND
;
3400 ctx
= get_ctx(tline
->text
, &mname
);
3402 tline
= expand_smacro(tline
->next
);
3406 while (tok_type_(t
, TOK_WHITESPACE
))
3408 /* t should now point to the string */
3409 if (!tok_type_(t
, TOK_STRING
)) {
3411 "`%s` requires string as second parameter",
3414 free_tlist(origline
);
3415 return DIRECTIVE_FOUND
;
3419 * Convert the string to a token stream. Note that smacros
3420 * are stored with the token stream reversed, so we have to
3421 * reverse the output of tokenize().
3423 nasm_unquote_cstr(t
->text
, i
);
3424 macro_start
= reverse_tokens(tokenize(t
->text
));
3427 * We now have a macro name, an implicit parameter count of
3428 * zero, and a numeric token to use as an expansion. Create
3429 * and store an SMacro.
3431 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3433 free_tlist(origline
);
3434 return DIRECTIVE_FOUND
;
3437 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3440 StrList
*xsl
= NULL
;
3441 StrList
**xst
= &xsl
;
3445 tline
= tline
->next
;
3447 tline
= expand_id(tline
);
3448 if (!tline
|| (tline
->type
!= TOK_ID
&&
3449 (tline
->type
!= TOK_PREPROC_ID
||
3450 tline
->text
[1] != '$'))) {
3452 "`%%pathsearch' expects a macro identifier as first parameter");
3453 free_tlist(origline
);
3454 return DIRECTIVE_FOUND
;
3456 ctx
= get_ctx(tline
->text
, &mname
);
3458 tline
= expand_smacro(tline
->next
);
3462 while (tok_type_(t
, TOK_WHITESPACE
))
3465 if (!t
|| (t
->type
!= TOK_STRING
&&
3466 t
->type
!= TOK_INTERNAL_STRING
)) {
3467 error(ERR_NONFATAL
, "`%%pathsearch' expects a file name");
3469 free_tlist(origline
);
3470 return DIRECTIVE_FOUND
; /* but we did _something_ */
3473 error(ERR_WARNING
|ERR_PASS1
,
3474 "trailing garbage after `%%pathsearch' ignored");
3476 if (t
->type
!= TOK_INTERNAL_STRING
)
3477 nasm_unquote(p
, NULL
);
3479 fp
= inc_fopen(p
, &xsl
, &xst
, true);
3482 fclose(fp
); /* Don't actually care about the file */
3484 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3485 macro_start
->text
= nasm_quote(p
, strlen(p
));
3486 macro_start
->type
= TOK_STRING
;
3490 * We now have a macro name, an implicit parameter count of
3491 * zero, and a string token to use as an expansion. Create
3492 * and store an SMacro.
3494 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3496 free_tlist(origline
);
3497 return DIRECTIVE_FOUND
;
3501 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3504 tline
= tline
->next
;
3506 tline
= expand_id(tline
);
3507 if (!tline
|| (tline
->type
!= TOK_ID
&&
3508 (tline
->type
!= TOK_PREPROC_ID
||
3509 tline
->text
[1] != '$'))) {
3511 "`%%strlen' expects a macro identifier as first parameter");
3512 free_tlist(origline
);
3513 return DIRECTIVE_FOUND
;
3515 ctx
= get_ctx(tline
->text
, &mname
);
3517 tline
= expand_smacro(tline
->next
);
3521 while (tok_type_(t
, TOK_WHITESPACE
))
3523 /* t should now point to the string */
3524 if (!tok_type_(t
, TOK_STRING
)) {
3526 "`%%strlen` requires string as second parameter");
3528 free_tlist(origline
);
3529 return DIRECTIVE_FOUND
;
3532 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3533 make_tok_num(macro_start
, nasm_unquote(t
->text
, NULL
));
3536 * We now have a macro name, an implicit parameter count of
3537 * zero, and a numeric token to use as an expansion. Create
3538 * and store an SMacro.
3540 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3542 free_tlist(origline
);
3543 return DIRECTIVE_FOUND
;
3546 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3549 tline
= tline
->next
;
3551 tline
= expand_id(tline
);
3552 if (!tline
|| (tline
->type
!= TOK_ID
&&
3553 (tline
->type
!= TOK_PREPROC_ID
||
3554 tline
->text
[1] != '$'))) {
3556 "`%%strcat' expects a macro identifier as first parameter");
3557 free_tlist(origline
);
3558 return DIRECTIVE_FOUND
;
3560 ctx
= get_ctx(tline
->text
, &mname
);
3562 tline
= expand_smacro(tline
->next
);
3566 list_for_each(t
, tline
) {
3568 case TOK_WHITESPACE
:
3571 len
+= t
->a
.len
= nasm_unquote(t
->text
, NULL
);
3574 if (!strcmp(t
->text
, ",")) /* permit comma separators */
3576 /* else fall through */
3579 "non-string passed to `%%strcat' (%d)", t
->type
);
3581 free_tlist(origline
);
3582 return DIRECTIVE_FOUND
;
3586 p
= pp
= nasm_malloc(len
);
3587 list_for_each(t
, tline
) {
3588 if (t
->type
== TOK_STRING
) {
3589 memcpy(p
, t
->text
, t
->a
.len
);
3595 * We now have a macro name, an implicit parameter count of
3596 * zero, and a numeric token to use as an expansion. Create
3597 * and store an SMacro.
3599 macro_start
= new_Token(NULL
, TOK_STRING
, NULL
, 0);
3600 macro_start
->text
= nasm_quote(pp
, len
);
3602 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3604 free_tlist(origline
);
3605 return DIRECTIVE_FOUND
;
3608 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3610 int64_t start
, count
;
3615 tline
= tline
->next
;
3617 tline
= expand_id(tline
);
3618 if (!tline
|| (tline
->type
!= TOK_ID
&&
3619 (tline
->type
!= TOK_PREPROC_ID
||
3620 tline
->text
[1] != '$'))) {
3622 "`%%substr' expects a macro identifier as first parameter");
3623 free_tlist(origline
);
3624 return DIRECTIVE_FOUND
;
3626 ctx
= get_ctx(tline
->text
, &mname
);
3628 tline
= expand_smacro(tline
->next
);
3631 if (tline
) /* skip expanded id */
3633 while (tok_type_(t
, TOK_WHITESPACE
))
3636 /* t should now point to the string */
3637 if (!tok_type_(t
, TOK_STRING
)) {
3639 "`%%substr` requires string as second parameter");
3641 free_tlist(origline
);
3642 return DIRECTIVE_FOUND
;
3647 tokval
.t_type
= TOKEN_INVALID
;
3648 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3652 free_tlist(origline
);
3653 return DIRECTIVE_FOUND
;
3654 } else if (!is_simple(evalresult
)) {
3655 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3657 free_tlist(origline
);
3658 return DIRECTIVE_FOUND
;
3660 start
= evalresult
->value
- 1;
3662 while (tok_type_(tt
, TOK_WHITESPACE
))
3665 count
= 1; /* Backwards compatibility: one character */
3667 tokval
.t_type
= TOKEN_INVALID
;
3668 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3672 free_tlist(origline
);
3673 return DIRECTIVE_FOUND
;
3674 } else if (!is_simple(evalresult
)) {
3675 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3677 free_tlist(origline
);
3678 return DIRECTIVE_FOUND
;
3680 count
= evalresult
->value
;
3683 len
= nasm_unquote(t
->text
, NULL
);
3684 /* make start and count being in range */
3688 count
= len
+ count
+ 1 - start
;
3689 if (start
+ count
> (int64_t)len
)
3690 count
= len
- start
;
3691 if (!len
|| count
< 0 || start
>=(int64_t)len
)
3692 start
= -1, count
= 0; /* empty string */
3694 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3695 macro_start
->text
= nasm_quote((start
< 0) ? "" : t
->text
+ start
, count
);
3696 macro_start
->type
= TOK_STRING
;
3699 * We now have a macro name, an implicit parameter count of
3700 * zero, and a numeric token to use as an expansion. Create
3701 * and store an SMacro.
3703 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3705 free_tlist(origline
);
3706 return DIRECTIVE_FOUND
;
3711 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3712 casesense
= (i
== PP_ASSIGN
);
3714 tline
= tline
->next
;
3716 tline
= expand_id(tline
);
3717 if (!tline
|| (tline
->type
!= TOK_ID
&&
3718 (tline
->type
!= TOK_PREPROC_ID
||
3719 tline
->text
[1] != '$'))) {
3721 "`%%%sassign' expects a macro identifier",
3722 (i
== PP_IASSIGN
? "i" : ""));
3723 free_tlist(origline
);
3724 return DIRECTIVE_FOUND
;
3726 ctx
= get_ctx(tline
->text
, &mname
);
3728 tline
= expand_smacro(tline
->next
);
3733 tokval
.t_type
= TOKEN_INVALID
;
3735 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3738 free_tlist(origline
);
3739 return DIRECTIVE_FOUND
;
3743 error(ERR_WARNING
|ERR_PASS1
,
3744 "trailing garbage after expression ignored");
3746 if (!is_simple(evalresult
)) {
3748 "non-constant value given to `%%%sassign'",
3749 (i
== PP_IASSIGN
? "i" : ""));
3750 free_tlist(origline
);
3751 return DIRECTIVE_FOUND
;
3754 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3755 make_tok_num(macro_start
, reloc_value(evalresult
));
3758 * We now have a macro name, an implicit parameter count of
3759 * zero, and a numeric token to use as an expansion. Create
3760 * and store an SMacro.
3762 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3763 free_tlist(origline
);
3764 return DIRECTIVE_FOUND
;
3767 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3769 * Syntax is `%line nnn[+mmm] [filename]'
3771 tline
= tline
->next
;
3773 if (!tok_type_(tline
, TOK_NUMBER
)) {
3774 error(ERR_NONFATAL
, "`%%line' expects line number");
3775 free_tlist(origline
);
3776 return DIRECTIVE_FOUND
;
3778 k
= readnum(tline
->text
, &err
);
3780 tline
= tline
->next
;
3781 if (tok_is_(tline
, "+")) {
3782 tline
= tline
->next
;
3783 if (!tok_type_(tline
, TOK_NUMBER
)) {
3784 error(ERR_NONFATAL
, "`%%line' expects line increment");
3785 free_tlist(origline
);
3786 return DIRECTIVE_FOUND
;
3788 m
= readnum(tline
->text
, &err
);
3789 tline
= tline
->next
;
3795 nasm_free(src_set_fname(detoken(tline
, false)));
3797 free_tlist(origline
);
3798 return DIRECTIVE_FOUND
;
3801 if (defining
!= NULL
) {
3802 if (defining
->type
== EXP_WHILE
) {
3803 defining
->def_depth
++;
3805 return NO_DIRECTIVE_FOUND
;
3808 if ((istk
->expansion
!= NULL
) &&
3809 (istk
->expansion
->emitting
== false)) {
3813 l
->first
= copy_Token(tline
->next
);
3814 j
= if_condition(tline
->next
, i
);
3815 tline
->next
= NULL
; /* it got freed */
3816 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
3818 ed
= new_ExpDef(EXP_WHILE
);
3821 ed
->max_depth
= DEADMAN_LIMIT
;
3822 ed
->ignoring
= ((ed
->state
== COND_IF_TRUE
) ? false : true);
3823 if (ed
->ignoring
== false) {
3826 } else if (l
!= NULL
) {
3827 delete_Token(l
->first
);
3831 ed
->prev
= defining
;
3833 free_tlist(origline
);
3834 return DIRECTIVE_FOUND
;
3837 if (defining
!= NULL
) {
3838 if (defining
->type
== EXP_WHILE
) {
3839 if (defining
->def_depth
> 0) {
3840 defining
->def_depth
--;
3841 return NO_DIRECTIVE_FOUND
;
3844 return NO_DIRECTIVE_FOUND
;
3847 if (tline
->next
!= NULL
) {
3848 error_precond(ERR_WARNING
|ERR_PASS1
,
3849 "trailing garbage after `%%endwhile' ignored");
3851 if ((defining
== NULL
) || (defining
->type
!= EXP_WHILE
)) {
3852 error(ERR_NONFATAL
, "`%%endwhile': no matching `%%while'");
3853 return DIRECTIVE_FOUND
;
3856 defining
= ed
->prev
;
3857 if (ed
->ignoring
== false) {
3858 ed
->prev
= expansions
;
3860 ei
= new_ExpInv(EXP_WHILE
, ed
);
3861 ei
->current
= ed
->line
->next
;
3862 ei
->emitting
= true;
3863 ei
->prev
= istk
->expansion
;
3864 istk
->expansion
= ei
;
3868 free_tlist(origline
);
3869 return DIRECTIVE_FOUND
;
3872 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3874 * We must search along istk->expansion until we hit a
3875 * while invocation. Then we disable the emitting state(s)
3876 * between exitwhile and endwhile.
3878 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3879 if (ei
->type
== EXP_WHILE
) {
3886 * Set all invocations leading back to the while
3887 * invocation to a non-emitting state.
3889 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3890 eei
->emitting
= false;
3892 eei
->emitting
= false;
3893 eei
->current
= NULL
;
3894 eei
->def
->cur_depth
= eei
->def
->max_depth
;
3896 error(ERR_NONFATAL
, "`%%exitwhile' not within `%%while' block");
3898 free_tlist(origline
);
3899 return DIRECTIVE_FOUND
;
3902 if (defining
!= NULL
) {
3903 if (defining
->type
== EXP_COMMENT
) {
3904 defining
->def_depth
++;
3906 return NO_DIRECTIVE_FOUND
;
3908 ed
= new_ExpDef(EXP_COMMENT
);
3909 ed
->ignoring
= true;
3910 ed
->prev
= defining
;
3912 free_tlist(origline
);
3913 return DIRECTIVE_FOUND
;
3916 if (defining
!= NULL
) {
3917 if (defining
->type
== EXP_COMMENT
) {
3918 if (defining
->def_depth
> 0) {
3919 defining
->def_depth
--;
3920 return NO_DIRECTIVE_FOUND
;
3923 return NO_DIRECTIVE_FOUND
;
3926 if ((defining
== NULL
) || (defining
->type
!= EXP_COMMENT
)) {
3927 error(ERR_NONFATAL
, "`%%endcomment': no matching `%%comment'");
3928 return DIRECTIVE_FOUND
;
3931 defining
= ed
->prev
;
3933 free_tlist(origline
);
3934 return DIRECTIVE_FOUND
;
3937 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3938 if (in_final
!= false) {
3939 error(ERR_FATAL
, "`%%final' cannot be used recursively");
3941 tline
= tline
->next
;
3943 if (tline
== NULL
) {
3944 error(ERR_NONFATAL
, "`%%final' expects at least one parameter");
3947 l
->first
= copy_Token(tline
);
3951 free_tlist(origline
);
3952 return DIRECTIVE_FOUND
;
3956 "preprocessor directive `%s' not yet implemented",
3958 return DIRECTIVE_FOUND
;
3963 * Ensure that a macro parameter contains a condition code and
3964 * nothing else. Return the condition code index if so, or -1
3967 static int find_cc(Token
* t
)
3973 return -1; /* Probably a %+ without a space */
3976 if (t
->type
!= TOK_ID
)
3980 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
3984 j
= ARRAY_SIZE(conditions
);
3987 m
= nasm_stricmp(t
->text
, conditions
[k
]);
4002 static bool paste_tokens(Token
**head
, const struct tokseq_match
*m
,
4003 int mnum
, bool handle_paste_tokens
)
4005 Token
**tail
, *t
, *tt
;
4007 bool did_paste
= false;
4011 /* Now handle token pasting... */
4014 while ((t
= *tail
) && (tt
= t
->next
)) {
4016 case TOK_WHITESPACE
:
4017 if (tt
->type
== TOK_WHITESPACE
) {
4018 /* Zap adjacent whitespace tokens */
4019 t
->next
= delete_Token(tt
);
4021 /* Do not advance paste_head here */
4025 case TOK_PASTE
: /* %+ */
4026 if (handle_paste_tokens
) {
4027 /* Zap %+ and whitespace tokens to the right */
4028 while (t
&& (t
->type
== TOK_WHITESPACE
||
4029 t
->type
== TOK_PASTE
))
4030 t
= *tail
= delete_Token(t
);
4031 if (!paste_head
|| !t
)
4032 break; /* Nothing to paste with */
4036 while (tok_type_(tt
, TOK_WHITESPACE
))
4037 tt
= t
->next
= delete_Token(tt
);
4039 tmp
= nasm_strcat(t
->text
, tt
->text
);
4041 tt
= delete_Token(tt
);
4042 t
= *tail
= tokenize(tmp
);
4048 t
->next
= tt
; /* Attach the remaining token chain */
4055 /* else fall through */
4058 * Concatenation of tokens might look nontrivial
4059 * but in real it's pretty simple -- the caller
4060 * prepares the masks of token types to be concatenated
4061 * and we simply find matched sequences and slip
4064 for (i
= 0; i
< mnum
; i
++) {
4065 if (PP_CONCAT_MASK(t
->type
) & m
[i
].mask_head
) {
4069 while (tt
&& (PP_CONCAT_MASK(tt
->type
) & m
[i
].mask_tail
)) {
4070 len
+= strlen(tt
->text
);
4074 nasm_dump_token(tt
);
4077 * Now tt points to the first token after
4078 * the potential paste area...
4080 if (tt
!= t
->next
) {
4081 /* We have at least two tokens... */
4082 len
+= strlen(t
->text
);
4083 p
= tmp
= nasm_malloc(len
+1);
4086 p
= strchr(p
, '\0');
4087 t
= delete_Token(t
);
4089 t
= *tail
= tokenize(tmp
);
4095 t
->next
= tt
; /* Attach the remaining token chain */
4103 if (i
>= mnum
) { /* no match */
4105 if (!tok_type_(t
->next
, TOK_WHITESPACE
))
4115 * expands to a list of tokens from %{x:y}
4117 static Token
*expand_mmac_params_range(ExpInv
*ei
, Token
*tline
, Token
***last
)
4119 Token
*t
= tline
, **tt
, *tm
, *head
;
4123 pos
= strchr(tline
->text
, ':');
4126 lst
= atoi(pos
+ 1);
4127 fst
= atoi(tline
->text
+ 1);
4130 * only macros params are accounted so
4131 * if someone passes %0 -- we reject such
4134 if (lst
== 0 || fst
== 0)
4137 /* the values should be sane */
4138 if ((fst
> (int)ei
->nparam
|| fst
< (-(int)ei
->nparam
)) ||
4139 (lst
> (int)ei
->nparam
|| lst
< (-(int)ei
->nparam
)))
4142 fst
= fst
< 0 ? fst
+ (int)ei
->nparam
+ 1: fst
;
4143 lst
= lst
< 0 ? lst
+ (int)ei
->nparam
+ 1: lst
;
4145 /* counted from zero */
4149 * it will be at least one token
4151 tm
= ei
->params
[(fst
+ ei
->rotate
) % ei
->nparam
];
4152 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4153 head
= t
, tt
= &t
->next
;
4155 for (i
= fst
+ 1; i
<= lst
; i
++) {
4156 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
4157 *tt
= t
, tt
= &t
->next
;
4158 j
= (i
+ ei
->rotate
) % ei
->nparam
;
4160 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4161 *tt
= t
, tt
= &t
->next
;
4164 for (i
= fst
- 1; i
>= lst
; i
--) {
4165 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
4166 *tt
= t
, tt
= &t
->next
;
4167 j
= (i
+ ei
->rotate
) % ei
->nparam
;
4169 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4170 *tt
= t
, tt
= &t
->next
;
4178 error(ERR_NONFATAL
, "`%%{%s}': macro parameters out of range",
4184 * Expand MMacro-local things: parameter references (%0, %n, %+n,
4185 * %-n) and MMacro-local identifiers (%%foo) as well as
4186 * macro indirection (%[...]) and range (%{..:..}).
4188 static Token
*expand_mmac_params(Token
* tline
)
4190 Token
*t
, *tt
, **tail
, *thead
;
4191 bool changed
= false;
4197 nasm_dump_stream(tline
);
4200 if (tline
->type
== TOK_PREPROC_ID
&&
4201 (((tline
->text
[1] == '+' || tline
->text
[1] == '-') && tline
->text
[2]) ||
4202 (tline
->text
[1] >= '0' && tline
->text
[1] <= '9') ||
4203 tline
->text
[1] == '%')) {
4205 int type
= 0, cc
; /* type = 0 to placate optimisers */
4212 tline
= tline
->next
;
4214 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
4215 if (ei
->type
== EXP_MMACRO
) {
4220 error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
4222 pos
= strchr(t
->text
, ':');
4224 switch (t
->text
[1]) {
4226 * We have to make a substitution of one of the
4227 * forms %1, %-1, %+1, %%foo, %0.
4230 if ((strlen(t
->text
) > 2) && (t
->text
[2] == '0')) {
4232 text
= nasm_strdup(ei
->label_text
);
4235 snprintf(tmpbuf
, sizeof(tmpbuf
), "%d", ei
->nparam
);
4236 text
= nasm_strdup(tmpbuf
);
4241 snprintf(tmpbuf
, sizeof(tmpbuf
), "..@%"PRIu64
".",
4243 text
= nasm_strcat(tmpbuf
, t
->text
+ 2);
4246 n
= atoi(t
->text
+ 2) - 1;
4247 if (n
>= ei
->nparam
)
4251 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4257 "macro parameter %d is not a condition code",
4262 if (inverse_ccs
[cc
] == -1) {
4264 "condition code `%s' is not invertible",
4268 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
4272 n
= atoi(t
->text
+ 2) - 1;
4273 if (n
>= ei
->nparam
)
4277 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4283 "macro parameter %d is not a condition code",
4288 text
= nasm_strdup(conditions
[cc
]);
4292 n
= atoi(t
->text
+ 1) - 1;
4293 if (n
>= ei
->nparam
)
4297 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4301 for (i
= 0; i
< ei
->paramlen
[n
]; i
++) {
4302 *tail
= new_Token(NULL
, tt
->type
, tt
->text
, 0);
4303 tail
= &(*tail
)->next
;
4307 text
= NULL
; /* we've done it here */
4312 * seems we have a parameters range here
4314 Token
*head
, **last
;
4315 head
= expand_mmac_params_range(ei
, t
, &last
);
4336 } else if (tline
->type
== TOK_INDIRECT
) {
4338 tline
= tline
->next
;
4339 tt
= tokenize(t
->text
);
4340 tt
= expand_mmac_params(tt
);
4341 tt
= expand_smacro(tt
);
4344 tt
->a
.mac
= NULL
; /* Necessary? */
4352 tline
= tline
->next
;
4360 const struct tokseq_match t
[] = {
4362 PP_CONCAT_MASK(TOK_ID
) |
4363 PP_CONCAT_MASK(TOK_FLOAT
), /* head */
4364 PP_CONCAT_MASK(TOK_ID
) |
4365 PP_CONCAT_MASK(TOK_NUMBER
) |
4366 PP_CONCAT_MASK(TOK_FLOAT
) |
4367 PP_CONCAT_MASK(TOK_OTHER
) /* tail */
4370 PP_CONCAT_MASK(TOK_NUMBER
), /* head */
4371 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4374 paste_tokens(&thead
, t
, ARRAY_SIZE(t
), false);
4377 nasm_dump_token(thead
);
4383 * Expand all single-line macro calls made in the given line.
4384 * Return the expanded version of the line. The original is deemed
4385 * to be destroyed in the process. (In reality we'll just move
4386 * Tokens from input to output a lot of the time, rather than
4387 * actually bothering to destroy and replicate.)
4390 static Token
*expand_smacro(Token
* tline
)
4392 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
4393 SMacro
*head
= NULL
, *m
;
4396 unsigned int nparam
, sparam
;
4398 Token
*org_tline
= tline
;
4401 int deadman
= DEADMAN_LIMIT
;
4405 * Trick: we should avoid changing the start token pointer since it can
4406 * be contained in "next" field of other token. Because of this
4407 * we allocate a copy of first token and work with it; at the end of
4408 * routine we copy it back
4411 tline
= new_Token(org_tline
->next
, org_tline
->type
,
4412 org_tline
->text
, 0);
4413 tline
->a
.mac
= org_tline
->a
.mac
;
4414 nasm_free(org_tline
->text
);
4415 org_tline
->text
= NULL
;
4418 expanded
= true; /* Always expand %+ at least once */
4424 while (tline
) { /* main token loop */
4426 error(ERR_NONFATAL
, "interminable macro recursion");
4430 if ((mname
= tline
->text
)) {
4431 /* if this token is a local macro, look in local context */
4432 if (tline
->type
== TOK_ID
) {
4433 head
= (SMacro
*)hash_findix(&smacros
, mname
);
4434 } else if (tline
->type
== TOK_PREPROC_ID
) {
4435 ctx
= get_ctx(mname
, &mname
);
4436 head
= ctx
? (SMacro
*)hash_findix(&ctx
->localmac
, mname
) : NULL
;
4441 * We've hit an identifier. As in is_mmacro below, we first
4442 * check whether the identifier is a single-line macro at
4443 * all, then think about checking for parameters if
4446 list_for_each(m
, head
)
4447 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
4453 if (m
->nparam
== 0) {
4455 * Simple case: the macro is parameterless. Discard the
4456 * one token that the macro call took, and push the
4457 * expansion back on the to-do stack.
4459 if (!m
->expansion
) {
4460 if (!strcmp("__FILE__", m
->name
)) {
4463 src_get(&num
, &file
);
4464 tline
->text
= nasm_quote(file
, strlen(file
));
4465 tline
->type
= TOK_STRING
;
4469 if (!strcmp("__LINE__", m
->name
)) {
4470 nasm_free(tline
->text
);
4471 make_tok_num(tline
, src_get_linnum());
4474 if (!strcmp("__BITS__", m
->name
)) {
4475 nasm_free(tline
->text
);
4476 make_tok_num(tline
, globalbits
);
4479 tline
= delete_Token(tline
);
4484 * Complicated case: at least one macro with this name
4485 * exists and takes parameters. We must find the
4486 * parameters in the call, count them, find the SMacro
4487 * that corresponds to that form of the macro call, and
4488 * substitute for the parameters when we expand. What a
4491 /*tline = tline->next;
4492 skip_white_(tline); */
4495 while (tok_type_(t
, TOK_SMAC_END
)) {
4496 t
->a
.mac
->in_progress
= false;
4498 t
= tline
->next
= delete_Token(t
);
4501 } while (tok_type_(tline
, TOK_WHITESPACE
));
4502 if (!tok_is_(tline
, "(")) {
4504 * This macro wasn't called with parameters: ignore
4505 * the call. (Behaviour borrowed from gnu cpp.)
4514 sparam
= PARAM_DELTA
;
4515 params
= nasm_malloc(sparam
* sizeof(Token
*));
4516 params
[0] = tline
->next
;
4517 paramsize
= nasm_malloc(sparam
* sizeof(int));
4519 while (true) { /* parameter loop */
4521 * For some unusual expansions
4522 * which concatenates function call
4525 while (tok_type_(t
, TOK_SMAC_END
)) {
4526 t
->a
.mac
->in_progress
= false;
4528 t
= tline
->next
= delete_Token(t
);
4534 "macro call expects terminating `)'");
4537 if (tline
->type
== TOK_WHITESPACE
4539 if (paramsize
[nparam
])
4542 params
[nparam
] = tline
->next
;
4543 continue; /* parameter loop */
4545 if (tline
->type
== TOK_OTHER
4546 && tline
->text
[1] == 0) {
4547 char ch
= tline
->text
[0];
4548 if (ch
== ',' && !paren
&& brackets
<= 0) {
4549 if (++nparam
>= sparam
) {
4550 sparam
+= PARAM_DELTA
;
4551 params
= nasm_realloc(params
,
4552 sparam
* sizeof(Token
*));
4553 paramsize
= nasm_realloc(paramsize
,
4554 sparam
* sizeof(int));
4556 params
[nparam
] = tline
->next
;
4557 paramsize
[nparam
] = 0;
4559 continue; /* parameter loop */
4562 (brackets
> 0 || (brackets
== 0 &&
4563 !paramsize
[nparam
])))
4565 if (!(brackets
++)) {
4566 params
[nparam
] = tline
->next
;
4567 continue; /* parameter loop */
4570 if (ch
== '}' && brackets
> 0)
4571 if (--brackets
== 0) {
4573 continue; /* parameter loop */
4575 if (ch
== '(' && !brackets
)
4577 if (ch
== ')' && brackets
<= 0)
4583 error(ERR_NONFATAL
, "braces do not "
4584 "enclose all of macro parameter");
4586 paramsize
[nparam
] += white
+ 1;
4588 } /* parameter loop */
4590 while (m
&& (m
->nparam
!= nparam
||
4591 mstrcmp(m
->name
, mname
,
4595 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4596 "macro `%s' exists, "
4597 "but not taking %d parameters",
4598 mstart
->text
, nparam
);
4601 if (m
&& m
->in_progress
)
4603 if (!m
) { /* in progess or didn't find '(' or wrong nparam */
4605 * Design question: should we handle !tline, which
4606 * indicates missing ')' here, or expand those
4607 * macros anyway, which requires the (t) test a few
4611 nasm_free(paramsize
);
4615 * Expand the macro: we are placed on the last token of the
4616 * call, so that we can easily split the call from the
4617 * following tokens. We also start by pushing an SMAC_END
4618 * token for the cycle removal.
4625 tt
= new_Token(tline
, TOK_SMAC_END
, NULL
, 0);
4627 m
->in_progress
= true;
4629 list_for_each(t
, m
->expansion
) {
4630 if (is_smacro_param(t
)) {
4631 Token
*pcopy
= tline
, **ptail
= &pcopy
;
4635 idx
= smacro_get_param_idx(t
);
4639 * We need smacro paramters appended.
4641 for (i
= paramsize
[idx
]; i
> 0; i
--) {
4642 *ptail
= new_Token(tline
, ttt
->type
, ttt
->text
, 0);
4643 ptail
= &(*ptail
)->next
;
4648 } else if (t
->type
== TOK_PREPROC_Q
) {
4649 tt
= new_Token(tline
, TOK_ID
, mname
, 0);
4651 } else if (t
->type
== TOK_PREPROC_QQ
) {
4652 tt
= new_Token(tline
, TOK_ID
, m
->name
, 0);
4655 tt
= new_Token(tline
, t
->type
, t
->text
, 0);
4661 * Having done that, get rid of the macro call, and clean
4662 * up the parameters.
4665 nasm_free(paramsize
);
4668 continue; /* main token loop */
4673 if (tline
->type
== TOK_SMAC_END
) {
4674 tline
->a
.mac
->in_progress
= false;
4675 tline
= delete_Token(tline
);
4678 tline
= tline
->next
;
4686 * Now scan the entire line and look for successive TOK_IDs that resulted
4687 * after expansion (they can't be produced by tokenize()). The successive
4688 * TOK_IDs should be concatenated.
4689 * Also we look for %+ tokens and concatenate the tokens before and after
4690 * them (without white spaces in between).
4693 const struct tokseq_match t
[] = {
4695 PP_CONCAT_MASK(TOK_ID
) |
4696 PP_CONCAT_MASK(TOK_PREPROC_ID
), /* head */
4697 PP_CONCAT_MASK(TOK_ID
) |
4698 PP_CONCAT_MASK(TOK_PREPROC_ID
) |
4699 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4702 if (paste_tokens(&thead
, t
, ARRAY_SIZE(t
), true)) {
4704 * If we concatenated something, *and* we had previously expanded
4705 * an actual macro, scan the lines again for macros...
4716 *org_tline
= *thead
;
4717 /* since we just gave text to org_line, don't free it */
4719 delete_Token(thead
);
4721 /* the expression expanded to empty line;
4722 we can't return NULL for some reasons
4723 we just set the line to a single WHITESPACE token. */
4724 memset(org_tline
, 0, sizeof(*org_tline
));
4725 org_tline
->text
= NULL
;
4726 org_tline
->type
= TOK_WHITESPACE
;
4735 * Similar to expand_smacro but used exclusively with macro identifiers
4736 * right before they are fetched in. The reason is that there can be
4737 * identifiers consisting of several subparts. We consider that if there
4738 * are more than one element forming the name, user wants a expansion,
4739 * otherwise it will be left as-is. Example:
4743 * the identifier %$abc will be left as-is so that the handler for %define
4744 * will suck it and define the corresponding value. Other case:
4746 * %define _%$abc cde
4748 * In this case user wants name to be expanded *before* %define starts
4749 * working, so we'll expand %$abc into something (if it has a value;
4750 * otherwise it will be left as-is) then concatenate all successive
4753 static Token
*expand_id(Token
* tline
)
4755 Token
*cur
, *oldnext
= NULL
;
4757 if (!tline
|| !tline
->next
)
4762 (cur
->next
->type
== TOK_ID
||
4763 cur
->next
->type
== TOK_PREPROC_ID
||
4764 cur
->next
->type
== TOK_NUMBER
))
4767 /* If identifier consists of just one token, don't expand */
4772 oldnext
= cur
->next
; /* Detach the tail past identifier */
4773 cur
->next
= NULL
; /* so that expand_smacro stops here */
4776 tline
= expand_smacro(tline
);
4779 /* expand_smacro possibly changhed tline; re-scan for EOL */
4781 while (cur
&& cur
->next
)
4784 cur
->next
= oldnext
;
4791 * Determine whether the given line constitutes a multi-line macro
4792 * call, and return the ExpDef structure called if so. Doesn't have
4793 * to check for an initial label - that's taken care of in
4794 * expand_mmacro - but must check numbers of parameters. Guaranteed
4795 * to be called with tline->type == TOK_ID, so the putative macro
4796 * name is easy to find.
4798 static ExpDef
*is_mmacro(Token
* tline
, Token
*** params_array
)
4804 head
= (ExpDef
*) hash_findix(&expdefs
, tline
->text
);
4807 * Efficiency: first we see if any macro exists with the given
4808 * name. If not, we can return NULL immediately. _Then_ we
4809 * count the parameters, and then we look further along the
4810 * list if necessary to find the proper ExpDef.
4812 list_for_each(ed
, head
)
4813 if (!mstrcmp(ed
->name
, tline
->text
, ed
->casesense
))
4819 * OK, we have a potential macro. Count and demarcate the
4822 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
4825 * So we know how many parameters we've got. Find the ExpDef
4826 * structure that handles this number.
4829 if (ed
->nparam_min
<= nparam
4830 && (ed
->plus
|| nparam
<= ed
->nparam_max
)) {
4832 * It's right, and we can use it. Add its default
4833 * parameters to the end of our list if necessary.
4835 if (ed
->defaults
&& nparam
< ed
->nparam_min
+ ed
->ndefs
) {
4837 nasm_realloc(params
,
4838 ((ed
->nparam_min
+ ed
->ndefs
+
4839 1) * sizeof(*params
)));
4840 while (nparam
< ed
->nparam_min
+ ed
->ndefs
) {
4841 params
[nparam
] = ed
->defaults
[nparam
- ed
->nparam_min
];
4846 * If we've gone over the maximum parameter count (and
4847 * we're in Plus mode), ignore parameters beyond
4850 if (ed
->plus
&& nparam
> ed
->nparam_max
)
4851 nparam
= ed
->nparam_max
;
4853 * Then terminate the parameter list, and leave.
4855 if (!params
) { /* need this special case */
4856 params
= nasm_malloc(sizeof(*params
));
4859 params
[nparam
] = NULL
;
4860 *params_array
= params
;
4864 * This one wasn't right: look for the next one with the
4867 list_for_each(ed
, ed
->next
)
4868 if (!mstrcmp(ed
->name
, tline
->text
, ed
->casesense
))
4873 * After all that, we didn't find one with the right number of
4874 * parameters. Issue a warning, and fail to expand the macro.
4876 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4877 "macro `%s' exists, but not taking %d parameters",
4878 tline
->text
, nparam
);
4884 * Expand the multi-line macro call made by the given line, if
4885 * there is one to be expanded. If there is, push the expansion on
4886 * istk->expansion and return true. Otherwise return false.
4888 static bool expand_mmacro(Token
* tline
)
4890 Token
*label
= NULL
;
4891 int dont_prepend
= 0;
4896 int i
, nparam
, *paramlen
;
4901 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4902 if (!tok_type_(t
, TOK_ID
) && !tok_type_(t
, TOK_PREPROC_ID
))
4904 ed
= is_mmacro(t
, ¶ms
);
4910 * We have an id which isn't a macro call. We'll assume
4911 * it might be a label; we'll also check to see if a
4912 * colon follows it. Then, if there's another id after
4913 * that lot, we'll check it again for macro-hood.
4917 if (tok_type_(t
, TOK_WHITESPACE
))
4918 last
= t
, t
= t
->next
;
4919 if (tok_is_(t
, ":")) {
4921 last
= t
, t
= t
->next
;
4922 if (tok_type_(t
, TOK_WHITESPACE
))
4923 last
= t
, t
= t
->next
;
4925 if (!tok_type_(t
, TOK_ID
) || !(ed
= is_mmacro(t
, ¶ms
)))
4933 * Fix up the parameters: this involves stripping leading and
4934 * trailing whitespace, then stripping braces if they are
4937 for (nparam
= 0; params
[nparam
]; nparam
++) ;
4938 paramlen
= nparam
? nasm_malloc(nparam
* sizeof(*paramlen
)) : NULL
;
4940 for (i
= 0; params
[i
]; i
++) {
4942 int comma
= (!ed
->plus
|| i
< nparam
- 1);
4946 if (tok_is_(t
, "{"))
4947 t
= t
->next
, brace
= true, comma
= false;
4951 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
4952 break; /* ... because we have hit a comma */
4953 if (comma
&& t
->type
== TOK_WHITESPACE
4954 && tok_is_(t
->next
, ","))
4955 break; /* ... or a space then a comma */
4956 if (brace
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "}"))
4957 break; /* ... or a brace */
4963 if (ed
->cur_depth
>= ed
->max_depth
) {
4964 if (ed
->max_depth
> 1) {
4966 "reached maximum macro recursion depth of %i for %s",
4967 ed
->max_depth
,ed
->name
);
4975 * OK, we have found a ExpDef structure representing a
4976 * previously defined mmacro. Create an expansion invocation
4977 * and point it back to the expansion definition. Substitution of
4978 * parameter tokens and macro-local tokens doesn't get done
4979 * until the single-line macro substitution process; this is
4980 * because delaying them allows us to change the semantics
4981 * later through %rotate.
4983 ei
= new_ExpInv(EXP_MMACRO
, ed
);
4984 ei
->name
= nasm_strdup(mname
);
4985 //ei->label = label;
4986 //ei->label_text = detoken(label, false);
4987 ei
->current
= ed
->line
;
4988 ei
->emitting
= true;
4989 //ei->iline = tline;
4990 ei
->params
= params
;
4991 ei
->nparam
= nparam
;
4993 ei
->paramlen
= paramlen
;
4996 ei
->prev
= istk
->expansion
;
4997 istk
->expansion
= ei
;
5000 * Special case: detect %00 on first invocation; if found,
5001 * avoid emitting any labels that precede the mmacro call.
5002 * ed->prepend is set to -1 when %00 is detected, else 1.
5004 if (ed
->prepend
== 0) {
5005 for (l
= ed
->line
; l
!= NULL
; l
= l
->next
) {
5006 for (t
= l
->first
; t
!= NULL
; t
= t
->next
) {
5007 if ((t
->type
== TOK_PREPROC_ID
) &&
5008 (strlen(t
->text
) == 3) &&
5009 (t
->text
[1] == '0') && (t
->text
[2] == '0')) {
5014 if (dont_prepend
< 0) {
5018 ed
->prepend
= ((dont_prepend
< 0) ? -1 : 1);
5022 * If we had a label, push it on as the first line of
5023 * the macro expansion.
5025 if (label
!= NULL
) {
5026 if (ed
->prepend
< 0) {
5027 ei
->label_text
= detoken(label
, false);
5029 if (dont_prepend
== 0) {
5031 while (t
->next
!= NULL
) {
5034 t
->next
= new_Token(NULL
, TOK_OTHER
, ":", 0);
5037 l
->first
= copy_Token(label
);
5038 l
->next
= ei
->current
;
5043 list
->uplevel(ed
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
5049 /* The function that actually does the error reporting */
5050 static void verror(int severity
, const char *fmt
, va_list arg
)
5054 vsnprintf(buff
, sizeof(buff
), fmt
, arg
);
5056 if (istk
&& istk
->mmac_depth
> 0) {
5057 ExpInv
*ei
= istk
->expansion
;
5058 int lineno
= ei
->lineno
;
5060 if (ei
->type
== EXP_MMACRO
)
5062 lineno
+= ei
->relno
;
5065 nasm_error(severity
, "(%s:%d) %s", ei
->def
->name
,
5068 nasm_error(severity
, "%s", buff
);
5072 * Since preprocessor always operate only on the line that didn't
5073 * arrived yet, we should always use ERR_OFFBY1.
5075 static void error(int severity
, const char *fmt
, ...)
5079 verror(severity
, fmt
, arg
);
5084 * Because %else etc are evaluated in the state context
5085 * of the previous branch, errors might get lost with error():
5086 * %if 0 ... %else trailing garbage ... %endif
5087 * So %else etc should report errors with this function.
5089 static void error_precond(int severity
, const char *fmt
, ...)
5093 /* Only ignore the error if it's really in a dead branch */
5094 if ((istk
!= NULL
) &&
5095 (istk
->expansion
!= NULL
) &&
5096 (istk
->expansion
->type
== EXP_IF
) &&
5097 (istk
->expansion
->def
->state
== COND_NEVER
))
5101 verror(severity
, fmt
, arg
);
5106 pp_reset(char *file
, int apass
, ListGen
* listgen
, StrList
**deplist
)
5111 istk
= nasm_zalloc(sizeof(Include
));
5112 istk
->fp
= fopen(file
, "r");
5113 src_set_fname(nasm_strdup(file
));
5117 error(ERR_FATAL
|ERR_NOFILE
, "unable to open input file `%s'",
5122 nested_mac_count
= 0;
5123 nested_rep_count
= 0;
5126 if (tasm_compatible_mode
) {
5127 stdmacpos
= nasm_stdmac
;
5129 stdmacpos
= nasm_stdmac_after_tasm
;
5131 any_extrastdmac
= extrastdmac
&& *extrastdmac
;
5136 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
5137 * The caller, however, will also pass in 3 for preprocess-only so
5138 * we can set __PASS__ accordingly.
5140 pass
= apass
> 2 ? 2 : apass
;
5142 dephead
= deptail
= deplist
;
5144 StrList
*sl
= nasm_malloc(strlen(file
)+1+sizeof sl
->next
);
5146 strcpy(sl
->str
, file
);
5148 deptail
= &sl
->next
;
5152 * Define the __PASS__ macro. This is defined here unlike
5153 * all the other builtins, because it is special -- it varies between
5156 t
= nasm_zalloc(sizeof(*t
));
5157 make_tok_num(t
, apass
);
5158 define_smacro(NULL
, "__PASS__", true, 0, t
);
5161 static char *pp_getline(void)
5172 * Fetch a tokenized line, either from the expansion
5173 * buffer or from the input file.
5177 while (1) { /* until we get a line we can use */
5179 * Fetch a tokenized line from the expansion buffer
5181 if (istk
->expansion
!= NULL
) {
5182 ei
= istk
->expansion
;
5183 if (ei
->current
!= NULL
) {
5184 if (ei
->emitting
== false) {
5189 ei
->current
= l
->next
;
5191 tline
= copy_Token(l
->first
);
5192 if (((ei
->type
== EXP_REP
) ||
5193 (ei
->type
== EXP_MMACRO
) ||
5194 (ei
->type
== EXP_WHILE
))
5195 && (ei
->def
->nolist
== false)) {
5196 char *p
= detoken(tline
, false);
5197 list
->line(LIST_MACRO
, p
);
5200 if (ei
->linnum
> -1) {
5201 src_set_linnum(src_get_linnum() + 1);
5204 } else if ((ei
->type
== EXP_REP
) &&
5205 (ei
->def
->cur_depth
< ei
->def
->max_depth
)) {
5206 ei
->def
->cur_depth
++;
5207 ei
->current
= ei
->def
->line
;
5210 } else if ((ei
->type
== EXP_WHILE
) &&
5211 (ei
->def
->cur_depth
< ei
->def
->max_depth
)) {
5212 ei
->current
= ei
->def
->line
;
5214 tline
= copy_Token(ei
->current
->first
);
5215 j
= if_condition(tline
, PP_WHILE
);
5217 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
5218 if (j
== COND_IF_TRUE
) {
5219 ei
->current
= ei
->current
->next
;
5220 ei
->def
->cur_depth
++;
5222 ei
->emitting
= false;
5224 ei
->def
->cur_depth
= ei
->def
->max_depth
;
5228 istk
->expansion
= ei
->prev
;
5231 if ((ei
->emitting
== true) &&
5232 (ed
->max_depth
== DEADMAN_LIMIT
) &&
5233 (ed
->cur_depth
== DEADMAN_LIMIT
)
5235 error(ERR_FATAL
, "runaway expansion detected, aborting");
5237 if (ed
->cur_depth
> 0) {
5239 } else if (ed
->type
!= EXP_MMACRO
) {
5240 expansions
= ed
->prev
;
5243 if ((ei
->type
== EXP_REP
) ||
5244 (ei
->type
== EXP_MMACRO
) ||
5245 (ei
->type
== EXP_WHILE
)) {
5246 list
->downlevel(LIST_MACRO
);
5247 if (ei
->type
== EXP_MMACRO
) {
5252 if (ei
->linnum
> -1) {
5253 src_set_linnum(ei
->linnum
);
5261 * Read in line from input and tokenize
5264 if (line
) { /* from the current input file */
5265 line
= prepreproc(line
);
5266 tline
= tokenize(line
);
5272 * The current file has ended; work down the istk
5277 if (i
->expansion
!= NULL
) {
5279 "end of file while still in an expansion");
5281 /* only set line and file name if there's a next node */
5283 src_set_linnum(i
->lineno
);
5284 nasm_free(src_set_fname(nasm_strdup(i
->fname
)));
5286 if ((i
->next
== NULL
) && (finals
!= NULL
)) {
5288 ei
= new_ExpInv(EXP_FINAL
, NULL
);
5289 ei
->emitting
= true;
5290 ei
->current
= finals
;
5291 istk
->expansion
= ei
;
5296 list
->downlevel(LIST_INCLUDE
);
5299 if (finals
!= NULL
) {
5309 if (defining
== NULL
) {
5310 tline
= expand_mmac_params(tline
);
5314 * Check the line to see if it's a preprocessor directive.
5316 if (do_directive(tline
) == DIRECTIVE_FOUND
) {
5318 } else if (defining
!= NULL
) {
5320 * We're defining an expansion. We emit nothing at all,
5321 * and just shove the tokenized line on to the definition.
5323 if (defining
->ignoring
== false) {
5324 Line
*l
= new_Line();
5326 if (defining
->line
== NULL
) {
5330 defining
->last
->next
= l
;
5336 defining
->linecount
++;
5338 } else if ((istk
->expansion
!= NULL
) &&
5339 (istk
->expansion
->emitting
!= true)) {
5341 * We're in a non-emitting branch of an expansion.
5342 * Emit nothing at all, not even a blank line: when we
5343 * emerge from the expansion we'll give a line-number
5344 * directive so we keep our place correctly.
5349 tline
= expand_smacro(tline
);
5350 if (expand_mmacro(tline
) != true) {
5352 * De-tokenize the line again, and emit it.
5354 line
= detoken(tline
, true);
5365 static void pp_cleanup(int pass
)
5367 if (defining
!= NULL
) {
5368 error(ERR_NONFATAL
, "end of file while still defining an expansion");
5369 while (defining
!= NULL
) {
5370 ExpDef
*ed
= defining
;
5371 defining
= ed
->prev
;
5376 while (cstk
!= NULL
)
5379 while (istk
!= NULL
) {
5383 nasm_free(i
->fname
);
5384 while (i
->expansion
!= NULL
) {
5385 ExpInv
*ei
= i
->expansion
;
5386 i
->expansion
= ei
->prev
;
5393 nasm_free(src_set_fname(NULL
));
5398 while ((i
= ipath
)) {
5406 void pp_include_path(char *path
)
5408 IncPath
*i
= nasm_zalloc(sizeof(IncPath
));
5411 i
->path
= nasm_strdup(path
);
5423 void pp_pre_include(char *fname
)
5425 Token
*inc
, *space
, *name
;
5428 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
5429 space
= new_Token(name
, TOK_WHITESPACE
, NULL
, 0);
5430 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
5438 void pp_pre_define(char *definition
)
5444 equals
= strchr(definition
, '=');
5445 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5446 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
5449 space
->next
= tokenize(definition
);
5459 void pp_pre_undefine(char *definition
)
5464 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5465 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
5466 space
->next
= tokenize(definition
);
5475 * This function is used to assist with "runtime" preprocessor
5476 * directives, e.g. pp_runtime("%define __BITS__ 64");
5478 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
5479 * PASS A VALID STRING TO THIS FUNCTION!!!!!
5482 void pp_runtime(char *definition
)
5486 def
= tokenize(definition
);
5487 if (do_directive(def
) == NO_DIRECTIVE_FOUND
)
5492 void pp_extra_stdmac(macros_t
*macros
)
5494 extrastdmac
= macros
;
5497 static void make_tok_num(Token
* tok
, int64_t val
)
5500 snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
5501 tok
->text
= nasm_strdup(numbuf
);
5502 tok
->type
= TOK_NUMBER
;
5505 struct preproc_ops nasmpp
= {