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 enum pp_exp_type type
; /* expansion type */
248 ExpDef
*def
; /* pointer to expansion definition */
249 char *name
; /* invocation name */
250 Line
*label
; /* pointer to label */
251 char *label_text
; /* pointer to label text */
252 Line
*current
; /* pointer to current line in invocation */
254 Token
**params
; /* actual parameters */
255 Token
*iline
; /* invocation line */
256 unsigned int nparam
, rotate
;
261 int lineno
; /* current line number in expansion */
262 int linnum
; /* line number at invocation */
263 int relno
; /* relative line number at invocation */
267 * To handle an arbitrary level of file inclusion, we maintain a
268 * stack (ie linked list) of these things.
281 * Include search path. This is simply a list of strings which get
282 * prepended, in turn, to the name of an include file, in an
283 * attempt to find the file if it's not in the current directory.
291 * Conditional assembly: we maintain a separate stack of these for
292 * each level of file inclusion. (The only reason we keep the
293 * stacks separate is to ensure that a stray `%endif' in a file
294 * included from within the true branch of a `%if' won't terminate
295 * it and cause confusion: instead, rightly, it'll cause an error.)
299 * These states are for use just after %if or %elif: IF_TRUE
300 * means the condition has evaluated to truth so we are
301 * currently emitting, whereas IF_FALSE means we are not
302 * currently emitting but will start doing so if a %else comes
303 * up. In these states, all directives are admissible: %elif,
304 * %else and %endif. (And of course %if.)
306 COND_IF_TRUE
, COND_IF_FALSE
,
308 * These states come up after a %else: ELSE_TRUE means we're
309 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
310 * any %elif or %else will cause an error.
312 COND_ELSE_TRUE
, COND_ELSE_FALSE
,
314 * These states mean that we're not emitting now, and also that
315 * nothing until %endif will be emitted at all. COND_DONE is
316 * used when we've had our moment of emission
317 * and have now started seeing %elifs. COND_NEVER is used when
318 * the condition construct in question is contained within a
319 * non-emitting branch of a larger condition construct,
320 * or if there is an error.
322 COND_DONE
, COND_NEVER
324 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
327 * These defines are used as the possible return values for do_directive
329 #define NO_DIRECTIVE_FOUND 0
330 #define DIRECTIVE_FOUND 1
333 * This define sets the upper limit for smacro and expansions
335 #define DEADMAN_LIMIT (1 << 20)
338 #define REP_LIMIT ((INT64_C(1) << 62))
340 const struct tokseq_match pp_concat_match
[] = {
342 PP_CONCAT_MASK(TOK_ID
) |
343 PP_CONCAT_MASK(TOK_PREPROC_ID
) |
344 PP_CONCAT_MASK(TOK_NUMBER
) |
345 PP_CONCAT_MASK(TOK_FLOAT
) |
346 PP_CONCAT_MASK(TOK_OTHER
),
348 PP_CONCAT_MASK(TOK_ID
) |
349 PP_CONCAT_MASK(TOK_PREPROC_ID
) |
350 PP_CONCAT_MASK(TOK_NUMBER
) |
351 PP_CONCAT_MASK(TOK_FLOAT
) |
352 PP_CONCAT_MASK(TOK_OTHER
)
357 * Condition codes. Note that we use c_ prefix not C_ because C_ is
358 * used in nasm.h for the "real" condition codes. At _this_ level,
359 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
360 * ones, so we need a different enum...
362 static const char * const conditions
[] = {
363 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
364 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
365 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
368 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
369 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
370 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_RCXZ
, c_S
, c_Z
,
373 static const enum pp_conds inverse_ccs
[] = {
374 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
375 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
,
376 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, -1, c_NS
, c_NZ
379 /* For TASM compatibility we need to be able to recognise TASM compatible
380 * conditional compilation directives. Using the NASM pre-processor does
381 * not work, so we look for them specifically from the following list and
382 * then jam in the equivalent NASM directive into the input stream.
386 TM_ARG
, TM_ELIF
, TM_ELSE
, TM_ENDIF
, TM_IF
, TM_IFDEF
, TM_IFDIFI
,
387 TM_IFNDEF
, TM_INCLUDE
, TM_LOCAL
390 static const char * const tasm_directives
[] = {
391 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
392 "ifndef", "include", "local"
395 static int StackSize
= 4;
396 static char *StackPointer
= "ebp";
397 static int ArgOffset
= 8;
398 static int LocalOffset
= 0;
400 static Context
*cstk
;
401 static Include
*istk
;
402 static IncPath
*ipath
= NULL
;
404 static int pass
; /* HACK: pass 0 = generate dependencies only */
405 static StrList
**dephead
, **deptail
; /* Dependency list */
407 static uint64_t unique
; /* unique identifier numbers */
409 static Line
*predef
= NULL
;
410 static bool do_predef
;
412 static ListGen
*list
;
415 * The current set of expansion definitions we have defined.
417 static struct hash_table expdefs
;
420 * The current set of single-line macros we have defined.
422 static struct hash_table smacros
;
425 * Linked List of all active expansion definitions
427 struct ExpDef
*expansions
= NULL
;
430 * The expansion we are currently defining
432 static ExpDef
*defining
= NULL
;
434 static uint64_t nested_mac_count
;
435 static uint64_t nested_rep_count
;
438 * Linked-list of lines to preprocess, prior to cleanup
440 static Line
*finals
= NULL
;
441 static bool in_final
= false;
444 * The number of macro parameters to allocate space for at a time.
446 #define PARAM_DELTA 16
449 * The standard macro set: defined in macros.c in the array nasm_stdmac.
450 * This gives our position in the macro set, when we're processing it.
452 static macros_t
*stdmacpos
;
455 * The extra standard macros that come from the object format, if
458 static macros_t
*extrastdmac
= NULL
;
459 static bool any_extrastdmac
;
462 * Tokens are allocated in blocks to improve speed
464 #define TOKEN_BLOCKSIZE 4096
465 static Token
*freeTokens
= NULL
;
471 static Blocks blocks
= { NULL
, NULL
};
474 * Forward declarations.
476 static Token
*expand_mmac_params(Token
* tline
);
477 static Token
*expand_smacro(Token
* tline
);
478 static Token
*expand_id(Token
* tline
);
479 static Context
*get_ctx(const char *name
, const char **namep
,
481 static void make_tok_num(Token
* tok
, int64_t val
);
482 static void error(int severity
, const char *fmt
, ...);
483 static void error_precond(int severity
, const char *fmt
, ...);
484 static void *new_Block(size_t size
);
485 static void delete_Blocks(void);
486 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
487 const char *text
, int txtlen
);
488 static Token
*copy_Token(Token
* tline
);
489 static Token
*delete_Token(Token
* t
);
490 static Line
*new_Line(void);
491 static ExpDef
*new_ExpDef(int exp_type
);
492 static ExpInv
*new_ExpInv(int exp_type
, ExpDef
*ed
);
495 * Macros for safe checking of token pointers, avoid *(NULL)
497 #define tok_type_(x,t) ((x) && (x)->type == (t))
498 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
499 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
500 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
504 #define stringify(x) #x
506 #define nasm_trace(msg, ...) printf("(%s:%d): " msg "\n", __func__, __LINE__, __VA_ARGS__)
507 #define nasm_dump_token(t) nasm_raw_dump_token(t, __FILE__, __LINE__, __func__);
509 /* FIXME: we really need some compound type here instead of inplace code */
510 static const char *nasm_get_tok_type_str(enum pp_token_type type
)
512 #define SWITCH_TOK_NAME(type) \
514 return stringify(type)
517 SWITCH_TOK_NAME(TOK_NONE
);
518 SWITCH_TOK_NAME(TOK_WHITESPACE
);
519 SWITCH_TOK_NAME(TOK_COMMENT
);
520 SWITCH_TOK_NAME(TOK_ID
);
521 SWITCH_TOK_NAME(TOK_PREPROC_ID
);
522 SWITCH_TOK_NAME(TOK_STRING
);
523 SWITCH_TOK_NAME(TOK_NUMBER
);
524 SWITCH_TOK_NAME(TOK_FLOAT
);
525 SWITCH_TOK_NAME(TOK_SMAC_END
);
526 SWITCH_TOK_NAME(TOK_OTHER
);
527 SWITCH_TOK_NAME(TOK_INTERNAL_STRING
);
528 SWITCH_TOK_NAME(TOK_PREPROC_Q
);
529 SWITCH_TOK_NAME(TOK_PREPROC_QQ
);
530 SWITCH_TOK_NAME(TOK_PASTE
);
531 SWITCH_TOK_NAME(TOK_INDIRECT
);
532 SWITCH_TOK_NAME(TOK_SMAC_PARAM
);
533 SWITCH_TOK_NAME(TOK_MAX
);
539 static void nasm_raw_dump_token(Token
*token
, const char *file
, int line
, const char *func
)
541 printf("---[%s (%s:%d): %p]---\n", func
, file
, line
, (void *)token
);
544 list_for_each(t
, token
) {
546 printf("'%s'(%s) ", t
->text
,
547 nasm_get_tok_type_str(t
->type
));
554 #define nasm_trace(msg, ...)
555 #define nasm_dump_token(t)
559 * nasm_unquote with error if the string contains NUL characters.
560 * If the string contains NUL characters, issue an error and return
561 * the C len, i.e. truncate at the NUL.
563 static size_t nasm_unquote_cstr(char *qstr
, enum preproc_token directive
)
565 size_t len
= nasm_unquote(qstr
, NULL
);
566 size_t clen
= strlen(qstr
);
569 error(ERR_NONFATAL
, "NUL character in `%s' directive",
570 pp_directives
[directive
]);
576 * In-place reverse a list of tokens.
578 static Token
*reverse_tokens(Token
*t
)
582 list_reverse(t
, prev
, next
);
588 * Handle TASM specific directives, which do not contain a % in
589 * front of them. We do it here because I could not find any other
590 * place to do it for the moment, and it is a hack (ideally it would
591 * be nice to be able to use the NASM pre-processor to do it).
593 static char *check_tasm_directive(char *line
)
595 int32_t i
, j
, k
, m
, len
;
596 char *p
, *q
, *oldline
, oldchar
;
598 p
= nasm_skip_spaces(line
);
600 /* Binary search for the directive name */
602 j
= ARRAY_SIZE(tasm_directives
);
603 q
= nasm_skip_word(p
);
610 m
= nasm_stricmp(p
, tasm_directives
[k
]);
612 /* We have found a directive, so jam a % in front of it
613 * so that NASM will then recognise it as one if it's own.
618 line
= nasm_malloc(len
+ 2);
620 if (k
== TM_IFDIFI
) {
622 * NASM does not recognise IFDIFI, so we convert
623 * it to %if 0. This is not used in NASM
624 * compatible code, but does need to parse for the
625 * TASM macro package.
627 strcpy(line
+ 1, "if 0");
629 memcpy(line
+ 1, p
, len
+ 1);
644 * The pre-preprocessing stage... This function translates line
645 * number indications as they emerge from GNU cpp (`# lineno "file"
646 * flags') into NASM preprocessor line number indications (`%line
649 static char *prepreproc(char *line
)
652 char *fname
, *oldline
;
654 if (line
[0] == '#' && line
[1] == ' ') {
657 lineno
= atoi(fname
);
658 fname
+= strspn(fname
, "0123456789 ");
661 fnlen
= strcspn(fname
, "\"");
662 line
= nasm_malloc(20 + fnlen
);
663 snprintf(line
, 20 + fnlen
, "%%line %d %.*s", lineno
, fnlen
, fname
);
666 if (tasm_compatible_mode
)
667 return check_tasm_directive(line
);
672 * Free a linked list of tokens.
674 static void free_tlist(Token
* list
)
677 list
= delete_Token(list
);
681 * Free a linked list of lines.
683 static void free_llist(Line
* list
)
686 list_for_each_safe(l
, tmp
, list
) {
687 free_tlist(l
->first
);
695 static void free_expdef(ExpDef
* ed
)
698 free_tlist(ed
->dlist
);
699 nasm_free(ed
->defaults
);
700 free_llist(ed
->line
);
707 static void free_expinv(ExpInv
* ei
)
709 if (ei
->name
!= NULL
)
711 if (ei
->label_text
!= NULL
)
712 nasm_free(ei
->label_text
);
717 * Free all currently defined macros, and free the hash tables
719 static void free_smacro_table(struct hash_table
*smt
)
723 struct hash_tbl_node
*it
= NULL
;
725 while ((s
= hash_iterate(smt
, &it
, &key
)) != NULL
) {
726 nasm_free((void *)key
);
727 list_for_each_safe(s
, tmp
, s
) {
729 free_tlist(s
->expansion
);
736 static void free_expdef_table(struct hash_table
*edt
)
740 struct hash_tbl_node
*it
= NULL
;
743 while ((ed
= hash_iterate(edt
, &it
, &key
)) != NULL
) {
744 nasm_free((void *)key
);
745 list_for_each_safe(ed
,tmp
, ed
)
751 static void free_macros(void)
753 free_smacro_table(&smacros
);
754 free_expdef_table(&expdefs
);
758 * Initialize the hash tables
760 static void init_macros(void)
762 hash_init(&smacros
, HASH_LARGE
);
763 hash_init(&expdefs
, HASH_LARGE
);
767 * Pop the context stack.
769 static void ctx_pop(void)
774 free_smacro_table(&c
->localmac
);
780 * Search for a key in the hash index; adding it if necessary
781 * (in which case we initialize the data pointer to NULL.)
784 hash_findi_add(struct hash_table
*hash
, const char *str
)
786 struct hash_insert hi
;
790 r
= hash_findi(hash
, str
, &hi
);
794 strx
= nasm_strdup(str
); /* Use a more efficient allocator here? */
795 return hash_add(&hi
, strx
, NULL
);
799 * Like hash_findi, but returns the data element rather than a pointer
800 * to it. Used only when not adding a new element, hence no third
804 hash_findix(struct hash_table
*hash
, const char *str
)
808 p
= hash_findi(hash
, str
, NULL
);
809 return p
? *p
: NULL
;
813 * read line from standard macros set,
814 * if there no more left -- return NULL
816 static char *line_from_stdmac(void)
819 const unsigned char *p
= stdmacpos
;
828 len
+= pp_directives_len
[c
- 0x80] + 1;
833 line
= nasm_malloc(len
+ 1);
835 while ((c
= *stdmacpos
++)) {
837 memcpy(q
, pp_directives
[c
- 0x80], pp_directives_len
[c
- 0x80]);
838 q
+= pp_directives_len
[c
- 0x80];
848 /* This was the last of the standard macro chain... */
850 if (any_extrastdmac
) {
851 stdmacpos
= extrastdmac
;
852 any_extrastdmac
= false;
853 } else if (do_predef
) {
856 Token
*head
, **tail
, *t
;
859 * Nasty hack: here we push the contents of
860 * `predef' on to the top-level expansion stack,
861 * since this is the most convenient way to
862 * implement the pre-include and pre-define
865 list_for_each(pd
, predef
) {
868 list_for_each(t
, pd
->first
) {
869 *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
870 tail
= &(*tail
)->next
;
875 ei
= new_ExpInv(EXP_PREDEF
, NULL
);
878 ei
->prev
= istk
->expansion
;
879 istk
->expansion
= ei
;
888 #define BUF_DELTA 512
890 * Read a line from the top file in istk, handling multiple CR/LFs
891 * at the end of the line read, and handling spurious ^Zs. Will
892 * return lines from the standard macro set if this has not already
895 static char *read_line(void)
897 char *buffer
, *p
, *q
;
898 int bufsize
, continued_count
;
901 * standart macros set (predefined) goes first
903 p
= line_from_stdmac();
908 * regular read from a file
911 buffer
= nasm_malloc(BUF_DELTA
);
915 q
= fgets(p
, bufsize
- (p
- buffer
), istk
->fp
);
919 if (p
> buffer
&& p
[-1] == '\n') {
921 * Convert backslash-CRLF line continuation sequences into
922 * nothing at all (for DOS and Windows)
924 if (((p
- 2) > buffer
) && (p
[-3] == '\\') && (p
[-2] == '\r')) {
930 * Also convert backslash-LF line continuation sequences into
931 * nothing at all (for Unix)
933 else if (((p
- 1) > buffer
) && (p
[-2] == '\\')) {
941 if (p
- buffer
> bufsize
- 10) {
942 int32_t offset
= p
- buffer
;
943 bufsize
+= BUF_DELTA
;
944 buffer
= nasm_realloc(buffer
, bufsize
);
945 p
= buffer
+ offset
; /* prevent stale-pointer problems */
949 if (!q
&& p
== buffer
) {
954 src_set_linnum(src_get_linnum() + istk
->lineinc
+
955 (continued_count
* istk
->lineinc
));
958 * Play safe: remove CRs as well as LFs, if any of either are
959 * present at the end of the line.
961 while (--p
>= buffer
&& (*p
== '\n' || *p
== '\r'))
965 * Handle spurious ^Z, which may be inserted into source files
966 * by some file transfer utilities.
968 buffer
[strcspn(buffer
, "\032")] = '\0';
970 list
->line(LIST_READ
, buffer
);
976 * Tokenize a line of text. This is a very simple process since we
977 * don't need to parse the value out of e.g. numeric tokens: we
978 * simply split one string into many.
980 static Token
*tokenize(char *line
)
983 enum pp_token_type type
;
985 Token
*t
, **tail
= &list
;
988 nasm_trace("Tokenize for '%s'", line
);
990 if ((defining
!= NULL
) && (defining
->ignoring
== true)) {
998 if (*p
== '+' && !nasm_isdigit(p
[1])) {
1001 } else if (nasm_isdigit(*p
) ||
1002 ((*p
== '-' || *p
== '+') && nasm_isdigit(p
[1]))) {
1006 while (nasm_isdigit(*p
));
1007 type
= TOK_PREPROC_ID
;
1008 } else if (*p
== '{') {
1010 while (*p
&& *p
!= '}') {
1017 type
= TOK_PREPROC_ID
;
1018 } else if (*p
== '[') {
1020 line
+= 2; /* Skip the leading %[ */
1022 while (lvl
&& (c
= *p
++)) {
1034 p
= nasm_skip_string(p
- 1) + 1;
1044 error(ERR_NONFATAL
, "unterminated %[ construct");
1045 type
= TOK_INDIRECT
;
1046 } else if (*p
== '?') {
1047 type
= TOK_PREPROC_Q
; /* %? */
1050 type
= TOK_PREPROC_QQ
; /* %?? */
1053 } else if (*p
== '!') {
1054 type
= TOK_PREPROC_ID
;
1059 } while (isidchar(*p
));
1060 } else if (*p
== '\'' || *p
== '\"' || *p
== '`') {
1061 p
= nasm_skip_string(p
);
1065 error(ERR_NONFATAL
|ERR_PASS1
, "unterminated %! string");
1067 /* %! without string or identifier */
1068 type
= TOK_OTHER
; /* Legacy behavior... */
1070 } else if (isidchar(*p
) ||
1071 ((*p
== '!' || *p
== '%' || *p
== '$') &&
1076 while (isidchar(*p
));
1077 type
= TOK_PREPROC_ID
;
1083 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
1086 while (*p
&& isidchar(*p
))
1088 } else if (*p
== '\'' || *p
== '"' || *p
== '`') {
1093 p
= nasm_skip_string(p
);
1097 } else if(verbose
) {
1098 error(ERR_WARNING
|ERR_PASS1
, "unterminated string");
1099 /* Handling unterminated strings by UNV */
1102 } else if (p
[0] == '$' && p
[1] == '$') {
1103 type
= TOK_OTHER
; /* TOKEN_BASE */
1105 } else if (isnumstart(*p
)) {
1106 bool is_hex
= false;
1107 bool is_float
= false;
1123 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
1125 if (*p
== '+' || *p
== '-') {
1127 * e can only be followed by +/- if it is either a
1128 * prefixed hex number or a floating-point number
1133 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
1135 } else if (c
== 'P' || c
== 'p') {
1137 if (*p
== '+' || *p
== '-')
1139 } else if (isnumchar(c
) || c
== '_')
1140 ; /* just advance */
1141 else if (c
== '.') {
1143 * we need to deal with consequences of the legacy
1144 * parser, like "1.nolist" being two tokens
1145 * (TOK_NUMBER, TOK_ID) here; at least give it
1146 * a shot for now. In the future, we probably need
1147 * a flex-based scanner with proper pattern matching
1148 * to do it as well as it can be done. Nothing in
1149 * the world is going to help the person who wants
1150 * 0x123.p16 interpreted as two tokens, though.
1156 if (nasm_isdigit(*r
) || (is_hex
&& nasm_isxdigit(*r
)) ||
1157 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
1158 (*r
== 'p' || *r
== 'P')) {
1162 break; /* Terminate the token */
1166 p
--; /* Point to first character beyond number */
1168 if (p
== line
+1 && *line
== '$') {
1169 type
= TOK_OTHER
; /* TOKEN_HERE */
1171 if (has_e
&& !is_hex
) {
1172 /* 1e13 is floating-point, but 1e13h is not */
1176 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
1178 } else if (nasm_isspace(*p
)) {
1179 type
= TOK_WHITESPACE
;
1180 p
= nasm_skip_spaces(p
);
1182 * Whitespace just before end-of-line is discarded by
1183 * pretending it's a comment; whitespace just before a
1184 * comment gets lumped into the comment.
1186 if (!*p
|| *p
== ';') {
1191 } else if (*p
== ';') {
1197 * Anything else is an operator of some kind. We check
1198 * for all the double-character operators (>>, <<, //,
1199 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1200 * else is a single-character operator.
1203 if ((p
[0] == '>' && p
[1] == '>') ||
1204 (p
[0] == '<' && p
[1] == '<') ||
1205 (p
[0] == '/' && p
[1] == '/') ||
1206 (p
[0] == '<' && p
[1] == '=') ||
1207 (p
[0] == '>' && p
[1] == '=') ||
1208 (p
[0] == '=' && p
[1] == '=') ||
1209 (p
[0] == '!' && p
[1] == '=') ||
1210 (p
[0] == '<' && p
[1] == '>') ||
1211 (p
[0] == '&' && p
[1] == '&') ||
1212 (p
[0] == '|' && p
[1] == '|') ||
1213 (p
[0] == '^' && p
[1] == '^')) {
1219 /* Handling unterminated string by UNV */
1222 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1223 t->text[p-line] = *line;
1227 if (type
!= TOK_COMMENT
) {
1228 *tail
= t
= new_Token(NULL
, type
, line
, p
- line
);
1234 nasm_dump_token(list
);
1240 * this function allocates a new managed block of memory and
1241 * returns a pointer to the block. The managed blocks are
1242 * deleted only all at once by the delete_Blocks function.
1244 static void *new_Block(size_t size
)
1246 Blocks
*b
= &blocks
;
1248 /* first, get to the end of the linked list */
1252 /* now allocate the requested chunk */
1253 b
->chunk
= nasm_malloc(size
);
1255 /* now allocate a new block for the next request */
1256 b
->next
= nasm_zalloc(sizeof(Blocks
));
1262 * this function deletes all managed blocks of memory
1264 static void delete_Blocks(void)
1266 Blocks
*a
, *b
= &blocks
;
1269 * keep in mind that the first block, pointed to by blocks
1270 * is a static and not dynamically allocated, so we don't
1275 nasm_free(b
->chunk
);
1284 * this function creates a new Token and passes a pointer to it
1285 * back to the caller. It sets the type and text elements, and
1286 * also the a.mac and next elements to NULL.
1288 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
1289 const char *text
, int txtlen
)
1295 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1296 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1297 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1298 freeTokens
[i
].next
= NULL
;
1301 freeTokens
= t
->next
;
1305 if (type
== TOK_WHITESPACE
|| !text
) {
1309 txtlen
= strlen(text
);
1310 t
->text
= nasm_malloc(txtlen
+1);
1311 memcpy(t
->text
, text
, txtlen
);
1312 t
->text
[txtlen
] = '\0';
1317 static Token
*copy_Token(Token
* tline
)
1319 Token
*t
, *tt
, *first
= NULL
, *prev
= NULL
;
1321 for (tt
= tline
; tt
!= NULL
; tt
= tt
->next
) {
1323 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1324 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1325 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1326 freeTokens
[i
].next
= NULL
;
1329 freeTokens
= t
->next
;
1331 t
->text
= tt
->text
? nasm_strdup(tt
->text
) : NULL
;
1332 t
->a
.mac
= tt
->a
.mac
;
1333 t
->a
.len
= tt
->a
.len
;
1345 static Token
*delete_Token(Token
* t
)
1347 Token
*next
= t
->next
;
1349 t
->next
= freeTokens
;
1355 * Convert a line of tokens back into text.
1356 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1357 * will be transformed into ..@ctxnum.xxx
1359 static char *detoken(Token
* tlist
, bool expand_locals
)
1366 list_for_each(t
, tlist
) {
1367 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
1372 if (*v
== '\'' || *v
== '\"' || *v
== '`') {
1373 size_t len
= nasm_unquote(v
, NULL
);
1374 size_t clen
= strlen(v
);
1377 error(ERR_NONFATAL
| ERR_PASS1
,
1378 "NUL character in %! string");
1384 char *p
= getenv(v
);
1386 error(ERR_NONFATAL
| ERR_PASS1
,
1387 "nonexistent environment variable `%s'", v
);
1390 t
->text
= nasm_strdup(p
);
1395 /* Expand local macros here and not during preprocessing */
1396 if (expand_locals
&&
1397 t
->type
== TOK_PREPROC_ID
&& t
->text
&&
1398 t
->text
[0] == '%' && t
->text
[1] == '$') {
1401 Context
*ctx
= get_ctx(t
->text
, &q
, false);
1404 snprintf(buffer
, sizeof(buffer
), "..@%"PRIu32
".", ctx
->number
);
1405 p
= nasm_strcat(buffer
, q
);
1411 /* Expand %? and %?? directives */
1412 if ((istk
->expansion
!= NULL
) &&
1413 ((t
->type
== TOK_PREPROC_Q
) ||
1414 (t
->type
== TOK_PREPROC_QQ
))) {
1416 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
){
1417 if (ei
->type
== EXP_MMACRO
) {
1419 if (t
->type
== TOK_PREPROC_Q
) {
1420 t
->text
= nasm_strdup(ei
->name
);
1422 t
->text
= nasm_strdup(ei
->def
->name
);
1429 if (t
->type
== TOK_WHITESPACE
)
1432 len
+= strlen(t
->text
);
1435 p
= line
= nasm_malloc(len
+ 1);
1437 list_for_each(t
, tlist
) {
1438 if (t
->type
== TOK_WHITESPACE
) {
1440 } else if (t
->text
) {
1452 * Initialize a new Line
1454 static inline Line
*new_Line(void)
1456 return (Line
*)nasm_zalloc(sizeof(Line
));
1461 * Initialize a new Expansion Definition
1463 static ExpDef
*new_ExpDef(int exp_type
)
1465 ExpDef
*ed
= (ExpDef
*)nasm_zalloc(sizeof(ExpDef
));
1466 ed
->type
= exp_type
;
1467 ed
->casesense
= true;
1468 ed
->state
= COND_NEVER
;
1475 * Initialize a new Expansion Instance
1477 static ExpInv
*new_ExpInv(int exp_type
, ExpDef
*ed
)
1479 ExpInv
*ei
= (ExpInv
*)nasm_zalloc(sizeof(ExpInv
));
1480 ei
->type
= exp_type
;
1482 ei
->unique
= ++unique
;
1484 if ((istk
->mmac_depth
< 1) &&
1485 (istk
->expansion
== NULL
) &&
1487 (ed
->type
!= EXP_MMACRO
) &&
1488 (ed
->type
!= EXP_REP
) &&
1489 (ed
->type
!= EXP_WHILE
)) {
1490 ei
->linnum
= src_get_linnum();
1491 src_set_linnum(ei
->linnum
- ed
->linecount
- 1);
1495 if ((istk
->expansion
== NULL
) ||
1496 (ei
->type
== EXP_MMACRO
)) {
1499 ei
->relno
= istk
->expansion
->lineno
;
1501 ei
->relno
-= (ed
->linecount
+ 1);
1508 * A scanner, suitable for use by the expression evaluator, which
1509 * operates on a line of Tokens. Expects a pointer to a pointer to
1510 * the first token in the line to be passed in as its private_data
1513 * FIX: This really needs to be unified with stdscan.
1515 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1517 Token
**tlineptr
= private_data
;
1519 char ourcopy
[MAX_KEYWORD
+1], *p
, *r
, *s
;
1523 *tlineptr
= tline
? tline
->next
: NULL
;
1524 } while (tline
&& (tline
->type
== TOK_WHITESPACE
||
1525 tline
->type
== TOK_COMMENT
));
1528 return tokval
->t_type
= TOKEN_EOS
;
1530 tokval
->t_charptr
= tline
->text
;
1532 if (tline
->text
[0] == '$' && !tline
->text
[1])
1533 return tokval
->t_type
= TOKEN_HERE
;
1534 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[2])
1535 return tokval
->t_type
= TOKEN_BASE
;
1537 if (tline
->type
== TOK_ID
) {
1538 p
= tokval
->t_charptr
= tline
->text
;
1540 tokval
->t_charptr
++;
1541 return tokval
->t_type
= TOKEN_ID
;
1544 for (r
= p
, s
= ourcopy
; *r
; r
++) {
1545 if (r
>= p
+MAX_KEYWORD
)
1546 return tokval
->t_type
= TOKEN_ID
; /* Not a keyword */
1547 *s
++ = nasm_tolower(*r
);
1550 /* right, so we have an identifier sitting in temp storage. now,
1551 * is it actually a register or instruction name, or what? */
1552 return nasm_token_hash(ourcopy
, tokval
);
1555 if (tline
->type
== TOK_NUMBER
) {
1557 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
1558 tokval
->t_charptr
= tline
->text
;
1560 return tokval
->t_type
= TOKEN_ERRNUM
;
1562 return tokval
->t_type
= TOKEN_NUM
;
1565 if (tline
->type
== TOK_FLOAT
) {
1566 return tokval
->t_type
= TOKEN_FLOAT
;
1569 if (tline
->type
== TOK_STRING
) {
1572 bq
= tline
->text
[0];
1573 tokval
->t_charptr
= tline
->text
;
1574 tokval
->t_inttwo
= nasm_unquote(tline
->text
, &ep
);
1576 if (ep
[0] != bq
|| ep
[1] != '\0')
1577 return tokval
->t_type
= TOKEN_ERRSTR
;
1579 return tokval
->t_type
= TOKEN_STR
;
1582 if (tline
->type
== TOK_OTHER
) {
1583 if (!strcmp(tline
->text
, "<<"))
1584 return tokval
->t_type
= TOKEN_SHL
;
1585 if (!strcmp(tline
->text
, ">>"))
1586 return tokval
->t_type
= TOKEN_SHR
;
1587 if (!strcmp(tline
->text
, "//"))
1588 return tokval
->t_type
= TOKEN_SDIV
;
1589 if (!strcmp(tline
->text
, "%%"))
1590 return tokval
->t_type
= TOKEN_SMOD
;
1591 if (!strcmp(tline
->text
, "=="))
1592 return tokval
->t_type
= TOKEN_EQ
;
1593 if (!strcmp(tline
->text
, "<>"))
1594 return tokval
->t_type
= TOKEN_NE
;
1595 if (!strcmp(tline
->text
, "!="))
1596 return tokval
->t_type
= TOKEN_NE
;
1597 if (!strcmp(tline
->text
, "<="))
1598 return tokval
->t_type
= TOKEN_LE
;
1599 if (!strcmp(tline
->text
, ">="))
1600 return tokval
->t_type
= TOKEN_GE
;
1601 if (!strcmp(tline
->text
, "&&"))
1602 return tokval
->t_type
= TOKEN_DBL_AND
;
1603 if (!strcmp(tline
->text
, "^^"))
1604 return tokval
->t_type
= TOKEN_DBL_XOR
;
1605 if (!strcmp(tline
->text
, "||"))
1606 return tokval
->t_type
= TOKEN_DBL_OR
;
1610 * We have no other options: just return the first character of
1613 return tokval
->t_type
= tline
->text
[0];
1617 * Compare a string to the name of an existing macro; this is a
1618 * simple wrapper which calls either strcmp or nasm_stricmp
1619 * depending on the value of the `casesense' parameter.
1621 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
1623 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
1627 * Compare a string to the name of an existing macro; this is a
1628 * simple wrapper which calls either strcmp or nasm_stricmp
1629 * depending on the value of the `casesense' parameter.
1631 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
1633 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
1637 * Return the Context structure associated with a %$ token. Return
1638 * NULL, having _already_ reported an error condition, if the
1639 * context stack isn't deep enough for the supplied number of $
1641 * If all_contexts == true, contexts that enclose current are
1642 * also scanned for such smacro, until it is found; if not -
1643 * only the context that directly results from the number of $'s
1644 * in variable's name.
1646 * If "namep" is non-NULL, set it to the pointer to the macro name
1647 * tail, i.e. the part beyond %$...
1649 static Context
*get_ctx(const char *name
, const char **namep
,
1659 if (!name
|| name
[0] != '%' || name
[1] != '$')
1663 error(ERR_NONFATAL
, "`%s': context stack is empty", name
);
1670 while (ctx
&& *name
== '$') {
1676 error(ERR_NONFATAL
, "`%s': context stack is only"
1677 " %d level%s deep", name
, i
, (i
== 1 ? "" : "s"));
1688 /* Search for this smacro in found context */
1689 m
= hash_findix(&ctx
->localmac
, name
);
1691 if (!mstrcmp(m
->name
, name
, m
->casesense
))
1702 * Check to see if a file is already in a string list
1704 static bool in_list(const StrList
*list
, const char *str
)
1707 if (!strcmp(list
->str
, str
))
1715 * Open an include file. This routine must always return a valid
1716 * file pointer if it returns - it's responsible for throwing an
1717 * ERR_FATAL and bombing out completely if not. It should also try
1718 * the include path one by one until it finds the file or reaches
1719 * the end of the path.
1721 static FILE *inc_fopen(const char *file
, StrList
**dhead
, StrList
***dtail
,
1726 IncPath
*ip
= ipath
;
1727 int len
= strlen(file
);
1728 size_t prefix_len
= 0;
1732 sl
= nasm_malloc(prefix_len
+len
+1+sizeof sl
->next
);
1734 memcpy(sl
->str
, prefix
, prefix_len
);
1735 memcpy(sl
->str
+prefix_len
, file
, len
+1);
1736 fp
= fopen(sl
->str
, "r");
1737 if (fp
&& dhead
&& !in_list(*dhead
, sl
->str
)) {
1754 prefix_len
= strlen(prefix
);
1756 /* -MG given and file not found */
1757 if (dhead
&& !in_list(*dhead
, file
)) {
1758 sl
= nasm_malloc(len
+1+sizeof sl
->next
);
1760 strcpy(sl
->str
, file
);
1768 error(ERR_FATAL
, "unable to open include file `%s'", file
);
1773 * Determine if we should warn on defining a single-line macro of
1774 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1775 * return true if _any_ single-line macro of that name is defined.
1776 * Otherwise, will return true if a single-line macro with either
1777 * `nparam' or no parameters is defined.
1779 * If a macro with precisely the right number of parameters is
1780 * defined, or nparam is -1, the address of the definition structure
1781 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1782 * is NULL, no action will be taken regarding its contents, and no
1785 * Note that this is also called with nparam zero to resolve
1788 * If you already know which context macro belongs to, you can pass
1789 * the context pointer as first parameter; if you won't but name begins
1790 * with %$ the context will be automatically computed. If all_contexts
1791 * is true, macro will be searched in outer contexts as well.
1794 smacro_defined(Context
* ctx
, const char *name
, int nparam
, SMacro
** defn
,
1797 struct hash_table
*smtbl
;
1801 smtbl
= &ctx
->localmac
;
1802 } else if (name
[0] == '%' && name
[1] == '$') {
1804 ctx
= get_ctx(name
, &name
, false);
1806 return false; /* got to return _something_ */
1807 smtbl
= &ctx
->localmac
;
1811 m
= (SMacro
*) hash_findix(smtbl
, name
);
1814 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
1815 (nparam
<= 0 || m
->nparam
== 0 || nparam
== (int) m
->nparam
)) {
1817 if (nparam
== (int) m
->nparam
|| nparam
== -1)
1831 * Count and mark off the parameters in a multi-line macro call.
1832 * This is called both from within the multi-line macro expansion
1833 * code, and also to mark off the default parameters when provided
1834 * in a %macro definition line.
1836 static void count_mmac_params(Token
* t
, int *nparam
, Token
*** params
)
1838 int paramsize
, brace
;
1840 *nparam
= paramsize
= 0;
1843 /* +1: we need space for the final NULL */
1844 if (*nparam
+1 >= paramsize
) {
1845 paramsize
+= PARAM_DELTA
;
1846 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
1850 if (tok_is_(t
, "{"))
1852 (*params
)[(*nparam
)++] = t
;
1853 while (tok_isnt_(t
, brace
? "}" : ","))
1855 if (t
) { /* got a comma/brace */
1859 * Now we've found the closing brace, look further
1863 if (tok_isnt_(t
, ",")) {
1865 "braces do not enclose all of macro parameter");
1866 while (tok_isnt_(t
, ","))
1870 t
= t
->next
; /* eat the comma */
1877 * Determine whether one of the various `if' conditions is true or
1880 * We must free the tline we get passed.
1882 static bool if_condition(Token
* tline
, enum preproc_token ct
)
1884 enum pp_conditional i
= PP_COND(ct
);
1886 Token
*t
, *tt
, **tptr
, *origline
;
1887 struct tokenval tokval
;
1889 enum pp_token_type needtype
;
1896 j
= false; /* have we matched yet? */
1901 if (tline
->type
!= TOK_ID
) {
1903 "`%s' expects context identifiers", pp_directives
[ct
]);
1904 free_tlist(origline
);
1907 if (cstk
&& cstk
->name
&& !nasm_stricmp(tline
->text
, cstk
->name
))
1909 tline
= tline
->next
;
1914 j
= false; /* have we matched yet? */
1917 if (!tline
|| (tline
->type
!= TOK_ID
&&
1918 (tline
->type
!= TOK_PREPROC_ID
||
1919 tline
->text
[1] != '$'))) {
1921 "`%s' expects macro identifiers", pp_directives
[ct
]);
1924 if (smacro_defined(NULL
, tline
->text
, 0, NULL
, true))
1926 tline
= tline
->next
;
1931 tline
= expand_smacro(tline
);
1932 j
= false; /* have we matched yet? */
1935 if (!tline
|| (tline
->type
!= TOK_ID
&&
1936 tline
->type
!= TOK_STRING
&&
1937 (tline
->type
!= TOK_PREPROC_ID
||
1938 tline
->text
[1] != '!'))) {
1940 "`%s' expects environment variable names",
1945 if (tline
->type
== TOK_PREPROC_ID
)
1946 p
+= 2; /* Skip leading %! */
1947 if (*p
== '\'' || *p
== '\"' || *p
== '`')
1948 nasm_unquote_cstr(p
, ct
);
1951 tline
= tline
->next
;
1957 tline
= expand_smacro(tline
);
1959 while (tok_isnt_(tt
, ","))
1963 "`%s' expects two comma-separated arguments",
1968 j
= true; /* assume equality unless proved not */
1969 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1970 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1971 error(ERR_NONFATAL
, "`%s': more than one comma on line",
1975 if (t
->type
== TOK_WHITESPACE
) {
1979 if (tt
->type
== TOK_WHITESPACE
) {
1983 if (tt
->type
!= t
->type
) {
1984 j
= false; /* found mismatching tokens */
1987 /* When comparing strings, need to unquote them first */
1988 if (t
->type
== TOK_STRING
) {
1989 size_t l1
= nasm_unquote(t
->text
, NULL
);
1990 size_t l2
= nasm_unquote(tt
->text
, NULL
);
1996 if (mmemcmp(t
->text
, tt
->text
, l1
, i
== PPC_IFIDN
)) {
2000 } else if (mstrcmp(tt
->text
, t
->text
, i
== PPC_IFIDN
) != 0) {
2001 j
= false; /* found mismatching tokens */
2008 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
2009 j
= false; /* trailing gunk on one end or other */
2015 ExpDef searching
, *ed
;
2018 tline
= expand_id(tline
);
2019 if (!tok_type_(tline
, TOK_ID
)) {
2021 "`%s' expects a macro name", pp_directives
[ct
]);
2024 memset(&searching
, 0, sizeof(searching
));
2025 searching
.name
= nasm_strdup(tline
->text
);
2026 searching
.casesense
= true;
2027 searching
.nparam_max
= INT_MAX
;
2028 tline
= expand_smacro(tline
->next
);
2031 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2033 "`%s' expects a parameter count or nothing",
2036 searching
.nparam_min
= searching
.nparam_max
=
2037 readnum(tline
->text
, &j
);
2040 "unable to parse parameter count `%s'",
2043 if (tline
&& tok_is_(tline
->next
, "-")) {
2044 tline
= tline
->next
->next
;
2045 if (tok_is_(tline
, "*"))
2046 searching
.nparam_max
= INT_MAX
;
2047 else if (!tok_type_(tline
, TOK_NUMBER
))
2049 "`%s' expects a parameter count after `-'",
2052 searching
.nparam_max
= readnum(tline
->text
, &j
);
2055 "unable to parse parameter count `%s'",
2057 if (searching
.nparam_min
> searching
.nparam_max
)
2059 "minimum parameter count exceeds maximum");
2062 if (tline
&& tok_is_(tline
->next
, "+")) {
2063 tline
= tline
->next
;
2064 searching
.plus
= true;
2066 ed
= (ExpDef
*) hash_findix(&expdefs
, searching
.name
);
2067 while (ed
!= NULL
) {
2068 if (!strcmp(ed
->name
, searching
.name
) &&
2069 (ed
->nparam_min
<= searching
.nparam_max
|| searching
.plus
) &&
2070 (searching
.nparam_min
<= ed
->nparam_max
|| ed
->plus
)) {
2076 if (tline
&& tline
->next
)
2077 error(ERR_WARNING
|ERR_PASS1
,
2078 "trailing garbage after %%ifmacro ignored");
2079 nasm_free(searching
.name
);
2088 needtype
= TOK_NUMBER
;
2091 needtype
= TOK_STRING
;
2095 t
= tline
= expand_smacro(tline
);
2097 while (tok_type_(t
, TOK_WHITESPACE
) ||
2098 (needtype
== TOK_NUMBER
&&
2099 tok_type_(t
, TOK_OTHER
) &&
2100 (t
->text
[0] == '-' || t
->text
[0] == '+') &&
2104 j
= tok_type_(t
, needtype
);
2108 t
= tline
= expand_smacro(tline
);
2109 while (tok_type_(t
, TOK_WHITESPACE
))
2114 t
= t
->next
; /* Skip the actual token */
2115 while (tok_type_(t
, TOK_WHITESPACE
))
2117 j
= !t
; /* Should be nothing left */
2122 t
= tline
= expand_smacro(tline
);
2123 while (tok_type_(t
, TOK_WHITESPACE
))
2126 j
= !t
; /* Should be empty */
2130 t
= tline
= expand_smacro(tline
);
2132 tokval
.t_type
= TOKEN_INVALID
;
2133 evalresult
= evaluate(ppscan
, tptr
, &tokval
,
2134 NULL
, pass
| CRITICAL
, error
, NULL
);
2138 error(ERR_WARNING
|ERR_PASS1
,
2139 "trailing garbage after expression ignored");
2140 if (!is_simple(evalresult
)) {
2142 "non-constant value given to `%s'", pp_directives
[ct
]);
2145 j
= reloc_value(evalresult
) != 0;
2150 "preprocessor directive `%s' not yet implemented",
2155 free_tlist(origline
);
2156 return j
^ PP_NEGATIVE(ct
);
2159 free_tlist(origline
);
2164 * Common code for defining an smacro
2166 static bool define_smacro(Context
*ctx
, const char *mname
, bool casesense
,
2167 int nparam
, Token
*expansion
)
2169 SMacro
*smac
, **smhead
;
2170 struct hash_table
*smtbl
;
2172 if (smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
)) {
2174 error(ERR_WARNING
|ERR_PASS1
,
2175 "single-line macro `%s' defined both with and"
2176 " without parameters", mname
);
2178 * Some instances of the old code considered this a failure,
2179 * some others didn't. What is the right thing to do here?
2181 free_tlist(expansion
);
2182 return false; /* Failure */
2185 * We're redefining, so we have to take over an
2186 * existing SMacro structure. This means freeing
2187 * what was already in it.
2189 nasm_free(smac
->name
);
2190 free_tlist(smac
->expansion
);
2193 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2194 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
2195 smac
= nasm_zalloc(sizeof(SMacro
));
2196 smac
->next
= *smhead
;
2199 smac
->name
= nasm_strdup(mname
);
2200 smac
->casesense
= casesense
;
2201 smac
->nparam
= nparam
;
2202 smac
->expansion
= expansion
;
2203 smac
->in_progress
= false;
2204 return true; /* Success */
2208 * Undefine an smacro
2210 static void undef_smacro(Context
*ctx
, const char *mname
)
2212 SMacro
**smhead
, *s
, **sp
;
2213 struct hash_table
*smtbl
;
2215 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2216 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
2220 * We now have a macro name... go hunt for it.
2223 while ((s
= *sp
) != NULL
) {
2224 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
2227 free_tlist(s
->expansion
);
2237 * Parse a mmacro specification.
2239 static bool parse_mmacro_spec(Token
*tline
, ExpDef
*def
, const char *directive
)
2243 tline
= tline
->next
;
2245 tline
= expand_id(tline
);
2246 if (!tok_type_(tline
, TOK_ID
)) {
2247 error(ERR_NONFATAL
, "`%s' expects a macro name", directive
);
2251 def
->name
= nasm_strdup(tline
->text
);
2253 def
->nolist
= false;
2254 // def->in_progress = 0;
2255 // def->rep_nest = NULL;
2256 def
->nparam_min
= 0;
2257 def
->nparam_max
= 0;
2259 tline
= expand_smacro(tline
->next
);
2261 if (!tok_type_(tline
, TOK_NUMBER
)) {
2262 error(ERR_NONFATAL
, "`%s' expects a parameter count", directive
);
2264 def
->nparam_min
= def
->nparam_max
=
2265 readnum(tline
->text
, &err
);
2268 "unable to parse parameter count `%s'", tline
->text
);
2270 if (tline
&& tok_is_(tline
->next
, "-")) {
2271 tline
= tline
->next
->next
;
2272 if (tok_is_(tline
, "*")) {
2273 def
->nparam_max
= INT_MAX
;
2274 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2276 "`%s' expects a parameter count after `-'", directive
);
2278 def
->nparam_max
= readnum(tline
->text
, &err
);
2280 error(ERR_NONFATAL
, "unable to parse parameter count `%s'",
2283 if (def
->nparam_min
> def
->nparam_max
) {
2284 error(ERR_NONFATAL
, "minimum parameter count exceeds maximum");
2288 if (tline
&& tok_is_(tline
->next
, "+")) {
2289 tline
= tline
->next
;
2292 if (tline
&& tok_type_(tline
->next
, TOK_ID
) &&
2293 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
2294 tline
= tline
->next
;
2299 * Handle default parameters.
2301 if (tline
&& tline
->next
) {
2302 def
->dlist
= tline
->next
;
2304 count_mmac_params(def
->dlist
, &def
->ndefs
, &def
->defaults
);
2307 def
->defaults
= NULL
;
2311 if (def
->defaults
&& def
->ndefs
> def
->nparam_max
- def
->nparam_min
&&
2313 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MDP
,
2314 "too many default macro parameters");
2321 * Decode a size directive
2323 static int parse_size(const char *str
) {
2324 static const char *size_names
[] =
2325 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2326 static const int sizes
[] =
2327 { 0, 1, 4, 16, 8, 10, 2, 32 };
2329 return sizes
[bsii(str
, size_names
, ARRAY_SIZE(size_names
))+1];
2333 * find and process preprocessor directive in passed line
2334 * Find out if a line contains a preprocessor directive, and deal
2337 * If a directive _is_ found, it is the responsibility of this routine
2338 * (and not the caller) to free_tlist() the line.
2340 * @param tline a pointer to the current tokeninzed line linked list
2341 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2344 static int do_directive(Token
* tline
)
2346 enum preproc_token i
;
2359 Token
*t
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
2360 struct tokenval tokval
;
2362 ExpDef
*ed
, *eed
, **edhead
;
2371 if (!tline
|| !tok_type_(tline
, TOK_PREPROC_ID
) ||
2372 (tline
->text
[1] == '%' || tline
->text
[1] == '$'
2373 || tline
->text
[1] == '!'))
2374 return NO_DIRECTIVE_FOUND
;
2376 i
= pp_token_hash(tline
->text
);
2380 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2381 error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2383 return NO_DIRECTIVE_FOUND
; /* didn't get it */
2386 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2387 /* Directive to tell NASM what the default stack size is. The
2388 * default is for a 16-bit stack, and this can be overriden with
2391 tline
= tline
->next
;
2392 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2393 tline
= tline
->next
;
2394 if (!tline
|| tline
->type
!= TOK_ID
) {
2395 error(ERR_NONFATAL
, "`%%stacksize' missing size parameter");
2396 free_tlist(origline
);
2397 return DIRECTIVE_FOUND
;
2399 if (nasm_stricmp(tline
->text
, "flat") == 0) {
2400 /* All subsequent ARG directives are for a 32-bit stack */
2402 StackPointer
= "ebp";
2405 } else if (nasm_stricmp(tline
->text
, "flat64") == 0) {
2406 /* All subsequent ARG directives are for a 64-bit stack */
2408 StackPointer
= "rbp";
2411 } else if (nasm_stricmp(tline
->text
, "large") == 0) {
2412 /* All subsequent ARG directives are for a 16-bit stack,
2413 * far function call.
2416 StackPointer
= "bp";
2419 } else if (nasm_stricmp(tline
->text
, "small") == 0) {
2420 /* All subsequent ARG directives are for a 16-bit stack,
2421 * far function call. We don't support near functions.
2424 StackPointer
= "bp";
2428 error(ERR_NONFATAL
, "`%%stacksize' invalid size type");
2429 free_tlist(origline
);
2430 return DIRECTIVE_FOUND
;
2432 free_tlist(origline
);
2433 return DIRECTIVE_FOUND
;
2436 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2437 /* TASM like ARG directive to define arguments to functions, in
2438 * the following form:
2440 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2444 char *arg
, directive
[256];
2445 int size
= StackSize
;
2447 /* Find the argument name */
2448 tline
= tline
->next
;
2449 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2450 tline
= tline
->next
;
2451 if (!tline
|| tline
->type
!= TOK_ID
) {
2452 error(ERR_NONFATAL
, "`%%arg' missing argument parameter");
2453 free_tlist(origline
);
2454 return DIRECTIVE_FOUND
;
2458 /* Find the argument size type */
2459 tline
= tline
->next
;
2460 if (!tline
|| tline
->type
!= TOK_OTHER
2461 || tline
->text
[0] != ':') {
2463 "Syntax error processing `%%arg' directive");
2464 free_tlist(origline
);
2465 return DIRECTIVE_FOUND
;
2467 tline
= tline
->next
;
2468 if (!tline
|| tline
->type
!= TOK_ID
) {
2469 error(ERR_NONFATAL
, "`%%arg' missing size type parameter");
2470 free_tlist(origline
);
2471 return DIRECTIVE_FOUND
;
2474 /* Allow macro expansion of type parameter */
2475 tt
= tokenize(tline
->text
);
2476 tt
= expand_smacro(tt
);
2477 size
= parse_size(tt
->text
);
2480 "Invalid size type for `%%arg' missing directive");
2482 free_tlist(origline
);
2483 return DIRECTIVE_FOUND
;
2487 /* Round up to even stack slots */
2488 size
= ALIGN(size
, StackSize
);
2490 /* Now define the macro for the argument */
2491 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
2492 arg
, StackPointer
, offset
);
2493 do_directive(tokenize(directive
));
2496 /* Move to the next argument in the list */
2497 tline
= tline
->next
;
2498 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2499 tline
= tline
->next
;
2500 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2502 free_tlist(origline
);
2503 return DIRECTIVE_FOUND
;
2506 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2507 /* TASM like LOCAL directive to define local variables for a
2508 * function, in the following form:
2510 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2512 * The '= LocalSize' at the end is ignored by NASM, but is
2513 * required by TASM to define the local parameter size (and used
2514 * by the TASM macro package).
2516 offset
= LocalOffset
;
2518 char *local
, directive
[256];
2519 int size
= StackSize
;
2521 /* Find the argument name */
2522 tline
= tline
->next
;
2523 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2524 tline
= tline
->next
;
2525 if (!tline
|| tline
->type
!= TOK_ID
) {
2527 "`%%local' missing argument parameter");
2528 free_tlist(origline
);
2529 return DIRECTIVE_FOUND
;
2531 local
= tline
->text
;
2533 /* Find the argument size type */
2534 tline
= tline
->next
;
2535 if (!tline
|| tline
->type
!= TOK_OTHER
2536 || tline
->text
[0] != ':') {
2538 "Syntax error processing `%%local' directive");
2539 free_tlist(origline
);
2540 return DIRECTIVE_FOUND
;
2542 tline
= tline
->next
;
2543 if (!tline
|| tline
->type
!= TOK_ID
) {
2545 "`%%local' missing size type parameter");
2546 free_tlist(origline
);
2547 return DIRECTIVE_FOUND
;
2550 /* Allow macro expansion of type parameter */
2551 tt
= tokenize(tline
->text
);
2552 tt
= expand_smacro(tt
);
2553 size
= parse_size(tt
->text
);
2556 "Invalid size type for `%%local' missing directive");
2558 free_tlist(origline
);
2559 return DIRECTIVE_FOUND
;
2563 /* Round up to even stack slots */
2564 size
= ALIGN(size
, StackSize
);
2566 offset
+= size
; /* Negative offset, increment before */
2568 /* Now define the macro for the argument */
2569 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
2570 local
, StackPointer
, offset
);
2571 do_directive(tokenize(directive
));
2573 /* Now define the assign to setup the enter_c macro correctly */
2574 snprintf(directive
, sizeof(directive
),
2575 "%%assign %%$localsize %%$localsize+%d", size
);
2576 do_directive(tokenize(directive
));
2578 /* Move to the next argument in the list */
2579 tline
= tline
->next
;
2580 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2581 tline
= tline
->next
;
2582 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2583 LocalOffset
= offset
;
2584 free_tlist(origline
);
2585 return DIRECTIVE_FOUND
;
2588 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2590 error(ERR_WARNING
|ERR_PASS1
,
2591 "trailing garbage after `%%clear' ignored");
2594 free_tlist(origline
);
2595 return DIRECTIVE_FOUND
;
2598 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2599 t
= tline
->next
= expand_smacro(tline
->next
);
2601 if (!t
|| (t
->type
!= TOK_STRING
&&
2602 t
->type
!= TOK_INTERNAL_STRING
)) {
2603 error(ERR_NONFATAL
, "`%%depend' expects a file name");
2604 free_tlist(origline
);
2605 return DIRECTIVE_FOUND
; /* but we did _something_ */
2608 error(ERR_WARNING
|ERR_PASS1
,
2609 "trailing garbage after `%%depend' ignored");
2611 if (t
->type
!= TOK_INTERNAL_STRING
)
2612 nasm_unquote_cstr(p
, i
);
2613 if (dephead
&& !in_list(*dephead
, p
)) {
2614 StrList
*sl
= nasm_malloc(strlen(p
)+1+sizeof sl
->next
);
2618 deptail
= &sl
->next
;
2620 free_tlist(origline
);
2621 return DIRECTIVE_FOUND
;
2624 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2625 t
= tline
->next
= expand_smacro(tline
->next
);
2628 if (!t
|| (t
->type
!= TOK_STRING
&&
2629 t
->type
!= TOK_INTERNAL_STRING
)) {
2630 error(ERR_NONFATAL
, "`%%include' expects a file name");
2631 free_tlist(origline
);
2632 return DIRECTIVE_FOUND
; /* but we did _something_ */
2635 error(ERR_WARNING
|ERR_PASS1
,
2636 "trailing garbage after `%%include' ignored");
2638 if (t
->type
!= TOK_INTERNAL_STRING
)
2639 nasm_unquote_cstr(p
, i
);
2640 inc
= nasm_zalloc(sizeof(Include
));
2642 inc
->fp
= inc_fopen(p
, dephead
, &deptail
, pass
== 0);
2644 /* -MG given but file not found */
2647 inc
->fname
= src_set_fname(nasm_strdup(p
));
2648 inc
->lineno
= src_set_linnum(0);
2650 inc
->expansion
= NULL
;
2652 list
->uplevel(LIST_INCLUDE
);
2654 free_tlist(origline
);
2655 return DIRECTIVE_FOUND
;
2658 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2660 static macros_t
*use_pkg
;
2661 const char *pkg_macro
= NULL
;
2663 tline
= tline
->next
;
2665 tline
= expand_id(tline
);
2667 if (!tline
|| (tline
->type
!= TOK_STRING
&&
2668 tline
->type
!= TOK_INTERNAL_STRING
&&
2669 tline
->type
!= TOK_ID
)) {
2670 error(ERR_NONFATAL
, "`%%use' expects a package name");
2671 free_tlist(origline
);
2672 return DIRECTIVE_FOUND
; /* but we did _something_ */
2675 error(ERR_WARNING
|ERR_PASS1
,
2676 "trailing garbage after `%%use' ignored");
2677 if (tline
->type
== TOK_STRING
)
2678 nasm_unquote_cstr(tline
->text
, i
);
2679 use_pkg
= nasm_stdmac_find_package(tline
->text
);
2681 error(ERR_NONFATAL
, "unknown `%%use' package: %s", tline
->text
);
2683 pkg_macro
= (char *)use_pkg
+ 1; /* The first string will be <%define>__USE_*__ */
2684 if (use_pkg
&& ! smacro_defined(NULL
, pkg_macro
, 0, NULL
, true)) {
2685 /* Not already included, go ahead and include it */
2686 stdmacpos
= use_pkg
;
2688 free_tlist(origline
);
2689 return DIRECTIVE_FOUND
;
2694 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2695 tline
= tline
->next
;
2697 tline
= expand_id(tline
);
2699 if (!tok_type_(tline
, TOK_ID
)) {
2700 error(ERR_NONFATAL
, "`%s' expects a context identifier",
2702 free_tlist(origline
);
2703 return DIRECTIVE_FOUND
; /* but we did _something_ */
2706 error(ERR_WARNING
|ERR_PASS1
,
2707 "trailing garbage after `%s' ignored",
2709 p
= nasm_strdup(tline
->text
);
2711 p
= NULL
; /* Anonymous */
2715 ctx
= nasm_zalloc(sizeof(Context
));
2717 hash_init(&ctx
->localmac
, HASH_SMALL
);
2719 ctx
->number
= unique
++;
2724 error(ERR_NONFATAL
, "`%s': context stack is empty",
2726 } else if (i
== PP_POP
) {
2727 if (p
&& (!cstk
->name
|| nasm_stricmp(p
, cstk
->name
)))
2728 error(ERR_NONFATAL
, "`%%pop' in wrong context: %s, "
2730 cstk
->name
? cstk
->name
: "anonymous", p
);
2735 nasm_free(cstk
->name
);
2741 free_tlist(origline
);
2742 return DIRECTIVE_FOUND
;
2744 severity
= ERR_FATAL
;
2747 severity
= ERR_NONFATAL
;
2750 severity
= ERR_WARNING
|ERR_WARN_USER
;
2754 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2756 /* Only error out if this is the final pass */
2757 if (pass
!= 2 && i
!= PP_FATAL
)
2758 return DIRECTIVE_FOUND
;
2760 tline
->next
= expand_smacro(tline
->next
);
2761 tline
= tline
->next
;
2763 t
= tline
? tline
->next
: NULL
;
2765 if (tok_type_(tline
, TOK_STRING
) && !t
) {
2766 /* The line contains only a quoted string */
2768 nasm_unquote(p
, NULL
); /* Ignore NUL character truncation */
2769 error(severity
, "%s", p
);
2771 /* Not a quoted string, or more than a quoted string */
2772 p
= detoken(tline
, false);
2773 error(severity
, "%s", p
);
2776 free_tlist(origline
);
2777 return DIRECTIVE_FOUND
;
2781 if (defining
!= NULL
) {
2782 if (defining
->type
== EXP_IF
) {
2783 defining
->def_depth
++;
2785 return NO_DIRECTIVE_FOUND
;
2787 if ((istk
->expansion
!= NULL
) &&
2788 (istk
->expansion
->emitting
== false)) {
2791 j
= if_condition(tline
->next
, i
);
2792 tline
->next
= NULL
; /* it got freed */
2793 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
2795 ed
= new_ExpDef(EXP_IF
);
2801 ed
->ignoring
= ((ed
->state
== COND_IF_TRUE
) ? false : true);
2802 ed
->prev
= defining
;
2804 free_tlist(origline
);
2805 return DIRECTIVE_FOUND
;
2808 if (defining
!= NULL
) {
2809 if ((defining
->type
!= EXP_IF
) || (defining
->def_depth
> 0)) {
2810 return NO_DIRECTIVE_FOUND
;
2813 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2814 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2816 switch (defining
->state
) {
2818 defining
->state
= COND_DONE
;
2819 defining
->ignoring
= true;
2824 defining
->ignoring
= true;
2827 case COND_ELSE_TRUE
:
2828 case COND_ELSE_FALSE
:
2829 error_precond(ERR_WARNING
|ERR_PASS1
,
2830 "`%%elif' after `%%else' ignored");
2831 defining
->state
= COND_NEVER
;
2832 defining
->ignoring
= true;
2837 * IMPORTANT: In the case of %if, we will already have
2838 * called expand_mmac_params(); however, if we're
2839 * processing an %elif we must have been in a
2840 * non-emitting mode, which would have inhibited
2841 * the normal invocation of expand_mmac_params().
2842 * Therefore, we have to do it explicitly here.
2844 j
= if_condition(expand_mmac_params(tline
->next
), i
);
2845 tline
->next
= NULL
; /* it got freed */
2847 j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2848 defining
->ignoring
= ((defining
->state
== COND_IF_TRUE
) ? false : true);
2851 free_tlist(origline
);
2852 return DIRECTIVE_FOUND
;
2855 if (defining
!= NULL
) {
2856 if ((defining
->type
!= EXP_IF
) || (defining
->def_depth
> 0)) {
2857 return NO_DIRECTIVE_FOUND
;
2861 error_precond(ERR_WARNING
|ERR_PASS1
,
2862 "trailing garbage after `%%else' ignored");
2863 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2864 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2866 switch (defining
->state
) {
2869 defining
->state
= COND_ELSE_FALSE
;
2870 defining
->ignoring
= true;
2874 defining
->ignoring
= true;
2878 defining
->state
= COND_ELSE_TRUE
;
2879 defining
->ignoring
= false;
2882 case COND_ELSE_TRUE
:
2883 case COND_ELSE_FALSE
:
2884 error_precond(ERR_WARNING
|ERR_PASS1
,
2885 "`%%else' after `%%else' ignored.");
2886 defining
->state
= COND_NEVER
;
2887 defining
->ignoring
= true;
2890 free_tlist(origline
);
2891 return DIRECTIVE_FOUND
;
2894 if (defining
!= NULL
) {
2895 if (defining
->type
== EXP_IF
) {
2896 if (defining
->def_depth
> 0) {
2897 defining
->def_depth
--;
2898 return NO_DIRECTIVE_FOUND
;
2901 return NO_DIRECTIVE_FOUND
;
2905 error_precond(ERR_WARNING
|ERR_PASS1
,
2906 "trailing garbage after `%%endif' ignored");
2907 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2908 error(ERR_NONFATAL
, "`%%endif': no matching `%%if'");
2909 return DIRECTIVE_FOUND
;
2912 defining
= ed
->prev
;
2913 ed
->prev
= expansions
;
2915 ei
= new_ExpInv(EXP_IF
, ed
);
2916 ei
->current
= ed
->line
;
2917 ei
->emitting
= true;
2918 ei
->prev
= istk
->expansion
;
2919 istk
->expansion
= ei
;
2920 free_tlist(origline
);
2921 return DIRECTIVE_FOUND
;
2927 if (defining
!= NULL
) {
2928 if (defining
->type
== EXP_MMACRO
) {
2929 defining
->def_depth
++;
2931 return NO_DIRECTIVE_FOUND
;
2933 ed
= new_ExpDef(EXP_MMACRO
);
2935 (i
== PP_RMACRO
) || (i
== PP_IRMACRO
) ? DEADMAN_LIMIT
: 0;
2936 ed
->casesense
= (i
== PP_MACRO
) || (i
== PP_RMACRO
);
2937 if (!parse_mmacro_spec(tline
, ed
, pp_directives
[i
])) {
2940 return DIRECTIVE_FOUND
;
2944 ed
->max_depth
= (ed
->max_depth
+ 1);
2945 ed
->ignoring
= false;
2946 ed
->prev
= defining
;
2949 eed
= (ExpDef
*) hash_findix(&expdefs
, ed
->name
);
2951 if (!strcmp(eed
->name
, ed
->name
) &&
2952 (eed
->nparam_min
<= ed
->nparam_max
|| ed
->plus
) &&
2953 (ed
->nparam_min
<= eed
->nparam_max
|| eed
->plus
)) {
2954 error(ERR_WARNING
|ERR_PASS1
,
2955 "redefining multi-line macro `%s'", ed
->name
);
2956 return DIRECTIVE_FOUND
;
2960 free_tlist(origline
);
2961 return DIRECTIVE_FOUND
;
2965 if (defining
!= NULL
) {
2966 if (defining
->type
== EXP_MMACRO
) {
2967 if (defining
->def_depth
> 0) {
2968 defining
->def_depth
--;
2969 return NO_DIRECTIVE_FOUND
;
2972 return NO_DIRECTIVE_FOUND
;
2975 if (!(defining
) || (defining
->type
!= EXP_MMACRO
)) {
2976 error(ERR_NONFATAL
, "`%s': not defining a macro", tline
->text
);
2977 return DIRECTIVE_FOUND
;
2979 edhead
= (ExpDef
**) hash_findi_add(&expdefs
, defining
->name
);
2980 defining
->next
= *edhead
;
2983 defining
= ed
->prev
;
2984 ed
->prev
= expansions
;
2987 free_tlist(origline
);
2988 return DIRECTIVE_FOUND
;
2991 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2993 * We must search along istk->expansion until we hit a
2994 * macro invocation. Then we disable the emitting state(s)
2995 * between exitmacro and endmacro.
2997 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
2998 if(ei
->type
== EXP_MMACRO
) {
3005 * Set all invocations leading back to the macro
3006 * invocation to a non-emitting state.
3008 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3009 eei
->emitting
= false;
3011 eei
->emitting
= false;
3013 error(ERR_NONFATAL
, "`%%exitmacro' not within `%%macro' block");
3015 free_tlist(origline
);
3016 return DIRECTIVE_FOUND
;
3020 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3025 spec
.casesense
= (i
== PP_UNMACRO
);
3026 if (!parse_mmacro_spec(tline
, &spec
, pp_directives
[i
])) {
3027 return DIRECTIVE_FOUND
;
3029 ed_p
= (ExpDef
**) hash_findi(&expdefs
, spec
.name
, NULL
);
3030 while (ed_p
&& *ed_p
) {
3032 if (ed
->casesense
== spec
.casesense
&&
3033 !mstrcmp(ed
->name
, spec
.name
, spec
.casesense
) &&
3034 ed
->nparam_min
== spec
.nparam_min
&&
3035 ed
->nparam_max
== spec
.nparam_max
&&
3036 ed
->plus
== spec
.plus
) {
3037 if (ed
->cur_depth
> 0) {
3038 error(ERR_NONFATAL
, "`%s' ignored on active macro",
3049 free_tlist(origline
);
3050 free_tlist(spec
.dlist
);
3051 return DIRECTIVE_FOUND
;
3055 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3056 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
3057 tline
= tline
->next
;
3059 free_tlist(origline
);
3060 error(ERR_NONFATAL
, "`%%rotate' missing rotate count");
3061 return DIRECTIVE_FOUND
;
3063 t
= expand_smacro(tline
->next
);
3065 free_tlist(origline
);
3068 tokval
.t_type
= TOKEN_INVALID
;
3070 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3073 return DIRECTIVE_FOUND
;
3075 error(ERR_WARNING
|ERR_PASS1
,
3076 "trailing garbage after expression ignored");
3077 if (!is_simple(evalresult
)) {
3078 error(ERR_NONFATAL
, "non-constant value given to `%%rotate'");
3079 return DIRECTIVE_FOUND
;
3081 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3082 if (ei
->type
== EXP_MMACRO
) {
3087 error(ERR_NONFATAL
, "`%%rotate' invoked outside a macro call");
3088 } else if (ei
->nparam
== 0) {
3090 "`%%rotate' invoked within macro without parameters");
3092 int rotate
= ei
->rotate
+ reloc_value(evalresult
);
3094 rotate
%= (int)ei
->nparam
;
3096 rotate
+= ei
->nparam
;
3097 ei
->rotate
= rotate
;
3099 return DIRECTIVE_FOUND
;
3102 if (defining
!= NULL
) {
3103 if (defining
->type
== EXP_REP
) {
3104 defining
->def_depth
++;
3106 return NO_DIRECTIVE_FOUND
;
3110 tline
= tline
->next
;
3111 } while (tok_type_(tline
, TOK_WHITESPACE
));
3113 if (tok_type_(tline
, TOK_ID
) &&
3114 nasm_stricmp(tline
->text
, ".nolist") == 0) {
3117 tline
= tline
->next
;
3118 } while (tok_type_(tline
, TOK_WHITESPACE
));
3122 t
= expand_smacro(tline
);
3124 tokval
.t_type
= TOKEN_INVALID
;
3126 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3128 free_tlist(origline
);
3129 return DIRECTIVE_FOUND
;
3132 error(ERR_WARNING
|ERR_PASS1
,
3133 "trailing garbage after expression ignored");
3134 if (!is_simple(evalresult
)) {
3135 error(ERR_NONFATAL
, "non-constant value given to `%%rep'");
3136 return DIRECTIVE_FOUND
;
3138 count
= reloc_value(evalresult
);
3139 if (count
>= REP_LIMIT
) {
3140 error(ERR_NONFATAL
, "`%%rep' value exceeds limit");
3145 error(ERR_NONFATAL
, "`%%rep' expects a repeat count");
3148 free_tlist(origline
);
3149 ed
= new_ExpDef(EXP_REP
);
3150 ed
->nolist
= nolist
;
3153 ed
->max_depth
= (count
- 1);
3154 ed
->ignoring
= false;
3155 ed
->prev
= defining
;
3157 return DIRECTIVE_FOUND
;
3160 if (defining
!= NULL
) {
3161 if (defining
->type
== EXP_REP
) {
3162 if (defining
->def_depth
> 0) {
3163 defining
->def_depth
--;
3164 return NO_DIRECTIVE_FOUND
;
3167 return NO_DIRECTIVE_FOUND
;
3170 if ((defining
== NULL
) || (defining
->type
!= EXP_REP
)) {
3171 error(ERR_NONFATAL
, "`%%endrep': no matching `%%rep'");
3172 return DIRECTIVE_FOUND
;
3176 * Now we have a "macro" defined - although it has no name
3177 * and we won't be entering it in the hash tables - we must
3178 * push a macro-end marker for it on to istk->expansion.
3179 * After that, it will take care of propagating itself (a
3180 * macro-end marker line for a macro which is really a %rep
3181 * block will cause the macro to be re-expanded, complete
3182 * with another macro-end marker to ensure the process
3183 * continues) until the whole expansion is forcibly removed
3184 * from istk->expansion by a %exitrep.
3187 defining
= ed
->prev
;
3188 ed
->prev
= expansions
;
3190 ei
= new_ExpInv(EXP_REP
, ed
);
3191 ei
->current
= ed
->line
;
3192 ei
->emitting
= ((ed
->max_depth
> 0) ? true : false);
3193 list
->uplevel(ed
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
3194 ei
->prev
= istk
->expansion
;
3195 istk
->expansion
= ei
;
3196 free_tlist(origline
);
3197 return DIRECTIVE_FOUND
;
3200 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3202 * We must search along istk->expansion until we hit a
3203 * rep invocation. Then we disable the emitting state(s)
3204 * between exitrep and endrep.
3206 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3207 if (ei
->type
== EXP_REP
) {
3214 * Set all invocations leading back to the rep
3215 * invocation to a non-emitting state.
3217 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3218 eei
->emitting
= false;
3220 eei
->emitting
= false;
3221 eei
->current
= NULL
;
3222 eei
->def
->cur_depth
= eei
->def
->max_depth
;
3224 error(ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
3226 free_tlist(origline
);
3227 return DIRECTIVE_FOUND
;
3233 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3234 casesense
= (i
== PP_DEFINE
|| i
== PP_XDEFINE
);
3236 tline
= tline
->next
;
3238 tline
= expand_id(tline
);
3239 if (!tline
|| (tline
->type
!= TOK_ID
&&
3240 (tline
->type
!= TOK_PREPROC_ID
||
3241 tline
->text
[1] != '$'))) {
3242 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3244 free_tlist(origline
);
3245 return DIRECTIVE_FOUND
;
3248 ctx
= get_ctx(tline
->text
, &mname
, false);
3250 param_start
= tline
= tline
->next
;
3253 /* Expand the macro definition now for %xdefine and %ixdefine */
3254 if ((i
== PP_XDEFINE
) || (i
== PP_IXDEFINE
))
3255 tline
= expand_smacro(tline
);
3257 if (tok_is_(tline
, "(")) {
3259 * This macro has parameters.
3262 tline
= tline
->next
;
3266 error(ERR_NONFATAL
, "parameter identifier expected");
3267 free_tlist(origline
);
3268 return DIRECTIVE_FOUND
;
3270 if (tline
->type
!= TOK_ID
) {
3272 "`%s': parameter identifier expected",
3274 free_tlist(origline
);
3275 return DIRECTIVE_FOUND
;
3277 tline
->type
= TOK_SMAC_PARAM
+ nparam
++;
3278 tline
= tline
->next
;
3280 if (tok_is_(tline
, ",")) {
3281 tline
= tline
->next
;
3283 if (!tok_is_(tline
, ")")) {
3285 "`)' expected to terminate macro template");
3286 free_tlist(origline
);
3287 return DIRECTIVE_FOUND
;
3293 tline
= tline
->next
;
3295 if (tok_type_(tline
, TOK_WHITESPACE
))
3296 last
= tline
, tline
= tline
->next
;
3301 if (t
->type
== TOK_ID
) {
3302 list_for_each(tt
, param_start
)
3303 if (tt
->type
>= TOK_SMAC_PARAM
&&
3304 !strcmp(tt
->text
, t
->text
))
3308 t
->next
= macro_start
;
3313 * Good. We now have a macro name, a parameter count, and a
3314 * token list (in reverse order) for an expansion. We ought
3315 * to be OK just to create an SMacro, store it, and let
3316 * free_tlist have the rest of the line (which we have
3317 * carefully re-terminated after chopping off the expansion
3320 define_smacro(ctx
, mname
, casesense
, nparam
, macro_start
);
3321 free_tlist(origline
);
3322 return DIRECTIVE_FOUND
;
3325 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3326 tline
= tline
->next
;
3328 tline
= expand_id(tline
);
3329 if (!tline
|| (tline
->type
!= TOK_ID
&&
3330 (tline
->type
!= TOK_PREPROC_ID
||
3331 tline
->text
[1] != '$'))) {
3332 error(ERR_NONFATAL
, "`%%undef' expects a macro identifier");
3333 free_tlist(origline
);
3334 return DIRECTIVE_FOUND
;
3337 error(ERR_WARNING
|ERR_PASS1
,
3338 "trailing garbage after macro name ignored");
3341 /* Find the context that symbol belongs to */
3342 ctx
= get_ctx(tline
->text
, &mname
, false);
3343 undef_smacro(ctx
, mname
);
3344 free_tlist(origline
);
3345 return DIRECTIVE_FOUND
;
3349 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3350 casesense
= (i
== PP_DEFSTR
);
3352 tline
= tline
->next
;
3354 tline
= expand_id(tline
);
3355 if (!tline
|| (tline
->type
!= TOK_ID
&&
3356 (tline
->type
!= TOK_PREPROC_ID
||
3357 tline
->text
[1] != '$'))) {
3358 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3360 free_tlist(origline
);
3361 return DIRECTIVE_FOUND
;
3364 ctx
= get_ctx(tline
->text
, &mname
, false);
3366 tline
= expand_smacro(tline
->next
);
3369 while (tok_type_(tline
, TOK_WHITESPACE
))
3370 tline
= delete_Token(tline
);
3372 p
= detoken(tline
, false);
3373 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3374 macro_start
->text
= nasm_quote(p
, strlen(p
));
3375 macro_start
->type
= TOK_STRING
;
3379 * We now have a macro name, an implicit parameter count of
3380 * zero, and a string token to use as an expansion. Create
3381 * and store an SMacro.
3383 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3384 free_tlist(origline
);
3385 return DIRECTIVE_FOUND
;
3389 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3390 casesense
= (i
== PP_DEFTOK
);
3392 tline
= tline
->next
;
3394 tline
= expand_id(tline
);
3395 if (!tline
|| (tline
->type
!= TOK_ID
&&
3396 (tline
->type
!= TOK_PREPROC_ID
||
3397 tline
->text
[1] != '$'))) {
3399 "`%s' expects a macro identifier as first parameter",
3401 free_tlist(origline
);
3402 return DIRECTIVE_FOUND
;
3404 ctx
= get_ctx(tline
->text
, &mname
, false);
3406 tline
= expand_smacro(tline
->next
);
3410 while (tok_type_(t
, TOK_WHITESPACE
))
3412 /* t should now point to the string */
3413 if (!tok_type_(t
, TOK_STRING
)) {
3415 "`%s` requires string as second parameter",
3418 free_tlist(origline
);
3419 return DIRECTIVE_FOUND
;
3423 * Convert the string to a token stream. Note that smacros
3424 * are stored with the token stream reversed, so we have to
3425 * reverse the output of tokenize().
3427 nasm_unquote_cstr(t
->text
, i
);
3428 macro_start
= reverse_tokens(tokenize(t
->text
));
3431 * We now have a macro name, an implicit parameter count of
3432 * zero, and a numeric token to use as an expansion. Create
3433 * and store an SMacro.
3435 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3437 free_tlist(origline
);
3438 return DIRECTIVE_FOUND
;
3441 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3444 StrList
*xsl
= NULL
;
3445 StrList
**xst
= &xsl
;
3449 tline
= tline
->next
;
3451 tline
= expand_id(tline
);
3452 if (!tline
|| (tline
->type
!= TOK_ID
&&
3453 (tline
->type
!= TOK_PREPROC_ID
||
3454 tline
->text
[1] != '$'))) {
3456 "`%%pathsearch' expects a macro identifier as first parameter");
3457 free_tlist(origline
);
3458 return DIRECTIVE_FOUND
;
3460 ctx
= get_ctx(tline
->text
, &mname
, false);
3462 tline
= expand_smacro(tline
->next
);
3466 while (tok_type_(t
, TOK_WHITESPACE
))
3469 if (!t
|| (t
->type
!= TOK_STRING
&&
3470 t
->type
!= TOK_INTERNAL_STRING
)) {
3471 error(ERR_NONFATAL
, "`%%pathsearch' expects a file name");
3473 free_tlist(origline
);
3474 return DIRECTIVE_FOUND
; /* but we did _something_ */
3477 error(ERR_WARNING
|ERR_PASS1
,
3478 "trailing garbage after `%%pathsearch' ignored");
3480 if (t
->type
!= TOK_INTERNAL_STRING
)
3481 nasm_unquote(p
, NULL
);
3483 fp
= inc_fopen(p
, &xsl
, &xst
, true);
3486 fclose(fp
); /* Don't actually care about the file */
3488 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3489 macro_start
->text
= nasm_quote(p
, strlen(p
));
3490 macro_start
->type
= TOK_STRING
;
3495 * We now have a macro name, an implicit parameter count of
3496 * zero, and a string token to use as an expansion. Create
3497 * and store an SMacro.
3499 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3501 free_tlist(origline
);
3502 return DIRECTIVE_FOUND
;
3506 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3509 tline
= tline
->next
;
3511 tline
= expand_id(tline
);
3512 if (!tline
|| (tline
->type
!= TOK_ID
&&
3513 (tline
->type
!= TOK_PREPROC_ID
||
3514 tline
->text
[1] != '$'))) {
3516 "`%%strlen' expects a macro identifier as first parameter");
3517 free_tlist(origline
);
3518 return DIRECTIVE_FOUND
;
3520 ctx
= get_ctx(tline
->text
, &mname
, false);
3522 tline
= expand_smacro(tline
->next
);
3526 while (tok_type_(t
, TOK_WHITESPACE
))
3528 /* t should now point to the string */
3529 if (!tok_type_(t
, TOK_STRING
)) {
3531 "`%%strlen` requires string as second parameter");
3533 free_tlist(origline
);
3534 return DIRECTIVE_FOUND
;
3537 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3538 make_tok_num(macro_start
, nasm_unquote(t
->text
, NULL
));
3541 * We now have a macro name, an implicit parameter count of
3542 * zero, and a numeric token to use as an expansion. Create
3543 * and store an SMacro.
3545 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3547 free_tlist(origline
);
3548 return DIRECTIVE_FOUND
;
3551 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3554 tline
= tline
->next
;
3556 tline
= expand_id(tline
);
3557 if (!tline
|| (tline
->type
!= TOK_ID
&&
3558 (tline
->type
!= TOK_PREPROC_ID
||
3559 tline
->text
[1] != '$'))) {
3561 "`%%strcat' expects a macro identifier as first parameter");
3562 free_tlist(origline
);
3563 return DIRECTIVE_FOUND
;
3565 ctx
= get_ctx(tline
->text
, &mname
, false);
3567 tline
= expand_smacro(tline
->next
);
3571 list_for_each(t
, tline
) {
3573 case TOK_WHITESPACE
:
3576 len
+= t
->a
.len
= nasm_unquote(t
->text
, NULL
);
3579 if (!strcmp(t
->text
, ",")) /* permit comma separators */
3581 /* else fall through */
3584 "non-string passed to `%%strcat' (%d)", t
->type
);
3586 free_tlist(origline
);
3587 return DIRECTIVE_FOUND
;
3591 p
= pp
= nasm_malloc(len
);
3592 list_for_each(t
, tline
) {
3593 if (t
->type
== TOK_STRING
) {
3594 memcpy(p
, t
->text
, t
->a
.len
);
3600 * We now have a macro name, an implicit parameter count of
3601 * zero, and a numeric token to use as an expansion. Create
3602 * and store an SMacro.
3604 macro_start
= new_Token(NULL
, TOK_STRING
, NULL
, 0);
3605 macro_start
->text
= nasm_quote(pp
, len
);
3607 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3609 free_tlist(origline
);
3610 return DIRECTIVE_FOUND
;
3613 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3615 int64_t start
, count
;
3620 tline
= tline
->next
;
3622 tline
= expand_id(tline
);
3623 if (!tline
|| (tline
->type
!= TOK_ID
&&
3624 (tline
->type
!= TOK_PREPROC_ID
||
3625 tline
->text
[1] != '$'))) {
3627 "`%%substr' expects a macro identifier as first parameter");
3628 free_tlist(origline
);
3629 return DIRECTIVE_FOUND
;
3631 ctx
= get_ctx(tline
->text
, &mname
, false);
3633 tline
= expand_smacro(tline
->next
);
3636 if (tline
) /* skip expanded id */
3638 while (tok_type_(t
, TOK_WHITESPACE
))
3641 /* t should now point to the string */
3642 if (!tok_type_(t
, TOK_STRING
)) {
3644 "`%%substr` requires string as second parameter");
3646 free_tlist(origline
);
3647 return DIRECTIVE_FOUND
;
3652 tokval
.t_type
= TOKEN_INVALID
;
3653 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3657 free_tlist(origline
);
3658 return DIRECTIVE_FOUND
;
3659 } else if (!is_simple(evalresult
)) {
3660 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3662 free_tlist(origline
);
3663 return DIRECTIVE_FOUND
;
3665 start
= evalresult
->value
- 1;
3667 while (tok_type_(tt
, TOK_WHITESPACE
))
3670 count
= 1; /* Backwards compatibility: one character */
3672 tokval
.t_type
= TOKEN_INVALID
;
3673 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3677 free_tlist(origline
);
3678 return DIRECTIVE_FOUND
;
3679 } else if (!is_simple(evalresult
)) {
3680 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3682 free_tlist(origline
);
3683 return DIRECTIVE_FOUND
;
3685 count
= evalresult
->value
;
3688 len
= nasm_unquote(t
->text
, NULL
);
3689 /* make start and count being in range */
3693 count
= len
+ count
+ 1 - start
;
3694 if (start
+ count
> (int64_t)len
)
3695 count
= len
- start
;
3696 if (!len
|| count
< 0 || start
>=(int64_t)len
)
3697 start
= -1, count
= 0; /* empty string */
3699 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3700 macro_start
->text
= nasm_quote((start
< 0) ? "" : t
->text
+ start
, count
);
3701 macro_start
->type
= TOK_STRING
;
3704 * We now have a macro name, an implicit parameter count of
3705 * zero, and a numeric token to use as an expansion. Create
3706 * and store an SMacro.
3708 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3710 free_tlist(origline
);
3711 return DIRECTIVE_FOUND
;
3716 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3717 casesense
= (i
== PP_ASSIGN
);
3719 tline
= tline
->next
;
3721 tline
= expand_id(tline
);
3722 if (!tline
|| (tline
->type
!= TOK_ID
&&
3723 (tline
->type
!= TOK_PREPROC_ID
||
3724 tline
->text
[1] != '$'))) {
3726 "`%%%sassign' expects a macro identifier",
3727 (i
== PP_IASSIGN
? "i" : ""));
3728 free_tlist(origline
);
3729 return DIRECTIVE_FOUND
;
3731 ctx
= get_ctx(tline
->text
, &mname
, false);
3733 tline
= expand_smacro(tline
->next
);
3738 tokval
.t_type
= TOKEN_INVALID
;
3740 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3743 free_tlist(origline
);
3744 return DIRECTIVE_FOUND
;
3748 error(ERR_WARNING
|ERR_PASS1
,
3749 "trailing garbage after expression ignored");
3751 if (!is_simple(evalresult
)) {
3753 "non-constant value given to `%%%sassign'",
3754 (i
== PP_IASSIGN
? "i" : ""));
3755 free_tlist(origline
);
3756 return DIRECTIVE_FOUND
;
3759 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3760 make_tok_num(macro_start
, reloc_value(evalresult
));
3763 * We now have a macro name, an implicit parameter count of
3764 * zero, and a numeric token to use as an expansion. Create
3765 * and store an SMacro.
3767 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3768 free_tlist(origline
);
3769 return DIRECTIVE_FOUND
;
3772 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3774 * Syntax is `%line nnn[+mmm] [filename]'
3776 tline
= tline
->next
;
3778 if (!tok_type_(tline
, TOK_NUMBER
)) {
3779 error(ERR_NONFATAL
, "`%%line' expects line number");
3780 free_tlist(origline
);
3781 return DIRECTIVE_FOUND
;
3783 k
= readnum(tline
->text
, &err
);
3785 tline
= tline
->next
;
3786 if (tok_is_(tline
, "+")) {
3787 tline
= tline
->next
;
3788 if (!tok_type_(tline
, TOK_NUMBER
)) {
3789 error(ERR_NONFATAL
, "`%%line' expects line increment");
3790 free_tlist(origline
);
3791 return DIRECTIVE_FOUND
;
3793 m
= readnum(tline
->text
, &err
);
3794 tline
= tline
->next
;
3800 nasm_free(src_set_fname(detoken(tline
, false)));
3802 free_tlist(origline
);
3803 return DIRECTIVE_FOUND
;
3806 if (defining
!= NULL
) {
3807 if (defining
->type
== EXP_WHILE
) {
3808 defining
->def_depth
++;
3810 return NO_DIRECTIVE_FOUND
;
3813 if ((istk
->expansion
!= NULL
) &&
3814 (istk
->expansion
->emitting
== false)) {
3818 l
->first
= copy_Token(tline
->next
);
3819 j
= if_condition(tline
->next
, i
);
3820 tline
->next
= NULL
; /* it got freed */
3821 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
3823 ed
= new_ExpDef(EXP_WHILE
);
3826 ed
->max_depth
= DEADMAN_LIMIT
;
3827 ed
->ignoring
= ((ed
->state
== COND_IF_TRUE
) ? false : true);
3828 if (ed
->ignoring
== false) {
3831 } else if (l
!= NULL
) {
3832 delete_Token(l
->first
);
3836 ed
->prev
= defining
;
3838 free_tlist(origline
);
3839 return DIRECTIVE_FOUND
;
3842 if (defining
!= NULL
) {
3843 if (defining
->type
== EXP_WHILE
) {
3844 if (defining
->def_depth
> 0) {
3845 defining
->def_depth
--;
3846 return NO_DIRECTIVE_FOUND
;
3849 return NO_DIRECTIVE_FOUND
;
3852 if (tline
->next
!= NULL
) {
3853 error_precond(ERR_WARNING
|ERR_PASS1
,
3854 "trailing garbage after `%%endwhile' ignored");
3856 if ((defining
== NULL
) || (defining
->type
!= EXP_WHILE
)) {
3857 error(ERR_NONFATAL
, "`%%endwhile': no matching `%%while'");
3858 return DIRECTIVE_FOUND
;
3861 defining
= ed
->prev
;
3862 if (ed
->ignoring
== false) {
3863 ed
->prev
= expansions
;
3865 ei
= new_ExpInv(EXP_WHILE
, ed
);
3866 ei
->current
= ed
->line
->next
;
3867 ei
->emitting
= true;
3868 ei
->prev
= istk
->expansion
;
3869 istk
->expansion
= ei
;
3873 free_tlist(origline
);
3874 return DIRECTIVE_FOUND
;
3877 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3879 * We must search along istk->expansion until we hit a
3880 * while invocation. Then we disable the emitting state(s)
3881 * between exitwhile and endwhile.
3883 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3884 if (ei
->type
== EXP_WHILE
) {
3891 * Set all invocations leading back to the while
3892 * invocation to a non-emitting state.
3894 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3895 eei
->emitting
= false;
3897 eei
->emitting
= false;
3898 eei
->current
= NULL
;
3899 eei
->def
->cur_depth
= eei
->def
->max_depth
;
3901 error(ERR_NONFATAL
, "`%%exitwhile' not within `%%while' block");
3903 free_tlist(origline
);
3904 return DIRECTIVE_FOUND
;
3907 if (defining
!= NULL
) {
3908 if (defining
->type
== EXP_COMMENT
) {
3909 defining
->def_depth
++;
3911 return NO_DIRECTIVE_FOUND
;
3913 ed
= new_ExpDef(EXP_COMMENT
);
3914 ed
->ignoring
= true;
3915 ed
->prev
= defining
;
3917 free_tlist(origline
);
3918 return DIRECTIVE_FOUND
;
3921 if (defining
!= NULL
) {
3922 if (defining
->type
== EXP_COMMENT
) {
3923 if (defining
->def_depth
> 0) {
3924 defining
->def_depth
--;
3925 return NO_DIRECTIVE_FOUND
;
3928 return NO_DIRECTIVE_FOUND
;
3931 if ((defining
== NULL
) || (defining
->type
!= EXP_COMMENT
)) {
3932 error(ERR_NONFATAL
, "`%%endcomment': no matching `%%comment'");
3933 return DIRECTIVE_FOUND
;
3936 defining
= ed
->prev
;
3938 free_tlist(origline
);
3939 return DIRECTIVE_FOUND
;
3942 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3943 if (in_final
!= false) {
3944 error(ERR_FATAL
, "`%%final' cannot be used recursively");
3946 tline
= tline
->next
;
3948 if (tline
== NULL
) {
3949 error(ERR_NONFATAL
, "`%%final' expects at least one parameter");
3952 l
->first
= copy_Token(tline
);
3956 free_tlist(origline
);
3957 return DIRECTIVE_FOUND
;
3961 "preprocessor directive `%s' not yet implemented",
3963 return DIRECTIVE_FOUND
;
3968 * Ensure that a macro parameter contains a condition code and
3969 * nothing else. Return the condition code index if so, or -1
3972 static int find_cc(Token
* t
)
3978 return -1; /* Probably a %+ without a space */
3981 if (t
->type
!= TOK_ID
)
3985 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
3989 j
= ARRAY_SIZE(conditions
);
3992 m
= nasm_stricmp(t
->text
, conditions
[k
]);
4007 static bool paste_tokens(Token
**head
, const struct tokseq_match
*m
,
4008 int mnum
, bool handle_paste_tokens
)
4010 Token
**tail
, *t
, *tt
;
4012 bool did_paste
= false;
4016 /* Now handle token pasting... */
4019 while ((t
= *tail
) && (tt
= t
->next
)) {
4021 case TOK_WHITESPACE
:
4022 if (tt
->type
== TOK_WHITESPACE
) {
4023 /* Zap adjacent whitespace tokens */
4024 t
->next
= delete_Token(tt
);
4026 /* Do not advance paste_head here */
4030 case TOK_PASTE
: /* %+ */
4031 if (handle_paste_tokens
) {
4032 /* Zap %+ and whitespace tokens to the right */
4033 while (t
&& (t
->type
== TOK_WHITESPACE
||
4034 t
->type
== TOK_PASTE
))
4035 t
= *tail
= delete_Token(t
);
4036 if (!paste_head
|| !t
)
4037 break; /* Nothing to paste with */
4041 while (tok_type_(tt
, TOK_WHITESPACE
))
4042 tt
= t
->next
= delete_Token(tt
);
4044 tmp
= nasm_strcat(t
->text
, tt
->text
);
4046 tt
= delete_Token(tt
);
4047 t
= *tail
= tokenize(tmp
);
4053 t
->next
= tt
; /* Attach the remaining token chain */
4060 /* else fall through */
4063 * Concatenation of tokens might look nontrivial
4064 * but in real it's pretty simple -- the caller
4065 * prepares the masks of token types to be concatenated
4066 * and we simply find matched sequences and slip
4069 for (i
= 0; i
< mnum
; i
++) {
4070 if (PP_CONCAT_MASK(t
->type
) & m
[i
].mask_head
) {
4074 while (tt
&& (PP_CONCAT_MASK(tt
->type
) & m
[i
].mask_tail
)) {
4075 len
+= strlen(tt
->text
);
4080 * Now tt points to the first token after
4081 * the potential paste area...
4083 if (tt
!= t
->next
) {
4084 /* We have at least two tokens... */
4085 len
+= strlen(t
->text
);
4086 p
= tmp
= nasm_malloc(len
+1);
4089 p
= strchr(p
, '\0');
4090 t
= delete_Token(t
);
4092 t
= *tail
= tokenize(tmp
);
4098 t
->next
= tt
; /* Attach the remaining token chain */
4106 if (i
>= mnum
) { /* no match */
4108 if (!tok_type_(t
->next
, TOK_WHITESPACE
))
4118 * expands to a list of tokens from %{x:y}
4120 static Token
*expand_mmac_params_range(ExpInv
*ei
, Token
*tline
, Token
***last
)
4122 Token
*t
= tline
, **tt
, *tm
, *head
;
4126 pos
= strchr(tline
->text
, ':');
4129 lst
= atoi(pos
+ 1);
4130 fst
= atoi(tline
->text
+ 1);
4133 * only macros params are accounted so
4134 * if someone passes %0 -- we reject such
4137 if (lst
== 0 || fst
== 0)
4140 /* the values should be sane */
4141 if ((fst
> (int)ei
->nparam
|| fst
< (-(int)ei
->nparam
)) ||
4142 (lst
> (int)ei
->nparam
|| lst
< (-(int)ei
->nparam
)))
4145 fst
= fst
< 0 ? fst
+ (int)ei
->nparam
+ 1: fst
;
4146 lst
= lst
< 0 ? lst
+ (int)ei
->nparam
+ 1: lst
;
4148 /* counted from zero */
4152 * it will be at least one token
4154 tm
= ei
->params
[(fst
+ ei
->rotate
) % ei
->nparam
];
4155 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4156 head
= t
, tt
= &t
->next
;
4158 for (i
= fst
+ 1; i
<= lst
; i
++) {
4159 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
4160 *tt
= t
, tt
= &t
->next
;
4161 j
= (i
+ ei
->rotate
) % ei
->nparam
;
4163 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4164 *tt
= t
, tt
= &t
->next
;
4167 for (i
= fst
- 1; i
>= lst
; i
--) {
4168 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
4169 *tt
= t
, tt
= &t
->next
;
4170 j
= (i
+ ei
->rotate
) % ei
->nparam
;
4172 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4173 *tt
= t
, tt
= &t
->next
;
4181 error(ERR_NONFATAL
, "`%%{%s}': macro parameters out of range",
4187 * Expand MMacro-local things: parameter references (%0, %n, %+n,
4188 * %-n) and MMacro-local identifiers (%%foo) as well as
4189 * macro indirection (%[...]) and range (%{..:..}).
4191 static Token
*expand_mmac_params(Token
* tline
)
4193 Token
*t
, *tt
, **tail
, *thead
;
4194 bool changed
= false;
4201 if (tline
->type
== TOK_PREPROC_ID
&&
4202 (((tline
->text
[1] == '+' || tline
->text
[1] == '-') && tline
->text
[2]) ||
4203 (tline
->text
[1] >= '0' && tline
->text
[1] <= '9') ||
4204 tline
->text
[1] == '%')) {
4206 int type
= 0, cc
; /* type = 0 to placate optimisers */
4213 tline
= tline
->next
;
4215 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
4216 if (ei
->type
== EXP_MMACRO
) {
4221 error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
4223 pos
= strchr(t
->text
, ':');
4225 switch (t
->text
[1]) {
4227 * We have to make a substitution of one of the
4228 * forms %1, %-1, %+1, %%foo, %0.
4231 if ((strlen(t
->text
) > 2) && (t
->text
[2] == '0')) {
4233 text
= nasm_strdup(ei
->label_text
);
4236 snprintf(tmpbuf
, sizeof(tmpbuf
), "%d", ei
->nparam
);
4237 text
= nasm_strdup(tmpbuf
);
4242 snprintf(tmpbuf
, sizeof(tmpbuf
), "..@%"PRIu64
".",
4244 text
= nasm_strcat(tmpbuf
, t
->text
+ 2);
4247 n
= atoi(t
->text
+ 2) - 1;
4248 if (n
>= ei
->nparam
)
4252 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4258 "macro parameter %d is not a condition code",
4263 if (inverse_ccs
[cc
] == -1) {
4265 "condition code `%s' is not invertible",
4269 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
4273 n
= atoi(t
->text
+ 2) - 1;
4274 if (n
>= ei
->nparam
)
4278 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4284 "macro parameter %d is not a condition code",
4289 text
= nasm_strdup(conditions
[cc
]);
4293 n
= atoi(t
->text
+ 1) - 1;
4294 if (n
>= ei
->nparam
)
4298 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4302 for (i
= 0; i
< ei
->paramlen
[n
]; i
++) {
4303 *tail
= new_Token(NULL
, tt
->type
, tt
->text
, 0);
4304 tail
= &(*tail
)->next
;
4308 text
= NULL
; /* we've done it here */
4313 * seems we have a parameters range here
4315 Token
*head
, **last
;
4316 head
= expand_mmac_params_range(ei
, t
, &last
);
4337 } else if (tline
->type
== TOK_INDIRECT
) {
4339 tline
= tline
->next
;
4340 tt
= tokenize(t
->text
);
4341 tt
= expand_mmac_params(tt
);
4342 tt
= expand_smacro(tt
);
4345 tt
->a
.mac
= NULL
; /* Necessary? */
4353 tline
= tline
->next
;
4361 paste_tokens(&thead
, pp_concat_match
,
4362 ARRAY_SIZE(pp_concat_match
),
4369 * Expand all single-line macro calls made in the given line.
4370 * Return the expanded version of the line. The original is deemed
4371 * to be destroyed in the process. (In reality we'll just move
4372 * Tokens from input to output a lot of the time, rather than
4373 * actually bothering to destroy and replicate.)
4376 static Token
*expand_smacro(Token
* tline
)
4378 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
4379 SMacro
*head
= NULL
, *m
;
4382 unsigned int nparam
, sparam
;
4384 Token
*org_tline
= tline
;
4387 int deadman
= DEADMAN_LIMIT
;
4391 * Trick: we should avoid changing the start token pointer since it can
4392 * be contained in "next" field of other token. Because of this
4393 * we allocate a copy of first token and work with it; at the end of
4394 * routine we copy it back
4397 tline
= new_Token(org_tline
->next
, org_tline
->type
,
4398 org_tline
->text
, 0);
4399 tline
->a
.mac
= org_tline
->a
.mac
;
4400 nasm_free(org_tline
->text
);
4401 org_tline
->text
= NULL
;
4404 expanded
= true; /* Always expand %+ at least once */
4410 while (tline
) { /* main token loop */
4412 error(ERR_NONFATAL
, "interminable macro recursion");
4416 if ((mname
= tline
->text
)) {
4417 /* if this token is a local macro, look in local context */
4418 if (tline
->type
== TOK_ID
) {
4419 head
= (SMacro
*)hash_findix(&smacros
, mname
);
4420 } else if (tline
->type
== TOK_PREPROC_ID
) {
4421 ctx
= get_ctx(mname
, &mname
, false);
4422 head
= ctx
? (SMacro
*)hash_findix(&ctx
->localmac
, mname
) : NULL
;
4427 * We've hit an identifier. As in is_mmacro below, we first
4428 * check whether the identifier is a single-line macro at
4429 * all, then think about checking for parameters if
4432 list_for_each(m
, head
)
4433 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
4439 if (m
->nparam
== 0) {
4441 * Simple case: the macro is parameterless. Discard the
4442 * one token that the macro call took, and push the
4443 * expansion back on the to-do stack.
4445 if (!m
->expansion
) {
4446 if (!strcmp("__FILE__", m
->name
)) {
4449 src_get(&num
, &file
);
4450 tline
->text
= nasm_quote(file
, strlen(file
));
4451 tline
->type
= TOK_STRING
;
4455 if (!strcmp("__LINE__", m
->name
)) {
4456 nasm_free(tline
->text
);
4457 make_tok_num(tline
, src_get_linnum());
4460 if (!strcmp("__BITS__", m
->name
)) {
4461 nasm_free(tline
->text
);
4462 make_tok_num(tline
, globalbits
);
4465 tline
= delete_Token(tline
);
4470 * Complicated case: at least one macro with this name
4471 * exists and takes parameters. We must find the
4472 * parameters in the call, count them, find the SMacro
4473 * that corresponds to that form of the macro call, and
4474 * substitute for the parameters when we expand. What a
4477 /*tline = tline->next;
4478 skip_white_(tline); */
4481 while (tok_type_(t
, TOK_SMAC_END
)) {
4482 t
->a
.mac
->in_progress
= false;
4484 t
= tline
->next
= delete_Token(t
);
4487 } while (tok_type_(tline
, TOK_WHITESPACE
));
4488 if (!tok_is_(tline
, "(")) {
4490 * This macro wasn't called with parameters: ignore
4491 * the call. (Behaviour borrowed from gnu cpp.)
4500 sparam
= PARAM_DELTA
;
4501 params
= nasm_malloc(sparam
* sizeof(Token
*));
4502 params
[0] = tline
->next
;
4503 paramsize
= nasm_malloc(sparam
* sizeof(int));
4505 while (true) { /* parameter loop */
4507 * For some unusual expansions
4508 * which concatenates function call
4511 while (tok_type_(t
, TOK_SMAC_END
)) {
4512 t
->a
.mac
->in_progress
= false;
4514 t
= tline
->next
= delete_Token(t
);
4520 "macro call expects terminating `)'");
4523 if (tline
->type
== TOK_WHITESPACE
4525 if (paramsize
[nparam
])
4528 params
[nparam
] = tline
->next
;
4529 continue; /* parameter loop */
4531 if (tline
->type
== TOK_OTHER
4532 && tline
->text
[1] == 0) {
4533 char ch
= tline
->text
[0];
4534 if (ch
== ',' && !paren
&& brackets
<= 0) {
4535 if (++nparam
>= sparam
) {
4536 sparam
+= PARAM_DELTA
;
4537 params
= nasm_realloc(params
,
4538 sparam
* sizeof(Token
*));
4539 paramsize
= nasm_realloc(paramsize
,
4540 sparam
* sizeof(int));
4542 params
[nparam
] = tline
->next
;
4543 paramsize
[nparam
] = 0;
4545 continue; /* parameter loop */
4548 (brackets
> 0 || (brackets
== 0 &&
4549 !paramsize
[nparam
])))
4551 if (!(brackets
++)) {
4552 params
[nparam
] = tline
->next
;
4553 continue; /* parameter loop */
4556 if (ch
== '}' && brackets
> 0)
4557 if (--brackets
== 0) {
4559 continue; /* parameter loop */
4561 if (ch
== '(' && !brackets
)
4563 if (ch
== ')' && brackets
<= 0)
4569 error(ERR_NONFATAL
, "braces do not "
4570 "enclose all of macro parameter");
4572 paramsize
[nparam
] += white
+ 1;
4574 } /* parameter loop */
4576 while (m
&& (m
->nparam
!= nparam
||
4577 mstrcmp(m
->name
, mname
,
4581 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4582 "macro `%s' exists, "
4583 "but not taking %d parameters",
4584 mstart
->text
, nparam
);
4587 if (m
&& m
->in_progress
)
4589 if (!m
) { /* in progess or didn't find '(' or wrong nparam */
4591 * Design question: should we handle !tline, which
4592 * indicates missing ')' here, or expand those
4593 * macros anyway, which requires the (t) test a few
4597 nasm_free(paramsize
);
4601 * Expand the macro: we are placed on the last token of the
4602 * call, so that we can easily split the call from the
4603 * following tokens. We also start by pushing an SMAC_END
4604 * token for the cycle removal.
4611 tt
= new_Token(tline
, TOK_SMAC_END
, NULL
, 0);
4613 m
->in_progress
= true;
4615 list_for_each(t
, m
->expansion
) {
4616 if (t
->type
>= TOK_SMAC_PARAM
) {
4617 Token
*pcopy
= tline
, **ptail
= &pcopy
;
4621 ttt
= params
[t
->type
- TOK_SMAC_PARAM
];
4622 i
= paramsize
[t
->type
- TOK_SMAC_PARAM
];
4624 pt
= *ptail
= new_Token(tline
, ttt
->type
,
4630 } else if (t
->type
== TOK_PREPROC_Q
) {
4631 tt
= new_Token(tline
, TOK_ID
, mname
, 0);
4633 } else if (t
->type
== TOK_PREPROC_QQ
) {
4634 tt
= new_Token(tline
, TOK_ID
, m
->name
, 0);
4637 tt
= new_Token(tline
, t
->type
, t
->text
, 0);
4643 * Having done that, get rid of the macro call, and clean
4644 * up the parameters.
4647 nasm_free(paramsize
);
4650 continue; /* main token loop */
4655 if (tline
->type
== TOK_SMAC_END
) {
4656 tline
->a
.mac
->in_progress
= false;
4657 tline
= delete_Token(tline
);
4660 tline
= tline
->next
;
4668 * Now scan the entire line and look for successive TOK_IDs that resulted
4669 * after expansion (they can't be produced by tokenize()). The successive
4670 * TOK_IDs should be concatenated.
4671 * Also we look for %+ tokens and concatenate the tokens before and after
4672 * them (without white spaces in between).
4675 if (paste_tokens(&thead
, pp_concat_match
,
4676 ARRAY_SIZE(pp_concat_match
),
4679 * If we concatenated something, *and* we had previously expanded
4680 * an actual macro, scan the lines again for macros...
4691 *org_tline
= *thead
;
4692 /* since we just gave text to org_line, don't free it */
4694 delete_Token(thead
);
4696 /* the expression expanded to empty line;
4697 we can't return NULL for some reasons
4698 we just set the line to a single WHITESPACE token. */
4699 memset(org_tline
, 0, sizeof(*org_tline
));
4700 org_tline
->text
= NULL
;
4701 org_tline
->type
= TOK_WHITESPACE
;
4710 * Similar to expand_smacro but used exclusively with macro identifiers
4711 * right before they are fetched in. The reason is that there can be
4712 * identifiers consisting of several subparts. We consider that if there
4713 * are more than one element forming the name, user wants a expansion,
4714 * otherwise it will be left as-is. Example:
4718 * the identifier %$abc will be left as-is so that the handler for %define
4719 * will suck it and define the corresponding value. Other case:
4721 * %define _%$abc cde
4723 * In this case user wants name to be expanded *before* %define starts
4724 * working, so we'll expand %$abc into something (if it has a value;
4725 * otherwise it will be left as-is) then concatenate all successive
4728 static Token
*expand_id(Token
* tline
)
4730 Token
*cur
, *oldnext
= NULL
;
4732 if (!tline
|| !tline
->next
)
4737 (cur
->next
->type
== TOK_ID
||
4738 cur
->next
->type
== TOK_PREPROC_ID
4739 || cur
->next
->type
== TOK_NUMBER
))
4742 /* If identifier consists of just one token, don't expand */
4747 oldnext
= cur
->next
; /* Detach the tail past identifier */
4748 cur
->next
= NULL
; /* so that expand_smacro stops here */
4751 tline
= expand_smacro(tline
);
4754 /* expand_smacro possibly changhed tline; re-scan for EOL */
4756 while (cur
&& cur
->next
)
4759 cur
->next
= oldnext
;
4766 * Determine whether the given line constitutes a multi-line macro
4767 * call, and return the ExpDef structure called if so. Doesn't have
4768 * to check for an initial label - that's taken care of in
4769 * expand_mmacro - but must check numbers of parameters. Guaranteed
4770 * to be called with tline->type == TOK_ID, so the putative macro
4771 * name is easy to find.
4773 static ExpDef
*is_mmacro(Token
* tline
, Token
*** params_array
)
4779 head
= (ExpDef
*) hash_findix(&expdefs
, tline
->text
);
4782 * Efficiency: first we see if any macro exists with the given
4783 * name. If not, we can return NULL immediately. _Then_ we
4784 * count the parameters, and then we look further along the
4785 * list if necessary to find the proper ExpDef.
4787 list_for_each(ed
, head
)
4788 if (!mstrcmp(ed
->name
, tline
->text
, ed
->casesense
))
4794 * OK, we have a potential macro. Count and demarcate the
4797 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
4800 * So we know how many parameters we've got. Find the ExpDef
4801 * structure that handles this number.
4804 if (ed
->nparam_min
<= nparam
4805 && (ed
->plus
|| nparam
<= ed
->nparam_max
)) {
4807 * It's right, and we can use it. Add its default
4808 * parameters to the end of our list if necessary.
4810 if (ed
->defaults
&& nparam
< ed
->nparam_min
+ ed
->ndefs
) {
4812 nasm_realloc(params
,
4813 ((ed
->nparam_min
+ ed
->ndefs
+
4814 1) * sizeof(*params
)));
4815 while (nparam
< ed
->nparam_min
+ ed
->ndefs
) {
4816 params
[nparam
] = ed
->defaults
[nparam
- ed
->nparam_min
];
4821 * If we've gone over the maximum parameter count (and
4822 * we're in Plus mode), ignore parameters beyond
4825 if (ed
->plus
&& nparam
> ed
->nparam_max
)
4826 nparam
= ed
->nparam_max
;
4828 * Then terminate the parameter list, and leave.
4830 if (!params
) { /* need this special case */
4831 params
= nasm_malloc(sizeof(*params
));
4834 params
[nparam
] = NULL
;
4835 *params_array
= params
;
4839 * This one wasn't right: look for the next one with the
4842 list_for_each(ed
, ed
->next
)
4843 if (!mstrcmp(ed
->name
, tline
->text
, ed
->casesense
))
4848 * After all that, we didn't find one with the right number of
4849 * parameters. Issue a warning, and fail to expand the macro.
4851 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4852 "macro `%s' exists, but not taking %d parameters",
4853 tline
->text
, nparam
);
4859 * Expand the multi-line macro call made by the given line, if
4860 * there is one to be expanded. If there is, push the expansion on
4861 * istk->expansion and return true. Otherwise return false.
4863 static bool expand_mmacro(Token
* tline
)
4865 Token
*label
= NULL
;
4866 int dont_prepend
= 0;
4871 int i
, nparam
, *paramlen
;
4876 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4877 if (!tok_type_(t
, TOK_ID
) && !tok_type_(t
, TOK_PREPROC_ID
))
4879 ed
= is_mmacro(t
, ¶ms
);
4885 * We have an id which isn't a macro call. We'll assume
4886 * it might be a label; we'll also check to see if a
4887 * colon follows it. Then, if there's another id after
4888 * that lot, we'll check it again for macro-hood.
4892 if (tok_type_(t
, TOK_WHITESPACE
))
4893 last
= t
, t
= t
->next
;
4894 if (tok_is_(t
, ":")) {
4896 last
= t
, t
= t
->next
;
4897 if (tok_type_(t
, TOK_WHITESPACE
))
4898 last
= t
, t
= t
->next
;
4900 if (!tok_type_(t
, TOK_ID
) || !(ed
= is_mmacro(t
, ¶ms
)))
4908 * Fix up the parameters: this involves stripping leading and
4909 * trailing whitespace, then stripping braces if they are
4912 for (nparam
= 0; params
[nparam
]; nparam
++) ;
4913 paramlen
= nparam
? nasm_malloc(nparam
* sizeof(*paramlen
)) : NULL
;
4915 for (i
= 0; params
[i
]; i
++) {
4917 int comma
= (!ed
->plus
|| i
< nparam
- 1);
4921 if (tok_is_(t
, "{"))
4922 t
= t
->next
, brace
= true, comma
= false;
4926 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
4927 break; /* ... because we have hit a comma */
4928 if (comma
&& t
->type
== TOK_WHITESPACE
4929 && tok_is_(t
->next
, ","))
4930 break; /* ... or a space then a comma */
4931 if (brace
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "}"))
4932 break; /* ... or a brace */
4938 if (ed
->cur_depth
>= ed
->max_depth
) {
4939 if (ed
->max_depth
> 1) {
4941 "reached maximum macro recursion depth of %i for %s",
4942 ed
->max_depth
,ed
->name
);
4950 * OK, we have found a ExpDef structure representing a
4951 * previously defined mmacro. Create an expansion invocation
4952 * and point it back to the expansion definition. Substitution of
4953 * parameter tokens and macro-local tokens doesn't get done
4954 * until the single-line macro substitution process; this is
4955 * because delaying them allows us to change the semantics
4956 * later through %rotate.
4958 ei
= new_ExpInv(EXP_MMACRO
, ed
);
4959 ei
->name
= nasm_strdup(mname
);
4960 //ei->label = label;
4961 //ei->label_text = detoken(label, false);
4962 ei
->current
= ed
->line
;
4963 ei
->emitting
= true;
4964 //ei->iline = tline;
4965 ei
->params
= params
;
4966 ei
->nparam
= nparam
;
4968 ei
->paramlen
= paramlen
;
4971 ei
->prev
= istk
->expansion
;
4972 istk
->expansion
= ei
;
4975 * Special case: detect %00 on first invocation; if found,
4976 * avoid emitting any labels that precede the mmacro call.
4977 * ed->prepend is set to -1 when %00 is detected, else 1.
4979 if (ed
->prepend
== 0) {
4980 for (l
= ed
->line
; l
!= NULL
; l
= l
->next
) {
4981 for (t
= l
->first
; t
!= NULL
; t
= t
->next
) {
4982 if ((t
->type
== TOK_PREPROC_ID
) &&
4983 (strlen(t
->text
) == 3) &&
4984 (t
->text
[1] == '0') && (t
->text
[2] == '0')) {
4989 if (dont_prepend
< 0) {
4993 ed
->prepend
= ((dont_prepend
< 0) ? -1 : 1);
4997 * If we had a label, push it on as the first line of
4998 * the macro expansion.
5000 if (label
!= NULL
) {
5001 if (ed
->prepend
< 0) {
5002 ei
->label_text
= detoken(label
, false);
5004 if (dont_prepend
== 0) {
5006 while (t
->next
!= NULL
) {
5009 t
->next
= new_Token(NULL
, TOK_OTHER
, ":", 0);
5012 l
->first
= copy_Token(label
);
5013 l
->next
= ei
->current
;
5018 list
->uplevel(ed
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
5024 /* The function that actually does the error reporting */
5025 static void verror(int severity
, const char *fmt
, va_list arg
)
5029 vsnprintf(buff
, sizeof(buff
), fmt
, arg
);
5031 if (istk
&& istk
->mmac_depth
> 0) {
5032 ExpInv
*ei
= istk
->expansion
;
5033 int lineno
= ei
->lineno
;
5035 if (ei
->type
== EXP_MMACRO
)
5037 lineno
+= ei
->relno
;
5040 nasm_error(severity
, "(%s:%d) %s", ei
->def
->name
,
5043 nasm_error(severity
, "%s", buff
);
5047 * Since preprocessor always operate only on the line that didn't
5048 * arrived yet, we should always use ERR_OFFBY1.
5050 static void error(int severity
, const char *fmt
, ...)
5054 verror(severity
, fmt
, arg
);
5059 * Because %else etc are evaluated in the state context
5060 * of the previous branch, errors might get lost with error():
5061 * %if 0 ... %else trailing garbage ... %endif
5062 * So %else etc should report errors with this function.
5064 static void error_precond(int severity
, const char *fmt
, ...)
5068 /* Only ignore the error if it's really in a dead branch */
5069 if ((istk
!= NULL
) &&
5070 (istk
->expansion
!= NULL
) &&
5071 (istk
->expansion
->type
== EXP_IF
) &&
5072 (istk
->expansion
->def
->state
== COND_NEVER
))
5076 verror(severity
, fmt
, arg
);
5081 pp_reset(char *file
, int apass
, ListGen
* listgen
, StrList
**deplist
)
5086 istk
= nasm_zalloc(sizeof(Include
));
5087 istk
->fp
= fopen(file
, "r");
5088 src_set_fname(nasm_strdup(file
));
5092 error(ERR_FATAL
|ERR_NOFILE
, "unable to open input file `%s'",
5097 nested_mac_count
= 0;
5098 nested_rep_count
= 0;
5101 if (tasm_compatible_mode
) {
5102 stdmacpos
= nasm_stdmac
;
5104 stdmacpos
= nasm_stdmac_after_tasm
;
5106 any_extrastdmac
= extrastdmac
&& *extrastdmac
;
5111 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
5112 * The caller, however, will also pass in 3 for preprocess-only so
5113 * we can set __PASS__ accordingly.
5115 pass
= apass
> 2 ? 2 : apass
;
5117 dephead
= deptail
= deplist
;
5119 StrList
*sl
= nasm_malloc(strlen(file
)+1+sizeof sl
->next
);
5121 strcpy(sl
->str
, file
);
5123 deptail
= &sl
->next
;
5127 * Define the __PASS__ macro. This is defined here unlike
5128 * all the other builtins, because it is special -- it varies between
5131 t
= nasm_zalloc(sizeof(*t
));
5132 make_tok_num(t
, apass
);
5133 define_smacro(NULL
, "__PASS__", true, 0, t
);
5136 static char *pp_getline(void)
5147 * Fetch a tokenized line, either from the expansion
5148 * buffer or from the input file.
5152 while (1) { /* until we get a line we can use */
5154 * Fetch a tokenized line from the expansion buffer
5156 if (istk
->expansion
!= NULL
) {
5157 ei
= istk
->expansion
;
5158 if (ei
->current
!= NULL
) {
5159 if (ei
->emitting
== false) {
5164 ei
->current
= l
->next
;
5166 tline
= copy_Token(l
->first
);
5167 if (((ei
->type
== EXP_REP
) ||
5168 (ei
->type
== EXP_MMACRO
) ||
5169 (ei
->type
== EXP_WHILE
))
5170 && (ei
->def
->nolist
== false)) {
5171 char *p
= detoken(tline
, false);
5172 list
->line(LIST_MACRO
, p
);
5175 if (ei
->linnum
> -1) {
5176 src_set_linnum(src_get_linnum() + 1);
5179 } else if ((ei
->type
== EXP_REP
) &&
5180 (ei
->def
->cur_depth
< ei
->def
->max_depth
)) {
5181 ei
->def
->cur_depth
++;
5182 ei
->current
= ei
->def
->line
;
5185 } else if ((ei
->type
== EXP_WHILE
) &&
5186 (ei
->def
->cur_depth
< ei
->def
->max_depth
)) {
5187 ei
->current
= ei
->def
->line
;
5189 tline
= copy_Token(ei
->current
->first
);
5190 j
= if_condition(tline
, PP_WHILE
);
5192 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
5193 if (j
== COND_IF_TRUE
) {
5194 ei
->current
= ei
->current
->next
;
5195 ei
->def
->cur_depth
++;
5197 ei
->emitting
= false;
5199 ei
->def
->cur_depth
= ei
->def
->max_depth
;
5203 istk
->expansion
= ei
->prev
;
5206 if ((ei
->emitting
== true) &&
5207 (ed
->max_depth
== DEADMAN_LIMIT
) &&
5208 (ed
->cur_depth
== DEADMAN_LIMIT
)
5210 error(ERR_FATAL
, "runaway expansion detected, aborting");
5212 if (ed
->cur_depth
> 0) {
5214 } else if (ed
->type
!= EXP_MMACRO
) {
5215 expansions
= ed
->prev
;
5218 if ((ei
->type
== EXP_REP
) ||
5219 (ei
->type
== EXP_MMACRO
) ||
5220 (ei
->type
== EXP_WHILE
)) {
5221 list
->downlevel(LIST_MACRO
);
5222 if (ei
->type
== EXP_MMACRO
) {
5227 if (ei
->linnum
> -1) {
5228 src_set_linnum(ei
->linnum
);
5236 * Read in line from input and tokenize
5239 if (line
) { /* from the current input file */
5240 line
= prepreproc(line
);
5241 tline
= tokenize(line
);
5247 * The current file has ended; work down the istk
5252 if (i
->expansion
!= NULL
) {
5254 "end of file while still in an expansion");
5256 /* only set line and file name if there's a next node */
5258 src_set_linnum(i
->lineno
);
5259 nasm_free(src_set_fname(nasm_strdup(i
->fname
)));
5261 if ((i
->next
== NULL
) && (finals
!= NULL
)) {
5263 ei
= new_ExpInv(EXP_FINAL
, NULL
);
5264 ei
->emitting
= true;
5265 ei
->current
= finals
;
5266 istk
->expansion
= ei
;
5271 list
->downlevel(LIST_INCLUDE
);
5274 if (finals
!= NULL
) {
5284 if (defining
== NULL
) {
5285 tline
= expand_mmac_params(tline
);
5289 * Check the line to see if it's a preprocessor directive.
5291 if (do_directive(tline
) == DIRECTIVE_FOUND
) {
5293 } else if (defining
!= NULL
) {
5295 * We're defining an expansion. We emit nothing at all,
5296 * and just shove the tokenized line on to the definition.
5298 if (defining
->ignoring
== false) {
5299 Line
*l
= new_Line();
5301 if (defining
->line
== NULL
) {
5305 defining
->last
->next
= l
;
5311 defining
->linecount
++;
5313 } else if ((istk
->expansion
!= NULL
) &&
5314 (istk
->expansion
->emitting
!= true)) {
5316 * We're in a non-emitting branch of an expansion.
5317 * Emit nothing at all, not even a blank line: when we
5318 * emerge from the expansion we'll give a line-number
5319 * directive so we keep our place correctly.
5324 tline
= expand_smacro(tline
);
5325 if (expand_mmacro(tline
) != true) {
5327 * De-tokenize the line again, and emit it.
5329 line
= detoken(tline
, true);
5340 static void pp_cleanup(int pass
)
5342 if (defining
!= NULL
) {
5343 error(ERR_NONFATAL
, "end of file while still defining an expansion");
5344 while (defining
!= NULL
) {
5345 ExpDef
*ed
= defining
;
5346 defining
= ed
->prev
;
5351 while (cstk
!= NULL
)
5354 while (istk
!= NULL
) {
5358 nasm_free(i
->fname
);
5359 while (i
->expansion
!= NULL
) {
5360 ExpInv
*ei
= i
->expansion
;
5361 i
->expansion
= ei
->prev
;
5368 nasm_free(src_set_fname(NULL
));
5373 while ((i
= ipath
)) {
5382 void pp_include_path(char *path
)
5384 IncPath
*i
= nasm_zalloc(sizeof(IncPath
));
5387 i
->path
= nasm_strdup(path
);
5399 void pp_pre_include(char *fname
)
5401 Token
*inc
, *space
, *name
;
5404 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
5405 space
= new_Token(name
, TOK_WHITESPACE
, NULL
, 0);
5406 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
5414 void pp_pre_define(char *definition
)
5420 equals
= strchr(definition
, '=');
5421 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5422 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
5425 space
->next
= tokenize(definition
);
5435 void pp_pre_undefine(char *definition
)
5440 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5441 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
5442 space
->next
= tokenize(definition
);
5451 * This function is used to assist with "runtime" preprocessor
5452 * directives, e.g. pp_runtime("%define __BITS__ 64");
5454 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
5455 * PASS A VALID STRING TO THIS FUNCTION!!!!!
5458 void pp_runtime(char *definition
)
5462 def
= tokenize(definition
);
5463 if (do_directive(def
) == NO_DIRECTIVE_FOUND
)
5468 void pp_extra_stdmac(macros_t
*macros
)
5470 extrastdmac
= macros
;
5473 static void make_tok_num(Token
* tok
, int64_t val
)
5476 snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
5477 tok
->text
= nasm_strdup(numbuf
);
5478 tok
->type
= TOK_NUMBER
;