1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2010 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
35 * preproc.c macro preprocessor for the Netwide Assembler
38 /* Typical flow of text through preproc
40 * pp_getline gets tokenized lines, either
42 * from a macro expansion
46 * read_line gets raw text from stdmacpos, or predef, or current input file
47 * tokenize converts to tokens
50 * expand_mmac_params is used to expand %1 etc., unless a macro is being
51 * defined or a false conditional is being processed
52 * (%0, %1, %+1, %-1, %%foo
54 * do_directive checks for directives
56 * expand_smacro is used to expand single line macros
58 * expand_mmacro is used to expand multi-line macros
60 * detoken is used to convert the line back to text
84 typedef struct SMacro SMacro
;
85 typedef struct ExpDef ExpDef
;
86 typedef struct ExpInv ExpInv
;
87 typedef struct Context Context
;
88 typedef struct Token Token
;
89 typedef struct Blocks Blocks
;
90 typedef struct Line Line
;
91 typedef struct Include Include
;
92 typedef struct Cond Cond
;
93 typedef struct IncPath IncPath
;
96 * Note on the storage of both SMacro and MMacros: the hash table
97 * indexes them case-insensitively, and we then have to go through a
98 * linked list of potential case aliases (and, for MMacros, parameter
99 * ranges); this is to preserve the matching semantics of the earlier
100 * code. If the number of case aliases for a specific macro is a
101 * performance issue, you may want to reconsider your coding style.
105 * Store the definition of a single-line macro.
117 * The context stack is composed of a linked list of these.
122 struct hash_table localmac
;
127 * This is the internal form which we break input lines up into.
128 * Typically stored in linked lists.
130 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
131 * necessarily used as-is, but is intended to denote the number of
132 * the substituted parameter. So in the definition
134 * %define a(x,y) ( (x) & ~(y) )
136 * the token representing `x' will have its type changed to
137 * TOK_SMAC_PARAM, but the one representing `y' will be
140 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
141 * which doesn't need quotes around it. Used in the pre-include
142 * mechanism as an alternative to trying to find a sensible type of
143 * quote to use on the filename we were passed.
146 TOK_NONE
= 0, TOK_WHITESPACE
, TOK_COMMENT
, TOK_ID
,
147 TOK_PREPROC_ID
, TOK_STRING
,
148 TOK_NUMBER
, TOK_FLOAT
, TOK_SMAC_END
, TOK_OTHER
,
150 TOK_PREPROC_Q
, TOK_PREPROC_QQ
,
152 TOK_INDIRECT
, /* %[...] */
153 TOK_SMAC_PARAM
, /* MUST BE LAST IN THE LIST!!! */
154 TOK_MAX
= INT_MAX
/* Keep compiler from reducing the range */
157 #define PP_CONCAT_MASK(x) (1 << (x))
159 struct tokseq_match
{
168 SMacro
*mac
; /* associated macro for TOK_SMAC_END */
169 size_t len
; /* scratch length field */
170 } a
; /* Auxiliary data */
171 enum pp_token_type type
;
175 * Expansion definitions are stored as a linked list of
176 * these, which is essentially a container to allow several linked
179 * Note that in this module, linked lists are treated as stacks
180 * wherever possible. For this reason, Lines are _pushed_ on to the
181 * `last' field in ExpDef structures, so that the linked list,
182 * if walked, would emit the expansion lines in the proper order.
193 EXP_NONE
= 0, EXP_PREDEF
,
196 EXP_COMMENT
, EXP_FINAL
,
197 EXP_MAX
= INT_MAX
/* Keep compiler from reducing the range */
201 * Store the definition of an expansion, in which is any
202 * preprocessor directive that has an ending pair.
204 * This design allows for arbitrary expansion/recursion depth,
205 * upto the DEADMAN_LIMIT.
207 * The `next' field is used for storing ExpDef in hash tables; the
208 * `prev' field is for the global `expansions` linked-list.
211 ExpDef
*prev
; /* previous definition */
212 ExpDef
*next
; /* next in hash table */
213 enum pp_exp_type type
; /* expansion type */
214 char *name
; /* definition name */
215 int nparam_min
, nparam_max
;
217 bool plus
; /* is the last parameter greedy? */
218 bool nolist
; /* is this expansion listing-inhibited? */
219 Token
*dlist
; /* all defaults as one list */
220 Token
**defaults
; /* parameter default pointers */
221 int ndefs
; /* number of default parameters */
223 int prepend
; /* label prepend state */
227 int linecount
; /* number of lines within expansion */
229 int64_t def_depth
; /* current number of definition pairs deep */
230 int64_t cur_depth
; /* current number of expansions */
231 int64_t max_depth
; /* maximum number of expansions allowed */
233 int state
; /* condition state */
234 bool ignoring
; /* ignoring definition lines */
238 * Store the invocation of an expansion.
240 * The `prev' field is for the `istk->expansion` linked-list.
242 * When an expansion is being expanded, `params', `iline', `nparam',
243 * `paramlen', `rotate' and `unique' are local to the invocation.
246 ExpInv
*prev
; /* previous invocation */
247 enum pp_exp_type type
; /* expansion type */
248 ExpDef
*def
; /* pointer to expansion definition */
249 char *name
; /* invocation name */
250 Line
*label
; /* pointer to label */
251 char *label_text
; /* pointer to label text */
252 Line
*current
; /* pointer to current line in invocation */
254 Token
**params
; /* actual parameters */
255 Token
*iline
; /* invocation line */
256 unsigned int nparam
, rotate
;
261 int lineno
; /* current line number in expansion */
262 int linnum
; /* line number at invocation */
263 int relno
; /* relative line number at invocation */
267 * To handle an arbitrary level of file inclusion, we maintain a
268 * stack (ie linked list) of these things.
281 * Include search path. This is simply a list of strings which get
282 * prepended, in turn, to the name of an include file, in an
283 * attempt to find the file if it's not in the current directory.
291 * Conditional assembly: we maintain a separate stack of these for
292 * each level of file inclusion. (The only reason we keep the
293 * stacks separate is to ensure that a stray `%endif' in a file
294 * included from within the true branch of a `%if' won't terminate
295 * it and cause confusion: instead, rightly, it'll cause an error.)
299 * These states are for use just after %if or %elif: IF_TRUE
300 * means the condition has evaluated to truth so we are
301 * currently emitting, whereas IF_FALSE means we are not
302 * currently emitting but will start doing so if a %else comes
303 * up. In these states, all directives are admissible: %elif,
304 * %else and %endif. (And of course %if.)
306 COND_IF_TRUE
, COND_IF_FALSE
,
308 * These states come up after a %else: ELSE_TRUE means we're
309 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
310 * any %elif or %else will cause an error.
312 COND_ELSE_TRUE
, COND_ELSE_FALSE
,
314 * These states mean that we're not emitting now, and also that
315 * nothing until %endif will be emitted at all. COND_DONE is
316 * used when we've had our moment of emission
317 * and have now started seeing %elifs. COND_NEVER is used when
318 * the condition construct in question is contained within a
319 * non-emitting branch of a larger condition construct,
320 * or if there is an error.
322 COND_DONE
, COND_NEVER
324 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
327 * These defines are used as the possible return values for do_directive
329 #define NO_DIRECTIVE_FOUND 0
330 #define DIRECTIVE_FOUND 1
333 * This define sets the upper limit for smacro and expansions
335 #define DEADMAN_LIMIT (1 << 20)
338 #define REP_LIMIT ((INT64_C(1) << 62))
341 * Condition codes. Note that we use c_ prefix not C_ because C_ is
342 * used in nasm.h for the "real" condition codes. At _this_ level,
343 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
344 * ones, so we need a different enum...
346 static const char * const conditions
[] = {
347 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
348 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
349 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
352 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
353 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
354 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_RCXZ
, c_S
, c_Z
,
357 static const enum pp_conds inverse_ccs
[] = {
358 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
359 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_E
, c_G
, c_GE
, c_L
, c_LE
, c_O
, c_P
, c_S
,
360 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, -1, c_NS
, c_NZ
363 /* For TASM compatibility we need to be able to recognise TASM compatible
364 * conditional compilation directives. Using the NASM pre-processor does
365 * not work, so we look for them specifically from the following list and
366 * then jam in the equivalent NASM directive into the input stream.
370 TM_ARG
, TM_ELIF
, TM_ELSE
, TM_ENDIF
, TM_IF
, TM_IFDEF
, TM_IFDIFI
,
371 TM_IFNDEF
, TM_INCLUDE
, TM_LOCAL
374 static const char * const tasm_directives
[] = {
375 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
376 "ifndef", "include", "local"
379 static int StackSize
= 4;
380 static char *StackPointer
= "ebp";
381 static int ArgOffset
= 8;
382 static int LocalOffset
= 0;
384 static Context
*cstk
;
385 static Include
*istk
;
386 static IncPath
*ipath
= NULL
;
388 static int pass
; /* HACK: pass 0 = generate dependencies only */
389 static StrList
**dephead
, **deptail
; /* Dependency list */
391 static uint64_t unique
; /* unique identifier numbers */
393 static Line
*predef
= NULL
;
394 static bool do_predef
;
396 static ListGen
*list
;
399 * The current set of expansion definitions we have defined.
401 static struct hash_table expdefs
;
404 * The current set of single-line macros we have defined.
406 static struct hash_table smacros
;
409 * Linked List of all active expansion definitions
411 struct ExpDef
*expansions
= NULL
;
414 * The expansion we are currently defining
416 static ExpDef
*defining
= NULL
;
418 static uint64_t nested_mac_count
;
419 static uint64_t nested_rep_count
;
422 * Linked-list of lines to preprocess, prior to cleanup
424 static Line
*finals
= NULL
;
425 static bool in_final
= false;
428 * The number of macro parameters to allocate space for at a time.
430 #define PARAM_DELTA 16
433 * The standard macro set: defined in macros.c in the array nasm_stdmac.
434 * This gives our position in the macro set, when we're processing it.
436 static macros_t
*stdmacpos
;
439 * The extra standard macros that come from the object format, if
442 static macros_t
*extrastdmac
= NULL
;
443 static bool any_extrastdmac
;
446 * Tokens are allocated in blocks to improve speed
448 #define TOKEN_BLOCKSIZE 4096
449 static Token
*freeTokens
= NULL
;
455 static Blocks blocks
= { NULL
, NULL
};
458 * Forward declarations.
460 static Token
*expand_mmac_params(Token
* tline
);
461 static Token
*expand_smacro(Token
* tline
);
462 static Token
*expand_id(Token
* tline
);
463 static Context
*get_ctx(const char *name
, const char **namep
,
465 static void make_tok_num(Token
* tok
, int64_t val
);
466 static void error(int severity
, const char *fmt
, ...);
467 static void error_precond(int severity
, const char *fmt
, ...);
468 static void *new_Block(size_t size
);
469 static void delete_Blocks(void);
470 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
471 const char *text
, int txtlen
);
472 static Token
*copy_Token(Token
* tline
);
473 static Token
*delete_Token(Token
* t
);
474 static Line
*new_Line(void);
475 static ExpDef
*new_ExpDef(int exp_type
);
476 static ExpInv
*new_ExpInv(int exp_type
, ExpDef
*ed
);
479 * Macros for safe checking of token pointers, avoid *(NULL)
481 #define tok_type_(x,t) ((x) && (x)->type == (t))
482 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
483 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
484 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
487 * nasm_unquote with error if the string contains NUL characters.
488 * If the string contains NUL characters, issue an error and return
489 * the C len, i.e. truncate at the NUL.
491 static size_t nasm_unquote_cstr(char *qstr
, enum preproc_token directive
)
493 size_t len
= nasm_unquote(qstr
, NULL
);
494 size_t clen
= strlen(qstr
);
497 error(ERR_NONFATAL
, "NUL character in `%s' directive",
498 pp_directives
[directive
]);
504 * In-place reverse a list of tokens.
506 static Token
*reverse_tokens(Token
*t
)
522 * Handle TASM specific directives, which do not contain a % in
523 * front of them. We do it here because I could not find any other
524 * place to do it for the moment, and it is a hack (ideally it would
525 * be nice to be able to use the NASM pre-processor to do it).
527 static char *check_tasm_directive(char *line
)
529 int32_t i
, j
, k
, m
, len
;
530 char *p
, *q
, *oldline
, oldchar
;
532 p
= nasm_skip_spaces(line
);
534 /* Binary search for the directive name */
536 j
= ARRAY_SIZE(tasm_directives
);
537 q
= nasm_skip_word(p
);
544 m
= nasm_stricmp(p
, tasm_directives
[k
]);
546 /* We have found a directive, so jam a % in front of it
547 * so that NASM will then recognise it as one if it's own.
552 line
= nasm_malloc(len
+ 2);
554 if (k
== TM_IFDIFI
) {
556 * NASM does not recognise IFDIFI, so we convert
557 * it to %if 0. This is not used in NASM
558 * compatible code, but does need to parse for the
559 * TASM macro package.
561 strcpy(line
+ 1, "if 0");
563 memcpy(line
+ 1, p
, len
+ 1);
578 * The pre-preprocessing stage... This function translates line
579 * number indications as they emerge from GNU cpp (`# lineno "file"
580 * flags') into NASM preprocessor line number indications (`%line
583 static char *prepreproc(char *line
)
586 char *fname
, *oldline
;
588 if (line
[0] == '#' && line
[1] == ' ') {
591 lineno
= atoi(fname
);
592 fname
+= strspn(fname
, "0123456789 ");
595 fnlen
= strcspn(fname
, "\"");
596 line
= nasm_malloc(20 + fnlen
);
597 snprintf(line
, 20 + fnlen
, "%%line %d %.*s", lineno
, fnlen
, fname
);
600 if (tasm_compatible_mode
)
601 return check_tasm_directive(line
);
606 * Free a linked list of tokens.
608 static void free_tlist(Token
* list
)
611 list
= delete_Token(list
);
615 * Free a linked list of lines.
617 static void free_llist(Line
* list
)
620 list_for_each_safe(l
, tmp
, list
) {
621 free_tlist(l
->first
);
629 static void free_expdef(ExpDef
* ed
)
632 free_tlist(ed
->dlist
);
633 nasm_free(ed
->defaults
);
634 free_llist(ed
->line
);
641 static void free_expinv(ExpInv
* ei
)
643 if (ei
->name
!= NULL
)
645 if (ei
->label_text
!= NULL
)
646 nasm_free(ei
->label_text
);
651 * Free all currently defined macros, and free the hash tables
653 static void free_smacro_table(struct hash_table
*smt
)
657 struct hash_tbl_node
*it
= NULL
;
659 while ((s
= hash_iterate(smt
, &it
, &key
)) != NULL
) {
660 nasm_free((void *)key
);
661 list_for_each_safe(s
, tmp
, s
) {
663 free_tlist(s
->expansion
);
670 static void free_expdef_table(struct hash_table
*edt
)
674 struct hash_tbl_node
*it
= NULL
;
677 while ((ed
= hash_iterate(edt
, &it
, &key
)) != NULL
) {
678 nasm_free((void *)key
);
679 list_for_each_safe(ed
,tmp
, ed
)
685 static void free_macros(void)
687 free_smacro_table(&smacros
);
688 free_expdef_table(&expdefs
);
692 * Initialize the hash tables
694 static void init_macros(void)
696 hash_init(&smacros
, HASH_LARGE
);
697 hash_init(&expdefs
, HASH_LARGE
);
701 * Pop the context stack.
703 static void ctx_pop(void)
708 free_smacro_table(&c
->localmac
);
714 * Search for a key in the hash index; adding it if necessary
715 * (in which case we initialize the data pointer to NULL.)
718 hash_findi_add(struct hash_table
*hash
, const char *str
)
720 struct hash_insert hi
;
724 r
= hash_findi(hash
, str
, &hi
);
728 strx
= nasm_strdup(str
); /* Use a more efficient allocator here? */
729 return hash_add(&hi
, strx
, NULL
);
733 * Like hash_findi, but returns the data element rather than a pointer
734 * to it. Used only when not adding a new element, hence no third
738 hash_findix(struct hash_table
*hash
, const char *str
)
742 p
= hash_findi(hash
, str
, NULL
);
743 return p
? *p
: NULL
;
747 * read line from standard macros set,
748 * if there no more left -- return NULL
750 static char *line_from_stdmac(void)
753 const unsigned char *p
= stdmacpos
;
762 len
+= pp_directives_len
[c
- 0x80] + 1;
767 line
= nasm_malloc(len
+ 1);
769 while ((c
= *stdmacpos
++)) {
771 memcpy(q
, pp_directives
[c
- 0x80], pp_directives_len
[c
- 0x80]);
772 q
+= pp_directives_len
[c
- 0x80];
782 /* This was the last of the standard macro chain... */
784 if (any_extrastdmac
) {
785 stdmacpos
= extrastdmac
;
786 any_extrastdmac
= false;
787 } else if (do_predef
) {
790 Token
*head
, **tail
, *t
;
793 * Nasty hack: here we push the contents of
794 * `predef' on to the top-level expansion stack,
795 * since this is the most convenient way to
796 * implement the pre-include and pre-define
799 list_for_each(pd
, predef
) {
802 list_for_each(t
, pd
->first
) {
803 *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
804 tail
= &(*tail
)->next
;
809 ei
= new_ExpInv(EXP_PREDEF
, NULL
);
812 ei
->prev
= istk
->expansion
;
813 istk
->expansion
= ei
;
822 #define BUF_DELTA 512
824 * Read a line from the top file in istk, handling multiple CR/LFs
825 * at the end of the line read, and handling spurious ^Zs. Will
826 * return lines from the standard macro set if this has not already
829 static char *read_line(void)
831 char *buffer
, *p
, *q
;
832 int bufsize
, continued_count
;
835 * standart macros set (predefined) goes first
837 p
= line_from_stdmac();
842 * regular read from a file
845 buffer
= nasm_malloc(BUF_DELTA
);
849 q
= fgets(p
, bufsize
- (p
- buffer
), istk
->fp
);
853 if (p
> buffer
&& p
[-1] == '\n') {
855 * Convert backslash-CRLF line continuation sequences into
856 * nothing at all (for DOS and Windows)
858 if (((p
- 2) > buffer
) && (p
[-3] == '\\') && (p
[-2] == '\r')) {
864 * Also convert backslash-LF line continuation sequences into
865 * nothing at all (for Unix)
867 else if (((p
- 1) > buffer
) && (p
[-2] == '\\')) {
875 if (p
- buffer
> bufsize
- 10) {
876 int32_t offset
= p
- buffer
;
877 bufsize
+= BUF_DELTA
;
878 buffer
= nasm_realloc(buffer
, bufsize
);
879 p
= buffer
+ offset
; /* prevent stale-pointer problems */
883 if (!q
&& p
== buffer
) {
888 src_set_linnum(src_get_linnum() + istk
->lineinc
+
889 (continued_count
* istk
->lineinc
));
892 * Play safe: remove CRs as well as LFs, if any of either are
893 * present at the end of the line.
895 while (--p
>= buffer
&& (*p
== '\n' || *p
== '\r'))
899 * Handle spurious ^Z, which may be inserted into source files
900 * by some file transfer utilities.
902 buffer
[strcspn(buffer
, "\032")] = '\0';
904 list
->line(LIST_READ
, buffer
);
910 * Tokenize a line of text. This is a very simple process since we
911 * don't need to parse the value out of e.g. numeric tokens: we
912 * simply split one string into many.
914 static Token
*tokenize(char *line
)
917 enum pp_token_type type
;
919 Token
*t
, **tail
= &list
;
925 if (*p
== '+' && !nasm_isdigit(p
[1])) {
928 } else if (nasm_isdigit(*p
) ||
929 ((*p
== '-' || *p
== '+') && nasm_isdigit(p
[1]))) {
933 while (nasm_isdigit(*p
));
934 type
= TOK_PREPROC_ID
;
935 } else if (*p
== '{') {
937 while (*p
&& *p
!= '}') {
944 type
= TOK_PREPROC_ID
;
945 } else if (*p
== '[') {
947 line
+= 2; /* Skip the leading %[ */
949 while (lvl
&& (c
= *p
++)) {
961 p
= nasm_skip_string(p
- 1) + 1;
971 error(ERR_NONFATAL
, "unterminated %[ construct");
973 } else if (*p
== '?') {
974 type
= TOK_PREPROC_Q
; /* %? */
977 type
= TOK_PREPROC_QQ
; /* %?? */
980 } else if (*p
== '!') {
981 type
= TOK_PREPROC_ID
;
986 } while (isidchar(*p
));
987 } else if (*p
== '\'' || *p
== '\"' || *p
== '`') {
988 p
= nasm_skip_string(p
);
992 error(ERR_NONFATAL
|ERR_PASS1
, "unterminated %! string");
994 /* %! without string or identifier */
995 type
= TOK_OTHER
; /* Legacy behavior... */
997 } else if (isidchar(*p
) ||
998 ((*p
== '!' || *p
== '%' || *p
== '$') &&
1003 while (isidchar(*p
));
1004 type
= TOK_PREPROC_ID
;
1010 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
1013 while (*p
&& isidchar(*p
))
1015 } else if (*p
== '\'' || *p
== '"' || *p
== '`') {
1020 p
= nasm_skip_string(p
);
1025 error(ERR_WARNING
|ERR_PASS1
, "unterminated string");
1026 /* Handling unterminated strings by UNV */
1029 } else if (p
[0] == '$' && p
[1] == '$') {
1030 type
= TOK_OTHER
; /* TOKEN_BASE */
1032 } else if (isnumstart(*p
)) {
1033 bool is_hex
= false;
1034 bool is_float
= false;
1050 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
1052 if (*p
== '+' || *p
== '-') {
1054 * e can only be followed by +/- if it is either a
1055 * prefixed hex number or a floating-point number
1060 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
1062 } else if (c
== 'P' || c
== 'p') {
1064 if (*p
== '+' || *p
== '-')
1066 } else if (isnumchar(c
) || c
== '_')
1067 ; /* just advance */
1068 else if (c
== '.') {
1070 * we need to deal with consequences of the legacy
1071 * parser, like "1.nolist" being two tokens
1072 * (TOK_NUMBER, TOK_ID) here; at least give it
1073 * a shot for now. In the future, we probably need
1074 * a flex-based scanner with proper pattern matching
1075 * to do it as well as it can be done. Nothing in
1076 * the world is going to help the person who wants
1077 * 0x123.p16 interpreted as two tokens, though.
1083 if (nasm_isdigit(*r
) || (is_hex
&& nasm_isxdigit(*r
)) ||
1084 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
1085 (*r
== 'p' || *r
== 'P')) {
1089 break; /* Terminate the token */
1093 p
--; /* Point to first character beyond number */
1095 if (p
== line
+1 && *line
== '$') {
1096 type
= TOK_OTHER
; /* TOKEN_HERE */
1098 if (has_e
&& !is_hex
) {
1099 /* 1e13 is floating-point, but 1e13h is not */
1103 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
1105 } else if (nasm_isspace(*p
)) {
1106 type
= TOK_WHITESPACE
;
1107 p
= nasm_skip_spaces(p
);
1109 * Whitespace just before end-of-line is discarded by
1110 * pretending it's a comment; whitespace just before a
1111 * comment gets lumped into the comment.
1113 if (!*p
|| *p
== ';') {
1118 } else if (*p
== ';') {
1124 * Anything else is an operator of some kind. We check
1125 * for all the double-character operators (>>, <<, //,
1126 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1127 * else is a single-character operator.
1130 if ((p
[0] == '>' && p
[1] == '>') ||
1131 (p
[0] == '<' && p
[1] == '<') ||
1132 (p
[0] == '/' && p
[1] == '/') ||
1133 (p
[0] == '<' && p
[1] == '=') ||
1134 (p
[0] == '>' && p
[1] == '=') ||
1135 (p
[0] == '=' && p
[1] == '=') ||
1136 (p
[0] == '!' && p
[1] == '=') ||
1137 (p
[0] == '<' && p
[1] == '>') ||
1138 (p
[0] == '&' && p
[1] == '&') ||
1139 (p
[0] == '|' && p
[1] == '|') ||
1140 (p
[0] == '^' && p
[1] == '^')) {
1146 /* Handling unterminated string by UNV */
1149 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1150 t->text[p-line] = *line;
1154 if (type
!= TOK_COMMENT
) {
1155 *tail
= t
= new_Token(NULL
, type
, line
, p
- line
);
1164 * this function allocates a new managed block of memory and
1165 * returns a pointer to the block. The managed blocks are
1166 * deleted only all at once by the delete_Blocks function.
1168 static void *new_Block(size_t size
)
1170 Blocks
*b
= &blocks
;
1172 /* first, get to the end of the linked list */
1175 /* now allocate the requested chunk */
1176 b
->chunk
= nasm_malloc(size
);
1178 /* now allocate a new block for the next request */
1179 b
->next
= nasm_malloc(sizeof(Blocks
));
1180 /* and initialize the contents of the new block */
1181 b
->next
->next
= NULL
;
1182 b
->next
->chunk
= NULL
;
1187 * this function deletes all managed blocks of memory
1189 static void delete_Blocks(void)
1191 Blocks
*a
, *b
= &blocks
;
1194 * keep in mind that the first block, pointed to by blocks
1195 * is a static and not dynamically allocated, so we don't
1200 nasm_free(b
->chunk
);
1209 * this function creates a new Token and passes a pointer to it
1210 * back to the caller. It sets the type and text elements, and
1211 * also the a.mac and next elements to NULL.
1213 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
1214 const char *text
, int txtlen
)
1220 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1221 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1222 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1223 freeTokens
[i
].next
= NULL
;
1226 freeTokens
= t
->next
;
1230 if (type
== TOK_WHITESPACE
|| !text
) {
1234 txtlen
= strlen(text
);
1235 t
->text
= nasm_malloc(txtlen
+1);
1236 memcpy(t
->text
, text
, txtlen
);
1237 t
->text
[txtlen
] = '\0';
1242 static Token
*copy_Token(Token
* tline
)
1244 Token
*t
, *tt
, *first
= NULL
, *prev
= NULL
;
1246 for (tt
= tline
; tt
!= NULL
; tt
= tt
->next
) {
1248 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1249 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1250 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1251 freeTokens
[i
].next
= NULL
;
1254 freeTokens
= t
->next
;
1256 t
->text
= ((tt
->text
!= NULL
) ? strdup(tt
->text
) : NULL
);
1257 t
->a
.mac
= tt
->a
.mac
;
1258 t
->a
.len
= tt
->a
.len
;
1270 static Token
*delete_Token(Token
* t
)
1272 Token
*next
= t
->next
;
1274 t
->next
= freeTokens
;
1280 * Convert a line of tokens back into text.
1281 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1282 * will be transformed into ..@ctxnum.xxx
1284 static char *detoken(Token
* tlist
, bool expand_locals
)
1291 list_for_each(t
, tlist
) {
1292 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
1297 if (*v
== '\'' || *v
== '\"' || *v
== '`') {
1298 size_t len
= nasm_unquote(v
, NULL
);
1299 size_t clen
= strlen(v
);
1302 error(ERR_NONFATAL
| ERR_PASS1
,
1303 "NUL character in %! string");
1309 char *p
= getenv(v
);
1311 error(ERR_NONFATAL
| ERR_PASS1
,
1312 "nonexistent environment variable `%s'", v
);
1315 t
->text
= nasm_strdup(p
);
1320 /* Expand local macros here and not during preprocessing */
1321 if (expand_locals
&&
1322 t
->type
== TOK_PREPROC_ID
&& t
->text
&&
1323 t
->text
[0] == '%' && t
->text
[1] == '$') {
1326 Context
*ctx
= get_ctx(t
->text
, &q
, false);
1329 snprintf(buffer
, sizeof(buffer
), "..@%"PRIu32
".", ctx
->number
);
1330 p
= nasm_strcat(buffer
, q
);
1336 /* Expand %? and %?? directives */
1337 if (expand_locals
&& (istk
->expansion
!= NULL
) &&
1338 ((t
->type
== TOK_PREPROC_Q
) ||
1339 (t
->type
== TOK_PREPROC_QQ
))) {
1341 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
){
1342 if (ei
->type
== EXP_MMACRO
) {
1344 if (t
->type
== TOK_PREPROC_Q
) {
1345 t
->text
= nasm_strdup(ei
->name
);
1347 t
->text
= nasm_strdup(ei
->def
->name
);
1354 if (t
->type
== TOK_WHITESPACE
)
1357 len
+= strlen(t
->text
);
1360 p
= line
= nasm_malloc(len
+ 1);
1362 list_for_each(t
, tlist
) {
1363 if (t
->type
== TOK_WHITESPACE
) {
1365 } else if (t
->text
) {
1377 * Initialize a new Line
1379 static Line
*new_Line(void)
1381 Line
*l
= nasm_malloc(sizeof(Line
));
1389 * Initialize a new Expansion Definition
1391 static ExpDef
*new_ExpDef(int exp_type
)
1393 ExpDef
*ed
= (ExpDef
*)nasm_malloc(sizeof(ExpDef
));
1396 ed
->type
= exp_type
;
1400 ed
->casesense
= true;
1408 ed
->defaults
= NULL
;
1410 ed
->state
= COND_NEVER
;
1415 ed
->ignoring
= false;
1421 * Initialize a new Expansion Instance
1423 static ExpInv
*new_ExpInv(int exp_type
, ExpDef
*ed
)
1425 ExpInv
*ei
= (ExpInv
*)nasm_malloc(sizeof(ExpInv
));
1427 ei
->type
= exp_type
;
1431 ei
->label_text
= NULL
;
1437 ei
->paramlen
= NULL
;
1438 ei
->unique
= ++unique
;
1439 ei
->emitting
= false;
1441 if ((istk
->mmac_depth
< 1) &&
1442 (istk
->expansion
== NULL
) &&
1444 (ed
->type
!= EXP_MMACRO
) &&
1445 (ed
->type
!= EXP_REP
) &&
1446 (ed
->type
!= EXP_WHILE
)) {
1447 ei
->linnum
= src_get_linnum();
1448 src_set_linnum(ei
->linnum
- ed
->linecount
- 1);
1452 if ((istk
->expansion
== NULL
) ||
1453 (ei
->type
== EXP_MMACRO
)) {
1456 ei
->relno
= istk
->expansion
->lineno
;
1458 ei
->relno
-= (ed
->linecount
+ 1);
1465 * A scanner, suitable for use by the expression evaluator, which
1466 * operates on a line of Tokens. Expects a pointer to a pointer to
1467 * the first token in the line to be passed in as its private_data
1470 * FIX: This really needs to be unified with stdscan.
1472 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1474 Token
**tlineptr
= private_data
;
1476 char ourcopy
[MAX_KEYWORD
+1], *p
, *r
, *s
;
1480 *tlineptr
= tline
? tline
->next
: NULL
;
1481 } while (tline
&& (tline
->type
== TOK_WHITESPACE
||
1482 tline
->type
== TOK_COMMENT
));
1485 return tokval
->t_type
= TOKEN_EOS
;
1487 tokval
->t_charptr
= tline
->text
;
1489 if (tline
->text
[0] == '$' && !tline
->text
[1])
1490 return tokval
->t_type
= TOKEN_HERE
;
1491 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[2])
1492 return tokval
->t_type
= TOKEN_BASE
;
1494 if (tline
->type
== TOK_ID
) {
1495 p
= tokval
->t_charptr
= tline
->text
;
1497 tokval
->t_charptr
++;
1498 return tokval
->t_type
= TOKEN_ID
;
1501 for (r
= p
, s
= ourcopy
; *r
; r
++) {
1502 if (r
>= p
+MAX_KEYWORD
)
1503 return tokval
->t_type
= TOKEN_ID
; /* Not a keyword */
1504 *s
++ = nasm_tolower(*r
);
1507 /* right, so we have an identifier sitting in temp storage. now,
1508 * is it actually a register or instruction name, or what? */
1509 return nasm_token_hash(ourcopy
, tokval
);
1512 if (tline
->type
== TOK_NUMBER
) {
1514 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
1515 tokval
->t_charptr
= tline
->text
;
1517 return tokval
->t_type
= TOKEN_ERRNUM
;
1519 return tokval
->t_type
= TOKEN_NUM
;
1522 if (tline
->type
== TOK_FLOAT
) {
1523 return tokval
->t_type
= TOKEN_FLOAT
;
1526 if (tline
->type
== TOK_STRING
) {
1529 bq
= tline
->text
[0];
1530 tokval
->t_charptr
= tline
->text
;
1531 tokval
->t_inttwo
= nasm_unquote(tline
->text
, &ep
);
1533 if (ep
[0] != bq
|| ep
[1] != '\0')
1534 return tokval
->t_type
= TOKEN_ERRSTR
;
1536 return tokval
->t_type
= TOKEN_STR
;
1539 if (tline
->type
== TOK_OTHER
) {
1540 if (!strcmp(tline
->text
, "<<"))
1541 return tokval
->t_type
= TOKEN_SHL
;
1542 if (!strcmp(tline
->text
, ">>"))
1543 return tokval
->t_type
= TOKEN_SHR
;
1544 if (!strcmp(tline
->text
, "//"))
1545 return tokval
->t_type
= TOKEN_SDIV
;
1546 if (!strcmp(tline
->text
, "%%"))
1547 return tokval
->t_type
= TOKEN_SMOD
;
1548 if (!strcmp(tline
->text
, "=="))
1549 return tokval
->t_type
= TOKEN_EQ
;
1550 if (!strcmp(tline
->text
, "<>"))
1551 return tokval
->t_type
= TOKEN_NE
;
1552 if (!strcmp(tline
->text
, "!="))
1553 return tokval
->t_type
= TOKEN_NE
;
1554 if (!strcmp(tline
->text
, "<="))
1555 return tokval
->t_type
= TOKEN_LE
;
1556 if (!strcmp(tline
->text
, ">="))
1557 return tokval
->t_type
= TOKEN_GE
;
1558 if (!strcmp(tline
->text
, "&&"))
1559 return tokval
->t_type
= TOKEN_DBL_AND
;
1560 if (!strcmp(tline
->text
, "^^"))
1561 return tokval
->t_type
= TOKEN_DBL_XOR
;
1562 if (!strcmp(tline
->text
, "||"))
1563 return tokval
->t_type
= TOKEN_DBL_OR
;
1567 * We have no other options: just return the first character of
1570 return tokval
->t_type
= tline
->text
[0];
1574 * Compare a string to the name of an existing macro; this is a
1575 * simple wrapper which calls either strcmp or nasm_stricmp
1576 * depending on the value of the `casesense' parameter.
1578 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
1580 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
1584 * Compare a string to the name of an existing macro; this is a
1585 * simple wrapper which calls either strcmp or nasm_stricmp
1586 * depending on the value of the `casesense' parameter.
1588 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
1590 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
1594 * Return the Context structure associated with a %$ token. Return
1595 * NULL, having _already_ reported an error condition, if the
1596 * context stack isn't deep enough for the supplied number of $
1598 * If all_contexts == true, contexts that enclose current are
1599 * also scanned for such smacro, until it is found; if not -
1600 * only the context that directly results from the number of $'s
1601 * in variable's name.
1603 * If "namep" is non-NULL, set it to the pointer to the macro name
1604 * tail, i.e. the part beyond %$...
1606 static Context
*get_ctx(const char *name
, const char **namep
,
1616 if (!name
|| name
[0] != '%' || name
[1] != '$')
1620 error(ERR_NONFATAL
, "`%s': context stack is empty", name
);
1627 while (ctx
&& *name
== '$') {
1633 error(ERR_NONFATAL
, "`%s': context stack is only"
1634 " %d level%s deep", name
, i
, (i
== 1 ? "" : "s"));
1645 /* Search for this smacro in found context */
1646 m
= hash_findix(&ctx
->localmac
, name
);
1648 if (!mstrcmp(m
->name
, name
, m
->casesense
))
1659 * Check to see if a file is already in a string list
1661 static bool in_list(const StrList
*list
, const char *str
)
1664 if (!strcmp(list
->str
, str
))
1672 * Open an include file. This routine must always return a valid
1673 * file pointer if it returns - it's responsible for throwing an
1674 * ERR_FATAL and bombing out completely if not. It should also try
1675 * the include path one by one until it finds the file or reaches
1676 * the end of the path.
1678 static FILE *inc_fopen(const char *file
, StrList
**dhead
, StrList
***dtail
,
1683 IncPath
*ip
= ipath
;
1684 int len
= strlen(file
);
1685 size_t prefix_len
= 0;
1689 sl
= nasm_malloc(prefix_len
+len
+1+sizeof sl
->next
);
1690 memcpy(sl
->str
, prefix
, prefix_len
);
1691 memcpy(sl
->str
+prefix_len
, file
, len
+1);
1692 fp
= fopen(sl
->str
, "r");
1693 if (fp
&& dhead
&& !in_list(*dhead
, sl
->str
)) {
1711 prefix_len
= strlen(prefix
);
1713 /* -MG given and file not found */
1714 if (dhead
&& !in_list(*dhead
, file
)) {
1715 sl
= nasm_malloc(len
+1+sizeof sl
->next
);
1717 strcpy(sl
->str
, file
);
1725 error(ERR_FATAL
, "unable to open include file `%s'", file
);
1730 * Determine if we should warn on defining a single-line macro of
1731 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1732 * return true if _any_ single-line macro of that name is defined.
1733 * Otherwise, will return true if a single-line macro with either
1734 * `nparam' or no parameters is defined.
1736 * If a macro with precisely the right number of parameters is
1737 * defined, or nparam is -1, the address of the definition structure
1738 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1739 * is NULL, no action will be taken regarding its contents, and no
1742 * Note that this is also called with nparam zero to resolve
1745 * If you already know which context macro belongs to, you can pass
1746 * the context pointer as first parameter; if you won't but name begins
1747 * with %$ the context will be automatically computed. If all_contexts
1748 * is true, macro will be searched in outer contexts as well.
1751 smacro_defined(Context
* ctx
, const char *name
, int nparam
, SMacro
** defn
,
1754 struct hash_table
*smtbl
;
1758 smtbl
= &ctx
->localmac
;
1759 } else if (name
[0] == '%' && name
[1] == '$') {
1761 ctx
= get_ctx(name
, &name
, false);
1763 return false; /* got to return _something_ */
1764 smtbl
= &ctx
->localmac
;
1768 m
= (SMacro
*) hash_findix(smtbl
, name
);
1771 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
1772 (nparam
<= 0 || m
->nparam
== 0 || nparam
== (int) m
->nparam
)) {
1774 if (nparam
== (int) m
->nparam
|| nparam
== -1)
1788 * Count and mark off the parameters in a multi-line macro call.
1789 * This is called both from within the multi-line macro expansion
1790 * code, and also to mark off the default parameters when provided
1791 * in a %macro definition line.
1793 static void count_mmac_params(Token
* t
, int *nparam
, Token
*** params
)
1795 int paramsize
, brace
;
1797 *nparam
= paramsize
= 0;
1800 /* +1: we need space for the final NULL */
1801 if (*nparam
+1 >= paramsize
) {
1802 paramsize
+= PARAM_DELTA
;
1803 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
1807 if (tok_is_(t
, "{"))
1809 (*params
)[(*nparam
)++] = t
;
1810 while (tok_isnt_(t
, brace
? "}" : ","))
1812 if (t
) { /* got a comma/brace */
1816 * Now we've found the closing brace, look further
1820 if (tok_isnt_(t
, ",")) {
1822 "braces do not enclose all of macro parameter");
1823 while (tok_isnt_(t
, ","))
1827 t
= t
->next
; /* eat the comma */
1834 * Determine whether one of the various `if' conditions is true or
1837 * We must free the tline we get passed.
1839 static bool if_condition(Token
* tline
, enum preproc_token ct
)
1841 enum pp_conditional i
= PP_COND(ct
);
1843 Token
*t
, *tt
, **tptr
, *origline
;
1844 struct tokenval tokval
;
1846 enum pp_token_type needtype
;
1853 j
= false; /* have we matched yet? */
1858 if (tline
->type
!= TOK_ID
) {
1860 "`%s' expects context identifiers", pp_directives
[ct
]);
1861 free_tlist(origline
);
1864 if (cstk
&& cstk
->name
&& !nasm_stricmp(tline
->text
, cstk
->name
))
1866 tline
= tline
->next
;
1871 j
= false; /* have we matched yet? */
1874 if (!tline
|| (tline
->type
!= TOK_ID
&&
1875 (tline
->type
!= TOK_PREPROC_ID
||
1876 tline
->text
[1] != '$'))) {
1878 "`%s' expects macro identifiers", pp_directives
[ct
]);
1881 if (smacro_defined(NULL
, tline
->text
, 0, NULL
, true))
1883 tline
= tline
->next
;
1888 tline
= expand_smacro(tline
);
1889 j
= false; /* have we matched yet? */
1892 if (!tline
|| (tline
->type
!= TOK_ID
&&
1893 tline
->type
!= TOK_STRING
&&
1894 (tline
->type
!= TOK_PREPROC_ID
||
1895 tline
->text
[1] != '!'))) {
1897 "`%s' expects environment variable names",
1902 if (tline
->type
== TOK_PREPROC_ID
)
1903 p
+= 2; /* Skip leading %! */
1904 if (*p
== '\'' || *p
== '\"' || *p
== '`')
1905 nasm_unquote_cstr(p
, ct
);
1908 tline
= tline
->next
;
1914 tline
= expand_smacro(tline
);
1916 while (tok_isnt_(tt
, ","))
1920 "`%s' expects two comma-separated arguments",
1925 j
= true; /* assume equality unless proved not */
1926 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1927 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1928 error(ERR_NONFATAL
, "`%s': more than one comma on line",
1932 if (t
->type
== TOK_WHITESPACE
) {
1936 if (tt
->type
== TOK_WHITESPACE
) {
1940 if (tt
->type
!= t
->type
) {
1941 j
= false; /* found mismatching tokens */
1944 /* When comparing strings, need to unquote them first */
1945 if (t
->type
== TOK_STRING
) {
1946 size_t l1
= nasm_unquote(t
->text
, NULL
);
1947 size_t l2
= nasm_unquote(tt
->text
, NULL
);
1953 if (mmemcmp(t
->text
, tt
->text
, l1
, i
== PPC_IFIDN
)) {
1957 } else if (mstrcmp(tt
->text
, t
->text
, i
== PPC_IFIDN
) != 0) {
1958 j
= false; /* found mismatching tokens */
1965 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
1966 j
= false; /* trailing gunk on one end or other */
1972 ExpDef searching
, *ed
;
1975 tline
= expand_id(tline
);
1976 if (!tok_type_(tline
, TOK_ID
)) {
1978 "`%s' expects a macro name", pp_directives
[ct
]);
1981 searching
.name
= nasm_strdup(tline
->text
);
1982 searching
.casesense
= true;
1983 searching
.plus
= false;
1984 searching
.nolist
= false;
1985 //searching.in_progress = 0;
1986 searching
.max_depth
= 0;
1987 //searching.rep_nest = NULL;
1988 searching
.nparam_min
= 0;
1989 searching
.nparam_max
= INT_MAX
;
1990 tline
= expand_smacro(tline
->next
);
1993 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
1995 "`%s' expects a parameter count or nothing",
1998 searching
.nparam_min
= searching
.nparam_max
=
1999 readnum(tline
->text
, &j
);
2002 "unable to parse parameter count `%s'",
2005 if (tline
&& tok_is_(tline
->next
, "-")) {
2006 tline
= tline
->next
->next
;
2007 if (tok_is_(tline
, "*"))
2008 searching
.nparam_max
= INT_MAX
;
2009 else if (!tok_type_(tline
, TOK_NUMBER
))
2011 "`%s' expects a parameter count after `-'",
2014 searching
.nparam_max
= readnum(tline
->text
, &j
);
2017 "unable to parse parameter count `%s'",
2019 if (searching
.nparam_min
> searching
.nparam_max
)
2021 "minimum parameter count exceeds maximum");
2024 if (tline
&& tok_is_(tline
->next
, "+")) {
2025 tline
= tline
->next
;
2026 searching
.plus
= true;
2028 ed
= (ExpDef
*) hash_findix(&expdefs
, searching
.name
);
2029 while (ed
!= NULL
) {
2030 if (!strcmp(ed
->name
, searching
.name
) &&
2031 (ed
->nparam_min
<= searching
.nparam_max
2033 && (searching
.nparam_min
<= ed
->nparam_max
2040 if (tline
&& tline
->next
)
2041 error(ERR_WARNING
|ERR_PASS1
,
2042 "trailing garbage after %%ifmacro ignored");
2043 nasm_free(searching
.name
);
2052 needtype
= TOK_NUMBER
;
2055 needtype
= TOK_STRING
;
2059 t
= tline
= expand_smacro(tline
);
2061 while (tok_type_(t
, TOK_WHITESPACE
) ||
2062 (needtype
== TOK_NUMBER
&&
2063 tok_type_(t
, TOK_OTHER
) &&
2064 (t
->text
[0] == '-' || t
->text
[0] == '+') &&
2068 j
= tok_type_(t
, needtype
);
2072 t
= tline
= expand_smacro(tline
);
2073 while (tok_type_(t
, TOK_WHITESPACE
))
2078 t
= t
->next
; /* Skip the actual token */
2079 while (tok_type_(t
, TOK_WHITESPACE
))
2081 j
= !t
; /* Should be nothing left */
2086 t
= tline
= expand_smacro(tline
);
2087 while (tok_type_(t
, TOK_WHITESPACE
))
2090 j
= !t
; /* Should be empty */
2094 t
= tline
= expand_smacro(tline
);
2096 tokval
.t_type
= TOKEN_INVALID
;
2097 evalresult
= evaluate(ppscan
, tptr
, &tokval
,
2098 NULL
, pass
| CRITICAL
, error
, NULL
);
2102 error(ERR_WARNING
|ERR_PASS1
,
2103 "trailing garbage after expression ignored");
2104 if (!is_simple(evalresult
)) {
2106 "non-constant value given to `%s'", pp_directives
[ct
]);
2109 j
= reloc_value(evalresult
) != 0;
2114 "preprocessor directive `%s' not yet implemented",
2119 free_tlist(origline
);
2120 return j
^ PP_NEGATIVE(ct
);
2123 free_tlist(origline
);
2128 * Common code for defining an smacro
2130 static bool define_smacro(Context
*ctx
, const char *mname
, bool casesense
,
2131 int nparam
, Token
*expansion
)
2133 SMacro
*smac
, **smhead
;
2134 struct hash_table
*smtbl
;
2136 if (smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
)) {
2138 error(ERR_WARNING
|ERR_PASS1
,
2139 "single-line macro `%s' defined both with and"
2140 " without parameters", mname
);
2142 * Some instances of the old code considered this a failure,
2143 * some others didn't. What is the right thing to do here?
2145 free_tlist(expansion
);
2146 return false; /* Failure */
2149 * We're redefining, so we have to take over an
2150 * existing SMacro structure. This means freeing
2151 * what was already in it.
2153 nasm_free(smac
->name
);
2154 free_tlist(smac
->expansion
);
2157 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2158 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
2159 smac
= nasm_malloc(sizeof(SMacro
));
2160 smac
->next
= *smhead
;
2163 smac
->name
= nasm_strdup(mname
);
2164 smac
->casesense
= casesense
;
2165 smac
->nparam
= nparam
;
2166 smac
->expansion
= expansion
;
2167 smac
->in_progress
= false;
2168 return true; /* Success */
2172 * Undefine an smacro
2174 static void undef_smacro(Context
*ctx
, const char *mname
)
2176 SMacro
**smhead
, *s
, **sp
;
2177 struct hash_table
*smtbl
;
2179 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2180 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
2184 * We now have a macro name... go hunt for it.
2187 while ((s
= *sp
) != NULL
) {
2188 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
2191 free_tlist(s
->expansion
);
2201 * Parse a mmacro specification.
2203 static bool parse_mmacro_spec(Token
*tline
, ExpDef
*def
, const char *directive
)
2207 tline
= tline
->next
;
2209 tline
= expand_id(tline
);
2210 if (!tok_type_(tline
, TOK_ID
)) {
2211 error(ERR_NONFATAL
, "`%s' expects a macro name", directive
);
2215 def
->name
= nasm_strdup(tline
->text
);
2217 def
->nolist
= false;
2218 // def->in_progress = 0;
2219 // def->rep_nest = NULL;
2220 def
->nparam_min
= 0;
2221 def
->nparam_max
= 0;
2223 tline
= expand_smacro(tline
->next
);
2225 if (!tok_type_(tline
, TOK_NUMBER
)) {
2226 error(ERR_NONFATAL
, "`%s' expects a parameter count", directive
);
2228 def
->nparam_min
= def
->nparam_max
=
2229 readnum(tline
->text
, &err
);
2232 "unable to parse parameter count `%s'", tline
->text
);
2234 if (tline
&& tok_is_(tline
->next
, "-")) {
2235 tline
= tline
->next
->next
;
2236 if (tok_is_(tline
, "*")) {
2237 def
->nparam_max
= INT_MAX
;
2238 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2240 "`%s' expects a parameter count after `-'", directive
);
2242 def
->nparam_max
= readnum(tline
->text
, &err
);
2244 error(ERR_NONFATAL
, "unable to parse parameter count `%s'",
2247 if (def
->nparam_min
> def
->nparam_max
) {
2248 error(ERR_NONFATAL
, "minimum parameter count exceeds maximum");
2252 if (tline
&& tok_is_(tline
->next
, "+")) {
2253 tline
= tline
->next
;
2256 if (tline
&& tok_type_(tline
->next
, TOK_ID
) &&
2257 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
2258 tline
= tline
->next
;
2263 * Handle default parameters.
2265 if (tline
&& tline
->next
) {
2266 def
->dlist
= tline
->next
;
2268 count_mmac_params(def
->dlist
, &def
->ndefs
, &def
->defaults
);
2271 def
->defaults
= NULL
;
2275 if (def
->defaults
&& def
->ndefs
> def
->nparam_max
- def
->nparam_min
&&
2277 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MDP
,
2278 "too many default macro parameters");
2285 * Decode a size directive
2287 static int parse_size(const char *str
) {
2288 static const char *size_names
[] =
2289 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2290 static const int sizes
[] =
2291 { 0, 1, 4, 16, 8, 10, 2, 32 };
2293 return sizes
[bsii(str
, size_names
, ARRAY_SIZE(size_names
))+1];
2297 * find and process preprocessor directive in passed line
2298 * Find out if a line contains a preprocessor directive, and deal
2301 * If a directive _is_ found, it is the responsibility of this routine
2302 * (and not the caller) to free_tlist() the line.
2304 * @param tline a pointer to the current tokeninzed line linked list
2305 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2308 static int do_directive(Token
* tline
)
2310 enum preproc_token i
;
2323 Token
*t
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
2324 struct tokenval tokval
;
2326 ExpDef
*ed
, *eed
, **edhead
;
2335 if (!tline
|| !tok_type_(tline
, TOK_PREPROC_ID
) ||
2336 (tline
->text
[1] == '%' || tline
->text
[1] == '$'
2337 || tline
->text
[1] == '!'))
2338 return NO_DIRECTIVE_FOUND
;
2340 i
= pp_token_hash(tline
->text
);
2344 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2345 error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2347 return NO_DIRECTIVE_FOUND
; /* didn't get it */
2350 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2351 /* Directive to tell NASM what the default stack size is. The
2352 * default is for a 16-bit stack, and this can be overriden with
2355 tline
= tline
->next
;
2356 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2357 tline
= tline
->next
;
2358 if (!tline
|| tline
->type
!= TOK_ID
) {
2359 error(ERR_NONFATAL
, "`%%stacksize' missing size parameter");
2360 free_tlist(origline
);
2361 return DIRECTIVE_FOUND
;
2363 if (nasm_stricmp(tline
->text
, "flat") == 0) {
2364 /* All subsequent ARG directives are for a 32-bit stack */
2366 StackPointer
= "ebp";
2369 } else if (nasm_stricmp(tline
->text
, "flat64") == 0) {
2370 /* All subsequent ARG directives are for a 64-bit stack */
2372 StackPointer
= "rbp";
2375 } else if (nasm_stricmp(tline
->text
, "large") == 0) {
2376 /* All subsequent ARG directives are for a 16-bit stack,
2377 * far function call.
2380 StackPointer
= "bp";
2383 } else if (nasm_stricmp(tline
->text
, "small") == 0) {
2384 /* All subsequent ARG directives are for a 16-bit stack,
2385 * far function call. We don't support near functions.
2388 StackPointer
= "bp";
2392 error(ERR_NONFATAL
, "`%%stacksize' invalid size type");
2393 free_tlist(origline
);
2394 return DIRECTIVE_FOUND
;
2396 free_tlist(origline
);
2397 return DIRECTIVE_FOUND
;
2400 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2401 /* TASM like ARG directive to define arguments to functions, in
2402 * the following form:
2404 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2408 char *arg
, directive
[256];
2409 int size
= StackSize
;
2411 /* Find the argument name */
2412 tline
= tline
->next
;
2413 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2414 tline
= tline
->next
;
2415 if (!tline
|| tline
->type
!= TOK_ID
) {
2416 error(ERR_NONFATAL
, "`%%arg' missing argument parameter");
2417 free_tlist(origline
);
2418 return DIRECTIVE_FOUND
;
2422 /* Find the argument size type */
2423 tline
= tline
->next
;
2424 if (!tline
|| tline
->type
!= TOK_OTHER
2425 || tline
->text
[0] != ':') {
2427 "Syntax error processing `%%arg' directive");
2428 free_tlist(origline
);
2429 return DIRECTIVE_FOUND
;
2431 tline
= tline
->next
;
2432 if (!tline
|| tline
->type
!= TOK_ID
) {
2433 error(ERR_NONFATAL
, "`%%arg' missing size type parameter");
2434 free_tlist(origline
);
2435 return DIRECTIVE_FOUND
;
2438 /* Allow macro expansion of type parameter */
2439 tt
= tokenize(tline
->text
);
2440 tt
= expand_smacro(tt
);
2441 size
= parse_size(tt
->text
);
2444 "Invalid size type for `%%arg' missing directive");
2446 free_tlist(origline
);
2447 return DIRECTIVE_FOUND
;
2451 /* Round up to even stack slots */
2452 size
= ALIGN(size
, StackSize
);
2454 /* Now define the macro for the argument */
2455 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
2456 arg
, StackPointer
, offset
);
2457 do_directive(tokenize(directive
));
2460 /* Move to the next argument in the list */
2461 tline
= tline
->next
;
2462 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2463 tline
= tline
->next
;
2464 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2466 free_tlist(origline
);
2467 return DIRECTIVE_FOUND
;
2470 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2471 /* TASM like LOCAL directive to define local variables for a
2472 * function, in the following form:
2474 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2476 * The '= LocalSize' at the end is ignored by NASM, but is
2477 * required by TASM to define the local parameter size (and used
2478 * by the TASM macro package).
2480 offset
= LocalOffset
;
2482 char *local
, directive
[256];
2483 int size
= StackSize
;
2485 /* Find the argument name */
2486 tline
= tline
->next
;
2487 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2488 tline
= tline
->next
;
2489 if (!tline
|| tline
->type
!= TOK_ID
) {
2491 "`%%local' missing argument parameter");
2492 free_tlist(origline
);
2493 return DIRECTIVE_FOUND
;
2495 local
= tline
->text
;
2497 /* Find the argument size type */
2498 tline
= tline
->next
;
2499 if (!tline
|| tline
->type
!= TOK_OTHER
2500 || tline
->text
[0] != ':') {
2502 "Syntax error processing `%%local' directive");
2503 free_tlist(origline
);
2504 return DIRECTIVE_FOUND
;
2506 tline
= tline
->next
;
2507 if (!tline
|| tline
->type
!= TOK_ID
) {
2509 "`%%local' missing size type parameter");
2510 free_tlist(origline
);
2511 return DIRECTIVE_FOUND
;
2514 /* Allow macro expansion of type parameter */
2515 tt
= tokenize(tline
->text
);
2516 tt
= expand_smacro(tt
);
2517 size
= parse_size(tt
->text
);
2520 "Invalid size type for `%%local' missing directive");
2522 free_tlist(origline
);
2523 return DIRECTIVE_FOUND
;
2527 /* Round up to even stack slots */
2528 size
= ALIGN(size
, StackSize
);
2530 offset
+= size
; /* Negative offset, increment before */
2532 /* Now define the macro for the argument */
2533 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
2534 local
, StackPointer
, offset
);
2535 do_directive(tokenize(directive
));
2537 /* Now define the assign to setup the enter_c macro correctly */
2538 snprintf(directive
, sizeof(directive
),
2539 "%%assign %%$localsize %%$localsize+%d", size
);
2540 do_directive(tokenize(directive
));
2542 /* Move to the next argument in the list */
2543 tline
= tline
->next
;
2544 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2545 tline
= tline
->next
;
2546 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2547 LocalOffset
= offset
;
2548 free_tlist(origline
);
2549 return DIRECTIVE_FOUND
;
2552 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2554 error(ERR_WARNING
|ERR_PASS1
,
2555 "trailing garbage after `%%clear' ignored");
2558 free_tlist(origline
);
2559 return DIRECTIVE_FOUND
;
2562 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2563 t
= tline
->next
= expand_smacro(tline
->next
);
2565 if (!t
|| (t
->type
!= TOK_STRING
&&
2566 t
->type
!= TOK_INTERNAL_STRING
)) {
2567 error(ERR_NONFATAL
, "`%%depend' expects a file name");
2568 free_tlist(origline
);
2569 return DIRECTIVE_FOUND
; /* but we did _something_ */
2572 error(ERR_WARNING
|ERR_PASS1
,
2573 "trailing garbage after `%%depend' ignored");
2575 if (t
->type
!= TOK_INTERNAL_STRING
)
2576 nasm_unquote_cstr(p
, i
);
2577 if (dephead
&& !in_list(*dephead
, p
)) {
2578 StrList
*sl
= nasm_malloc(strlen(p
)+1+sizeof sl
->next
);
2582 deptail
= &sl
->next
;
2584 free_tlist(origline
);
2585 return DIRECTIVE_FOUND
;
2588 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2589 t
= tline
->next
= expand_smacro(tline
->next
);
2592 if (!t
|| (t
->type
!= TOK_STRING
&&
2593 t
->type
!= TOK_INTERNAL_STRING
)) {
2594 error(ERR_NONFATAL
, "`%%include' expects a file name");
2595 free_tlist(origline
);
2596 return DIRECTIVE_FOUND
; /* but we did _something_ */
2599 error(ERR_WARNING
|ERR_PASS1
,
2600 "trailing garbage after `%%include' ignored");
2602 if (t
->type
!= TOK_INTERNAL_STRING
)
2603 nasm_unquote_cstr(p
, i
);
2604 inc
= nasm_malloc(sizeof(Include
));
2606 inc
->fp
= inc_fopen(p
, dephead
, &deptail
, pass
== 0);
2608 /* -MG given but file not found */
2611 inc
->fname
= src_set_fname(nasm_strdup(p
));
2612 inc
->lineno
= src_set_linnum(0);
2614 inc
->expansion
= NULL
;
2616 list
->uplevel(LIST_INCLUDE
);
2618 free_tlist(origline
);
2619 return DIRECTIVE_FOUND
;
2622 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2624 static macros_t
*use_pkg
;
2625 const char *pkg_macro
= NULL
;
2627 tline
= tline
->next
;
2629 tline
= expand_id(tline
);
2631 if (!tline
|| (tline
->type
!= TOK_STRING
&&
2632 tline
->type
!= TOK_INTERNAL_STRING
&&
2633 tline
->type
!= TOK_ID
)) {
2634 error(ERR_NONFATAL
, "`%%use' expects a package name");
2635 free_tlist(origline
);
2636 return DIRECTIVE_FOUND
; /* but we did _something_ */
2639 error(ERR_WARNING
|ERR_PASS1
,
2640 "trailing garbage after `%%use' ignored");
2641 if (tline
->type
== TOK_STRING
)
2642 nasm_unquote_cstr(tline
->text
, i
);
2643 use_pkg
= nasm_stdmac_find_package(tline
->text
);
2645 error(ERR_NONFATAL
, "unknown `%%use' package: %s", tline
->text
);
2647 pkg_macro
= (char *)use_pkg
+ 1; /* The first string will be <%define>__USE_*__ */
2648 if (use_pkg
&& ! smacro_defined(NULL
, pkg_macro
, 0, NULL
, true)) {
2649 /* Not already included, go ahead and include it */
2650 stdmacpos
= use_pkg
;
2652 free_tlist(origline
);
2653 return DIRECTIVE_FOUND
;
2658 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2659 tline
= tline
->next
;
2661 tline
= expand_id(tline
);
2663 if (!tok_type_(tline
, TOK_ID
)) {
2664 error(ERR_NONFATAL
, "`%s' expects a context identifier",
2666 free_tlist(origline
);
2667 return DIRECTIVE_FOUND
; /* but we did _something_ */
2670 error(ERR_WARNING
|ERR_PASS1
,
2671 "trailing garbage after `%s' ignored",
2673 p
= nasm_strdup(tline
->text
);
2675 p
= NULL
; /* Anonymous */
2679 ctx
= nasm_malloc(sizeof(Context
));
2681 hash_init(&ctx
->localmac
, HASH_SMALL
);
2683 ctx
->number
= unique
++;
2688 error(ERR_NONFATAL
, "`%s': context stack is empty",
2690 } else if (i
== PP_POP
) {
2691 if (p
&& (!cstk
->name
|| nasm_stricmp(p
, cstk
->name
)))
2692 error(ERR_NONFATAL
, "`%%pop' in wrong context: %s, "
2694 cstk
->name
? cstk
->name
: "anonymous", p
);
2699 nasm_free(cstk
->name
);
2705 free_tlist(origline
);
2706 return DIRECTIVE_FOUND
;
2708 severity
= ERR_FATAL
;
2711 severity
= ERR_NONFATAL
;
2714 severity
= ERR_WARNING
|ERR_WARN_USER
;
2718 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2720 /* Only error out if this is the final pass */
2721 if (pass
!= 2 && i
!= PP_FATAL
)
2722 return DIRECTIVE_FOUND
;
2724 tline
->next
= expand_smacro(tline
->next
);
2725 tline
= tline
->next
;
2727 t
= tline
? tline
->next
: NULL
;
2729 if (tok_type_(tline
, TOK_STRING
) && !t
) {
2730 /* The line contains only a quoted string */
2732 nasm_unquote(p
, NULL
); /* Ignore NUL character truncation */
2733 error(severity
, "%s", p
);
2735 /* Not a quoted string, or more than a quoted string */
2736 p
= detoken(tline
, false);
2737 error(severity
, "%s", p
);
2740 free_tlist(origline
);
2741 return DIRECTIVE_FOUND
;
2745 if (defining
!= NULL
) {
2746 if (defining
->type
== EXP_IF
) {
2747 defining
->def_depth
++;
2749 return NO_DIRECTIVE_FOUND
;
2751 if ((istk
->expansion
!= NULL
) &&
2752 (istk
->expansion
->emitting
== false)) {
2755 j
= if_condition(tline
->next
, i
);
2756 tline
->next
= NULL
; /* it got freed */
2757 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
2759 ed
= new_ExpDef(EXP_IF
);
2765 ed
->ignoring
= ((ed
->state
== COND_IF_TRUE
) ? false : true);
2766 ed
->prev
= defining
;
2768 free_tlist(origline
);
2769 return DIRECTIVE_FOUND
;
2772 if (defining
!= NULL
) {
2773 if ((defining
->type
!= EXP_IF
) || (defining
->def_depth
> 0)) {
2774 return NO_DIRECTIVE_FOUND
;
2777 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2778 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2780 switch (defining
->state
) {
2782 defining
->state
= COND_DONE
;
2783 defining
->ignoring
= true;
2788 defining
->ignoring
= true;
2791 case COND_ELSE_TRUE
:
2792 case COND_ELSE_FALSE
:
2793 error_precond(ERR_WARNING
|ERR_PASS1
,
2794 "`%%elif' after `%%else' ignored");
2795 defining
->state
= COND_NEVER
;
2796 defining
->ignoring
= true;
2801 * IMPORTANT: In the case of %if, we will already have
2802 * called expand_mmac_params(); however, if we're
2803 * processing an %elif we must have been in a
2804 * non-emitting mode, which would have inhibited
2805 * the normal invocation of expand_mmac_params().
2806 * Therefore, we have to do it explicitly here.
2808 j
= if_condition(expand_mmac_params(tline
->next
), i
);
2809 tline
->next
= NULL
; /* it got freed */
2811 j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2812 defining
->ignoring
= ((defining
->state
== COND_IF_TRUE
) ? false : true);
2815 free_tlist(origline
);
2816 return DIRECTIVE_FOUND
;
2819 if (defining
!= NULL
) {
2820 if ((defining
->type
!= EXP_IF
) || (defining
->def_depth
> 0)) {
2821 return NO_DIRECTIVE_FOUND
;
2825 error_precond(ERR_WARNING
|ERR_PASS1
,
2826 "trailing garbage after `%%else' ignored");
2827 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2828 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2830 switch (defining
->state
) {
2833 defining
->state
= COND_ELSE_FALSE
;
2834 defining
->ignoring
= true;
2838 defining
->ignoring
= true;
2842 defining
->state
= COND_ELSE_TRUE
;
2843 defining
->ignoring
= false;
2846 case COND_ELSE_TRUE
:
2847 case COND_ELSE_FALSE
:
2848 error_precond(ERR_WARNING
|ERR_PASS1
,
2849 "`%%else' after `%%else' ignored.");
2850 defining
->state
= COND_NEVER
;
2851 defining
->ignoring
= true;
2854 free_tlist(origline
);
2855 return DIRECTIVE_FOUND
;
2858 if (defining
!= NULL
) {
2859 if (defining
->type
== EXP_IF
) {
2860 if (defining
->def_depth
> 0) {
2861 defining
->def_depth
--;
2862 return NO_DIRECTIVE_FOUND
;
2865 return NO_DIRECTIVE_FOUND
;
2869 error_precond(ERR_WARNING
|ERR_PASS1
,
2870 "trailing garbage after `%%endif' ignored");
2871 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2872 error(ERR_NONFATAL
, "`%%endif': no matching `%%if'");
2873 return DIRECTIVE_FOUND
;
2876 defining
= ed
->prev
;
2877 ed
->prev
= expansions
;
2879 ei
= new_ExpInv(EXP_IF
, ed
);
2880 ei
->current
= ed
->line
;
2881 ei
->emitting
= true;
2882 ei
->prev
= istk
->expansion
;
2883 istk
->expansion
= ei
;
2884 free_tlist(origline
);
2885 return DIRECTIVE_FOUND
;
2891 if (defining
!= NULL
) {
2892 if (defining
->type
== EXP_MMACRO
) {
2893 defining
->def_depth
++;
2895 return NO_DIRECTIVE_FOUND
;
2897 ed
= new_ExpDef(EXP_MMACRO
);
2899 (i
== PP_RMACRO
) || (i
== PP_IRMACRO
) ? DEADMAN_LIMIT
: 0;
2900 ed
->casesense
= (i
== PP_MACRO
) || (i
== PP_RMACRO
);
2901 if (!parse_mmacro_spec(tline
, ed
, pp_directives
[i
])) {
2904 return DIRECTIVE_FOUND
;
2908 ed
->max_depth
= (ed
->max_depth
+ 1);
2909 ed
->ignoring
= false;
2910 ed
->prev
= defining
;
2913 eed
= (ExpDef
*) hash_findix(&expdefs
, ed
->name
);
2915 if (!strcmp(eed
->name
, ed
->name
) &&
2916 (eed
->nparam_min
<= ed
->nparam_max
2918 && (ed
->nparam_min
<= eed
->nparam_max
2920 error(ERR_WARNING
|ERR_PASS1
,
2921 "redefining multi-line macro `%s'", ed
->name
);
2922 return DIRECTIVE_FOUND
;
2926 free_tlist(origline
);
2927 return DIRECTIVE_FOUND
;
2931 if (defining
!= NULL
) {
2932 if (defining
->type
== EXP_MMACRO
) {
2933 if (defining
->def_depth
> 0) {
2934 defining
->def_depth
--;
2935 return NO_DIRECTIVE_FOUND
;
2938 return NO_DIRECTIVE_FOUND
;
2941 if (!(defining
) || (defining
->type
!= EXP_MMACRO
)) {
2942 error(ERR_NONFATAL
, "`%s': not defining a macro", tline
->text
);
2943 return DIRECTIVE_FOUND
;
2945 edhead
= (ExpDef
**) hash_findi_add(&expdefs
, defining
->name
);
2946 defining
->next
= *edhead
;
2949 defining
= ed
->prev
;
2950 ed
->prev
= expansions
;
2953 free_tlist(origline
);
2954 return DIRECTIVE_FOUND
;
2957 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2959 * We must search along istk->expansion until we hit a
2960 * macro invocation. Then we disable the emitting state(s)
2961 * between exitmacro and endmacro.
2963 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
2964 if(ei
->type
== EXP_MMACRO
) {
2971 * Set all invocations leading back to the macro
2972 * invocation to a non-emitting state.
2974 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
2975 eei
->emitting
= false;
2977 eei
->emitting
= false;
2979 error(ERR_NONFATAL
, "`%%exitmacro' not within `%%macro' block");
2981 free_tlist(origline
);
2982 return DIRECTIVE_FOUND
;
2986 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2991 spec
.casesense
= (i
== PP_UNMACRO
);
2992 if (!parse_mmacro_spec(tline
, &spec
, pp_directives
[i
])) {
2993 return DIRECTIVE_FOUND
;
2995 ed_p
= (ExpDef
**) hash_findi(&expdefs
, spec
.name
, NULL
);
2996 while (ed_p
&& *ed_p
) {
2998 if (ed
->casesense
== spec
.casesense
&&
2999 !mstrcmp(ed
->name
, spec
.name
, spec
.casesense
) &&
3000 ed
->nparam_min
== spec
.nparam_min
&&
3001 ed
->nparam_max
== spec
.nparam_max
&&
3002 ed
->plus
== spec
.plus
) {
3009 free_tlist(origline
);
3010 free_tlist(spec
.dlist
);
3011 return DIRECTIVE_FOUND
;
3015 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3016 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
3017 tline
= tline
->next
;
3019 free_tlist(origline
);
3020 error(ERR_NONFATAL
, "`%%rotate' missing rotate count");
3021 return DIRECTIVE_FOUND
;
3023 t
= expand_smacro(tline
->next
);
3025 free_tlist(origline
);
3028 tokval
.t_type
= TOKEN_INVALID
;
3030 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3033 return DIRECTIVE_FOUND
;
3035 error(ERR_WARNING
|ERR_PASS1
,
3036 "trailing garbage after expression ignored");
3037 if (!is_simple(evalresult
)) {
3038 error(ERR_NONFATAL
, "non-constant value given to `%%rotate'");
3039 return DIRECTIVE_FOUND
;
3041 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3042 if (ei
->type
== EXP_MMACRO
) {
3047 error(ERR_NONFATAL
, "`%%rotate' invoked outside a macro call");
3048 } else if (ei
->nparam
== 0) {
3050 "`%%rotate' invoked within macro without parameters");
3052 int rotate
= ei
->rotate
+ reloc_value(evalresult
);
3054 rotate
%= (int)ei
->nparam
;
3056 rotate
+= ei
->nparam
;
3057 ei
->rotate
= rotate
;
3059 return DIRECTIVE_FOUND
;
3062 if (defining
!= NULL
) {
3063 if (defining
->type
== EXP_REP
) {
3064 defining
->def_depth
++;
3066 return NO_DIRECTIVE_FOUND
;
3070 tline
= tline
->next
;
3071 } while (tok_type_(tline
, TOK_WHITESPACE
));
3073 if (tok_type_(tline
, TOK_ID
) &&
3074 nasm_stricmp(tline
->text
, ".nolist") == 0) {
3077 tline
= tline
->next
;
3078 } while (tok_type_(tline
, TOK_WHITESPACE
));
3082 t
= expand_smacro(tline
);
3084 tokval
.t_type
= TOKEN_INVALID
;
3086 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3088 free_tlist(origline
);
3089 return DIRECTIVE_FOUND
;
3092 error(ERR_WARNING
|ERR_PASS1
,
3093 "trailing garbage after expression ignored");
3094 if (!is_simple(evalresult
)) {
3095 error(ERR_NONFATAL
, "non-constant value given to `%%rep'");
3096 return DIRECTIVE_FOUND
;
3098 count
= reloc_value(evalresult
);
3099 if (count
>= REP_LIMIT
) {
3100 error(ERR_NONFATAL
, "`%%rep' value exceeds limit");
3105 error(ERR_NONFATAL
, "`%%rep' expects a repeat count");
3108 free_tlist(origline
);
3109 ed
= new_ExpDef(EXP_REP
);
3110 ed
->nolist
= nolist
;
3113 ed
->max_depth
= (count
- 1);
3114 ed
->ignoring
= false;
3115 ed
->prev
= defining
;
3117 return DIRECTIVE_FOUND
;
3120 if (defining
!= NULL
) {
3121 if (defining
->type
== EXP_REP
) {
3122 if (defining
->def_depth
> 0) {
3123 defining
->def_depth
--;
3124 return NO_DIRECTIVE_FOUND
;
3127 return NO_DIRECTIVE_FOUND
;
3130 if ((defining
== NULL
) || (defining
->type
!= EXP_REP
)) {
3131 error(ERR_NONFATAL
, "`%%endrep': no matching `%%rep'");
3132 return DIRECTIVE_FOUND
;
3136 * Now we have a "macro" defined - although it has no name
3137 * and we won't be entering it in the hash tables - we must
3138 * push a macro-end marker for it on to istk->expansion.
3139 * After that, it will take care of propagating itself (a
3140 * macro-end marker line for a macro which is really a %rep
3141 * block will cause the macro to be re-expanded, complete
3142 * with another macro-end marker to ensure the process
3143 * continues) until the whole expansion is forcibly removed
3144 * from istk->expansion by a %exitrep.
3147 defining
= ed
->prev
;
3148 ed
->prev
= expansions
;
3150 ei
= new_ExpInv(EXP_REP
, ed
);
3151 ei
->current
= ed
->line
;
3152 ei
->emitting
= ((ed
->max_depth
> 0) ? true : false);
3153 list
->uplevel(ed
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
3154 ei
->prev
= istk
->expansion
;
3155 istk
->expansion
= ei
;
3156 free_tlist(origline
);
3157 return DIRECTIVE_FOUND
;
3160 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3162 * We must search along istk->expansion until we hit a
3163 * rep invocation. Then we disable the emitting state(s)
3164 * between exitrep and endrep.
3166 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3167 if (ei
->type
== EXP_REP
) {
3174 * Set all invocations leading back to the rep
3175 * invocation to a non-emitting state.
3177 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3178 eei
->emitting
= false;
3180 eei
->emitting
= false;
3181 eei
->current
= NULL
;
3182 eei
->def
->cur_depth
= eei
->def
->max_depth
;
3184 error(ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
3186 free_tlist(origline
);
3187 return DIRECTIVE_FOUND
;
3193 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3194 casesense
= (i
== PP_DEFINE
|| i
== PP_XDEFINE
);
3196 tline
= tline
->next
;
3198 tline
= expand_id(tline
);
3199 if (!tline
|| (tline
->type
!= TOK_ID
&&
3200 (tline
->type
!= TOK_PREPROC_ID
||
3201 tline
->text
[1] != '$'))) {
3202 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3204 free_tlist(origline
);
3205 return DIRECTIVE_FOUND
;
3208 ctx
= get_ctx(tline
->text
, &mname
, false);
3210 param_start
= tline
= tline
->next
;
3213 /* Expand the macro definition now for %xdefine and %ixdefine */
3214 if ((i
== PP_XDEFINE
) || (i
== PP_IXDEFINE
))
3215 tline
= expand_smacro(tline
);
3217 if (tok_is_(tline
, "(")) {
3219 * This macro has parameters.
3222 tline
= tline
->next
;
3226 error(ERR_NONFATAL
, "parameter identifier expected");
3227 free_tlist(origline
);
3228 return DIRECTIVE_FOUND
;
3230 if (tline
->type
!= TOK_ID
) {
3232 "`%s': parameter identifier expected",
3234 free_tlist(origline
);
3235 return DIRECTIVE_FOUND
;
3237 tline
->type
= TOK_SMAC_PARAM
+ nparam
++;
3238 tline
= tline
->next
;
3240 if (tok_is_(tline
, ",")) {
3241 tline
= tline
->next
;
3243 if (!tok_is_(tline
, ")")) {
3245 "`)' expected to terminate macro template");
3246 free_tlist(origline
);
3247 return DIRECTIVE_FOUND
;
3253 tline
= tline
->next
;
3255 if (tok_type_(tline
, TOK_WHITESPACE
))
3256 last
= tline
, tline
= tline
->next
;
3261 if (t
->type
== TOK_ID
) {
3262 list_for_each(tt
, param_start
)
3263 if (tt
->type
>= TOK_SMAC_PARAM
&&
3264 !strcmp(tt
->text
, t
->text
))
3268 t
->next
= macro_start
;
3273 * Good. We now have a macro name, a parameter count, and a
3274 * token list (in reverse order) for an expansion. We ought
3275 * to be OK just to create an SMacro, store it, and let
3276 * free_tlist have the rest of the line (which we have
3277 * carefully re-terminated after chopping off the expansion
3280 define_smacro(ctx
, mname
, casesense
, nparam
, macro_start
);
3281 free_tlist(origline
);
3282 return DIRECTIVE_FOUND
;
3285 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3286 tline
= tline
->next
;
3288 tline
= expand_id(tline
);
3289 if (!tline
|| (tline
->type
!= TOK_ID
&&
3290 (tline
->type
!= TOK_PREPROC_ID
||
3291 tline
->text
[1] != '$'))) {
3292 error(ERR_NONFATAL
, "`%%undef' expects a macro identifier");
3293 free_tlist(origline
);
3294 return DIRECTIVE_FOUND
;
3297 error(ERR_WARNING
|ERR_PASS1
,
3298 "trailing garbage after macro name ignored");
3301 /* Find the context that symbol belongs to */
3302 ctx
= get_ctx(tline
->text
, &mname
, false);
3303 undef_smacro(ctx
, mname
);
3304 free_tlist(origline
);
3305 return DIRECTIVE_FOUND
;
3309 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3310 casesense
= (i
== PP_DEFSTR
);
3312 tline
= tline
->next
;
3314 tline
= expand_id(tline
);
3315 if (!tline
|| (tline
->type
!= TOK_ID
&&
3316 (tline
->type
!= TOK_PREPROC_ID
||
3317 tline
->text
[1] != '$'))) {
3318 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3320 free_tlist(origline
);
3321 return DIRECTIVE_FOUND
;
3324 ctx
= get_ctx(tline
->text
, &mname
, false);
3326 tline
= expand_smacro(tline
->next
);
3329 while (tok_type_(tline
, TOK_WHITESPACE
))
3330 tline
= delete_Token(tline
);
3332 p
= detoken(tline
, false);
3333 macro_start
= nasm_malloc(sizeof(*macro_start
));
3334 macro_start
->next
= NULL
;
3335 macro_start
->text
= nasm_quote(p
, strlen(p
));
3336 macro_start
->type
= TOK_STRING
;
3337 macro_start
->a
.mac
= NULL
;
3341 * We now have a macro name, an implicit parameter count of
3342 * zero, and a string token to use as an expansion. Create
3343 * and store an SMacro.
3345 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3346 free_tlist(origline
);
3347 return DIRECTIVE_FOUND
;
3351 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3352 casesense
= (i
== PP_DEFTOK
);
3354 tline
= tline
->next
;
3356 tline
= expand_id(tline
);
3357 if (!tline
|| (tline
->type
!= TOK_ID
&&
3358 (tline
->type
!= TOK_PREPROC_ID
||
3359 tline
->text
[1] != '$'))) {
3361 "`%s' expects a macro identifier as first parameter",
3363 free_tlist(origline
);
3364 return DIRECTIVE_FOUND
;
3366 ctx
= get_ctx(tline
->text
, &mname
, false);
3368 tline
= expand_smacro(tline
->next
);
3372 while (tok_type_(t
, TOK_WHITESPACE
))
3374 /* t should now point to the string */
3375 if (!tok_type_(t
, TOK_STRING
)) {
3377 "`%s` requires string as second parameter",
3380 free_tlist(origline
);
3381 return DIRECTIVE_FOUND
;
3385 * Convert the string to a token stream. Note that smacros
3386 * are stored with the token stream reversed, so we have to
3387 * reverse the output of tokenize().
3389 nasm_unquote_cstr(t
->text
, i
);
3390 macro_start
= reverse_tokens(tokenize(t
->text
));
3393 * We now have a macro name, an implicit parameter count of
3394 * zero, and a numeric token to use as an expansion. Create
3395 * and store an SMacro.
3397 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3399 free_tlist(origline
);
3400 return DIRECTIVE_FOUND
;
3403 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3406 StrList
*xsl
= NULL
;
3407 StrList
**xst
= &xsl
;
3411 tline
= tline
->next
;
3413 tline
= expand_id(tline
);
3414 if (!tline
|| (tline
->type
!= TOK_ID
&&
3415 (tline
->type
!= TOK_PREPROC_ID
||
3416 tline
->text
[1] != '$'))) {
3418 "`%%pathsearch' expects a macro identifier as first parameter");
3419 free_tlist(origline
);
3420 return DIRECTIVE_FOUND
;
3422 ctx
= get_ctx(tline
->text
, &mname
, false);
3424 tline
= expand_smacro(tline
->next
);
3428 while (tok_type_(t
, TOK_WHITESPACE
))
3431 if (!t
|| (t
->type
!= TOK_STRING
&&
3432 t
->type
!= TOK_INTERNAL_STRING
)) {
3433 error(ERR_NONFATAL
, "`%%pathsearch' expects a file name");
3435 free_tlist(origline
);
3436 return DIRECTIVE_FOUND
; /* but we did _something_ */
3439 error(ERR_WARNING
|ERR_PASS1
,
3440 "trailing garbage after `%%pathsearch' ignored");
3442 if (t
->type
!= TOK_INTERNAL_STRING
)
3443 nasm_unquote(p
, NULL
);
3445 fp
= inc_fopen(p
, &xsl
, &xst
, true);
3448 fclose(fp
); /* Don't actually care about the file */
3450 macro_start
= nasm_malloc(sizeof(*macro_start
));
3451 macro_start
->next
= NULL
;
3452 macro_start
->text
= nasm_quote(p
, strlen(p
));
3453 macro_start
->type
= TOK_STRING
;
3454 macro_start
->a
.mac
= NULL
;
3459 * We now have a macro name, an implicit parameter count of
3460 * zero, and a string token to use as an expansion. Create
3461 * and store an SMacro.
3463 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3465 free_tlist(origline
);
3466 return DIRECTIVE_FOUND
;
3470 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3473 tline
= tline
->next
;
3475 tline
= expand_id(tline
);
3476 if (!tline
|| (tline
->type
!= TOK_ID
&&
3477 (tline
->type
!= TOK_PREPROC_ID
||
3478 tline
->text
[1] != '$'))) {
3480 "`%%strlen' expects a macro identifier as first parameter");
3481 free_tlist(origline
);
3482 return DIRECTIVE_FOUND
;
3484 ctx
= get_ctx(tline
->text
, &mname
, false);
3486 tline
= expand_smacro(tline
->next
);
3490 while (tok_type_(t
, TOK_WHITESPACE
))
3492 /* t should now point to the string */
3493 if (!tok_type_(t
, TOK_STRING
)) {
3495 "`%%strlen` requires string as second parameter");
3497 free_tlist(origline
);
3498 return DIRECTIVE_FOUND
;
3501 macro_start
= nasm_malloc(sizeof(*macro_start
));
3502 macro_start
->next
= NULL
;
3503 make_tok_num(macro_start
, nasm_unquote(t
->text
, NULL
));
3504 macro_start
->a
.mac
= NULL
;
3507 * We now have a macro name, an implicit parameter count of
3508 * zero, and a numeric token to use as an expansion. Create
3509 * and store an SMacro.
3511 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3513 free_tlist(origline
);
3514 return DIRECTIVE_FOUND
;
3517 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3520 tline
= tline
->next
;
3522 tline
= expand_id(tline
);
3523 if (!tline
|| (tline
->type
!= TOK_ID
&&
3524 (tline
->type
!= TOK_PREPROC_ID
||
3525 tline
->text
[1] != '$'))) {
3527 "`%%strcat' expects a macro identifier as first parameter");
3528 free_tlist(origline
);
3529 return DIRECTIVE_FOUND
;
3531 ctx
= get_ctx(tline
->text
, &mname
, false);
3533 tline
= expand_smacro(tline
->next
);
3537 list_for_each(t
, tline
) {
3539 case TOK_WHITESPACE
:
3542 len
+= t
->a
.len
= nasm_unquote(t
->text
, NULL
);
3545 if (!strcmp(t
->text
, ",")) /* permit comma separators */
3547 /* else fall through */
3550 "non-string passed to `%%strcat' (%d)", t
->type
);
3552 free_tlist(origline
);
3553 return DIRECTIVE_FOUND
;
3557 p
= pp
= nasm_malloc(len
);
3558 list_for_each(t
, tline
) {
3559 if (t
->type
== TOK_STRING
) {
3560 memcpy(p
, t
->text
, t
->a
.len
);
3566 * We now have a macro name, an implicit parameter count of
3567 * zero, and a numeric token to use as an expansion. Create
3568 * and store an SMacro.
3570 macro_start
= new_Token(NULL
, TOK_STRING
, NULL
, 0);
3571 macro_start
->text
= nasm_quote(pp
, len
);
3573 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3575 free_tlist(origline
);
3576 return DIRECTIVE_FOUND
;
3579 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3581 int64_t start
, count
;
3586 tline
= tline
->next
;
3588 tline
= expand_id(tline
);
3589 if (!tline
|| (tline
->type
!= TOK_ID
&&
3590 (tline
->type
!= TOK_PREPROC_ID
||
3591 tline
->text
[1] != '$'))) {
3593 "`%%substr' expects a macro identifier as first parameter");
3594 free_tlist(origline
);
3595 return DIRECTIVE_FOUND
;
3597 ctx
= get_ctx(tline
->text
, &mname
, false);
3599 tline
= expand_smacro(tline
->next
);
3602 if (tline
) /* skip expanded id */
3604 while (tok_type_(t
, TOK_WHITESPACE
))
3607 /* t should now point to the string */
3608 if (!tok_type_(t
, TOK_STRING
)) {
3610 "`%%substr` requires string as second parameter");
3612 free_tlist(origline
);
3613 return DIRECTIVE_FOUND
;
3618 tokval
.t_type
= TOKEN_INVALID
;
3619 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3623 free_tlist(origline
);
3624 return DIRECTIVE_FOUND
;
3625 } else if (!is_simple(evalresult
)) {
3626 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3628 free_tlist(origline
);
3629 return DIRECTIVE_FOUND
;
3631 start
= evalresult
->value
- 1;
3633 while (tok_type_(tt
, TOK_WHITESPACE
))
3636 count
= 1; /* Backwards compatibility: one character */
3638 tokval
.t_type
= TOKEN_INVALID
;
3639 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3643 free_tlist(origline
);
3644 return DIRECTIVE_FOUND
;
3645 } else if (!is_simple(evalresult
)) {
3646 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3648 free_tlist(origline
);
3649 return DIRECTIVE_FOUND
;
3651 count
= evalresult
->value
;
3654 len
= nasm_unquote(t
->text
, NULL
);
3655 /* make start and count being in range */
3659 count
= len
+ count
+ 1 - start
;
3660 if (start
+ count
> (int64_t)len
)
3661 count
= len
- start
;
3662 if (!len
|| count
< 0 || start
>=(int64_t)len
)
3663 start
= -1, count
= 0; /* empty string */
3665 macro_start
= nasm_malloc(sizeof(*macro_start
));
3666 macro_start
->next
= NULL
;
3667 macro_start
->text
= nasm_quote((start
< 0) ? "" : t
->text
+ start
, count
);
3668 macro_start
->type
= TOK_STRING
;
3669 macro_start
->a
.mac
= NULL
;
3672 * We now have a macro name, an implicit parameter count of
3673 * zero, and a numeric token to use as an expansion. Create
3674 * and store an SMacro.
3676 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3678 free_tlist(origline
);
3679 return DIRECTIVE_FOUND
;
3684 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3685 casesense
= (i
== PP_ASSIGN
);
3687 tline
= tline
->next
;
3689 tline
= expand_id(tline
);
3690 if (!tline
|| (tline
->type
!= TOK_ID
&&
3691 (tline
->type
!= TOK_PREPROC_ID
||
3692 tline
->text
[1] != '$'))) {
3694 "`%%%sassign' expects a macro identifier",
3695 (i
== PP_IASSIGN
? "i" : ""));
3696 free_tlist(origline
);
3697 return DIRECTIVE_FOUND
;
3699 ctx
= get_ctx(tline
->text
, &mname
, false);
3701 tline
= expand_smacro(tline
->next
);
3706 tokval
.t_type
= TOKEN_INVALID
;
3708 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3711 free_tlist(origline
);
3712 return DIRECTIVE_FOUND
;
3716 error(ERR_WARNING
|ERR_PASS1
,
3717 "trailing garbage after expression ignored");
3719 if (!is_simple(evalresult
)) {
3721 "non-constant value given to `%%%sassign'",
3722 (i
== PP_IASSIGN
? "i" : ""));
3723 free_tlist(origline
);
3724 return DIRECTIVE_FOUND
;
3727 macro_start
= nasm_malloc(sizeof(*macro_start
));
3728 macro_start
->next
= NULL
;
3729 make_tok_num(macro_start
, reloc_value(evalresult
));
3730 macro_start
->a
.mac
= NULL
;
3733 * We now have a macro name, an implicit parameter count of
3734 * zero, and a numeric token to use as an expansion. Create
3735 * and store an SMacro.
3737 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3738 free_tlist(origline
);
3739 return DIRECTIVE_FOUND
;
3742 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3744 * Syntax is `%line nnn[+mmm] [filename]'
3746 tline
= tline
->next
;
3748 if (!tok_type_(tline
, TOK_NUMBER
)) {
3749 error(ERR_NONFATAL
, "`%%line' expects line number");
3750 free_tlist(origline
);
3751 return DIRECTIVE_FOUND
;
3753 k
= readnum(tline
->text
, &err
);
3755 tline
= tline
->next
;
3756 if (tok_is_(tline
, "+")) {
3757 tline
= tline
->next
;
3758 if (!tok_type_(tline
, TOK_NUMBER
)) {
3759 error(ERR_NONFATAL
, "`%%line' expects line increment");
3760 free_tlist(origline
);
3761 return DIRECTIVE_FOUND
;
3763 m
= readnum(tline
->text
, &err
);
3764 tline
= tline
->next
;
3770 nasm_free(src_set_fname(detoken(tline
, false)));
3772 free_tlist(origline
);
3773 return DIRECTIVE_FOUND
;
3776 if (defining
!= NULL
) {
3777 if (defining
->type
== EXP_WHILE
) {
3778 defining
->def_depth
++;
3780 return NO_DIRECTIVE_FOUND
;
3783 if ((istk
->expansion
!= NULL
) &&
3784 (istk
->expansion
->emitting
== false)) {
3788 l
->first
= copy_Token(tline
->next
);
3789 j
= if_condition(tline
->next
, i
);
3790 tline
->next
= NULL
; /* it got freed */
3791 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
3793 ed
= new_ExpDef(EXP_WHILE
);
3796 ed
->max_depth
= DEADMAN_LIMIT
;
3797 ed
->ignoring
= ((ed
->state
== COND_IF_TRUE
) ? false : true);
3798 if (ed
->ignoring
== false) {
3801 } else if (l
!= NULL
) {
3802 delete_Token(l
->first
);
3806 ed
->prev
= defining
;
3808 free_tlist(origline
);
3809 return DIRECTIVE_FOUND
;
3812 if (defining
!= NULL
) {
3813 if (defining
->type
== EXP_WHILE
) {
3814 if (defining
->def_depth
> 0) {
3815 defining
->def_depth
--;
3816 return NO_DIRECTIVE_FOUND
;
3819 return NO_DIRECTIVE_FOUND
;
3822 if (tline
->next
!= NULL
) {
3823 error_precond(ERR_WARNING
|ERR_PASS1
,
3824 "trailing garbage after `%%endwhile' ignored");
3826 if ((defining
== NULL
) || (defining
->type
!= EXP_WHILE
)) {
3827 error(ERR_NONFATAL
, "`%%endwhile': no matching `%%while'");
3828 return DIRECTIVE_FOUND
;
3831 defining
= ed
->prev
;
3832 if (ed
->ignoring
== false) {
3833 ed
->prev
= expansions
;
3835 ei
= new_ExpInv(EXP_WHILE
, ed
);
3836 ei
->current
= ed
->line
->next
;
3837 ei
->emitting
= true;
3838 ei
->prev
= istk
->expansion
;
3839 istk
->expansion
= ei
;
3843 free_tlist(origline
);
3844 return DIRECTIVE_FOUND
;
3847 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3849 * We must search along istk->expansion until we hit a
3850 * while invocation. Then we disable the emitting state(s)
3851 * between exitwhile and endwhile.
3853 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3854 if (ei
->type
== EXP_WHILE
) {
3861 * Set all invocations leading back to the while
3862 * invocation to a non-emitting state.
3864 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3865 eei
->emitting
= false;
3867 eei
->emitting
= false;
3868 eei
->current
= NULL
;
3869 eei
->def
->cur_depth
= eei
->def
->max_depth
;
3871 error(ERR_NONFATAL
, "`%%exitwhile' not within `%%while' block");
3873 free_tlist(origline
);
3874 return DIRECTIVE_FOUND
;
3877 if (defining
!= NULL
) {
3878 if (defining
->type
== EXP_COMMENT
) {
3879 defining
->def_depth
++;
3881 return NO_DIRECTIVE_FOUND
;
3883 ed
= new_ExpDef(EXP_COMMENT
);
3884 ed
->ignoring
= true;
3885 ed
->prev
= defining
;
3887 free_tlist(origline
);
3888 return DIRECTIVE_FOUND
;
3891 if (defining
!= NULL
) {
3892 if (defining
->type
== EXP_COMMENT
) {
3893 if (defining
->def_depth
> 0) {
3894 defining
->def_depth
--;
3895 return NO_DIRECTIVE_FOUND
;
3898 return NO_DIRECTIVE_FOUND
;
3901 if ((defining
== NULL
) || (defining
->type
!= EXP_COMMENT
)) {
3902 error(ERR_NONFATAL
, "`%%endcomment': no matching `%%comment'");
3903 return DIRECTIVE_FOUND
;
3906 defining
= ed
->prev
;
3908 free_tlist(origline
);
3909 return DIRECTIVE_FOUND
;
3912 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3913 if (in_final
!= false) {
3914 error(ERR_FATAL
, "`%%final' cannot be used recursively");
3916 tline
= tline
->next
;
3918 if (tline
== NULL
) {
3919 error(ERR_NONFATAL
, "`%%final' expects at least one parameter");
3922 l
->first
= copy_Token(tline
);
3926 free_tlist(origline
);
3927 return DIRECTIVE_FOUND
;
3931 "preprocessor directive `%s' not yet implemented",
3933 return DIRECTIVE_FOUND
;
3938 * Ensure that a macro parameter contains a condition code and
3939 * nothing else. Return the condition code index if so, or -1
3942 static int find_cc(Token
* t
)
3948 return -1; /* Probably a %+ without a space */
3951 if (t
->type
!= TOK_ID
)
3955 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
3959 j
= ARRAY_SIZE(conditions
);
3962 m
= nasm_stricmp(t
->text
, conditions
[k
]);
3977 static bool paste_tokens(Token
**head
, const struct tokseq_match
*m
,
3978 int mnum
, bool handle_paste_tokens
)
3980 Token
**tail
, *t
, *tt
;
3982 bool did_paste
= false;
3986 /* Now handle token pasting... */
3989 while ((t
= *tail
) && (tt
= t
->next
)) {
3991 case TOK_WHITESPACE
:
3992 if (tt
->type
== TOK_WHITESPACE
) {
3993 /* Zap adjacent whitespace tokens */
3994 t
->next
= delete_Token(tt
);
3996 /* Do not advance paste_head here */
4000 case TOK_PASTE
: /* %+ */
4001 if (handle_paste_tokens
) {
4002 /* Zap %+ and whitespace tokens to the right */
4003 while (t
&& (t
->type
== TOK_WHITESPACE
||
4004 t
->type
== TOK_PASTE
))
4005 t
= *tail
= delete_Token(t
);
4006 if (!paste_head
|| !t
)
4007 break; /* Nothing to paste with */
4011 while (tok_type_(tt
, TOK_WHITESPACE
))
4012 tt
= t
->next
= delete_Token(tt
);
4014 tmp
= nasm_strcat(t
->text
, tt
->text
);
4016 tt
= delete_Token(tt
);
4017 t
= *tail
= tokenize(tmp
);
4023 t
->next
= tt
; /* Attach the remaining token chain */
4030 /* else fall through */
4033 * Concatenation of tokens might look nontrivial
4034 * but in real it's pretty simple -- the caller
4035 * prepares the masks of token types to be concatenated
4036 * and we simply find matched sequences and slip
4039 for (i
= 0; i
< mnum
; i
++) {
4040 if (PP_CONCAT_MASK(t
->type
) & m
[i
].mask_head
) {
4044 while (tt
&& (PP_CONCAT_MASK(tt
->type
) & m
[i
].mask_tail
)) {
4045 len
+= strlen(tt
->text
);
4050 * Now tt points to the first token after
4051 * the potential paste area...
4053 if (tt
!= t
->next
) {
4054 /* We have at least two tokens... */
4055 len
+= strlen(t
->text
);
4056 p
= tmp
= nasm_malloc(len
+1);
4059 p
= strchr(p
, '\0');
4060 t
= delete_Token(t
);
4062 t
= *tail
= tokenize(tmp
);
4068 t
->next
= tt
; /* Attach the remaining token chain */
4076 if (i
>= mnum
) { /* no match */
4078 if (!tok_type_(t
->next
, TOK_WHITESPACE
))
4088 * expands to a list of tokens from %{x:y}
4090 static Token
*expand_mmac_params_range(ExpInv
*ei
, Token
*tline
, Token
***last
)
4092 Token
*t
= tline
, **tt
, *tm
, *head
;
4096 pos
= strchr(tline
->text
, ':');
4099 lst
= atoi(pos
+ 1);
4100 fst
= atoi(tline
->text
+ 1);
4103 * only macros params are accounted so
4104 * if someone passes %0 -- we reject such
4107 if (lst
== 0 || fst
== 0)
4110 /* the values should be sane */
4111 if ((fst
> (int)ei
->nparam
|| fst
< (-(int)ei
->nparam
)) ||
4112 (lst
> (int)ei
->nparam
|| lst
< (-(int)ei
->nparam
)))
4115 fst
= fst
< 0 ? fst
+ (int)ei
->nparam
+ 1: fst
;
4116 lst
= lst
< 0 ? lst
+ (int)ei
->nparam
+ 1: lst
;
4118 /* counted from zero */
4122 * it will be at least one token
4124 tm
= ei
->params
[(fst
+ ei
->rotate
) % ei
->nparam
];
4125 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4126 head
= t
, tt
= &t
->next
;
4128 for (i
= fst
+ 1; i
<= lst
; i
++) {
4129 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
4130 *tt
= t
, tt
= &t
->next
;
4131 j
= (i
+ ei
->rotate
) % ei
->nparam
;
4133 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4134 *tt
= t
, tt
= &t
->next
;
4137 for (i
= fst
- 1; i
>= lst
; i
--) {
4138 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
4139 *tt
= t
, tt
= &t
->next
;
4140 j
= (i
+ ei
->rotate
) % ei
->nparam
;
4142 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4143 *tt
= t
, tt
= &t
->next
;
4151 error(ERR_NONFATAL
, "`%%{%s}': macro parameters out of range",
4157 * Expand MMacro-local things: parameter references (%0, %n, %+n,
4158 * %-n) and MMacro-local identifiers (%%foo) as well as
4159 * macro indirection (%[...]) and range (%{..:..}).
4161 static Token
*expand_mmac_params(Token
* tline
)
4163 Token
*t
, *tt
, **tail
, *thead
;
4164 bool changed
= false;
4171 if (tline
->type
== TOK_PREPROC_ID
&&
4172 (((tline
->text
[1] == '+' || tline
->text
[1] == '-') && tline
->text
[2]) ||
4173 (tline
->text
[1] >= '0' && tline
->text
[1] <= '9') ||
4174 tline
->text
[1] == '%')) {
4176 int type
= 0, cc
; /* type = 0 to placate optimisers */
4183 tline
= tline
->next
;
4185 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
4186 if (ei
->type
== EXP_MMACRO
) {
4191 error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
4193 pos
= strchr(t
->text
, ':');
4195 switch (t
->text
[1]) {
4197 * We have to make a substitution of one of the
4198 * forms %1, %-1, %+1, %%foo, %0.
4201 if ((strlen(t
->text
) > 2) && (t
->text
[2] == '0')) {
4203 text
= nasm_strdup(ei
->label_text
);
4206 snprintf(tmpbuf
, sizeof(tmpbuf
), "%d", ei
->nparam
);
4207 text
= nasm_strdup(tmpbuf
);
4212 snprintf(tmpbuf
, sizeof(tmpbuf
), "..@%"PRIu64
".",
4214 text
= nasm_strcat(tmpbuf
, t
->text
+ 2);
4217 n
= atoi(t
->text
+ 2) - 1;
4218 if (n
>= ei
->nparam
)
4222 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4228 "macro parameter %d is not a condition code",
4233 if (inverse_ccs
[cc
] == -1) {
4235 "condition code `%s' is not invertible",
4239 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
4243 n
= atoi(t
->text
+ 2) - 1;
4244 if (n
>= ei
->nparam
)
4248 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4254 "macro parameter %d is not a condition code",
4259 text
= nasm_strdup(conditions
[cc
]);
4263 n
= atoi(t
->text
+ 1) - 1;
4264 if (n
>= ei
->nparam
)
4268 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4272 for (i
= 0; i
< ei
->paramlen
[n
]; i
++) {
4273 *tail
= new_Token(NULL
, tt
->type
, tt
->text
, 0);
4274 tail
= &(*tail
)->next
;
4278 text
= NULL
; /* we've done it here */
4283 * seems we have a parameters range here
4285 Token
*head
, **last
;
4286 head
= expand_mmac_params_range(ei
, t
, &last
);
4307 } else if (tline
->type
== TOK_INDIRECT
) {
4309 tline
= tline
->next
;
4310 tt
= tokenize(t
->text
);
4311 tt
= expand_mmac_params(tt
);
4312 tt
= expand_smacro(tt
);
4315 tt
->a
.mac
= NULL
; /* Necessary? */
4323 tline
= tline
->next
;
4331 const struct tokseq_match t
[] = {
4333 PP_CONCAT_MASK(TOK_ID
) |
4334 PP_CONCAT_MASK(TOK_FLOAT
), /* head */
4335 PP_CONCAT_MASK(TOK_ID
) |
4336 PP_CONCAT_MASK(TOK_NUMBER
) |
4337 PP_CONCAT_MASK(TOK_FLOAT
) |
4338 PP_CONCAT_MASK(TOK_OTHER
) /* tail */
4341 PP_CONCAT_MASK(TOK_NUMBER
), /* head */
4342 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4345 paste_tokens(&thead
, t
, ARRAY_SIZE(t
), false);
4352 * Expand all single-line macro calls made in the given line.
4353 * Return the expanded version of the line. The original is deemed
4354 * to be destroyed in the process. (In reality we'll just move
4355 * Tokens from input to output a lot of the time, rather than
4356 * actually bothering to destroy and replicate.)
4359 static Token
*expand_smacro(Token
* tline
)
4361 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
4362 SMacro
*head
= NULL
, *m
;
4365 unsigned int nparam
, sparam
;
4367 Token
*org_tline
= tline
;
4370 int deadman
= DEADMAN_LIMIT
;
4374 * Trick: we should avoid changing the start token pointer since it can
4375 * be contained in "next" field of other token. Because of this
4376 * we allocate a copy of first token and work with it; at the end of
4377 * routine we copy it back
4380 tline
= new_Token(org_tline
->next
, org_tline
->type
,
4381 org_tline
->text
, 0);
4382 tline
->a
.mac
= org_tline
->a
.mac
;
4383 nasm_free(org_tline
->text
);
4384 org_tline
->text
= NULL
;
4387 expanded
= true; /* Always expand %+ at least once */
4393 while (tline
) { /* main token loop */
4395 error(ERR_NONFATAL
, "interminable macro recursion");
4399 if ((mname
= tline
->text
)) {
4400 /* if this token is a local macro, look in local context */
4401 if (tline
->type
== TOK_ID
) {
4402 head
= (SMacro
*)hash_findix(&smacros
, mname
);
4403 } else if (tline
->type
== TOK_PREPROC_ID
) {
4404 ctx
= get_ctx(mname
, &mname
, false);
4405 head
= ctx
? (SMacro
*)hash_findix(&ctx
->localmac
, mname
) : NULL
;
4410 * We've hit an identifier. As in is_mmacro below, we first
4411 * check whether the identifier is a single-line macro at
4412 * all, then think about checking for parameters if
4415 list_for_each(m
, head
)
4416 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
4422 if (m
->nparam
== 0) {
4424 * Simple case: the macro is parameterless. Discard the
4425 * one token that the macro call took, and push the
4426 * expansion back on the to-do stack.
4428 if (!m
->expansion
) {
4429 if (!strcmp("__FILE__", m
->name
)) {
4432 src_get(&num
, &file
);
4433 tline
->text
= nasm_quote(file
, strlen(file
));
4434 tline
->type
= TOK_STRING
;
4438 if (!strcmp("__LINE__", m
->name
)) {
4439 nasm_free(tline
->text
);
4440 make_tok_num(tline
, src_get_linnum());
4443 if (!strcmp("__BITS__", m
->name
)) {
4444 nasm_free(tline
->text
);
4445 make_tok_num(tline
, globalbits
);
4448 tline
= delete_Token(tline
);
4453 * Complicated case: at least one macro with this name
4454 * exists and takes parameters. We must find the
4455 * parameters in the call, count them, find the SMacro
4456 * that corresponds to that form of the macro call, and
4457 * substitute for the parameters when we expand. What a
4460 /*tline = tline->next;
4461 skip_white_(tline); */
4464 while (tok_type_(t
, TOK_SMAC_END
)) {
4465 t
->a
.mac
->in_progress
= false;
4467 t
= tline
->next
= delete_Token(t
);
4470 } while (tok_type_(tline
, TOK_WHITESPACE
));
4471 if (!tok_is_(tline
, "(")) {
4473 * This macro wasn't called with parameters: ignore
4474 * the call. (Behaviour borrowed from gnu cpp.)
4483 sparam
= PARAM_DELTA
;
4484 params
= nasm_malloc(sparam
* sizeof(Token
*));
4485 params
[0] = tline
->next
;
4486 paramsize
= nasm_malloc(sparam
* sizeof(int));
4488 while (true) { /* parameter loop */
4490 * For some unusual expansions
4491 * which concatenates function call
4494 while (tok_type_(t
, TOK_SMAC_END
)) {
4495 t
->a
.mac
->in_progress
= false;
4497 t
= tline
->next
= delete_Token(t
);
4503 "macro call expects terminating `)'");
4506 if (tline
->type
== TOK_WHITESPACE
4508 if (paramsize
[nparam
])
4511 params
[nparam
] = tline
->next
;
4512 continue; /* parameter loop */
4514 if (tline
->type
== TOK_OTHER
4515 && tline
->text
[1] == 0) {
4516 char ch
= tline
->text
[0];
4517 if (ch
== ',' && !paren
&& brackets
<= 0) {
4518 if (++nparam
>= sparam
) {
4519 sparam
+= PARAM_DELTA
;
4520 params
= nasm_realloc(params
,
4521 sparam
* sizeof(Token
*));
4522 paramsize
= nasm_realloc(paramsize
,
4523 sparam
* sizeof(int));
4525 params
[nparam
] = tline
->next
;
4526 paramsize
[nparam
] = 0;
4528 continue; /* parameter loop */
4531 (brackets
> 0 || (brackets
== 0 &&
4532 !paramsize
[nparam
])))
4534 if (!(brackets
++)) {
4535 params
[nparam
] = tline
->next
;
4536 continue; /* parameter loop */
4539 if (ch
== '}' && brackets
> 0)
4540 if (--brackets
== 0) {
4542 continue; /* parameter loop */
4544 if (ch
== '(' && !brackets
)
4546 if (ch
== ')' && brackets
<= 0)
4552 error(ERR_NONFATAL
, "braces do not "
4553 "enclose all of macro parameter");
4555 paramsize
[nparam
] += white
+ 1;
4557 } /* parameter loop */
4559 while (m
&& (m
->nparam
!= nparam
||
4560 mstrcmp(m
->name
, mname
,
4564 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4565 "macro `%s' exists, "
4566 "but not taking %d parameters",
4567 mstart
->text
, nparam
);
4570 if (m
&& m
->in_progress
)
4572 if (!m
) { /* in progess or didn't find '(' or wrong nparam */
4574 * Design question: should we handle !tline, which
4575 * indicates missing ')' here, or expand those
4576 * macros anyway, which requires the (t) test a few
4580 nasm_free(paramsize
);
4584 * Expand the macro: we are placed on the last token of the
4585 * call, so that we can easily split the call from the
4586 * following tokens. We also start by pushing an SMAC_END
4587 * token for the cycle removal.
4594 tt
= new_Token(tline
, TOK_SMAC_END
, NULL
, 0);
4596 m
->in_progress
= true;
4598 list_for_each(t
, m
->expansion
) {
4599 if (t
->type
>= TOK_SMAC_PARAM
) {
4600 Token
*pcopy
= tline
, **ptail
= &pcopy
;
4604 ttt
= params
[t
->type
- TOK_SMAC_PARAM
];
4605 i
= paramsize
[t
->type
- TOK_SMAC_PARAM
];
4607 pt
= *ptail
= new_Token(tline
, ttt
->type
,
4613 } else if (t
->type
== TOK_PREPROC_Q
) {
4614 tt
= new_Token(tline
, TOK_ID
, mname
, 0);
4616 } else if (t
->type
== TOK_PREPROC_QQ
) {
4617 tt
= new_Token(tline
, TOK_ID
, m
->name
, 0);
4620 tt
= new_Token(tline
, t
->type
, t
->text
, 0);
4626 * Having done that, get rid of the macro call, and clean
4627 * up the parameters.
4630 nasm_free(paramsize
);
4633 continue; /* main token loop */
4638 if (tline
->type
== TOK_SMAC_END
) {
4639 tline
->a
.mac
->in_progress
= false;
4640 tline
= delete_Token(tline
);
4643 tline
= tline
->next
;
4651 * Now scan the entire line and look for successive TOK_IDs that resulted
4652 * after expansion (they can't be produced by tokenize()). The successive
4653 * TOK_IDs should be concatenated.
4654 * Also we look for %+ tokens and concatenate the tokens before and after
4655 * them (without white spaces in between).
4658 const struct tokseq_match t
[] = {
4660 PP_CONCAT_MASK(TOK_ID
) |
4661 PP_CONCAT_MASK(TOK_PREPROC_ID
), /* head */
4662 PP_CONCAT_MASK(TOK_ID
) |
4663 PP_CONCAT_MASK(TOK_PREPROC_ID
) |
4664 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4667 if (paste_tokens(&thead
, t
, ARRAY_SIZE(t
), true)) {
4669 * If we concatenated something, *and* we had previously expanded
4670 * an actual macro, scan the lines again for macros...
4681 *org_tline
= *thead
;
4682 /* since we just gave text to org_line, don't free it */
4684 delete_Token(thead
);
4686 /* the expression expanded to empty line;
4687 we can't return NULL for some reasons
4688 we just set the line to a single WHITESPACE token. */
4689 memset(org_tline
, 0, sizeof(*org_tline
));
4690 org_tline
->text
= NULL
;
4691 org_tline
->type
= TOK_WHITESPACE
;
4700 * Similar to expand_smacro but used exclusively with macro identifiers
4701 * right before they are fetched in. The reason is that there can be
4702 * identifiers consisting of several subparts. We consider that if there
4703 * are more than one element forming the name, user wants a expansion,
4704 * otherwise it will be left as-is. Example:
4708 * the identifier %$abc will be left as-is so that the handler for %define
4709 * will suck it and define the corresponding value. Other case:
4711 * %define _%$abc cde
4713 * In this case user wants name to be expanded *before* %define starts
4714 * working, so we'll expand %$abc into something (if it has a value;
4715 * otherwise it will be left as-is) then concatenate all successive
4718 static Token
*expand_id(Token
* tline
)
4720 Token
*cur
, *oldnext
= NULL
;
4722 if (!tline
|| !tline
->next
)
4727 (cur
->next
->type
== TOK_ID
||
4728 cur
->next
->type
== TOK_PREPROC_ID
4729 || cur
->next
->type
== TOK_NUMBER
))
4732 /* If identifier consists of just one token, don't expand */
4737 oldnext
= cur
->next
; /* Detach the tail past identifier */
4738 cur
->next
= NULL
; /* so that expand_smacro stops here */
4741 tline
= expand_smacro(tline
);
4744 /* expand_smacro possibly changhed tline; re-scan for EOL */
4746 while (cur
&& cur
->next
)
4749 cur
->next
= oldnext
;
4756 * Determine whether the given line constitutes a multi-line macro
4757 * call, and return the ExpDef structure called if so. Doesn't have
4758 * to check for an initial label - that's taken care of in
4759 * expand_mmacro - but must check numbers of parameters. Guaranteed
4760 * to be called with tline->type == TOK_ID, so the putative macro
4761 * name is easy to find.
4763 static ExpDef
*is_mmacro(Token
* tline
, Token
*** params_array
)
4769 head
= (ExpDef
*) hash_findix(&expdefs
, tline
->text
);
4772 * Efficiency: first we see if any macro exists with the given
4773 * name. If not, we can return NULL immediately. _Then_ we
4774 * count the parameters, and then we look further along the
4775 * list if necessary to find the proper ExpDef.
4777 list_for_each(ed
, head
)
4778 if (!mstrcmp(ed
->name
, tline
->text
, ed
->casesense
))
4784 * OK, we have a potential macro. Count and demarcate the
4787 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
4790 * So we know how many parameters we've got. Find the ExpDef
4791 * structure that handles this number.
4794 if (ed
->nparam_min
<= nparam
4795 && (ed
->plus
|| nparam
<= ed
->nparam_max
)) {
4797 * It's right, and we can use it. Add its default
4798 * parameters to the end of our list if necessary.
4800 if (ed
->defaults
&& nparam
< ed
->nparam_min
+ ed
->ndefs
) {
4802 nasm_realloc(params
,
4803 ((ed
->nparam_min
+ ed
->ndefs
+
4804 1) * sizeof(*params
)));
4805 while (nparam
< ed
->nparam_min
+ ed
->ndefs
) {
4806 params
[nparam
] = ed
->defaults
[nparam
- ed
->nparam_min
];
4811 * If we've gone over the maximum parameter count (and
4812 * we're in Plus mode), ignore parameters beyond
4815 if (ed
->plus
&& nparam
> ed
->nparam_max
)
4816 nparam
= ed
->nparam_max
;
4818 * Then terminate the parameter list, and leave.
4820 if (!params
) { /* need this special case */
4821 params
= nasm_malloc(sizeof(*params
));
4824 params
[nparam
] = NULL
;
4825 *params_array
= params
;
4829 * This one wasn't right: look for the next one with the
4832 list_for_each(ed
, ed
->next
)
4833 if (!mstrcmp(ed
->name
, tline
->text
, ed
->casesense
))
4838 * After all that, we didn't find one with the right number of
4839 * parameters. Issue a warning, and fail to expand the macro.
4841 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4842 "macro `%s' exists, but not taking %d parameters",
4843 tline
->text
, nparam
);
4849 * Expand the multi-line macro call made by the given line, if
4850 * there is one to be expanded. If there is, push the expansion on
4851 * istk->expansion and return true. Otherwise return false.
4853 static bool expand_mmacro(Token
* tline
)
4855 Token
*label
= NULL
;
4856 int dont_prepend
= 0;
4857 Token
**params
, *t
, *mtok
;
4861 int i
, nparam
, *paramlen
;
4866 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4867 if (!tok_type_(t
, TOK_ID
) && !tok_type_(t
, TOK_PREPROC_ID
))
4870 ed
= is_mmacro(t
, ¶ms
);
4876 * We have an id which isn't a macro call. We'll assume
4877 * it might be a label; we'll also check to see if a
4878 * colon follows it. Then, if there's another id after
4879 * that lot, we'll check it again for macro-hood.
4883 if (tok_type_(t
, TOK_WHITESPACE
))
4884 last
= t
, t
= t
->next
;
4885 if (tok_is_(t
, ":")) {
4887 last
= t
, t
= t
->next
;
4888 if (tok_type_(t
, TOK_WHITESPACE
))
4889 last
= t
, t
= t
->next
;
4891 if (!tok_type_(t
, TOK_ID
) || !(ed
= is_mmacro(t
, ¶ms
)))
4899 * Fix up the parameters: this involves stripping leading and
4900 * trailing whitespace, then stripping braces if they are
4903 for (nparam
= 0; params
[nparam
]; nparam
++) ;
4904 paramlen
= nparam
? nasm_malloc(nparam
* sizeof(*paramlen
)) : NULL
;
4906 for (i
= 0; params
[i
]; i
++) {
4908 int comma
= (!ed
->plus
|| i
< nparam
- 1);
4912 if (tok_is_(t
, "{"))
4913 t
= t
->next
, brace
= true, comma
= false;
4917 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
4918 break; /* ... because we have hit a comma */
4919 if (comma
&& t
->type
== TOK_WHITESPACE
4920 && tok_is_(t
->next
, ","))
4921 break; /* ... or a space then a comma */
4922 if (brace
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "}"))
4923 break; /* ... or a brace */
4929 if (ed
->cur_depth
>= ed
->max_depth
) {
4930 if (ed
->max_depth
> 1) {
4932 "reached maximum macro recursion depth of %i for %s",
4933 ed
->max_depth
,ed
->name
);
4941 * OK, we have found a ExpDef structure representing a
4942 * previously defined mmacro. Create an expansion invocation
4943 * and point it back to the expansion definition. Substitution of
4944 * parameter tokens and macro-local tokens doesn't get done
4945 * until the single-line macro substitution process; this is
4946 * because delaying them allows us to change the semantics
4947 * later through %rotate.
4949 ei
= new_ExpInv(EXP_MMACRO
, ed
);
4950 ei
->name
= nasm_strdup(mname
);
4951 // ei->label = label;
4952 // ei->label_text = detoken(label, false);
4953 ei
->current
= ed
->line
;
4954 ei
->emitting
= true;
4955 // ei->iline = tline;
4956 ei
->params
= params
;
4957 ei
->nparam
= nparam
;
4959 ei
->paramlen
= paramlen
;
4962 ei
->prev
= istk
->expansion
;
4963 istk
->expansion
= ei
;
4966 * Special case: detect %00 on first invocation; if found,
4967 * avoid emitting any labels that precede the mmacro call.
4968 * ed->prepend is set to -1 when %00 is detected, else 1.
4970 if (ed
->prepend
== 0) {
4971 for (l
= ed
->line
; l
!= NULL
; l
= l
->next
) {
4972 for (t
= l
->first
; t
!= NULL
; t
= t
->next
) {
4973 if ((t
->type
== TOK_PREPROC_ID
) &&
4974 (strlen(t
->text
) == 3) &&
4975 (t
->text
[1] == '0') && (t
->text
[2] == '0')) {
4980 if (dont_prepend
< 0) {
4984 ed
->prepend
= ((dont_prepend
< 0) ? -1 : 1);
4988 * If we had a label, push it on as the first line of
4989 * the macro expansion.
4991 if (label
!= NULL
) {
4992 if (ed
->prepend
< 0) {
4993 ei
->label_text
= detoken(label
, false);
4995 if (dont_prepend
== 0) {
4997 while (t
->next
!= NULL
) {
5000 t
->next
= new_Token(NULL
, TOK_OTHER
, ":", 0);
5002 Line
*l
= new_Line();
5003 l
->first
= copy_Token(label
);
5004 l
->next
= ei
->current
;
5009 list
->uplevel(ed
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
5015 /* The function that actually does the error reporting */
5016 static void verror(int severity
, const char *fmt
, va_list arg
)
5020 vsnprintf(buff
, sizeof(buff
), fmt
, arg
);
5022 if ((istk
!= NULL
) && (istk
->mmac_depth
> 0)) {
5023 ExpInv
*ei
= istk
->expansion
;
5024 int lineno
= ei
->lineno
;
5025 while (ei
!= NULL
) {
5026 if (ei
->type
== EXP_MMACRO
) {
5029 lineno
+= ei
->relno
;
5032 nasm_error(severity
, "(%s:%d) %s", ei
->def
->name
,
5035 nasm_error(severity
, "%s", buff
);
5040 * Since preprocessor always operate only on the line that didn't
5041 * arrived yet, we should always use ERR_OFFBY1.
5043 static void error(int severity
, const char *fmt
, ...)
5047 verror(severity
, fmt
, arg
);
5052 * Because %else etc are evaluated in the state context
5053 * of the previous branch, errors might get lost with error():
5054 * %if 0 ... %else trailing garbage ... %endif
5055 * So %else etc should report errors with this function.
5057 static void error_precond(int severity
, const char *fmt
, ...)
5061 /* Only ignore the error if it's really in a dead branch */
5062 if ((istk
!= NULL
) &&
5063 (istk
->expansion
!= NULL
) &&
5064 (istk
->expansion
->type
== EXP_IF
) &&
5065 (istk
->expansion
->def
->state
== COND_NEVER
))
5069 verror(severity
, fmt
, arg
);
5074 pp_reset(char *file
, int apass
, ListGen
* listgen
, StrList
**deplist
)
5079 istk
= nasm_malloc(sizeof(Include
));
5081 istk
->expansion
= NULL
;
5082 istk
->fp
= fopen(file
, "r");
5084 src_set_fname(nasm_strdup(file
));
5087 istk
->mmac_depth
= 0;
5089 error(ERR_FATAL
|ERR_NOFILE
, "unable to open input file `%s'",
5094 nested_mac_count
= 0;
5095 nested_rep_count
= 0;
5098 if (tasm_compatible_mode
) {
5099 stdmacpos
= nasm_stdmac
;
5101 stdmacpos
= nasm_stdmac_after_tasm
;
5103 any_extrastdmac
= extrastdmac
&& *extrastdmac
;
5108 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
5109 * The caller, however, will also pass in 3 for preprocess-only so
5110 * we can set __PASS__ accordingly.
5112 pass
= apass
> 2 ? 2 : apass
;
5114 dephead
= deptail
= deplist
;
5116 StrList
*sl
= nasm_malloc(strlen(file
)+1+sizeof sl
->next
);
5118 strcpy(sl
->str
, file
);
5120 deptail
= &sl
->next
;
5124 * Define the __PASS__ macro. This is defined here unlike
5125 * all the other builtins, because it is special -- it varies between
5128 t
= nasm_malloc(sizeof(*t
));
5130 make_tok_num(t
, apass
);
5132 define_smacro(NULL
, "__PASS__", true, 0, t
);
5135 static char *pp_getline(void)
5143 * Fetch a tokenized line, either from the expansion
5144 * buffer or from the input file.
5148 while (1) { /* until we get a line we can use */
5150 * Fetch a tokenized line from the expansion buffer
5152 if (istk
->expansion
!= NULL
) {
5153 ei
= istk
->expansion
;
5154 if (ei
->current
!= NULL
) {
5155 if (ei
->emitting
== false) {
5161 ei
->current
= l
->next
;
5163 tline
= copy_Token(l
->first
);
5164 if (((ei
->type
== EXP_REP
) ||
5165 (ei
->type
== EXP_MMACRO
) ||
5166 (ei
->type
== EXP_WHILE
))
5167 && (ei
->def
->nolist
== false)) {
5168 char *p
= detoken(tline
, false);
5169 list
->line(LIST_MACRO
, p
);
5172 if (ei
->linnum
> -1) {
5173 src_set_linnum(src_get_linnum() + 1);
5176 } else if ((ei
->type
== EXP_REP
) &&
5177 (ei
->def
->cur_depth
< ei
->def
->max_depth
)) {
5178 ei
->def
->cur_depth
++;
5179 ei
->current
= ei
->def
->line
;
5182 } else if ((ei
->type
== EXP_WHILE
) &&
5183 (ei
->def
->cur_depth
< ei
->def
->max_depth
)) {
5184 ei
->current
= ei
->def
->line
;
5186 tline
= copy_Token(ei
->current
->first
);
5187 int j
= if_condition(tline
, PP_WHILE
);
5189 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
5190 if (j
== COND_IF_TRUE
) {
5191 ei
->current
= ei
->current
->next
;
5192 ei
->def
->cur_depth
++;
5194 ei
->emitting
= false;
5196 ei
->def
->cur_depth
= ei
->def
->max_depth
;
5200 istk
->expansion
= ei
->prev
;
5201 ExpDef
*ed
= ei
->def
;
5203 if ((ei
->emitting
== true) &&
5204 (ed
->max_depth
== DEADMAN_LIMIT
) &&
5205 (ed
->cur_depth
== DEADMAN_LIMIT
)
5207 error(ERR_FATAL
, "runaway expansion detected, aborting");
5209 if (ed
->cur_depth
> 0) {
5211 } else if ((ed
->type
!= EXP_MMACRO
) && (ed
->type
!= EXP_IF
)) {
5212 /***** should this really be right here??? *****/
5214 Line *l = NULL, *ll = NULL;
5215 for (l = ed->line; l != NULL;) {
5216 if (l->first != NULL) {
5217 free_tlist(l->first);
5224 expansions = ed->prev;
5228 if ((ei
->type
== EXP_REP
) ||
5229 (ei
->type
== EXP_MMACRO
) ||
5230 (ei
->type
== EXP_WHILE
)) {
5231 list
->downlevel(LIST_MACRO
);
5232 if (ei
->type
== EXP_MMACRO
) {
5237 if (ei
->linnum
> -1) {
5238 src_set_linnum(ei
->linnum
);
5246 * Read in line from input and tokenize
5249 if (line
) { /* from the current input file */
5250 line
= prepreproc(line
);
5251 tline
= tokenize(line
);
5257 * The current file has ended; work down the istk
5262 if (i
->expansion
!= NULL
) {
5264 "end of file while still in an expansion");
5266 /* only set line and file name if there's a next node */
5268 src_set_linnum(i
->lineno
);
5269 nasm_free(src_set_fname(i
->fname
));
5271 if ((i
->next
== NULL
) && (finals
!= NULL
)) {
5273 ei
= new_ExpInv(EXP_FINAL
, NULL
);
5274 ei
->emitting
= true;
5275 ei
->current
= finals
;
5276 istk
->expansion
= ei
;
5281 list
->downlevel(LIST_INCLUDE
);
5284 if (finals
!= NULL
) {
5294 if (defining
== NULL
) {
5295 tline
= expand_mmac_params(tline
);
5299 * Check the line to see if it's a preprocessor directive.
5301 if (do_directive(tline
) == DIRECTIVE_FOUND
) {
5303 } else if (defining
!= NULL
) {
5305 * We're defining an expansion. We emit nothing at all,
5306 * and just shove the tokenized line on to the definition.
5308 if (defining
->ignoring
== false) {
5309 Line
*l
= new_Line();
5311 if (defining
->line
== NULL
) {
5315 defining
->last
->next
= l
;
5319 //free_tlist(tline); /***** sanity check: is this supposed to be here? *****/
5321 defining
->linecount
++;
5323 } else if ((istk
->expansion
!= NULL
) &&
5324 (istk
->expansion
->emitting
!= true)) {
5326 * We're in a non-emitting branch of an expansion.
5327 * Emit nothing at all, not even a blank line: when we
5328 * emerge from the expansion we'll give a line-number
5329 * directive so we keep our place correctly.
5334 tline
= expand_smacro(tline
);
5335 if (expand_mmacro(tline
) != true) {
5337 * De-tokenize the line again, and emit it.
5339 line
= detoken(tline
, true);
5350 static void pp_cleanup(int pass
)
5352 if (defining
!= NULL
) {
5353 error(ERR_NONFATAL
, "end of file while still defining an expansion");
5354 while (defining
!= NULL
) {
5355 ExpDef
*ed
= defining
;
5356 defining
= ed
->prev
;
5361 while (cstk
!= NULL
)
5364 while (istk
!= NULL
) {
5368 nasm_free(i
->fname
);
5370 while (i
->expansion
!= NULL
) {
5371 ExpInv
*ei
= i
->expansion
;
5372 i
->expansion
= ei
->prev
;
5378 nasm_free(src_set_fname(NULL
));
5383 while ((i
= ipath
)) {
5392 void pp_include_path(char *path
)
5396 i
= nasm_malloc(sizeof(IncPath
));
5397 i
->path
= path
? nasm_strdup(path
) : NULL
;
5410 void pp_pre_include(char *fname
)
5412 Token
*inc
, *space
, *name
;
5415 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
5416 space
= new_Token(name
, TOK_WHITESPACE
, NULL
, 0);
5417 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
5425 void pp_pre_define(char *definition
)
5431 equals
= strchr(definition
, '=');
5432 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5433 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
5436 space
->next
= tokenize(definition
);
5446 void pp_pre_undefine(char *definition
)
5451 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5452 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
5453 space
->next
= tokenize(definition
);
5462 * This function is used to assist with "runtime" preprocessor
5463 * directives, e.g. pp_runtime("%define __BITS__ 64");
5465 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
5466 * PASS A VALID STRING TO THIS FUNCTION!!!!!
5469 void pp_runtime(char *definition
)
5473 def
= tokenize(definition
);
5474 if (do_directive(def
) == NO_DIRECTIVE_FOUND
)
5479 void pp_extra_stdmac(macros_t
*macros
)
5481 extrastdmac
= macros
;
5484 static void make_tok_num(Token
* tok
, int64_t val
)
5487 snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
5488 tok
->text
= nasm_strdup(numbuf
);
5489 tok
->type
= TOK_NUMBER
;