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))
341 * Condition codes. Note that we use c_ prefix not C_ because C_ is
342 * used in nasm.h for the "real" condition codes. At _this_ level,
343 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
344 * ones, so we need a different enum...
346 static const char * const conditions
[] = {
347 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
348 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
349 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
352 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
353 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
354 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_RCXZ
, c_S
, c_Z
,
357 static const enum pp_conds inverse_ccs
[] = {
358 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
359 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_E
, c_G
, c_GE
, c_L
, c_LE
, c_O
, c_P
, c_S
,
360 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, -1, c_NS
, c_NZ
363 /* For TASM compatibility we need to be able to recognise TASM compatible
364 * conditional compilation directives. Using the NASM pre-processor does
365 * not work, so we look for them specifically from the following list and
366 * then jam in the equivalent NASM directive into the input stream.
370 TM_ARG
, TM_ELIF
, TM_ELSE
, TM_ENDIF
, TM_IF
, TM_IFDEF
, TM_IFDIFI
,
371 TM_IFNDEF
, TM_INCLUDE
, TM_LOCAL
374 static const char * const tasm_directives
[] = {
375 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
376 "ifndef", "include", "local"
379 static int StackSize
= 4;
380 static char *StackPointer
= "ebp";
381 static int ArgOffset
= 8;
382 static int LocalOffset
= 0;
384 static Context
*cstk
;
385 static Include
*istk
;
386 static IncPath
*ipath
= NULL
;
388 static int pass
; /* HACK: pass 0 = generate dependencies only */
389 static StrList
**dephead
, **deptail
; /* Dependency list */
391 static uint64_t unique
; /* unique identifier numbers */
393 static Line
*predef
= NULL
;
394 static bool do_predef
;
396 static ListGen
*list
;
399 * The current set of expansion definitions we have defined.
401 static struct hash_table expdefs
;
404 * The current set of single-line macros we have defined.
406 static struct hash_table smacros
;
409 * Linked List of all active expansion definitions
411 struct ExpDef
*expansions
= NULL
;
414 * The expansion we are currently defining
416 static ExpDef
*defining
= NULL
;
418 static uint64_t nested_mac_count
;
419 static uint64_t nested_rep_count
;
422 * Linked-list of lines to preprocess, prior to cleanup
424 static Line
*finals
= NULL
;
425 static bool in_final
= false;
428 * The number of macro parameters to allocate space for at a time.
430 #define PARAM_DELTA 16
433 * The standard macro set: defined in macros.c in the array nasm_stdmac.
434 * This gives our position in the macro set, when we're processing it.
436 static macros_t
*stdmacpos
;
439 * The extra standard macros that come from the object format, if
442 static macros_t
*extrastdmac
= NULL
;
443 static bool any_extrastdmac
;
446 * Tokens are allocated in blocks to improve speed
448 #define TOKEN_BLOCKSIZE 4096
449 static Token
*freeTokens
= NULL
;
455 static Blocks blocks
= { NULL
, NULL
};
458 * Forward declarations.
460 static Token
*expand_mmac_params(Token
* tline
);
461 static Token
*expand_smacro(Token
* tline
);
462 static Token
*expand_id(Token
* tline
);
463 static Context
*get_ctx(const char *name
, const char **namep
);
464 static void make_tok_num(Token
* tok
, int64_t val
);
465 static void error(int severity
, const char *fmt
, ...);
466 static void error_precond(int severity
, const char *fmt
, ...);
467 static void *new_Block(size_t size
);
468 static void delete_Blocks(void);
469 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
470 const char *text
, int txtlen
);
471 static Token
*copy_Token(Token
* tline
);
472 static Token
*delete_Token(Token
* t
);
473 static Line
*new_Line(void);
474 static ExpDef
*new_ExpDef(int exp_type
);
475 static ExpInv
*new_ExpInv(int exp_type
, ExpDef
*ed
);
478 * Macros for safe checking of token pointers, avoid *(NULL)
480 #define tok_type_(x,t) ((x) && (x)->type == (t))
481 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
482 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
483 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
487 #define stringify(x) #x
489 #define nasm_trace(msg, ...) printf("(%s:%d): " msg "\n", __func__, __LINE__, ##__VA_ARGS__)
490 #define nasm_dump_token(t) nasm_raw_dump_token(t, __FILE__, __LINE__, __func__);
491 #define nasm_dump_stream(t) nasm_raw_dump_stream(t, __FILE__, __LINE__, __func__);
493 /* FIXME: we really need some compound type here instead of inplace code */
494 static const char *nasm_get_tok_type_str(enum pp_token_type type
)
496 #define SWITCH_TOK_NAME(type) \
498 return stringify(type)
501 SWITCH_TOK_NAME(TOK_NONE
);
502 SWITCH_TOK_NAME(TOK_WHITESPACE
);
503 SWITCH_TOK_NAME(TOK_COMMENT
);
504 SWITCH_TOK_NAME(TOK_ID
);
505 SWITCH_TOK_NAME(TOK_PREPROC_ID
);
506 SWITCH_TOK_NAME(TOK_STRING
);
507 SWITCH_TOK_NAME(TOK_NUMBER
);
508 SWITCH_TOK_NAME(TOK_FLOAT
);
509 SWITCH_TOK_NAME(TOK_SMAC_END
);
510 SWITCH_TOK_NAME(TOK_OTHER
);
511 SWITCH_TOK_NAME(TOK_INTERNAL_STRING
);
512 SWITCH_TOK_NAME(TOK_PREPROC_Q
);
513 SWITCH_TOK_NAME(TOK_PREPROC_QQ
);
514 SWITCH_TOK_NAME(TOK_PASTE
);
515 SWITCH_TOK_NAME(TOK_INDIRECT
);
516 SWITCH_TOK_NAME(TOK_SMAC_PARAM
);
517 SWITCH_TOK_NAME(TOK_MAX
);
523 static void nasm_raw_dump_token(Token
*token
, const char *file
, int line
, const char *func
)
525 printf("---[%s (%s:%d): %p]---\n", func
, file
, line
, (void *)token
);
528 list_for_each(t
, token
) {
530 printf("'%s'(%s) ", t
->text
,
531 nasm_get_tok_type_str(t
->type
));
537 static void nasm_raw_dump_stream(Token
*token
, const char *file
, int line
, const char *func
)
539 printf("---[%s (%s:%d): %p]---\n", func
, file
, line
, (void *)token
);
542 list_for_each(t
, token
)
543 printf("%s", t
->text
? t
->text
: " ");
549 #define nasm_trace(msg, ...)
550 #define nasm_dump_token(t)
551 #define nasm_dump_stream(t)
555 * nasm_unquote with error if the string contains NUL characters.
556 * If the string contains NUL characters, issue an error and return
557 * the C len, i.e. truncate at the NUL.
559 static size_t nasm_unquote_cstr(char *qstr
, enum preproc_token directive
)
561 size_t len
= nasm_unquote(qstr
, NULL
);
562 size_t clen
= strlen(qstr
);
565 error(ERR_NONFATAL
, "NUL character in `%s' directive",
566 pp_directives
[directive
]);
572 * In-place reverse a list of tokens.
574 static Token
*reverse_tokens(Token
*t
)
578 list_reverse(t
, prev
, next
);
584 * Handle TASM specific directives, which do not contain a % in
585 * front of them. We do it here because I could not find any other
586 * place to do it for the moment, and it is a hack (ideally it would
587 * be nice to be able to use the NASM pre-processor to do it).
589 static char *check_tasm_directive(char *line
)
591 int32_t i
, j
, k
, m
, len
;
592 char *p
, *q
, *oldline
, oldchar
;
594 p
= nasm_skip_spaces(line
);
596 /* Binary search for the directive name */
598 j
= ARRAY_SIZE(tasm_directives
);
599 q
= nasm_skip_word(p
);
606 m
= nasm_stricmp(p
, tasm_directives
[k
]);
608 /* We have found a directive, so jam a % in front of it
609 * so that NASM will then recognise it as one if it's own.
614 line
= nasm_malloc(len
+ 2);
616 if (k
== TM_IFDIFI
) {
618 * NASM does not recognise IFDIFI, so we convert
619 * it to %if 0. This is not used in NASM
620 * compatible code, but does need to parse for the
621 * TASM macro package.
623 strcpy(line
+ 1, "if 0");
625 memcpy(line
+ 1, p
, len
+ 1);
640 * The pre-preprocessing stage... This function translates line
641 * number indications as they emerge from GNU cpp (`# lineno "file"
642 * flags') into NASM preprocessor line number indications (`%line
645 static char *prepreproc(char *line
)
648 char *fname
, *oldline
;
650 if (line
[0] == '#' && line
[1] == ' ') {
653 lineno
= atoi(fname
);
654 fname
+= strspn(fname
, "0123456789 ");
657 fnlen
= strcspn(fname
, "\"");
658 line
= nasm_malloc(20 + fnlen
);
659 snprintf(line
, 20 + fnlen
, "%%line %d %.*s", lineno
, fnlen
, fname
);
662 if (tasm_compatible_mode
)
663 return check_tasm_directive(line
);
668 * Free a linked list of tokens.
670 static void free_tlist(Token
* list
)
673 list
= delete_Token(list
);
677 * Free a linked list of lines.
679 static void free_llist(Line
* list
)
682 list_for_each_safe(l
, tmp
, list
) {
683 free_tlist(l
->first
);
691 static void free_expdef(ExpDef
* ed
)
694 free_tlist(ed
->dlist
);
695 nasm_free(ed
->defaults
);
696 free_llist(ed
->line
);
703 static void free_expinv(ExpInv
* ei
)
706 nasm_free(ei
->label_text
);
711 * Free all currently defined macros, and free the hash tables
713 static void free_smacro_table(struct hash_table
*smt
)
717 struct hash_tbl_node
*it
= NULL
;
719 while ((s
= hash_iterate(smt
, &it
, &key
)) != NULL
) {
720 nasm_free((void *)key
);
721 list_for_each_safe(s
, tmp
, s
) {
723 free_tlist(s
->expansion
);
730 static void free_expdef_table(struct hash_table
*edt
)
734 struct hash_tbl_node
*it
= NULL
;
737 while ((ed
= hash_iterate(edt
, &it
, &key
)) != NULL
) {
738 nasm_free((void *)key
);
739 list_for_each_safe(ed
,tmp
, ed
)
745 static void free_macros(void)
747 free_smacro_table(&smacros
);
748 free_expdef_table(&expdefs
);
752 * Initialize the hash tables
754 static void init_macros(void)
756 hash_init(&smacros
, HASH_LARGE
);
757 hash_init(&expdefs
, HASH_LARGE
);
761 * Pop the context stack.
763 static void ctx_pop(void)
768 free_smacro_table(&c
->localmac
);
774 * Search for a key in the hash index; adding it if necessary
775 * (in which case we initialize the data pointer to NULL.)
778 hash_findi_add(struct hash_table
*hash
, const char *str
)
780 struct hash_insert hi
;
784 r
= hash_findi(hash
, str
, &hi
);
788 strx
= nasm_strdup(str
); /* Use a more efficient allocator here? */
789 return hash_add(&hi
, strx
, NULL
);
793 * Like hash_findi, but returns the data element rather than a pointer
794 * to it. Used only when not adding a new element, hence no third
798 hash_findix(struct hash_table
*hash
, const char *str
)
802 p
= hash_findi(hash
, str
, NULL
);
803 return p
? *p
: NULL
;
807 * read line from standard macros set,
808 * if there no more left -- return NULL
810 static char *line_from_stdmac(void)
813 const unsigned char *p
= stdmacpos
;
822 len
+= pp_directives_len
[c
- 0x80] + 1;
827 line
= nasm_malloc(len
+ 1);
829 while ((c
= *stdmacpos
++)) {
831 memcpy(q
, pp_directives
[c
- 0x80], pp_directives_len
[c
- 0x80]);
832 q
+= pp_directives_len
[c
- 0x80];
842 /* This was the last of the standard macro chain... */
844 if (any_extrastdmac
) {
845 stdmacpos
= extrastdmac
;
846 any_extrastdmac
= false;
847 } else if (do_predef
) {
850 Token
*head
, **tail
, *t
;
853 * Nasty hack: here we push the contents of
854 * `predef' on to the top-level expansion stack,
855 * since this is the most convenient way to
856 * implement the pre-include and pre-define
859 list_for_each(pd
, predef
) {
862 list_for_each(t
, pd
->first
) {
863 *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
864 tail
= &(*tail
)->next
;
869 ei
= new_ExpInv(EXP_PREDEF
, NULL
);
872 ei
->prev
= istk
->expansion
;
873 istk
->expansion
= ei
;
882 #define BUF_DELTA 512
884 * Read a line from the top file in istk, handling multiple CR/LFs
885 * at the end of the line read, and handling spurious ^Zs. Will
886 * return lines from the standard macro set if this has not already
889 static char *read_line(void)
891 char *buffer
, *p
, *q
;
892 int bufsize
, continued_count
;
895 * standart macros set (predefined) goes first
897 p
= line_from_stdmac();
902 * regular read from a file
905 buffer
= nasm_malloc(BUF_DELTA
);
909 q
= fgets(p
, bufsize
- (p
- buffer
), istk
->fp
);
913 if (p
> buffer
&& p
[-1] == '\n') {
915 * Convert backslash-CRLF line continuation sequences into
916 * nothing at all (for DOS and Windows)
918 if (((p
- 2) > buffer
) && (p
[-3] == '\\') && (p
[-2] == '\r')) {
924 * Also convert backslash-LF line continuation sequences into
925 * nothing at all (for Unix)
927 else if (((p
- 1) > buffer
) && (p
[-2] == '\\')) {
935 if (p
- buffer
> bufsize
- 10) {
936 int32_t offset
= p
- buffer
;
937 bufsize
+= BUF_DELTA
;
938 buffer
= nasm_realloc(buffer
, bufsize
);
939 p
= buffer
+ offset
; /* prevent stale-pointer problems */
943 if (!q
&& p
== buffer
) {
948 src_set_linnum(src_get_linnum() + istk
->lineinc
+
949 (continued_count
* istk
->lineinc
));
952 * Play safe: remove CRs as well as LFs, if any of either are
953 * present at the end of the line.
955 while (--p
>= buffer
&& (*p
== '\n' || *p
== '\r'))
959 * Handle spurious ^Z, which may be inserted into source files
960 * by some file transfer utilities.
962 buffer
[strcspn(buffer
, "\032")] = '\0';
964 list
->line(LIST_READ
, buffer
);
970 * Tokenize a line of text. This is a very simple process since we
971 * don't need to parse the value out of e.g. numeric tokens: we
972 * simply split one string into many.
974 static Token
*tokenize(char *line
)
977 enum pp_token_type type
;
979 Token
*t
, **tail
= &list
;
982 nasm_trace("Tokenize for '%s'", line
);
984 if ((defining
!= NULL
) && (defining
->ignoring
== true)) {
992 if (*p
== '+' && !nasm_isdigit(p
[1])) {
995 } else if (nasm_isdigit(*p
) ||
996 ((*p
== '-' || *p
== '+') && nasm_isdigit(p
[1]))) {
1000 while (nasm_isdigit(*p
));
1001 type
= TOK_PREPROC_ID
;
1002 } else if (*p
== '{') {
1004 while (*p
&& *p
!= '}') {
1011 type
= TOK_PREPROC_ID
;
1012 } else if (*p
== '[') {
1014 line
+= 2; /* Skip the leading %[ */
1016 while (lvl
&& (c
= *p
++)) {
1028 p
= nasm_skip_string(p
- 1) + 1;
1038 error(ERR_NONFATAL
, "unterminated %[ construct");
1039 type
= TOK_INDIRECT
;
1040 } else if (*p
== '?') {
1041 type
= TOK_PREPROC_Q
; /* %? */
1044 type
= TOK_PREPROC_QQ
; /* %?? */
1047 } else if (*p
== '!') {
1048 type
= TOK_PREPROC_ID
;
1053 } while (isidchar(*p
));
1054 } else if (*p
== '\'' || *p
== '\"' || *p
== '`') {
1055 p
= nasm_skip_string(p
);
1059 error(ERR_NONFATAL
|ERR_PASS1
, "unterminated %! string");
1061 /* %! without string or identifier */
1062 type
= TOK_OTHER
; /* Legacy behavior... */
1064 } else if (isidchar(*p
) ||
1065 ((*p
== '!' || *p
== '%' || *p
== '$') &&
1070 while (isidchar(*p
));
1071 type
= TOK_PREPROC_ID
;
1077 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
1080 while (*p
&& isidchar(*p
))
1082 } else if (*p
== '\'' || *p
== '"' || *p
== '`') {
1087 p
= nasm_skip_string(p
);
1091 } else if(verbose
) {
1092 error(ERR_WARNING
|ERR_PASS1
, "unterminated string");
1093 /* Handling unterminated strings by UNV */
1096 } else if (p
[0] == '$' && p
[1] == '$') {
1097 type
= TOK_OTHER
; /* TOKEN_BASE */
1099 } else if (isnumstart(*p
)) {
1100 bool is_hex
= false;
1101 bool is_float
= false;
1117 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
1119 if (*p
== '+' || *p
== '-') {
1121 * e can only be followed by +/- if it is either a
1122 * prefixed hex number or a floating-point number
1127 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
1129 } else if (c
== 'P' || c
== 'p') {
1131 if (*p
== '+' || *p
== '-')
1133 } else if (isnumchar(c
) || c
== '_')
1134 ; /* just advance */
1135 else if (c
== '.') {
1137 * we need to deal with consequences of the legacy
1138 * parser, like "1.nolist" being two tokens
1139 * (TOK_NUMBER, TOK_ID) here; at least give it
1140 * a shot for now. In the future, we probably need
1141 * a flex-based scanner with proper pattern matching
1142 * to do it as well as it can be done. Nothing in
1143 * the world is going to help the person who wants
1144 * 0x123.p16 interpreted as two tokens, though.
1150 if (nasm_isdigit(*r
) || (is_hex
&& nasm_isxdigit(*r
)) ||
1151 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
1152 (*r
== 'p' || *r
== 'P')) {
1156 break; /* Terminate the token */
1160 p
--; /* Point to first character beyond number */
1162 if (p
== line
+1 && *line
== '$') {
1163 type
= TOK_OTHER
; /* TOKEN_HERE */
1165 if (has_e
&& !is_hex
) {
1166 /* 1e13 is floating-point, but 1e13h is not */
1170 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
1172 } else if (nasm_isspace(*p
)) {
1173 type
= TOK_WHITESPACE
;
1174 p
= nasm_skip_spaces(p
);
1176 * Whitespace just before end-of-line is discarded by
1177 * pretending it's a comment; whitespace just before a
1178 * comment gets lumped into the comment.
1180 if (!*p
|| *p
== ';') {
1185 } else if (*p
== ';') {
1191 * Anything else is an operator of some kind. We check
1192 * for all the double-character operators (>>, <<, //,
1193 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1194 * else is a single-character operator.
1197 if ((p
[0] == '>' && p
[1] == '>') ||
1198 (p
[0] == '<' && p
[1] == '<') ||
1199 (p
[0] == '/' && p
[1] == '/') ||
1200 (p
[0] == '<' && p
[1] == '=') ||
1201 (p
[0] == '>' && p
[1] == '=') ||
1202 (p
[0] == '=' && p
[1] == '=') ||
1203 (p
[0] == '!' && p
[1] == '=') ||
1204 (p
[0] == '<' && p
[1] == '>') ||
1205 (p
[0] == '&' && p
[1] == '&') ||
1206 (p
[0] == '|' && p
[1] == '|') ||
1207 (p
[0] == '^' && p
[1] == '^')) {
1213 /* Handling unterminated string by UNV */
1216 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1217 t->text[p-line] = *line;
1221 if (type
!= TOK_COMMENT
) {
1222 *tail
= t
= new_Token(NULL
, type
, line
, p
- line
);
1228 nasm_dump_token(list
);
1234 * this function allocates a new managed block of memory and
1235 * returns a pointer to the block. The managed blocks are
1236 * deleted only all at once by the delete_Blocks function.
1238 static void *new_Block(size_t size
)
1240 Blocks
*b
= &blocks
;
1242 /* first, get to the end of the linked list */
1246 /* now allocate the requested chunk */
1247 b
->chunk
= nasm_malloc(size
);
1249 /* now allocate a new block for the next request */
1250 b
->next
= nasm_zalloc(sizeof(Blocks
));
1256 * this function deletes all managed blocks of memory
1258 static void delete_Blocks(void)
1260 Blocks
*a
, *b
= &blocks
;
1263 * keep in mind that the first block, pointed to by blocks
1264 * is a static and not dynamically allocated, so we don't
1268 nasm_free(b
->chunk
);
1277 * this function creates a new Token and passes a pointer to it
1278 * back to the caller. It sets the type and text elements, and
1279 * also the a.mac and next elements to NULL.
1281 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
1282 const char *text
, int txtlen
)
1288 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1289 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1290 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1291 freeTokens
[i
].next
= NULL
;
1294 freeTokens
= t
->next
;
1298 if (type
== TOK_WHITESPACE
|| !text
) {
1302 txtlen
= strlen(text
);
1303 t
->text
= nasm_malloc(txtlen
+1);
1304 memcpy(t
->text
, text
, txtlen
);
1305 t
->text
[txtlen
] = '\0';
1310 static Token
*copy_Token(Token
* tline
)
1312 Token
*t
, *tt
, *first
= NULL
, *prev
= NULL
;
1314 for (tt
= tline
; tt
!= NULL
; tt
= tt
->next
) {
1316 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1317 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1318 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1319 freeTokens
[i
].next
= NULL
;
1322 freeTokens
= t
->next
;
1324 t
->text
= tt
->text
? nasm_strdup(tt
->text
) : NULL
;
1325 t
->a
.mac
= tt
->a
.mac
;
1326 t
->a
.len
= tt
->a
.len
;
1338 static Token
*delete_Token(Token
* t
)
1340 Token
*next
= t
->next
;
1342 t
->next
= freeTokens
;
1348 * Convert a line of tokens back into text.
1349 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1350 * will be transformed into ..@ctxnum.xxx
1352 static char *detoken(Token
* tlist
, bool expand_locals
)
1359 list_for_each(t
, tlist
) {
1360 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
1365 if (*v
== '\'' || *v
== '\"' || *v
== '`') {
1366 size_t len
= nasm_unquote(v
, NULL
);
1367 size_t clen
= strlen(v
);
1370 error(ERR_NONFATAL
| ERR_PASS1
,
1371 "NUL character in %! string");
1377 char *p
= getenv(v
);
1379 error(ERR_NONFATAL
| ERR_PASS1
,
1380 "nonexistent environment variable `%s'", v
);
1383 t
->text
= nasm_strdup(p
);
1388 /* Expand local macros here and not during preprocessing */
1389 if (expand_locals
&&
1390 t
->type
== TOK_PREPROC_ID
&& t
->text
&&
1391 t
->text
[0] == '%' && t
->text
[1] == '$') {
1394 Context
*ctx
= get_ctx(t
->text
, &q
);
1397 snprintf(buffer
, sizeof(buffer
), "..@%"PRIu32
".", ctx
->number
);
1398 p
= nasm_strcat(buffer
, q
);
1404 /* Expand %? and %?? directives */
1405 if ((istk
->expansion
!= NULL
) &&
1406 ((t
->type
== TOK_PREPROC_Q
) ||
1407 (t
->type
== TOK_PREPROC_QQ
))) {
1409 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
){
1410 if (ei
->type
== EXP_MMACRO
) {
1412 if (t
->type
== TOK_PREPROC_Q
) {
1413 t
->text
= nasm_strdup(ei
->name
);
1415 t
->text
= nasm_strdup(ei
->def
->name
);
1422 if (t
->type
== TOK_WHITESPACE
)
1425 len
+= strlen(t
->text
);
1428 p
= line
= nasm_malloc(len
+ 1);
1430 list_for_each(t
, tlist
) {
1431 if (t
->type
== TOK_WHITESPACE
) {
1433 } else if (t
->text
) {
1445 * Initialize a new Line
1447 static inline Line
*new_Line(void)
1449 return (Line
*)nasm_zalloc(sizeof(Line
));
1454 * Initialize a new Expansion Definition
1456 static ExpDef
*new_ExpDef(int exp_type
)
1458 ExpDef
*ed
= (ExpDef
*)nasm_zalloc(sizeof(ExpDef
));
1459 ed
->type
= exp_type
;
1460 ed
->casesense
= true;
1461 ed
->state
= COND_NEVER
;
1468 * Initialize a new Expansion Instance
1470 static ExpInv
*new_ExpInv(int exp_type
, ExpDef
*ed
)
1472 ExpInv
*ei
= (ExpInv
*)nasm_zalloc(sizeof(ExpInv
));
1473 ei
->type
= exp_type
;
1475 ei
->unique
= ++unique
;
1477 if ((istk
->mmac_depth
< 1) &&
1478 (istk
->expansion
== NULL
) &&
1480 (ed
->type
!= EXP_MMACRO
) &&
1481 (ed
->type
!= EXP_REP
) &&
1482 (ed
->type
!= EXP_WHILE
)) {
1483 ei
->linnum
= src_get_linnum();
1484 src_set_linnum(ei
->linnum
- ed
->linecount
- 1);
1488 if ((istk
->expansion
== NULL
) ||
1489 (ei
->type
== EXP_MMACRO
)) {
1492 ei
->relno
= istk
->expansion
->lineno
;
1494 ei
->relno
-= (ed
->linecount
+ 1);
1501 * A scanner, suitable for use by the expression evaluator, which
1502 * operates on a line of Tokens. Expects a pointer to a pointer to
1503 * the first token in the line to be passed in as its private_data
1506 * FIX: This really needs to be unified with stdscan.
1508 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1510 Token
**tlineptr
= private_data
;
1512 char ourcopy
[MAX_KEYWORD
+1], *p
, *r
, *s
;
1516 *tlineptr
= tline
? tline
->next
: NULL
;
1517 } while (tline
&& (tline
->type
== TOK_WHITESPACE
||
1518 tline
->type
== TOK_COMMENT
));
1521 return tokval
->t_type
= TOKEN_EOS
;
1523 tokval
->t_charptr
= tline
->text
;
1525 if (tline
->text
[0] == '$' && !tline
->text
[1])
1526 return tokval
->t_type
= TOKEN_HERE
;
1527 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[2])
1528 return tokval
->t_type
= TOKEN_BASE
;
1530 if (tline
->type
== TOK_ID
) {
1531 p
= tokval
->t_charptr
= tline
->text
;
1533 tokval
->t_charptr
++;
1534 return tokval
->t_type
= TOKEN_ID
;
1537 for (r
= p
, s
= ourcopy
; *r
; r
++) {
1538 if (r
>= p
+MAX_KEYWORD
)
1539 return tokval
->t_type
= TOKEN_ID
; /* Not a keyword */
1540 *s
++ = nasm_tolower(*r
);
1543 /* right, so we have an identifier sitting in temp storage. now,
1544 * is it actually a register or instruction name, or what? */
1545 return nasm_token_hash(ourcopy
, tokval
);
1548 if (tline
->type
== TOK_NUMBER
) {
1550 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
1551 tokval
->t_charptr
= tline
->text
;
1553 return tokval
->t_type
= TOKEN_ERRNUM
;
1555 return tokval
->t_type
= TOKEN_NUM
;
1558 if (tline
->type
== TOK_FLOAT
) {
1559 return tokval
->t_type
= TOKEN_FLOAT
;
1562 if (tline
->type
== TOK_STRING
) {
1565 bq
= tline
->text
[0];
1566 tokval
->t_charptr
= tline
->text
;
1567 tokval
->t_inttwo
= nasm_unquote(tline
->text
, &ep
);
1569 if (ep
[0] != bq
|| ep
[1] != '\0')
1570 return tokval
->t_type
= TOKEN_ERRSTR
;
1572 return tokval
->t_type
= TOKEN_STR
;
1575 if (tline
->type
== TOK_OTHER
) {
1576 if (!strcmp(tline
->text
, "<<"))
1577 return tokval
->t_type
= TOKEN_SHL
;
1578 if (!strcmp(tline
->text
, ">>"))
1579 return tokval
->t_type
= TOKEN_SHR
;
1580 if (!strcmp(tline
->text
, "//"))
1581 return tokval
->t_type
= TOKEN_SDIV
;
1582 if (!strcmp(tline
->text
, "%%"))
1583 return tokval
->t_type
= TOKEN_SMOD
;
1584 if (!strcmp(tline
->text
, "=="))
1585 return tokval
->t_type
= TOKEN_EQ
;
1586 if (!strcmp(tline
->text
, "<>"))
1587 return tokval
->t_type
= TOKEN_NE
;
1588 if (!strcmp(tline
->text
, "!="))
1589 return tokval
->t_type
= TOKEN_NE
;
1590 if (!strcmp(tline
->text
, "<="))
1591 return tokval
->t_type
= TOKEN_LE
;
1592 if (!strcmp(tline
->text
, ">="))
1593 return tokval
->t_type
= TOKEN_GE
;
1594 if (!strcmp(tline
->text
, "&&"))
1595 return tokval
->t_type
= TOKEN_DBL_AND
;
1596 if (!strcmp(tline
->text
, "^^"))
1597 return tokval
->t_type
= TOKEN_DBL_XOR
;
1598 if (!strcmp(tline
->text
, "||"))
1599 return tokval
->t_type
= TOKEN_DBL_OR
;
1603 * We have no other options: just return the first character of
1606 return tokval
->t_type
= tline
->text
[0];
1610 * Compare a string to the name of an existing macro; this is a
1611 * simple wrapper which calls either strcmp or nasm_stricmp
1612 * depending on the value of the `casesense' parameter.
1614 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
1616 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
1620 * Compare a string to the name of an existing macro; this is a
1621 * simple wrapper which calls either strcmp or nasm_stricmp
1622 * depending on the value of the `casesense' parameter.
1624 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
1626 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
1630 * Return the Context structure associated with a %$ token. Return
1631 * NULL, having _already_ reported an error condition, if the
1632 * context stack isn't deep enough for the supplied number of $
1635 * If "namep" is non-NULL, set it to the pointer to the macro name
1636 * tail, i.e. the part beyond %$...
1638 static Context
*get_ctx(const char *name
, const char **namep
)
1646 if (!name
|| name
[0] != '%' || name
[1] != '$')
1650 error(ERR_NONFATAL
, "`%s': context stack is empty", name
);
1657 while (ctx
&& *name
== '$') {
1664 error(ERR_NONFATAL
, "`%s': context stack is only"
1665 " %d level%s deep", name
, i
, (i
== 1 ? "" : "s"));
1676 * Check to see if a file is already in a string list
1678 static bool in_list(const StrList
*list
, const char *str
)
1681 if (!strcmp(list
->str
, str
))
1689 * Open an include file. This routine must always return a valid
1690 * file pointer if it returns - it's responsible for throwing an
1691 * ERR_FATAL and bombing out completely if not. It should also try
1692 * the include path one by one until it finds the file or reaches
1693 * the end of the path.
1695 static FILE *inc_fopen(const char *file
, StrList
**dhead
, StrList
***dtail
,
1700 IncPath
*ip
= ipath
;
1701 int len
= strlen(file
);
1702 size_t prefix_len
= 0;
1706 sl
= nasm_malloc(prefix_len
+len
+1+sizeof sl
->next
);
1708 memcpy(sl
->str
, prefix
, prefix_len
);
1709 memcpy(sl
->str
+prefix_len
, file
, len
+1);
1710 fp
= fopen(sl
->str
, "r");
1711 if (fp
&& dhead
&& !in_list(*dhead
, sl
->str
)) {
1728 prefix_len
= strlen(prefix
);
1730 /* -MG given and file not found */
1731 if (dhead
&& !in_list(*dhead
, file
)) {
1732 sl
= nasm_malloc(len
+1+sizeof sl
->next
);
1734 strcpy(sl
->str
, file
);
1742 error(ERR_FATAL
, "unable to open include file `%s'", file
);
1747 * Determine if we should warn on defining a single-line macro of
1748 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1749 * return true if _any_ single-line macro of that name is defined.
1750 * Otherwise, will return true if a single-line macro with either
1751 * `nparam' or no parameters is defined.
1753 * If a macro with precisely the right number of parameters is
1754 * defined, or nparam is -1, the address of the definition structure
1755 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1756 * is NULL, no action will be taken regarding its contents, and no
1759 * Note that this is also called with nparam zero to resolve
1762 * If you already know which context macro belongs to, you can pass
1763 * the context pointer as first parameter; if you won't but name begins
1764 * with %$ the context will be automatically computed. If all_contexts
1765 * is true, macro will be searched in outer contexts as well.
1768 smacro_defined(Context
* ctx
, const char *name
, int nparam
, SMacro
** defn
,
1771 struct hash_table
*smtbl
;
1775 smtbl
= &ctx
->localmac
;
1776 } else if (name
[0] == '%' && name
[1] == '$') {
1778 ctx
= get_ctx(name
, &name
);
1780 return false; /* got to return _something_ */
1781 smtbl
= &ctx
->localmac
;
1785 m
= (SMacro
*) hash_findix(smtbl
, name
);
1788 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
1789 (nparam
<= 0 || m
->nparam
== 0 || nparam
== (int) m
->nparam
)) {
1791 if (nparam
== (int) m
->nparam
|| nparam
== -1)
1805 * Count and mark off the parameters in a multi-line macro call.
1806 * This is called both from within the multi-line macro expansion
1807 * code, and also to mark off the default parameters when provided
1808 * in a %macro definition line.
1810 static void count_mmac_params(Token
* t
, int *nparam
, Token
*** params
)
1812 int paramsize
, brace
;
1814 *nparam
= paramsize
= 0;
1817 /* +1: we need space for the final NULL */
1818 if (*nparam
+1 >= paramsize
) {
1819 paramsize
+= PARAM_DELTA
;
1820 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
1824 if (tok_is_(t
, "{"))
1826 (*params
)[(*nparam
)++] = t
;
1827 while (tok_isnt_(t
, brace
? "}" : ","))
1829 if (t
) { /* got a comma/brace */
1833 * Now we've found the closing brace, look further
1837 if (tok_isnt_(t
, ",")) {
1839 "braces do not enclose all of macro parameter");
1840 while (tok_isnt_(t
, ","))
1844 t
= t
->next
; /* eat the comma */
1851 * Determine whether one of the various `if' conditions is true or
1854 * We must free the tline we get passed.
1856 static bool if_condition(Token
* tline
, enum preproc_token ct
)
1858 enum pp_conditional i
= PP_COND(ct
);
1860 Token
*t
, *tt
, **tptr
, *origline
;
1861 struct tokenval tokval
;
1863 enum pp_token_type needtype
;
1870 j
= false; /* have we matched yet? */
1875 if (tline
->type
!= TOK_ID
) {
1877 "`%s' expects context identifiers", pp_directives
[ct
]);
1878 free_tlist(origline
);
1881 if (cstk
&& cstk
->name
&& !nasm_stricmp(tline
->text
, cstk
->name
))
1883 tline
= tline
->next
;
1888 j
= false; /* have we matched yet? */
1891 if (!tline
|| (tline
->type
!= TOK_ID
&&
1892 (tline
->type
!= TOK_PREPROC_ID
||
1893 tline
->text
[1] != '$'))) {
1895 "`%s' expects macro identifiers", pp_directives
[ct
]);
1898 if (smacro_defined(NULL
, tline
->text
, 0, NULL
, true))
1900 tline
= tline
->next
;
1905 tline
= expand_smacro(tline
);
1906 j
= false; /* have we matched yet? */
1909 if (!tline
|| (tline
->type
!= TOK_ID
&&
1910 tline
->type
!= TOK_STRING
&&
1911 (tline
->type
!= TOK_PREPROC_ID
||
1912 tline
->text
[1] != '!'))) {
1914 "`%s' expects environment variable names",
1919 if (tline
->type
== TOK_PREPROC_ID
)
1920 p
+= 2; /* Skip leading %! */
1921 if (*p
== '\'' || *p
== '\"' || *p
== '`')
1922 nasm_unquote_cstr(p
, ct
);
1925 tline
= tline
->next
;
1931 tline
= expand_smacro(tline
);
1933 while (tok_isnt_(tt
, ","))
1937 "`%s' expects two comma-separated arguments",
1942 j
= true; /* assume equality unless proved not */
1943 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1944 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1945 error(ERR_NONFATAL
, "`%s': more than one comma on line",
1949 if (t
->type
== TOK_WHITESPACE
) {
1953 if (tt
->type
== TOK_WHITESPACE
) {
1957 if (tt
->type
!= t
->type
) {
1958 j
= false; /* found mismatching tokens */
1961 /* When comparing strings, need to unquote them first */
1962 if (t
->type
== TOK_STRING
) {
1963 size_t l1
= nasm_unquote(t
->text
, NULL
);
1964 size_t l2
= nasm_unquote(tt
->text
, NULL
);
1970 if (mmemcmp(t
->text
, tt
->text
, l1
, i
== PPC_IFIDN
)) {
1974 } else if (mstrcmp(tt
->text
, t
->text
, i
== PPC_IFIDN
) != 0) {
1975 j
= false; /* found mismatching tokens */
1982 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
1983 j
= false; /* trailing gunk on one end or other */
1989 ExpDef searching
, *ed
;
1992 tline
= expand_id(tline
);
1993 if (!tok_type_(tline
, TOK_ID
)) {
1995 "`%s' expects a macro name", pp_directives
[ct
]);
1998 memset(&searching
, 0, sizeof(searching
));
1999 searching
.name
= nasm_strdup(tline
->text
);
2000 searching
.casesense
= true;
2001 searching
.nparam_max
= INT_MAX
;
2002 tline
= expand_smacro(tline
->next
);
2005 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2007 "`%s' expects a parameter count or nothing",
2010 searching
.nparam_min
= searching
.nparam_max
=
2011 readnum(tline
->text
, &j
);
2014 "unable to parse parameter count `%s'",
2017 if (tline
&& tok_is_(tline
->next
, "-")) {
2018 tline
= tline
->next
->next
;
2019 if (tok_is_(tline
, "*"))
2020 searching
.nparam_max
= INT_MAX
;
2021 else if (!tok_type_(tline
, TOK_NUMBER
))
2023 "`%s' expects a parameter count after `-'",
2026 searching
.nparam_max
= readnum(tline
->text
, &j
);
2029 "unable to parse parameter count `%s'",
2031 if (searching
.nparam_min
> searching
.nparam_max
)
2033 "minimum parameter count exceeds maximum");
2036 if (tline
&& tok_is_(tline
->next
, "+")) {
2037 tline
= tline
->next
;
2038 searching
.plus
= true;
2040 ed
= (ExpDef
*) hash_findix(&expdefs
, searching
.name
);
2041 while (ed
!= NULL
) {
2042 if (!strcmp(ed
->name
, searching
.name
) &&
2043 (ed
->nparam_min
<= searching
.nparam_max
|| searching
.plus
) &&
2044 (searching
.nparam_min
<= ed
->nparam_max
|| ed
->plus
)) {
2050 if (tline
&& tline
->next
)
2051 error(ERR_WARNING
|ERR_PASS1
,
2052 "trailing garbage after %%ifmacro ignored");
2053 nasm_free(searching
.name
);
2062 needtype
= TOK_NUMBER
;
2065 needtype
= TOK_STRING
;
2069 t
= tline
= expand_smacro(tline
);
2071 while (tok_type_(t
, TOK_WHITESPACE
) ||
2072 (needtype
== TOK_NUMBER
&&
2073 tok_type_(t
, TOK_OTHER
) &&
2074 (t
->text
[0] == '-' || t
->text
[0] == '+') &&
2078 j
= tok_type_(t
, needtype
);
2082 t
= tline
= expand_smacro(tline
);
2083 while (tok_type_(t
, TOK_WHITESPACE
))
2088 t
= t
->next
; /* Skip the actual token */
2089 while (tok_type_(t
, TOK_WHITESPACE
))
2091 j
= !t
; /* Should be nothing left */
2096 t
= tline
= expand_smacro(tline
);
2097 while (tok_type_(t
, TOK_WHITESPACE
))
2100 j
= !t
; /* Should be empty */
2104 t
= tline
= expand_smacro(tline
);
2106 tokval
.t_type
= TOKEN_INVALID
;
2107 evalresult
= evaluate(ppscan
, tptr
, &tokval
,
2108 NULL
, pass
| CRITICAL
, error
, NULL
);
2112 error(ERR_WARNING
|ERR_PASS1
,
2113 "trailing garbage after expression ignored");
2114 if (!is_simple(evalresult
)) {
2116 "non-constant value given to `%s'", pp_directives
[ct
]);
2119 j
= reloc_value(evalresult
) != 0;
2124 "preprocessor directive `%s' not yet implemented",
2129 free_tlist(origline
);
2130 return j
^ PP_NEGATIVE(ct
);
2133 free_tlist(origline
);
2138 * Common code for defining an smacro
2140 static bool define_smacro(Context
*ctx
, const char *mname
, bool casesense
,
2141 int nparam
, Token
*expansion
)
2143 SMacro
*smac
, **smhead
;
2144 struct hash_table
*smtbl
;
2146 if (smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
)) {
2148 error(ERR_WARNING
|ERR_PASS1
,
2149 "single-line macro `%s' defined both with and"
2150 " without parameters", mname
);
2152 * Some instances of the old code considered this a failure,
2153 * some others didn't. What is the right thing to do here?
2155 free_tlist(expansion
);
2156 return false; /* Failure */
2159 * We're redefining, so we have to take over an
2160 * existing SMacro structure. This means freeing
2161 * what was already in it.
2163 nasm_free(smac
->name
);
2164 free_tlist(smac
->expansion
);
2167 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2168 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
2169 smac
= nasm_zalloc(sizeof(SMacro
));
2170 smac
->next
= *smhead
;
2173 smac
->name
= nasm_strdup(mname
);
2174 smac
->casesense
= casesense
;
2175 smac
->nparam
= nparam
;
2176 smac
->expansion
= expansion
;
2177 smac
->in_progress
= false;
2178 return true; /* Success */
2182 * Undefine an smacro
2184 static void undef_smacro(Context
*ctx
, const char *mname
)
2186 SMacro
**smhead
, *s
, **sp
;
2187 struct hash_table
*smtbl
;
2189 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2190 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
2194 * We now have a macro name... go hunt for it.
2197 while ((s
= *sp
) != NULL
) {
2198 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
2201 free_tlist(s
->expansion
);
2211 * Parse a mmacro specification.
2213 static bool parse_mmacro_spec(Token
*tline
, ExpDef
*def
, const char *directive
)
2217 tline
= tline
->next
;
2219 tline
= expand_id(tline
);
2220 if (!tok_type_(tline
, TOK_ID
)) {
2221 error(ERR_NONFATAL
, "`%s' expects a macro name", directive
);
2225 def
->name
= nasm_strdup(tline
->text
);
2227 def
->nolist
= false;
2228 // def->in_progress = 0;
2229 // def->rep_nest = NULL;
2230 def
->nparam_min
= 0;
2231 def
->nparam_max
= 0;
2233 tline
= expand_smacro(tline
->next
);
2235 if (!tok_type_(tline
, TOK_NUMBER
)) {
2236 error(ERR_NONFATAL
, "`%s' expects a parameter count", directive
);
2238 def
->nparam_min
= def
->nparam_max
=
2239 readnum(tline
->text
, &err
);
2242 "unable to parse parameter count `%s'", tline
->text
);
2244 if (tline
&& tok_is_(tline
->next
, "-")) {
2245 tline
= tline
->next
->next
;
2246 if (tok_is_(tline
, "*")) {
2247 def
->nparam_max
= INT_MAX
;
2248 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2250 "`%s' expects a parameter count after `-'", directive
);
2252 def
->nparam_max
= readnum(tline
->text
, &err
);
2254 error(ERR_NONFATAL
, "unable to parse parameter count `%s'",
2257 if (def
->nparam_min
> def
->nparam_max
) {
2258 error(ERR_NONFATAL
, "minimum parameter count exceeds maximum");
2262 if (tline
&& tok_is_(tline
->next
, "+")) {
2263 tline
= tline
->next
;
2266 if (tline
&& tok_type_(tline
->next
, TOK_ID
) &&
2267 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
2268 tline
= tline
->next
;
2273 * Handle default parameters.
2275 if (tline
&& tline
->next
) {
2276 def
->dlist
= tline
->next
;
2278 count_mmac_params(def
->dlist
, &def
->ndefs
, &def
->defaults
);
2281 def
->defaults
= NULL
;
2285 if (def
->defaults
&& def
->ndefs
> def
->nparam_max
- def
->nparam_min
&&
2287 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MDP
,
2288 "too many default macro parameters");
2295 * Decode a size directive
2297 static int parse_size(const char *str
) {
2298 static const char *size_names
[] =
2299 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2300 static const int sizes
[] =
2301 { 0, 1, 4, 16, 8, 10, 2, 32 };
2303 return sizes
[bsii(str
, size_names
, ARRAY_SIZE(size_names
))+1];
2307 * find and process preprocessor directive in passed line
2308 * Find out if a line contains a preprocessor directive, and deal
2311 * If a directive _is_ found, it is the responsibility of this routine
2312 * (and not the caller) to free_tlist() the line.
2314 * @param tline a pointer to the current tokeninzed line linked list
2315 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2318 static int do_directive(Token
* tline
)
2320 enum preproc_token i
;
2333 Token
*t
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
2334 struct tokenval tokval
;
2336 ExpDef
*ed
, *eed
, **edhead
;
2345 if (!tline
|| !tok_type_(tline
, TOK_PREPROC_ID
) ||
2346 (tline
->text
[1] == '%' || tline
->text
[1] == '$'
2347 || tline
->text
[1] == '!'))
2348 return NO_DIRECTIVE_FOUND
;
2350 i
= pp_token_hash(tline
->text
);
2354 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2355 error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2357 return NO_DIRECTIVE_FOUND
; /* didn't get it */
2360 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2361 /* Directive to tell NASM what the default stack size is. The
2362 * default is for a 16-bit stack, and this can be overriden with
2365 tline
= tline
->next
;
2366 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2367 tline
= tline
->next
;
2368 if (!tline
|| tline
->type
!= TOK_ID
) {
2369 error(ERR_NONFATAL
, "`%%stacksize' missing size parameter");
2370 free_tlist(origline
);
2371 return DIRECTIVE_FOUND
;
2373 if (nasm_stricmp(tline
->text
, "flat") == 0) {
2374 /* All subsequent ARG directives are for a 32-bit stack */
2376 StackPointer
= "ebp";
2379 } else if (nasm_stricmp(tline
->text
, "flat64") == 0) {
2380 /* All subsequent ARG directives are for a 64-bit stack */
2382 StackPointer
= "rbp";
2385 } else if (nasm_stricmp(tline
->text
, "large") == 0) {
2386 /* All subsequent ARG directives are for a 16-bit stack,
2387 * far function call.
2390 StackPointer
= "bp";
2393 } else if (nasm_stricmp(tline
->text
, "small") == 0) {
2394 /* All subsequent ARG directives are for a 16-bit stack,
2395 * far function call. We don't support near functions.
2398 StackPointer
= "bp";
2402 error(ERR_NONFATAL
, "`%%stacksize' invalid size type");
2403 free_tlist(origline
);
2404 return DIRECTIVE_FOUND
;
2406 free_tlist(origline
);
2407 return DIRECTIVE_FOUND
;
2410 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2411 /* TASM like ARG directive to define arguments to functions, in
2412 * the following form:
2414 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2418 char *arg
, directive
[256];
2419 int size
= StackSize
;
2421 /* Find the argument name */
2422 tline
= tline
->next
;
2423 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2424 tline
= tline
->next
;
2425 if (!tline
|| tline
->type
!= TOK_ID
) {
2426 error(ERR_NONFATAL
, "`%%arg' missing argument parameter");
2427 free_tlist(origline
);
2428 return DIRECTIVE_FOUND
;
2432 /* Find the argument size type */
2433 tline
= tline
->next
;
2434 if (!tline
|| tline
->type
!= TOK_OTHER
2435 || tline
->text
[0] != ':') {
2437 "Syntax error processing `%%arg' directive");
2438 free_tlist(origline
);
2439 return DIRECTIVE_FOUND
;
2441 tline
= tline
->next
;
2442 if (!tline
|| tline
->type
!= TOK_ID
) {
2443 error(ERR_NONFATAL
, "`%%arg' missing size type parameter");
2444 free_tlist(origline
);
2445 return DIRECTIVE_FOUND
;
2448 /* Allow macro expansion of type parameter */
2449 tt
= tokenize(tline
->text
);
2450 tt
= expand_smacro(tt
);
2451 size
= parse_size(tt
->text
);
2454 "Invalid size type for `%%arg' missing directive");
2456 free_tlist(origline
);
2457 return DIRECTIVE_FOUND
;
2461 /* Round up to even stack slots */
2462 size
= ALIGN(size
, StackSize
);
2464 /* Now define the macro for the argument */
2465 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
2466 arg
, StackPointer
, offset
);
2467 do_directive(tokenize(directive
));
2470 /* Move to the next argument in the list */
2471 tline
= tline
->next
;
2472 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2473 tline
= tline
->next
;
2474 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2476 free_tlist(origline
);
2477 return DIRECTIVE_FOUND
;
2480 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2481 /* TASM like LOCAL directive to define local variables for a
2482 * function, in the following form:
2484 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2486 * The '= LocalSize' at the end is ignored by NASM, but is
2487 * required by TASM to define the local parameter size (and used
2488 * by the TASM macro package).
2490 offset
= LocalOffset
;
2492 char *local
, directive
[256];
2493 int size
= StackSize
;
2495 /* Find the argument name */
2496 tline
= tline
->next
;
2497 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2498 tline
= tline
->next
;
2499 if (!tline
|| tline
->type
!= TOK_ID
) {
2501 "`%%local' missing argument parameter");
2502 free_tlist(origline
);
2503 return DIRECTIVE_FOUND
;
2505 local
= tline
->text
;
2507 /* Find the argument size type */
2508 tline
= tline
->next
;
2509 if (!tline
|| tline
->type
!= TOK_OTHER
2510 || tline
->text
[0] != ':') {
2512 "Syntax error processing `%%local' directive");
2513 free_tlist(origline
);
2514 return DIRECTIVE_FOUND
;
2516 tline
= tline
->next
;
2517 if (!tline
|| tline
->type
!= TOK_ID
) {
2519 "`%%local' missing size type parameter");
2520 free_tlist(origline
);
2521 return DIRECTIVE_FOUND
;
2524 /* Allow macro expansion of type parameter */
2525 tt
= tokenize(tline
->text
);
2526 tt
= expand_smacro(tt
);
2527 size
= parse_size(tt
->text
);
2530 "Invalid size type for `%%local' missing directive");
2532 free_tlist(origline
);
2533 return DIRECTIVE_FOUND
;
2537 /* Round up to even stack slots */
2538 size
= ALIGN(size
, StackSize
);
2540 offset
+= size
; /* Negative offset, increment before */
2542 /* Now define the macro for the argument */
2543 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
2544 local
, StackPointer
, offset
);
2545 do_directive(tokenize(directive
));
2547 /* Now define the assign to setup the enter_c macro correctly */
2548 snprintf(directive
, sizeof(directive
),
2549 "%%assign %%$localsize %%$localsize+%d", size
);
2550 do_directive(tokenize(directive
));
2552 /* Move to the next argument in the list */
2553 tline
= tline
->next
;
2554 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2555 tline
= tline
->next
;
2556 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2557 LocalOffset
= offset
;
2558 free_tlist(origline
);
2559 return DIRECTIVE_FOUND
;
2562 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2564 error(ERR_WARNING
|ERR_PASS1
,
2565 "trailing garbage after `%%clear' ignored");
2568 free_tlist(origline
);
2569 return DIRECTIVE_FOUND
;
2572 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2573 t
= tline
->next
= expand_smacro(tline
->next
);
2575 if (!t
|| (t
->type
!= TOK_STRING
&&
2576 t
->type
!= TOK_INTERNAL_STRING
)) {
2577 error(ERR_NONFATAL
, "`%%depend' expects a file name");
2578 free_tlist(origline
);
2579 return DIRECTIVE_FOUND
; /* but we did _something_ */
2582 error(ERR_WARNING
|ERR_PASS1
,
2583 "trailing garbage after `%%depend' ignored");
2585 if (t
->type
!= TOK_INTERNAL_STRING
)
2586 nasm_unquote_cstr(p
, i
);
2587 if (dephead
&& !in_list(*dephead
, p
)) {
2588 StrList
*sl
= nasm_malloc(strlen(p
)+1+sizeof sl
->next
);
2592 deptail
= &sl
->next
;
2594 free_tlist(origline
);
2595 return DIRECTIVE_FOUND
;
2598 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2599 t
= tline
->next
= expand_smacro(tline
->next
);
2602 if (!t
|| (t
->type
!= TOK_STRING
&&
2603 t
->type
!= TOK_INTERNAL_STRING
)) {
2604 error(ERR_NONFATAL
, "`%%include' expects a file name");
2605 free_tlist(origline
);
2606 return DIRECTIVE_FOUND
; /* but we did _something_ */
2609 error(ERR_WARNING
|ERR_PASS1
,
2610 "trailing garbage after `%%include' ignored");
2612 if (t
->type
!= TOK_INTERNAL_STRING
)
2613 nasm_unquote_cstr(p
, i
);
2614 inc
= nasm_zalloc(sizeof(Include
));
2616 inc
->fp
= inc_fopen(p
, dephead
, &deptail
, pass
== 0);
2618 /* -MG given but file not found */
2621 inc
->fname
= src_set_fname(nasm_strdup(p
));
2622 inc
->lineno
= src_set_linnum(0);
2624 inc
->expansion
= NULL
;
2626 list
->uplevel(LIST_INCLUDE
);
2628 free_tlist(origline
);
2629 return DIRECTIVE_FOUND
;
2632 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2634 static macros_t
*use_pkg
;
2635 const char *pkg_macro
= NULL
;
2637 tline
= tline
->next
;
2639 tline
= expand_id(tline
);
2641 if (!tline
|| (tline
->type
!= TOK_STRING
&&
2642 tline
->type
!= TOK_INTERNAL_STRING
&&
2643 tline
->type
!= TOK_ID
)) {
2644 error(ERR_NONFATAL
, "`%%use' expects a package name");
2645 free_tlist(origline
);
2646 return DIRECTIVE_FOUND
; /* but we did _something_ */
2649 error(ERR_WARNING
|ERR_PASS1
,
2650 "trailing garbage after `%%use' ignored");
2651 if (tline
->type
== TOK_STRING
)
2652 nasm_unquote_cstr(tline
->text
, i
);
2653 use_pkg
= nasm_stdmac_find_package(tline
->text
);
2655 error(ERR_NONFATAL
, "unknown `%%use' package: %s", tline
->text
);
2657 pkg_macro
= (char *)use_pkg
+ 1; /* The first string will be <%define>__USE_*__ */
2658 if (use_pkg
&& ! smacro_defined(NULL
, pkg_macro
, 0, NULL
, true)) {
2659 /* Not already included, go ahead and include it */
2660 stdmacpos
= use_pkg
;
2662 free_tlist(origline
);
2663 return DIRECTIVE_FOUND
;
2668 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2669 tline
= tline
->next
;
2671 tline
= expand_id(tline
);
2673 if (!tok_type_(tline
, TOK_ID
)) {
2674 error(ERR_NONFATAL
, "`%s' expects a context identifier",
2676 free_tlist(origline
);
2677 return DIRECTIVE_FOUND
; /* but we did _something_ */
2680 error(ERR_WARNING
|ERR_PASS1
,
2681 "trailing garbage after `%s' ignored",
2683 p
= nasm_strdup(tline
->text
);
2685 p
= NULL
; /* Anonymous */
2689 ctx
= nasm_zalloc(sizeof(Context
));
2691 hash_init(&ctx
->localmac
, HASH_SMALL
);
2693 ctx
->number
= unique
++;
2698 error(ERR_NONFATAL
, "`%s': context stack is empty",
2700 } else if (i
== PP_POP
) {
2701 if (p
&& (!cstk
->name
|| nasm_stricmp(p
, cstk
->name
)))
2702 error(ERR_NONFATAL
, "`%%pop' in wrong context: %s, "
2704 cstk
->name
? cstk
->name
: "anonymous", p
);
2709 nasm_free(cstk
->name
);
2715 free_tlist(origline
);
2716 return DIRECTIVE_FOUND
;
2718 severity
= ERR_FATAL
;
2721 severity
= ERR_NONFATAL
;
2724 severity
= ERR_WARNING
|ERR_WARN_USER
;
2728 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2730 /* Only error out if this is the final pass */
2731 if (pass
!= 2 && i
!= PP_FATAL
)
2732 return DIRECTIVE_FOUND
;
2734 tline
->next
= expand_smacro(tline
->next
);
2735 tline
= tline
->next
;
2737 t
= tline
? tline
->next
: NULL
;
2739 if (tok_type_(tline
, TOK_STRING
) && !t
) {
2740 /* The line contains only a quoted string */
2742 nasm_unquote(p
, NULL
); /* Ignore NUL character truncation */
2743 error(severity
, "%s", p
);
2745 /* Not a quoted string, or more than a quoted string */
2746 p
= detoken(tline
, false);
2747 error(severity
, "%s", p
);
2750 free_tlist(origline
);
2751 return DIRECTIVE_FOUND
;
2755 if (defining
!= NULL
) {
2756 if (defining
->type
== EXP_IF
) {
2757 defining
->def_depth
++;
2759 return NO_DIRECTIVE_FOUND
;
2761 if ((istk
->expansion
!= NULL
) &&
2762 (istk
->expansion
->emitting
== false)) {
2765 j
= if_condition(tline
->next
, i
);
2766 tline
->next
= NULL
; /* it got freed */
2767 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
2769 ed
= new_ExpDef(EXP_IF
);
2775 ed
->ignoring
= ((ed
->state
== COND_IF_TRUE
) ? false : true);
2776 ed
->prev
= defining
;
2778 free_tlist(origline
);
2779 return DIRECTIVE_FOUND
;
2782 if (defining
!= NULL
) {
2783 if ((defining
->type
!= EXP_IF
) || (defining
->def_depth
> 0)) {
2784 return NO_DIRECTIVE_FOUND
;
2787 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2788 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2790 switch (defining
->state
) {
2792 defining
->state
= COND_DONE
;
2793 defining
->ignoring
= true;
2798 defining
->ignoring
= true;
2801 case COND_ELSE_TRUE
:
2802 case COND_ELSE_FALSE
:
2803 error_precond(ERR_WARNING
|ERR_PASS1
,
2804 "`%%elif' after `%%else' ignored");
2805 defining
->state
= COND_NEVER
;
2806 defining
->ignoring
= true;
2811 * IMPORTANT: In the case of %if, we will already have
2812 * called expand_mmac_params(); however, if we're
2813 * processing an %elif we must have been in a
2814 * non-emitting mode, which would have inhibited
2815 * the normal invocation of expand_mmac_params().
2816 * Therefore, we have to do it explicitly here.
2818 j
= if_condition(expand_mmac_params(tline
->next
), i
);
2819 tline
->next
= NULL
; /* it got freed */
2821 j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2822 defining
->ignoring
= ((defining
->state
== COND_IF_TRUE
) ? false : true);
2825 free_tlist(origline
);
2826 return DIRECTIVE_FOUND
;
2829 if (defining
!= NULL
) {
2830 if ((defining
->type
!= EXP_IF
) || (defining
->def_depth
> 0)) {
2831 return NO_DIRECTIVE_FOUND
;
2835 error_precond(ERR_WARNING
|ERR_PASS1
,
2836 "trailing garbage after `%%else' ignored");
2837 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2838 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2840 switch (defining
->state
) {
2843 defining
->state
= COND_ELSE_FALSE
;
2844 defining
->ignoring
= true;
2848 defining
->ignoring
= true;
2852 defining
->state
= COND_ELSE_TRUE
;
2853 defining
->ignoring
= false;
2856 case COND_ELSE_TRUE
:
2857 case COND_ELSE_FALSE
:
2858 error_precond(ERR_WARNING
|ERR_PASS1
,
2859 "`%%else' after `%%else' ignored.");
2860 defining
->state
= COND_NEVER
;
2861 defining
->ignoring
= true;
2864 free_tlist(origline
);
2865 return DIRECTIVE_FOUND
;
2868 if (defining
!= NULL
) {
2869 if (defining
->type
== EXP_IF
) {
2870 if (defining
->def_depth
> 0) {
2871 defining
->def_depth
--;
2872 return NO_DIRECTIVE_FOUND
;
2875 return NO_DIRECTIVE_FOUND
;
2879 error_precond(ERR_WARNING
|ERR_PASS1
,
2880 "trailing garbage after `%%endif' ignored");
2881 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2882 error(ERR_NONFATAL
, "`%%endif': no matching `%%if'");
2883 return DIRECTIVE_FOUND
;
2886 defining
= ed
->prev
;
2887 ed
->prev
= expansions
;
2889 ei
= new_ExpInv(EXP_IF
, ed
);
2890 ei
->current
= ed
->line
;
2891 ei
->emitting
= true;
2892 ei
->prev
= istk
->expansion
;
2893 istk
->expansion
= ei
;
2894 free_tlist(origline
);
2895 return DIRECTIVE_FOUND
;
2901 if (defining
!= NULL
) {
2902 if (defining
->type
== EXP_MMACRO
) {
2903 defining
->def_depth
++;
2905 return NO_DIRECTIVE_FOUND
;
2907 ed
= new_ExpDef(EXP_MMACRO
);
2909 (i
== PP_RMACRO
) || (i
== PP_IRMACRO
) ? DEADMAN_LIMIT
: 0;
2910 ed
->casesense
= (i
== PP_MACRO
) || (i
== PP_RMACRO
);
2911 if (!parse_mmacro_spec(tline
, ed
, pp_directives
[i
])) {
2914 return DIRECTIVE_FOUND
;
2918 ed
->max_depth
= (ed
->max_depth
+ 1);
2919 ed
->ignoring
= false;
2920 ed
->prev
= defining
;
2923 eed
= (ExpDef
*) hash_findix(&expdefs
, ed
->name
);
2925 if (!strcmp(eed
->name
, ed
->name
) &&
2926 (eed
->nparam_min
<= ed
->nparam_max
|| ed
->plus
) &&
2927 (ed
->nparam_min
<= eed
->nparam_max
|| eed
->plus
)) {
2928 error(ERR_WARNING
|ERR_PASS1
,
2929 "redefining multi-line macro `%s'", ed
->name
);
2930 return DIRECTIVE_FOUND
;
2934 free_tlist(origline
);
2935 return DIRECTIVE_FOUND
;
2939 if (defining
!= NULL
) {
2940 if (defining
->type
== EXP_MMACRO
) {
2941 if (defining
->def_depth
> 0) {
2942 defining
->def_depth
--;
2943 return NO_DIRECTIVE_FOUND
;
2946 return NO_DIRECTIVE_FOUND
;
2949 if (!(defining
) || (defining
->type
!= EXP_MMACRO
)) {
2950 error(ERR_NONFATAL
, "`%s': not defining a macro", tline
->text
);
2951 return DIRECTIVE_FOUND
;
2953 edhead
= (ExpDef
**) hash_findi_add(&expdefs
, defining
->name
);
2954 defining
->next
= *edhead
;
2957 defining
= ed
->prev
;
2958 ed
->prev
= expansions
;
2961 free_tlist(origline
);
2962 return DIRECTIVE_FOUND
;
2965 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2967 * We must search along istk->expansion until we hit a
2968 * macro invocation. Then we disable the emitting state(s)
2969 * between exitmacro and endmacro.
2971 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
2972 if(ei
->type
== EXP_MMACRO
) {
2979 * Set all invocations leading back to the macro
2980 * invocation to a non-emitting state.
2982 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
2983 eei
->emitting
= false;
2985 eei
->emitting
= false;
2987 error(ERR_NONFATAL
, "`%%exitmacro' not within `%%macro' block");
2989 free_tlist(origline
);
2990 return DIRECTIVE_FOUND
;
2994 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2999 spec
.casesense
= (i
== PP_UNMACRO
);
3000 if (!parse_mmacro_spec(tline
, &spec
, pp_directives
[i
])) {
3001 return DIRECTIVE_FOUND
;
3003 ed_p
= (ExpDef
**) hash_findi(&expdefs
, spec
.name
, NULL
);
3004 while (ed_p
&& *ed_p
) {
3006 if (ed
->casesense
== spec
.casesense
&&
3007 !mstrcmp(ed
->name
, spec
.name
, spec
.casesense
) &&
3008 ed
->nparam_min
== spec
.nparam_min
&&
3009 ed
->nparam_max
== spec
.nparam_max
&&
3010 ed
->plus
== spec
.plus
) {
3011 if (ed
->cur_depth
> 0) {
3012 error(ERR_NONFATAL
, "`%s' ignored on active macro",
3023 free_tlist(origline
);
3024 free_tlist(spec
.dlist
);
3025 return DIRECTIVE_FOUND
;
3029 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3030 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
3031 tline
= tline
->next
;
3033 free_tlist(origline
);
3034 error(ERR_NONFATAL
, "`%%rotate' missing rotate count");
3035 return DIRECTIVE_FOUND
;
3037 t
= expand_smacro(tline
->next
);
3039 free_tlist(origline
);
3042 tokval
.t_type
= TOKEN_INVALID
;
3044 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3047 return DIRECTIVE_FOUND
;
3049 error(ERR_WARNING
|ERR_PASS1
,
3050 "trailing garbage after expression ignored");
3051 if (!is_simple(evalresult
)) {
3052 error(ERR_NONFATAL
, "non-constant value given to `%%rotate'");
3053 return DIRECTIVE_FOUND
;
3055 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3056 if (ei
->type
== EXP_MMACRO
) {
3061 error(ERR_NONFATAL
, "`%%rotate' invoked outside a macro call");
3062 } else if (ei
->nparam
== 0) {
3064 "`%%rotate' invoked within macro without parameters");
3066 int rotate
= ei
->rotate
+ reloc_value(evalresult
);
3068 rotate
%= (int)ei
->nparam
;
3070 rotate
+= ei
->nparam
;
3071 ei
->rotate
= rotate
;
3073 return DIRECTIVE_FOUND
;
3076 if (defining
!= NULL
) {
3077 if (defining
->type
== EXP_REP
) {
3078 defining
->def_depth
++;
3080 return NO_DIRECTIVE_FOUND
;
3084 tline
= tline
->next
;
3085 } while (tok_type_(tline
, TOK_WHITESPACE
));
3087 if (tok_type_(tline
, TOK_ID
) &&
3088 nasm_stricmp(tline
->text
, ".nolist") == 0) {
3091 tline
= tline
->next
;
3092 } while (tok_type_(tline
, TOK_WHITESPACE
));
3096 t
= expand_smacro(tline
);
3098 tokval
.t_type
= TOKEN_INVALID
;
3100 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3102 free_tlist(origline
);
3103 return DIRECTIVE_FOUND
;
3106 error(ERR_WARNING
|ERR_PASS1
,
3107 "trailing garbage after expression ignored");
3108 if (!is_simple(evalresult
)) {
3109 error(ERR_NONFATAL
, "non-constant value given to `%%rep'");
3110 return DIRECTIVE_FOUND
;
3112 count
= reloc_value(evalresult
);
3113 if (count
>= REP_LIMIT
) {
3114 error(ERR_NONFATAL
, "`%%rep' value exceeds limit");
3119 error(ERR_NONFATAL
, "`%%rep' expects a repeat count");
3122 free_tlist(origline
);
3123 ed
= new_ExpDef(EXP_REP
);
3124 ed
->nolist
= nolist
;
3127 ed
->max_depth
= (count
- 1);
3128 ed
->ignoring
= false;
3129 ed
->prev
= defining
;
3131 return DIRECTIVE_FOUND
;
3134 if (defining
!= NULL
) {
3135 if (defining
->type
== EXP_REP
) {
3136 if (defining
->def_depth
> 0) {
3137 defining
->def_depth
--;
3138 return NO_DIRECTIVE_FOUND
;
3141 return NO_DIRECTIVE_FOUND
;
3144 if ((defining
== NULL
) || (defining
->type
!= EXP_REP
)) {
3145 error(ERR_NONFATAL
, "`%%endrep': no matching `%%rep'");
3146 return DIRECTIVE_FOUND
;
3150 * Now we have a "macro" defined - although it has no name
3151 * and we won't be entering it in the hash tables - we must
3152 * push a macro-end marker for it on to istk->expansion.
3153 * After that, it will take care of propagating itself (a
3154 * macro-end marker line for a macro which is really a %rep
3155 * block will cause the macro to be re-expanded, complete
3156 * with another macro-end marker to ensure the process
3157 * continues) until the whole expansion is forcibly removed
3158 * from istk->expansion by a %exitrep.
3161 defining
= ed
->prev
;
3162 ed
->prev
= expansions
;
3164 ei
= new_ExpInv(EXP_REP
, ed
);
3165 ei
->current
= ed
->line
;
3166 ei
->emitting
= ((ed
->max_depth
> 0) ? true : false);
3167 list
->uplevel(ed
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
3168 ei
->prev
= istk
->expansion
;
3169 istk
->expansion
= ei
;
3170 free_tlist(origline
);
3171 return DIRECTIVE_FOUND
;
3174 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3176 * We must search along istk->expansion until we hit a
3177 * rep invocation. Then we disable the emitting state(s)
3178 * between exitrep and endrep.
3180 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3181 if (ei
->type
== EXP_REP
) {
3188 * Set all invocations leading back to the rep
3189 * invocation to a non-emitting state.
3191 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3192 eei
->emitting
= false;
3194 eei
->emitting
= false;
3195 eei
->current
= NULL
;
3196 eei
->def
->cur_depth
= eei
->def
->max_depth
;
3198 error(ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
3200 free_tlist(origline
);
3201 return DIRECTIVE_FOUND
;
3207 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3208 casesense
= (i
== PP_DEFINE
|| i
== PP_XDEFINE
);
3210 tline
= tline
->next
;
3212 tline
= expand_id(tline
);
3213 if (!tline
|| (tline
->type
!= TOK_ID
&&
3214 (tline
->type
!= TOK_PREPROC_ID
||
3215 tline
->text
[1] != '$'))) {
3216 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3218 free_tlist(origline
);
3219 return DIRECTIVE_FOUND
;
3222 ctx
= get_ctx(tline
->text
, &mname
);
3224 param_start
= tline
= tline
->next
;
3227 /* Expand the macro definition now for %xdefine and %ixdefine */
3228 if ((i
== PP_XDEFINE
) || (i
== PP_IXDEFINE
))
3229 tline
= expand_smacro(tline
);
3231 if (tok_is_(tline
, "(")) {
3233 * This macro has parameters.
3236 tline
= tline
->next
;
3240 error(ERR_NONFATAL
, "parameter identifier expected");
3241 free_tlist(origline
);
3242 return DIRECTIVE_FOUND
;
3244 if (tline
->type
!= TOK_ID
) {
3246 "`%s': parameter identifier expected",
3248 free_tlist(origline
);
3249 return DIRECTIVE_FOUND
;
3251 tline
->type
= TOK_SMAC_PARAM
+ nparam
++;
3252 tline
= tline
->next
;
3254 if (tok_is_(tline
, ",")) {
3255 tline
= tline
->next
;
3257 if (!tok_is_(tline
, ")")) {
3259 "`)' expected to terminate macro template");
3260 free_tlist(origline
);
3261 return DIRECTIVE_FOUND
;
3267 tline
= tline
->next
;
3269 if (tok_type_(tline
, TOK_WHITESPACE
))
3270 last
= tline
, tline
= tline
->next
;
3275 if (t
->type
== TOK_ID
) {
3276 list_for_each(tt
, param_start
)
3277 if (tt
->type
>= TOK_SMAC_PARAM
&&
3278 !strcmp(tt
->text
, t
->text
))
3282 t
->next
= macro_start
;
3287 * Good. We now have a macro name, a parameter count, and a
3288 * token list (in reverse order) for an expansion. We ought
3289 * to be OK just to create an SMacro, store it, and let
3290 * free_tlist have the rest of the line (which we have
3291 * carefully re-terminated after chopping off the expansion
3294 define_smacro(ctx
, mname
, casesense
, nparam
, macro_start
);
3295 free_tlist(origline
);
3296 return DIRECTIVE_FOUND
;
3299 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3300 tline
= tline
->next
;
3302 tline
= expand_id(tline
);
3303 if (!tline
|| (tline
->type
!= TOK_ID
&&
3304 (tline
->type
!= TOK_PREPROC_ID
||
3305 tline
->text
[1] != '$'))) {
3306 error(ERR_NONFATAL
, "`%%undef' expects a macro identifier");
3307 free_tlist(origline
);
3308 return DIRECTIVE_FOUND
;
3311 error(ERR_WARNING
|ERR_PASS1
,
3312 "trailing garbage after macro name ignored");
3315 /* Find the context that symbol belongs to */
3316 ctx
= get_ctx(tline
->text
, &mname
);
3317 undef_smacro(ctx
, mname
);
3318 free_tlist(origline
);
3319 return DIRECTIVE_FOUND
;
3323 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3324 casesense
= (i
== PP_DEFSTR
);
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
, "`%s' expects a macro identifier",
3334 free_tlist(origline
);
3335 return DIRECTIVE_FOUND
;
3338 ctx
= get_ctx(tline
->text
, &mname
);
3340 tline
= expand_smacro(tline
->next
);
3343 while (tok_type_(tline
, TOK_WHITESPACE
))
3344 tline
= delete_Token(tline
);
3346 p
= detoken(tline
, false);
3347 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3348 macro_start
->text
= nasm_quote(p
, strlen(p
));
3349 macro_start
->type
= TOK_STRING
;
3353 * We now have a macro name, an implicit parameter count of
3354 * zero, and a string token to use as an expansion. Create
3355 * and store an SMacro.
3357 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3358 free_tlist(origline
);
3359 return DIRECTIVE_FOUND
;
3363 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3364 casesense
= (i
== PP_DEFTOK
);
3366 tline
= tline
->next
;
3368 tline
= expand_id(tline
);
3369 if (!tline
|| (tline
->type
!= TOK_ID
&&
3370 (tline
->type
!= TOK_PREPROC_ID
||
3371 tline
->text
[1] != '$'))) {
3373 "`%s' expects a macro identifier as first parameter",
3375 free_tlist(origline
);
3376 return DIRECTIVE_FOUND
;
3378 ctx
= get_ctx(tline
->text
, &mname
);
3380 tline
= expand_smacro(tline
->next
);
3384 while (tok_type_(t
, TOK_WHITESPACE
))
3386 /* t should now point to the string */
3387 if (!tok_type_(t
, TOK_STRING
)) {
3389 "`%s` requires string as second parameter",
3392 free_tlist(origline
);
3393 return DIRECTIVE_FOUND
;
3397 * Convert the string to a token stream. Note that smacros
3398 * are stored with the token stream reversed, so we have to
3399 * reverse the output of tokenize().
3401 nasm_unquote_cstr(t
->text
, i
);
3402 macro_start
= reverse_tokens(tokenize(t
->text
));
3405 * We now have a macro name, an implicit parameter count of
3406 * zero, and a numeric token to use as an expansion. Create
3407 * and store an SMacro.
3409 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3411 free_tlist(origline
);
3412 return DIRECTIVE_FOUND
;
3415 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3418 StrList
*xsl
= NULL
;
3419 StrList
**xst
= &xsl
;
3423 tline
= tline
->next
;
3425 tline
= expand_id(tline
);
3426 if (!tline
|| (tline
->type
!= TOK_ID
&&
3427 (tline
->type
!= TOK_PREPROC_ID
||
3428 tline
->text
[1] != '$'))) {
3430 "`%%pathsearch' expects a macro identifier as first parameter");
3431 free_tlist(origline
);
3432 return DIRECTIVE_FOUND
;
3434 ctx
= get_ctx(tline
->text
, &mname
);
3436 tline
= expand_smacro(tline
->next
);
3440 while (tok_type_(t
, TOK_WHITESPACE
))
3443 if (!t
|| (t
->type
!= TOK_STRING
&&
3444 t
->type
!= TOK_INTERNAL_STRING
)) {
3445 error(ERR_NONFATAL
, "`%%pathsearch' expects a file name");
3447 free_tlist(origline
);
3448 return DIRECTIVE_FOUND
; /* but we did _something_ */
3451 error(ERR_WARNING
|ERR_PASS1
,
3452 "trailing garbage after `%%pathsearch' ignored");
3454 if (t
->type
!= TOK_INTERNAL_STRING
)
3455 nasm_unquote(p
, NULL
);
3457 fp
= inc_fopen(p
, &xsl
, &xst
, true);
3460 fclose(fp
); /* Don't actually care about the file */
3462 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3463 macro_start
->text
= nasm_quote(p
, strlen(p
));
3464 macro_start
->type
= TOK_STRING
;
3468 * We now have a macro name, an implicit parameter count of
3469 * zero, and a string token to use as an expansion. Create
3470 * and store an SMacro.
3472 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3474 free_tlist(origline
);
3475 return DIRECTIVE_FOUND
;
3479 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3482 tline
= tline
->next
;
3484 tline
= expand_id(tline
);
3485 if (!tline
|| (tline
->type
!= TOK_ID
&&
3486 (tline
->type
!= TOK_PREPROC_ID
||
3487 tline
->text
[1] != '$'))) {
3489 "`%%strlen' expects a macro identifier as first parameter");
3490 free_tlist(origline
);
3491 return DIRECTIVE_FOUND
;
3493 ctx
= get_ctx(tline
->text
, &mname
);
3495 tline
= expand_smacro(tline
->next
);
3499 while (tok_type_(t
, TOK_WHITESPACE
))
3501 /* t should now point to the string */
3502 if (!tok_type_(t
, TOK_STRING
)) {
3504 "`%%strlen` requires string as second parameter");
3506 free_tlist(origline
);
3507 return DIRECTIVE_FOUND
;
3510 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3511 make_tok_num(macro_start
, nasm_unquote(t
->text
, NULL
));
3514 * We now have a macro name, an implicit parameter count of
3515 * zero, and a numeric token to use as an expansion. Create
3516 * and store an SMacro.
3518 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3520 free_tlist(origline
);
3521 return DIRECTIVE_FOUND
;
3524 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3527 tline
= tline
->next
;
3529 tline
= expand_id(tline
);
3530 if (!tline
|| (tline
->type
!= TOK_ID
&&
3531 (tline
->type
!= TOK_PREPROC_ID
||
3532 tline
->text
[1] != '$'))) {
3534 "`%%strcat' expects a macro identifier as first parameter");
3535 free_tlist(origline
);
3536 return DIRECTIVE_FOUND
;
3538 ctx
= get_ctx(tline
->text
, &mname
);
3540 tline
= expand_smacro(tline
->next
);
3544 list_for_each(t
, tline
) {
3546 case TOK_WHITESPACE
:
3549 len
+= t
->a
.len
= nasm_unquote(t
->text
, NULL
);
3552 if (!strcmp(t
->text
, ",")) /* permit comma separators */
3554 /* else fall through */
3557 "non-string passed to `%%strcat' (%d)", t
->type
);
3559 free_tlist(origline
);
3560 return DIRECTIVE_FOUND
;
3564 p
= pp
= nasm_malloc(len
);
3565 list_for_each(t
, tline
) {
3566 if (t
->type
== TOK_STRING
) {
3567 memcpy(p
, t
->text
, t
->a
.len
);
3573 * We now have a macro name, an implicit parameter count of
3574 * zero, and a numeric token to use as an expansion. Create
3575 * and store an SMacro.
3577 macro_start
= new_Token(NULL
, TOK_STRING
, NULL
, 0);
3578 macro_start
->text
= nasm_quote(pp
, len
);
3580 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3582 free_tlist(origline
);
3583 return DIRECTIVE_FOUND
;
3586 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3588 int64_t start
, count
;
3593 tline
= tline
->next
;
3595 tline
= expand_id(tline
);
3596 if (!tline
|| (tline
->type
!= TOK_ID
&&
3597 (tline
->type
!= TOK_PREPROC_ID
||
3598 tline
->text
[1] != '$'))) {
3600 "`%%substr' expects a macro identifier as first parameter");
3601 free_tlist(origline
);
3602 return DIRECTIVE_FOUND
;
3604 ctx
= get_ctx(tline
->text
, &mname
);
3606 tline
= expand_smacro(tline
->next
);
3609 if (tline
) /* skip expanded id */
3611 while (tok_type_(t
, TOK_WHITESPACE
))
3614 /* t should now point to the string */
3615 if (!tok_type_(t
, TOK_STRING
)) {
3617 "`%%substr` requires string as second parameter");
3619 free_tlist(origline
);
3620 return DIRECTIVE_FOUND
;
3625 tokval
.t_type
= TOKEN_INVALID
;
3626 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3630 free_tlist(origline
);
3631 return DIRECTIVE_FOUND
;
3632 } else if (!is_simple(evalresult
)) {
3633 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3635 free_tlist(origline
);
3636 return DIRECTIVE_FOUND
;
3638 start
= evalresult
->value
- 1;
3640 while (tok_type_(tt
, TOK_WHITESPACE
))
3643 count
= 1; /* Backwards compatibility: one character */
3645 tokval
.t_type
= TOKEN_INVALID
;
3646 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3650 free_tlist(origline
);
3651 return DIRECTIVE_FOUND
;
3652 } else if (!is_simple(evalresult
)) {
3653 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3655 free_tlist(origline
);
3656 return DIRECTIVE_FOUND
;
3658 count
= evalresult
->value
;
3661 len
= nasm_unquote(t
->text
, NULL
);
3662 /* make start and count being in range */
3666 count
= len
+ count
+ 1 - start
;
3667 if (start
+ count
> (int64_t)len
)
3668 count
= len
- start
;
3669 if (!len
|| count
< 0 || start
>=(int64_t)len
)
3670 start
= -1, count
= 0; /* empty string */
3672 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3673 macro_start
->text
= nasm_quote((start
< 0) ? "" : t
->text
+ start
, count
);
3674 macro_start
->type
= TOK_STRING
;
3677 * We now have a macro name, an implicit parameter count of
3678 * zero, and a numeric token to use as an expansion. Create
3679 * and store an SMacro.
3681 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3683 free_tlist(origline
);
3684 return DIRECTIVE_FOUND
;
3689 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3690 casesense
= (i
== PP_ASSIGN
);
3692 tline
= tline
->next
;
3694 tline
= expand_id(tline
);
3695 if (!tline
|| (tline
->type
!= TOK_ID
&&
3696 (tline
->type
!= TOK_PREPROC_ID
||
3697 tline
->text
[1] != '$'))) {
3699 "`%%%sassign' expects a macro identifier",
3700 (i
== PP_IASSIGN
? "i" : ""));
3701 free_tlist(origline
);
3702 return DIRECTIVE_FOUND
;
3704 ctx
= get_ctx(tline
->text
, &mname
);
3706 tline
= expand_smacro(tline
->next
);
3711 tokval
.t_type
= TOKEN_INVALID
;
3713 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3716 free_tlist(origline
);
3717 return DIRECTIVE_FOUND
;
3721 error(ERR_WARNING
|ERR_PASS1
,
3722 "trailing garbage after expression ignored");
3724 if (!is_simple(evalresult
)) {
3726 "non-constant value given to `%%%sassign'",
3727 (i
== PP_IASSIGN
? "i" : ""));
3728 free_tlist(origline
);
3729 return DIRECTIVE_FOUND
;
3732 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3733 make_tok_num(macro_start
, reloc_value(evalresult
));
3736 * We now have a macro name, an implicit parameter count of
3737 * zero, and a numeric token to use as an expansion. Create
3738 * and store an SMacro.
3740 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3741 free_tlist(origline
);
3742 return DIRECTIVE_FOUND
;
3745 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3747 * Syntax is `%line nnn[+mmm] [filename]'
3749 tline
= tline
->next
;
3751 if (!tok_type_(tline
, TOK_NUMBER
)) {
3752 error(ERR_NONFATAL
, "`%%line' expects line number");
3753 free_tlist(origline
);
3754 return DIRECTIVE_FOUND
;
3756 k
= readnum(tline
->text
, &err
);
3758 tline
= tline
->next
;
3759 if (tok_is_(tline
, "+")) {
3760 tline
= tline
->next
;
3761 if (!tok_type_(tline
, TOK_NUMBER
)) {
3762 error(ERR_NONFATAL
, "`%%line' expects line increment");
3763 free_tlist(origline
);
3764 return DIRECTIVE_FOUND
;
3766 m
= readnum(tline
->text
, &err
);
3767 tline
= tline
->next
;
3773 nasm_free(src_set_fname(detoken(tline
, false)));
3775 free_tlist(origline
);
3776 return DIRECTIVE_FOUND
;
3779 if (defining
!= NULL
) {
3780 if (defining
->type
== EXP_WHILE
) {
3781 defining
->def_depth
++;
3783 return NO_DIRECTIVE_FOUND
;
3786 if ((istk
->expansion
!= NULL
) &&
3787 (istk
->expansion
->emitting
== false)) {
3791 l
->first
= copy_Token(tline
->next
);
3792 j
= if_condition(tline
->next
, i
);
3793 tline
->next
= NULL
; /* it got freed */
3794 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
3796 ed
= new_ExpDef(EXP_WHILE
);
3799 ed
->max_depth
= DEADMAN_LIMIT
;
3800 ed
->ignoring
= ((ed
->state
== COND_IF_TRUE
) ? false : true);
3801 if (ed
->ignoring
== false) {
3804 } else if (l
!= NULL
) {
3805 delete_Token(l
->first
);
3809 ed
->prev
= defining
;
3811 free_tlist(origline
);
3812 return DIRECTIVE_FOUND
;
3815 if (defining
!= NULL
) {
3816 if (defining
->type
== EXP_WHILE
) {
3817 if (defining
->def_depth
> 0) {
3818 defining
->def_depth
--;
3819 return NO_DIRECTIVE_FOUND
;
3822 return NO_DIRECTIVE_FOUND
;
3825 if (tline
->next
!= NULL
) {
3826 error_precond(ERR_WARNING
|ERR_PASS1
,
3827 "trailing garbage after `%%endwhile' ignored");
3829 if ((defining
== NULL
) || (defining
->type
!= EXP_WHILE
)) {
3830 error(ERR_NONFATAL
, "`%%endwhile': no matching `%%while'");
3831 return DIRECTIVE_FOUND
;
3834 defining
= ed
->prev
;
3835 if (ed
->ignoring
== false) {
3836 ed
->prev
= expansions
;
3838 ei
= new_ExpInv(EXP_WHILE
, ed
);
3839 ei
->current
= ed
->line
->next
;
3840 ei
->emitting
= true;
3841 ei
->prev
= istk
->expansion
;
3842 istk
->expansion
= ei
;
3846 free_tlist(origline
);
3847 return DIRECTIVE_FOUND
;
3850 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3852 * We must search along istk->expansion until we hit a
3853 * while invocation. Then we disable the emitting state(s)
3854 * between exitwhile and endwhile.
3856 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3857 if (ei
->type
== EXP_WHILE
) {
3864 * Set all invocations leading back to the while
3865 * invocation to a non-emitting state.
3867 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3868 eei
->emitting
= false;
3870 eei
->emitting
= false;
3871 eei
->current
= NULL
;
3872 eei
->def
->cur_depth
= eei
->def
->max_depth
;
3874 error(ERR_NONFATAL
, "`%%exitwhile' not within `%%while' block");
3876 free_tlist(origline
);
3877 return DIRECTIVE_FOUND
;
3880 if (defining
!= NULL
) {
3881 if (defining
->type
== EXP_COMMENT
) {
3882 defining
->def_depth
++;
3884 return NO_DIRECTIVE_FOUND
;
3886 ed
= new_ExpDef(EXP_COMMENT
);
3887 ed
->ignoring
= true;
3888 ed
->prev
= defining
;
3890 free_tlist(origline
);
3891 return DIRECTIVE_FOUND
;
3894 if (defining
!= NULL
) {
3895 if (defining
->type
== EXP_COMMENT
) {
3896 if (defining
->def_depth
> 0) {
3897 defining
->def_depth
--;
3898 return NO_DIRECTIVE_FOUND
;
3901 return NO_DIRECTIVE_FOUND
;
3904 if ((defining
== NULL
) || (defining
->type
!= EXP_COMMENT
)) {
3905 error(ERR_NONFATAL
, "`%%endcomment': no matching `%%comment'");
3906 return DIRECTIVE_FOUND
;
3909 defining
= ed
->prev
;
3911 free_tlist(origline
);
3912 return DIRECTIVE_FOUND
;
3915 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3916 if (in_final
!= false) {
3917 error(ERR_FATAL
, "`%%final' cannot be used recursively");
3919 tline
= tline
->next
;
3921 if (tline
== NULL
) {
3922 error(ERR_NONFATAL
, "`%%final' expects at least one parameter");
3925 l
->first
= copy_Token(tline
);
3929 free_tlist(origline
);
3930 return DIRECTIVE_FOUND
;
3934 "preprocessor directive `%s' not yet implemented",
3936 return DIRECTIVE_FOUND
;
3941 * Ensure that a macro parameter contains a condition code and
3942 * nothing else. Return the condition code index if so, or -1
3945 static int find_cc(Token
* t
)
3951 return -1; /* Probably a %+ without a space */
3954 if (t
->type
!= TOK_ID
)
3958 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
3962 j
= ARRAY_SIZE(conditions
);
3965 m
= nasm_stricmp(t
->text
, conditions
[k
]);
3980 static bool paste_tokens(Token
**head
, const struct tokseq_match
*m
,
3981 int mnum
, bool handle_paste_tokens
)
3983 Token
**tail
, *t
, *tt
;
3985 bool did_paste
= false;
3989 /* Now handle token pasting... */
3992 while ((t
= *tail
) && (tt
= t
->next
)) {
3994 case TOK_WHITESPACE
:
3995 if (tt
->type
== TOK_WHITESPACE
) {
3996 /* Zap adjacent whitespace tokens */
3997 t
->next
= delete_Token(tt
);
3999 /* Do not advance paste_head here */
4003 case TOK_PASTE
: /* %+ */
4004 if (handle_paste_tokens
) {
4005 /* Zap %+ and whitespace tokens to the right */
4006 while (t
&& (t
->type
== TOK_WHITESPACE
||
4007 t
->type
== TOK_PASTE
))
4008 t
= *tail
= delete_Token(t
);
4009 if (!paste_head
|| !t
)
4010 break; /* Nothing to paste with */
4014 while (tok_type_(tt
, TOK_WHITESPACE
))
4015 tt
= t
->next
= delete_Token(tt
);
4017 tmp
= nasm_strcat(t
->text
, tt
->text
);
4019 tt
= delete_Token(tt
);
4020 t
= *tail
= tokenize(tmp
);
4026 t
->next
= tt
; /* Attach the remaining token chain */
4033 /* else fall through */
4036 * Concatenation of tokens might look nontrivial
4037 * but in real it's pretty simple -- the caller
4038 * prepares the masks of token types to be concatenated
4039 * and we simply find matched sequences and slip
4042 for (i
= 0; i
< mnum
; i
++) {
4043 if (PP_CONCAT_MASK(t
->type
) & m
[i
].mask_head
) {
4047 while (tt
&& (PP_CONCAT_MASK(tt
->type
) & m
[i
].mask_tail
)) {
4048 len
+= strlen(tt
->text
);
4052 nasm_dump_token(tt
);
4055 * Now tt points to the first token after
4056 * the potential paste area...
4058 if (tt
!= t
->next
) {
4059 /* We have at least two tokens... */
4060 len
+= strlen(t
->text
);
4061 p
= tmp
= nasm_malloc(len
+1);
4064 p
= strchr(p
, '\0');
4065 t
= delete_Token(t
);
4067 t
= *tail
= tokenize(tmp
);
4073 t
->next
= tt
; /* Attach the remaining token chain */
4081 if (i
>= mnum
) { /* no match */
4083 if (!tok_type_(t
->next
, TOK_WHITESPACE
))
4093 * expands to a list of tokens from %{x:y}
4095 static Token
*expand_mmac_params_range(ExpInv
*ei
, Token
*tline
, Token
***last
)
4097 Token
*t
= tline
, **tt
, *tm
, *head
;
4101 pos
= strchr(tline
->text
, ':');
4104 lst
= atoi(pos
+ 1);
4105 fst
= atoi(tline
->text
+ 1);
4108 * only macros params are accounted so
4109 * if someone passes %0 -- we reject such
4112 if (lst
== 0 || fst
== 0)
4115 /* the values should be sane */
4116 if ((fst
> (int)ei
->nparam
|| fst
< (-(int)ei
->nparam
)) ||
4117 (lst
> (int)ei
->nparam
|| lst
< (-(int)ei
->nparam
)))
4120 fst
= fst
< 0 ? fst
+ (int)ei
->nparam
+ 1: fst
;
4121 lst
= lst
< 0 ? lst
+ (int)ei
->nparam
+ 1: lst
;
4123 /* counted from zero */
4127 * it will be at least one token
4129 tm
= ei
->params
[(fst
+ ei
->rotate
) % ei
->nparam
];
4130 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4131 head
= t
, tt
= &t
->next
;
4133 for (i
= fst
+ 1; i
<= lst
; i
++) {
4134 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
4135 *tt
= t
, tt
= &t
->next
;
4136 j
= (i
+ ei
->rotate
) % ei
->nparam
;
4138 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4139 *tt
= t
, tt
= &t
->next
;
4142 for (i
= fst
- 1; i
>= lst
; i
--) {
4143 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
4144 *tt
= t
, tt
= &t
->next
;
4145 j
= (i
+ ei
->rotate
) % ei
->nparam
;
4147 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4148 *tt
= t
, tt
= &t
->next
;
4156 error(ERR_NONFATAL
, "`%%{%s}': macro parameters out of range",
4162 * Expand MMacro-local things: parameter references (%0, %n, %+n,
4163 * %-n) and MMacro-local identifiers (%%foo) as well as
4164 * macro indirection (%[...]) and range (%{..:..}).
4166 static Token
*expand_mmac_params(Token
* tline
)
4168 Token
*t
, *tt
, **tail
, *thead
;
4169 bool changed
= false;
4175 nasm_dump_stream(tline
);
4178 if (tline
->type
== TOK_PREPROC_ID
&&
4179 (((tline
->text
[1] == '+' || tline
->text
[1] == '-') && tline
->text
[2]) ||
4180 (tline
->text
[1] >= '0' && tline
->text
[1] <= '9') ||
4181 tline
->text
[1] == '%')) {
4183 int type
= 0, cc
; /* type = 0 to placate optimisers */
4190 tline
= tline
->next
;
4192 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
4193 if (ei
->type
== EXP_MMACRO
) {
4198 error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
4200 pos
= strchr(t
->text
, ':');
4202 switch (t
->text
[1]) {
4204 * We have to make a substitution of one of the
4205 * forms %1, %-1, %+1, %%foo, %0.
4208 if ((strlen(t
->text
) > 2) && (t
->text
[2] == '0')) {
4210 text
= nasm_strdup(ei
->label_text
);
4213 snprintf(tmpbuf
, sizeof(tmpbuf
), "%d", ei
->nparam
);
4214 text
= nasm_strdup(tmpbuf
);
4219 snprintf(tmpbuf
, sizeof(tmpbuf
), "..@%"PRIu64
".",
4221 text
= nasm_strcat(tmpbuf
, t
->text
+ 2);
4224 n
= atoi(t
->text
+ 2) - 1;
4225 if (n
>= ei
->nparam
)
4229 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4235 "macro parameter %d is not a condition code",
4240 if (inverse_ccs
[cc
] == -1) {
4242 "condition code `%s' is not invertible",
4246 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
4250 n
= atoi(t
->text
+ 2) - 1;
4251 if (n
>= ei
->nparam
)
4255 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4261 "macro parameter %d is not a condition code",
4266 text
= nasm_strdup(conditions
[cc
]);
4270 n
= atoi(t
->text
+ 1) - 1;
4271 if (n
>= ei
->nparam
)
4275 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4279 for (i
= 0; i
< ei
->paramlen
[n
]; i
++) {
4280 *tail
= new_Token(NULL
, tt
->type
, tt
->text
, 0);
4281 tail
= &(*tail
)->next
;
4285 text
= NULL
; /* we've done it here */
4290 * seems we have a parameters range here
4292 Token
*head
, **last
;
4293 head
= expand_mmac_params_range(ei
, t
, &last
);
4314 } else if (tline
->type
== TOK_INDIRECT
) {
4316 tline
= tline
->next
;
4317 tt
= tokenize(t
->text
);
4318 tt
= expand_mmac_params(tt
);
4319 tt
= expand_smacro(tt
);
4322 tt
->a
.mac
= NULL
; /* Necessary? */
4330 tline
= tline
->next
;
4338 const struct tokseq_match t
[] = {
4340 PP_CONCAT_MASK(TOK_ID
) |
4341 PP_CONCAT_MASK(TOK_FLOAT
), /* head */
4342 PP_CONCAT_MASK(TOK_ID
) |
4343 PP_CONCAT_MASK(TOK_NUMBER
) |
4344 PP_CONCAT_MASK(TOK_FLOAT
) |
4345 PP_CONCAT_MASK(TOK_OTHER
) /* tail */
4348 PP_CONCAT_MASK(TOK_NUMBER
), /* head */
4349 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4352 paste_tokens(&thead
, t
, ARRAY_SIZE(t
), false);
4355 nasm_dump_token(thead
);
4361 * Expand all single-line macro calls made in the given line.
4362 * Return the expanded version of the line. The original is deemed
4363 * to be destroyed in the process. (In reality we'll just move
4364 * Tokens from input to output a lot of the time, rather than
4365 * actually bothering to destroy and replicate.)
4368 static Token
*expand_smacro(Token
* tline
)
4370 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
4371 SMacro
*head
= NULL
, *m
;
4374 unsigned int nparam
, sparam
;
4376 Token
*org_tline
= tline
;
4379 int deadman
= DEADMAN_LIMIT
;
4383 * Trick: we should avoid changing the start token pointer since it can
4384 * be contained in "next" field of other token. Because of this
4385 * we allocate a copy of first token and work with it; at the end of
4386 * routine we copy it back
4389 tline
= new_Token(org_tline
->next
, org_tline
->type
,
4390 org_tline
->text
, 0);
4391 tline
->a
.mac
= org_tline
->a
.mac
;
4392 nasm_free(org_tline
->text
);
4393 org_tline
->text
= NULL
;
4396 expanded
= true; /* Always expand %+ at least once */
4402 while (tline
) { /* main token loop */
4404 error(ERR_NONFATAL
, "interminable macro recursion");
4408 if ((mname
= tline
->text
)) {
4409 /* if this token is a local macro, look in local context */
4410 if (tline
->type
== TOK_ID
) {
4411 head
= (SMacro
*)hash_findix(&smacros
, mname
);
4412 } else if (tline
->type
== TOK_PREPROC_ID
) {
4413 ctx
= get_ctx(mname
, &mname
);
4414 head
= ctx
? (SMacro
*)hash_findix(&ctx
->localmac
, mname
) : NULL
;
4419 * We've hit an identifier. As in is_mmacro below, we first
4420 * check whether the identifier is a single-line macro at
4421 * all, then think about checking for parameters if
4424 list_for_each(m
, head
)
4425 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
4431 if (m
->nparam
== 0) {
4433 * Simple case: the macro is parameterless. Discard the
4434 * one token that the macro call took, and push the
4435 * expansion back on the to-do stack.
4437 if (!m
->expansion
) {
4438 if (!strcmp("__FILE__", m
->name
)) {
4441 src_get(&num
, &file
);
4442 tline
->text
= nasm_quote(file
, strlen(file
));
4443 tline
->type
= TOK_STRING
;
4447 if (!strcmp("__LINE__", m
->name
)) {
4448 nasm_free(tline
->text
);
4449 make_tok_num(tline
, src_get_linnum());
4452 if (!strcmp("__BITS__", m
->name
)) {
4453 nasm_free(tline
->text
);
4454 make_tok_num(tline
, globalbits
);
4457 tline
= delete_Token(tline
);
4462 * Complicated case: at least one macro with this name
4463 * exists and takes parameters. We must find the
4464 * parameters in the call, count them, find the SMacro
4465 * that corresponds to that form of the macro call, and
4466 * substitute for the parameters when we expand. What a
4469 /*tline = tline->next;
4470 skip_white_(tline); */
4473 while (tok_type_(t
, TOK_SMAC_END
)) {
4474 t
->a
.mac
->in_progress
= false;
4476 t
= tline
->next
= delete_Token(t
);
4479 } while (tok_type_(tline
, TOK_WHITESPACE
));
4480 if (!tok_is_(tline
, "(")) {
4482 * This macro wasn't called with parameters: ignore
4483 * the call. (Behaviour borrowed from gnu cpp.)
4492 sparam
= PARAM_DELTA
;
4493 params
= nasm_malloc(sparam
* sizeof(Token
*));
4494 params
[0] = tline
->next
;
4495 paramsize
= nasm_malloc(sparam
* sizeof(int));
4497 while (true) { /* parameter loop */
4499 * For some unusual expansions
4500 * which concatenates function call
4503 while (tok_type_(t
, TOK_SMAC_END
)) {
4504 t
->a
.mac
->in_progress
= false;
4506 t
= tline
->next
= delete_Token(t
);
4512 "macro call expects terminating `)'");
4515 if (tline
->type
== TOK_WHITESPACE
4517 if (paramsize
[nparam
])
4520 params
[nparam
] = tline
->next
;
4521 continue; /* parameter loop */
4523 if (tline
->type
== TOK_OTHER
4524 && tline
->text
[1] == 0) {
4525 char ch
= tline
->text
[0];
4526 if (ch
== ',' && !paren
&& brackets
<= 0) {
4527 if (++nparam
>= sparam
) {
4528 sparam
+= PARAM_DELTA
;
4529 params
= nasm_realloc(params
,
4530 sparam
* sizeof(Token
*));
4531 paramsize
= nasm_realloc(paramsize
,
4532 sparam
* sizeof(int));
4534 params
[nparam
] = tline
->next
;
4535 paramsize
[nparam
] = 0;
4537 continue; /* parameter loop */
4540 (brackets
> 0 || (brackets
== 0 &&
4541 !paramsize
[nparam
])))
4543 if (!(brackets
++)) {
4544 params
[nparam
] = tline
->next
;
4545 continue; /* parameter loop */
4548 if (ch
== '}' && brackets
> 0)
4549 if (--brackets
== 0) {
4551 continue; /* parameter loop */
4553 if (ch
== '(' && !brackets
)
4555 if (ch
== ')' && brackets
<= 0)
4561 error(ERR_NONFATAL
, "braces do not "
4562 "enclose all of macro parameter");
4564 paramsize
[nparam
] += white
+ 1;
4566 } /* parameter loop */
4568 while (m
&& (m
->nparam
!= nparam
||
4569 mstrcmp(m
->name
, mname
,
4573 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4574 "macro `%s' exists, "
4575 "but not taking %d parameters",
4576 mstart
->text
, nparam
);
4579 if (m
&& m
->in_progress
)
4581 if (!m
) { /* in progess or didn't find '(' or wrong nparam */
4583 * Design question: should we handle !tline, which
4584 * indicates missing ')' here, or expand those
4585 * macros anyway, which requires the (t) test a few
4589 nasm_free(paramsize
);
4593 * Expand the macro: we are placed on the last token of the
4594 * call, so that we can easily split the call from the
4595 * following tokens. We also start by pushing an SMAC_END
4596 * token for the cycle removal.
4603 tt
= new_Token(tline
, TOK_SMAC_END
, NULL
, 0);
4605 m
->in_progress
= true;
4607 list_for_each(t
, m
->expansion
) {
4608 if (t
->type
>= TOK_SMAC_PARAM
) {
4609 Token
*pcopy
= tline
, **ptail
= &pcopy
;
4613 ttt
= params
[t
->type
- TOK_SMAC_PARAM
];
4614 i
= paramsize
[t
->type
- TOK_SMAC_PARAM
];
4616 pt
= *ptail
= new_Token(tline
, ttt
->type
,
4622 } else if (t
->type
== TOK_PREPROC_Q
) {
4623 tt
= new_Token(tline
, TOK_ID
, mname
, 0);
4625 } else if (t
->type
== TOK_PREPROC_QQ
) {
4626 tt
= new_Token(tline
, TOK_ID
, m
->name
, 0);
4629 tt
= new_Token(tline
, t
->type
, t
->text
, 0);
4635 * Having done that, get rid of the macro call, and clean
4636 * up the parameters.
4639 nasm_free(paramsize
);
4642 continue; /* main token loop */
4647 if (tline
->type
== TOK_SMAC_END
) {
4648 tline
->a
.mac
->in_progress
= false;
4649 tline
= delete_Token(tline
);
4652 tline
= tline
->next
;
4660 * Now scan the entire line and look for successive TOK_IDs that resulted
4661 * after expansion (they can't be produced by tokenize()). The successive
4662 * TOK_IDs should be concatenated.
4663 * Also we look for %+ tokens and concatenate the tokens before and after
4664 * them (without white spaces in between).
4667 const struct tokseq_match t
[] = {
4669 PP_CONCAT_MASK(TOK_ID
) |
4670 PP_CONCAT_MASK(TOK_PREPROC_ID
), /* head */
4671 PP_CONCAT_MASK(TOK_ID
) |
4672 PP_CONCAT_MASK(TOK_PREPROC_ID
) |
4673 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4676 if (paste_tokens(&thead
, t
, ARRAY_SIZE(t
), true)) {
4678 * If we concatenated something, *and* we had previously expanded
4679 * an actual macro, scan the lines again for macros...
4690 *org_tline
= *thead
;
4691 /* since we just gave text to org_line, don't free it */
4693 delete_Token(thead
);
4695 /* the expression expanded to empty line;
4696 we can't return NULL for some reasons
4697 we just set the line to a single WHITESPACE token. */
4698 memset(org_tline
, 0, sizeof(*org_tline
));
4699 org_tline
->text
= NULL
;
4700 org_tline
->type
= TOK_WHITESPACE
;
4709 * Similar to expand_smacro but used exclusively with macro identifiers
4710 * right before they are fetched in. The reason is that there can be
4711 * identifiers consisting of several subparts. We consider that if there
4712 * are more than one element forming the name, user wants a expansion,
4713 * otherwise it will be left as-is. Example:
4717 * the identifier %$abc will be left as-is so that the handler for %define
4718 * will suck it and define the corresponding value. Other case:
4720 * %define _%$abc cde
4722 * In this case user wants name to be expanded *before* %define starts
4723 * working, so we'll expand %$abc into something (if it has a value;
4724 * otherwise it will be left as-is) then concatenate all successive
4727 static Token
*expand_id(Token
* tline
)
4729 Token
*cur
, *oldnext
= NULL
;
4731 if (!tline
|| !tline
->next
)
4736 (cur
->next
->type
== TOK_ID
||
4737 cur
->next
->type
== TOK_PREPROC_ID
||
4738 cur
->next
->type
== TOK_NUMBER
))
4741 /* If identifier consists of just one token, don't expand */
4746 oldnext
= cur
->next
; /* Detach the tail past identifier */
4747 cur
->next
= NULL
; /* so that expand_smacro stops here */
4750 tline
= expand_smacro(tline
);
4753 /* expand_smacro possibly changhed tline; re-scan for EOL */
4755 while (cur
&& cur
->next
)
4758 cur
->next
= oldnext
;
4765 * Determine whether the given line constitutes a multi-line macro
4766 * call, and return the ExpDef structure called if so. Doesn't have
4767 * to check for an initial label - that's taken care of in
4768 * expand_mmacro - but must check numbers of parameters. Guaranteed
4769 * to be called with tline->type == TOK_ID, so the putative macro
4770 * name is easy to find.
4772 static ExpDef
*is_mmacro(Token
* tline
, Token
*** params_array
)
4778 head
= (ExpDef
*) hash_findix(&expdefs
, tline
->text
);
4781 * Efficiency: first we see if any macro exists with the given
4782 * name. If not, we can return NULL immediately. _Then_ we
4783 * count the parameters, and then we look further along the
4784 * list if necessary to find the proper ExpDef.
4786 list_for_each(ed
, head
)
4787 if (!mstrcmp(ed
->name
, tline
->text
, ed
->casesense
))
4793 * OK, we have a potential macro. Count and demarcate the
4796 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
4799 * So we know how many parameters we've got. Find the ExpDef
4800 * structure that handles this number.
4803 if (ed
->nparam_min
<= nparam
4804 && (ed
->plus
|| nparam
<= ed
->nparam_max
)) {
4806 * It's right, and we can use it. Add its default
4807 * parameters to the end of our list if necessary.
4809 if (ed
->defaults
&& nparam
< ed
->nparam_min
+ ed
->ndefs
) {
4811 nasm_realloc(params
,
4812 ((ed
->nparam_min
+ ed
->ndefs
+
4813 1) * sizeof(*params
)));
4814 while (nparam
< ed
->nparam_min
+ ed
->ndefs
) {
4815 params
[nparam
] = ed
->defaults
[nparam
- ed
->nparam_min
];
4820 * If we've gone over the maximum parameter count (and
4821 * we're in Plus mode), ignore parameters beyond
4824 if (ed
->plus
&& nparam
> ed
->nparam_max
)
4825 nparam
= ed
->nparam_max
;
4827 * Then terminate the parameter list, and leave.
4829 if (!params
) { /* need this special case */
4830 params
= nasm_malloc(sizeof(*params
));
4833 params
[nparam
] = NULL
;
4834 *params_array
= params
;
4838 * This one wasn't right: look for the next one with the
4841 list_for_each(ed
, ed
->next
)
4842 if (!mstrcmp(ed
->name
, tline
->text
, ed
->casesense
))
4847 * After all that, we didn't find one with the right number of
4848 * parameters. Issue a warning, and fail to expand the macro.
4850 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4851 "macro `%s' exists, but not taking %d parameters",
4852 tline
->text
, nparam
);
4858 * Expand the multi-line macro call made by the given line, if
4859 * there is one to be expanded. If there is, push the expansion on
4860 * istk->expansion and return true. Otherwise return false.
4862 static bool expand_mmacro(Token
* tline
)
4864 Token
*label
= NULL
;
4865 int dont_prepend
= 0;
4870 int i
, nparam
, *paramlen
;
4875 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4876 if (!tok_type_(t
, TOK_ID
) && !tok_type_(t
, TOK_PREPROC_ID
))
4878 ed
= is_mmacro(t
, ¶ms
);
4884 * We have an id which isn't a macro call. We'll assume
4885 * it might be a label; we'll also check to see if a
4886 * colon follows it. Then, if there's another id after
4887 * that lot, we'll check it again for macro-hood.
4891 if (tok_type_(t
, TOK_WHITESPACE
))
4892 last
= t
, t
= t
->next
;
4893 if (tok_is_(t
, ":")) {
4895 last
= t
, t
= t
->next
;
4896 if (tok_type_(t
, TOK_WHITESPACE
))
4897 last
= t
, t
= t
->next
;
4899 if (!tok_type_(t
, TOK_ID
) || !(ed
= is_mmacro(t
, ¶ms
)))
4907 * Fix up the parameters: this involves stripping leading and
4908 * trailing whitespace, then stripping braces if they are
4911 for (nparam
= 0; params
[nparam
]; nparam
++) ;
4912 paramlen
= nparam
? nasm_malloc(nparam
* sizeof(*paramlen
)) : NULL
;
4914 for (i
= 0; params
[i
]; i
++) {
4916 int comma
= (!ed
->plus
|| i
< nparam
- 1);
4920 if (tok_is_(t
, "{"))
4921 t
= t
->next
, brace
= true, comma
= false;
4925 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
4926 break; /* ... because we have hit a comma */
4927 if (comma
&& t
->type
== TOK_WHITESPACE
4928 && tok_is_(t
->next
, ","))
4929 break; /* ... or a space then a comma */
4930 if (brace
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "}"))
4931 break; /* ... or a brace */
4937 if (ed
->cur_depth
>= ed
->max_depth
) {
4938 if (ed
->max_depth
> 1) {
4940 "reached maximum macro recursion depth of %i for %s",
4941 ed
->max_depth
,ed
->name
);
4949 * OK, we have found a ExpDef structure representing a
4950 * previously defined mmacro. Create an expansion invocation
4951 * and point it back to the expansion definition. Substitution of
4952 * parameter tokens and macro-local tokens doesn't get done
4953 * until the single-line macro substitution process; this is
4954 * because delaying them allows us to change the semantics
4955 * later through %rotate.
4957 ei
= new_ExpInv(EXP_MMACRO
, ed
);
4958 ei
->name
= nasm_strdup(mname
);
4959 //ei->label = label;
4960 //ei->label_text = detoken(label, false);
4961 ei
->current
= ed
->line
;
4962 ei
->emitting
= true;
4963 //ei->iline = tline;
4964 ei
->params
= params
;
4965 ei
->nparam
= nparam
;
4967 ei
->paramlen
= paramlen
;
4970 ei
->prev
= istk
->expansion
;
4971 istk
->expansion
= ei
;
4974 * Special case: detect %00 on first invocation; if found,
4975 * avoid emitting any labels that precede the mmacro call.
4976 * ed->prepend is set to -1 when %00 is detected, else 1.
4978 if (ed
->prepend
== 0) {
4979 for (l
= ed
->line
; l
!= NULL
; l
= l
->next
) {
4980 for (t
= l
->first
; t
!= NULL
; t
= t
->next
) {
4981 if ((t
->type
== TOK_PREPROC_ID
) &&
4982 (strlen(t
->text
) == 3) &&
4983 (t
->text
[1] == '0') && (t
->text
[2] == '0')) {
4988 if (dont_prepend
< 0) {
4992 ed
->prepend
= ((dont_prepend
< 0) ? -1 : 1);
4996 * If we had a label, push it on as the first line of
4997 * the macro expansion.
4999 if (label
!= NULL
) {
5000 if (ed
->prepend
< 0) {
5001 ei
->label_text
= detoken(label
, false);
5003 if (dont_prepend
== 0) {
5005 while (t
->next
!= NULL
) {
5008 t
->next
= new_Token(NULL
, TOK_OTHER
, ":", 0);
5011 l
->first
= copy_Token(label
);
5012 l
->next
= ei
->current
;
5017 list
->uplevel(ed
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
5023 /* The function that actually does the error reporting */
5024 static void verror(int severity
, const char *fmt
, va_list arg
)
5028 vsnprintf(buff
, sizeof(buff
), fmt
, arg
);
5030 if (istk
&& istk
->mmac_depth
> 0) {
5031 ExpInv
*ei
= istk
->expansion
;
5032 int lineno
= ei
->lineno
;
5034 if (ei
->type
== EXP_MMACRO
)
5036 lineno
+= ei
->relno
;
5039 nasm_error(severity
, "(%s:%d) %s", ei
->def
->name
,
5042 nasm_error(severity
, "%s", buff
);
5046 * Since preprocessor always operate only on the line that didn't
5047 * arrived yet, we should always use ERR_OFFBY1.
5049 static void error(int severity
, const char *fmt
, ...)
5053 verror(severity
, fmt
, arg
);
5058 * Because %else etc are evaluated in the state context
5059 * of the previous branch, errors might get lost with error():
5060 * %if 0 ... %else trailing garbage ... %endif
5061 * So %else etc should report errors with this function.
5063 static void error_precond(int severity
, const char *fmt
, ...)
5067 /* Only ignore the error if it's really in a dead branch */
5068 if ((istk
!= NULL
) &&
5069 (istk
->expansion
!= NULL
) &&
5070 (istk
->expansion
->type
== EXP_IF
) &&
5071 (istk
->expansion
->def
->state
== COND_NEVER
))
5075 verror(severity
, fmt
, arg
);
5080 pp_reset(char *file
, int apass
, ListGen
* listgen
, StrList
**deplist
)
5085 istk
= nasm_zalloc(sizeof(Include
));
5086 istk
->fp
= fopen(file
, "r");
5087 src_set_fname(nasm_strdup(file
));
5091 error(ERR_FATAL
|ERR_NOFILE
, "unable to open input file `%s'",
5096 nested_mac_count
= 0;
5097 nested_rep_count
= 0;
5100 if (tasm_compatible_mode
) {
5101 stdmacpos
= nasm_stdmac
;
5103 stdmacpos
= nasm_stdmac_after_tasm
;
5105 any_extrastdmac
= extrastdmac
&& *extrastdmac
;
5110 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
5111 * The caller, however, will also pass in 3 for preprocess-only so
5112 * we can set __PASS__ accordingly.
5114 pass
= apass
> 2 ? 2 : apass
;
5116 dephead
= deptail
= deplist
;
5118 StrList
*sl
= nasm_malloc(strlen(file
)+1+sizeof sl
->next
);
5120 strcpy(sl
->str
, file
);
5122 deptail
= &sl
->next
;
5126 * Define the __PASS__ macro. This is defined here unlike
5127 * all the other builtins, because it is special -- it varies between
5130 t
= nasm_zalloc(sizeof(*t
));
5131 make_tok_num(t
, apass
);
5132 define_smacro(NULL
, "__PASS__", true, 0, t
);
5135 static char *pp_getline(void)
5146 * Fetch a tokenized line, either from the expansion
5147 * buffer or from the input file.
5151 while (1) { /* until we get a line we can use */
5153 * Fetch a tokenized line from the expansion buffer
5155 if (istk
->expansion
!= NULL
) {
5156 ei
= istk
->expansion
;
5157 if (ei
->current
!= NULL
) {
5158 if (ei
->emitting
== false) {
5163 ei
->current
= l
->next
;
5165 tline
= copy_Token(l
->first
);
5166 if (((ei
->type
== EXP_REP
) ||
5167 (ei
->type
== EXP_MMACRO
) ||
5168 (ei
->type
== EXP_WHILE
))
5169 && (ei
->def
->nolist
== false)) {
5170 char *p
= detoken(tline
, false);
5171 list
->line(LIST_MACRO
, p
);
5174 if (ei
->linnum
> -1) {
5175 src_set_linnum(src_get_linnum() + 1);
5178 } else if ((ei
->type
== EXP_REP
) &&
5179 (ei
->def
->cur_depth
< ei
->def
->max_depth
)) {
5180 ei
->def
->cur_depth
++;
5181 ei
->current
= ei
->def
->line
;
5184 } else if ((ei
->type
== EXP_WHILE
) &&
5185 (ei
->def
->cur_depth
< ei
->def
->max_depth
)) {
5186 ei
->current
= ei
->def
->line
;
5188 tline
= copy_Token(ei
->current
->first
);
5189 j
= if_condition(tline
, PP_WHILE
);
5191 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
5192 if (j
== COND_IF_TRUE
) {
5193 ei
->current
= ei
->current
->next
;
5194 ei
->def
->cur_depth
++;
5196 ei
->emitting
= false;
5198 ei
->def
->cur_depth
= ei
->def
->max_depth
;
5202 istk
->expansion
= ei
->prev
;
5205 if ((ei
->emitting
== true) &&
5206 (ed
->max_depth
== DEADMAN_LIMIT
) &&
5207 (ed
->cur_depth
== DEADMAN_LIMIT
)
5209 error(ERR_FATAL
, "runaway expansion detected, aborting");
5211 if (ed
->cur_depth
> 0) {
5213 } else if (ed
->type
!= EXP_MMACRO
) {
5214 expansions
= ed
->prev
;
5217 if ((ei
->type
== EXP_REP
) ||
5218 (ei
->type
== EXP_MMACRO
) ||
5219 (ei
->type
== EXP_WHILE
)) {
5220 list
->downlevel(LIST_MACRO
);
5221 if (ei
->type
== EXP_MMACRO
) {
5226 if (ei
->linnum
> -1) {
5227 src_set_linnum(ei
->linnum
);
5235 * Read in line from input and tokenize
5238 if (line
) { /* from the current input file */
5239 line
= prepreproc(line
);
5240 tline
= tokenize(line
);
5246 * The current file has ended; work down the istk
5251 if (i
->expansion
!= NULL
) {
5253 "end of file while still in an expansion");
5255 /* only set line and file name if there's a next node */
5257 src_set_linnum(i
->lineno
);
5258 nasm_free(src_set_fname(nasm_strdup(i
->fname
)));
5260 if ((i
->next
== NULL
) && (finals
!= NULL
)) {
5262 ei
= new_ExpInv(EXP_FINAL
, NULL
);
5263 ei
->emitting
= true;
5264 ei
->current
= finals
;
5265 istk
->expansion
= ei
;
5270 list
->downlevel(LIST_INCLUDE
);
5273 if (finals
!= NULL
) {
5283 if (defining
== NULL
) {
5284 tline
= expand_mmac_params(tline
);
5288 * Check the line to see if it's a preprocessor directive.
5290 if (do_directive(tline
) == DIRECTIVE_FOUND
) {
5292 } else if (defining
!= NULL
) {
5294 * We're defining an expansion. We emit nothing at all,
5295 * and just shove the tokenized line on to the definition.
5297 if (defining
->ignoring
== false) {
5298 Line
*l
= new_Line();
5300 if (defining
->line
== NULL
) {
5304 defining
->last
->next
= l
;
5310 defining
->linecount
++;
5312 } else if ((istk
->expansion
!= NULL
) &&
5313 (istk
->expansion
->emitting
!= true)) {
5315 * We're in a non-emitting branch of an expansion.
5316 * Emit nothing at all, not even a blank line: when we
5317 * emerge from the expansion we'll give a line-number
5318 * directive so we keep our place correctly.
5323 tline
= expand_smacro(tline
);
5324 if (expand_mmacro(tline
) != true) {
5326 * De-tokenize the line again, and emit it.
5328 line
= detoken(tline
, true);
5339 static void pp_cleanup(int pass
)
5341 if (defining
!= NULL
) {
5342 error(ERR_NONFATAL
, "end of file while still defining an expansion");
5343 while (defining
!= NULL
) {
5344 ExpDef
*ed
= defining
;
5345 defining
= ed
->prev
;
5350 while (cstk
!= NULL
)
5353 while (istk
!= NULL
) {
5357 nasm_free(i
->fname
);
5358 while (i
->expansion
!= NULL
) {
5359 ExpInv
*ei
= i
->expansion
;
5360 i
->expansion
= ei
->prev
;
5367 nasm_free(src_set_fname(NULL
));
5372 while ((i
= ipath
)) {
5380 void pp_include_path(char *path
)
5382 IncPath
*i
= nasm_zalloc(sizeof(IncPath
));
5385 i
->path
= nasm_strdup(path
);
5397 void pp_pre_include(char *fname
)
5399 Token
*inc
, *space
, *name
;
5402 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
5403 space
= new_Token(name
, TOK_WHITESPACE
, NULL
, 0);
5404 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
5412 void pp_pre_define(char *definition
)
5418 equals
= strchr(definition
, '=');
5419 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5420 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
5423 space
->next
= tokenize(definition
);
5433 void pp_pre_undefine(char *definition
)
5438 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5439 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
5440 space
->next
= tokenize(definition
);
5449 * This function is used to assist with "runtime" preprocessor
5450 * directives, e.g. pp_runtime("%define __BITS__ 64");
5452 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
5453 * PASS A VALID STRING TO THIS FUNCTION!!!!!
5456 void pp_runtime(char *definition
)
5460 def
= tokenize(definition
);
5461 if (do_directive(def
) == NO_DIRECTIVE_FOUND
)
5466 void pp_extra_stdmac(macros_t
*macros
)
5468 extrastdmac
= macros
;
5471 static void make_tok_num(Token
* tok
, int64_t val
)
5474 snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
5475 tok
->text
= nasm_strdup(numbuf
);
5476 tok
->type
= TOK_NUMBER
;