1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2011 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
35 * preproc.c macro preprocessor for the Netwide Assembler
38 /* Typical flow of text through preproc
40 * pp_getline gets tokenized lines, either
42 * from a macro expansion
46 * read_line gets raw text from stdmacpos, or predef, or current input file
47 * tokenize converts to tokens
50 * expand_mmac_params is used to expand %1 etc., unless a macro is being
51 * defined or a false conditional is being processed
52 * (%0, %1, %+1, %-1, %%foo
54 * do_directive checks for directives
56 * expand_smacro is used to expand single line macros
58 * expand_mmacro is used to expand multi-line macros
60 * detoken is used to convert the line back to text
84 typedef struct SMacro SMacro
;
85 typedef struct ExpDef ExpDef
;
86 typedef struct ExpInv ExpInv
;
87 typedef struct Context Context
;
88 typedef struct Token Token
;
89 typedef struct Blocks Blocks
;
90 typedef struct Line Line
;
91 typedef struct Include Include
;
92 typedef struct IncPath IncPath
;
95 * Note on the storage of both SMacro and MMacros: the hash table
96 * indexes them case-insensitively, and we then have to go through a
97 * linked list of potential case aliases (and, for MMacros, parameter
98 * ranges); this is to preserve the matching semantics of the earlier
99 * code. If the number of case aliases for a specific macro is a
100 * performance issue, you may want to reconsider your coding style.
104 * Store the definition of a single-line macro.
116 * The context stack is composed of a linked list of these.
121 struct hash_table localmac
;
126 * This is the internal form which we break input lines up into.
127 * Typically stored in linked lists.
129 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
130 * necessarily used as-is, but is intended to denote the number of
131 * the substituted parameter. So in the definition
133 * %define a(x,y) ( (x) & ~(y) )
135 * the token representing `x' will have its type changed to
136 * TOK_SMAC_PARAM, but the one representing `y' will be
139 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
140 * which doesn't need quotes around it. Used in the pre-include
141 * mechanism as an alternative to trying to find a sensible type of
142 * quote to use on the filename we were passed.
159 TOK_INDIRECT
, /* %[...] */
160 TOK_SMAC_PARAM
, /* MUST BE LAST IN THE LIST!!! */
161 TOK_MAX
= INT_MAX
/* Keep compiler from reducing the range */
164 #define PP_CONCAT_MASK(x) (1 << (x))
166 struct tokseq_match
{
175 SMacro
*mac
; /* associated macro for TOK_SMAC_END */
176 size_t len
; /* scratch length field */
177 } a
; /* Auxiliary data */
178 enum pp_token_type type
;
182 * Expansion definitions are stored as a linked list of
183 * these, which is essentially a container to allow several linked
186 * Note that in this module, linked lists are treated as stacks
187 * wherever possible. For this reason, Lines are _pushed_ on to the
188 * `last' field in ExpDef structures, so that the linked list,
189 * if walked, would emit the expansion lines in the proper order.
208 EXP_MAX
= INT_MAX
/* Keep compiler from reducing the range */
212 * Store the definition of an expansion, in which is any
213 * preprocessor directive that has an ending pair.
215 * This design allows for arbitrary expansion/recursion depth,
216 * upto the DEADMAN_LIMIT.
218 * The `next' field is used for storing ExpDef in hash tables; the
219 * `prev' field is for the global `expansions` linked-list.
222 ExpDef
*prev
; /* previous definition */
223 ExpDef
*next
; /* next in hash table */
224 enum pp_exp_type type
; /* expansion type */
225 char *name
; /* definition name */
229 bool plus
; /* is the last parameter greedy? */
230 bool nolist
; /* is this expansion listing-inhibited? */
231 Token
*dlist
; /* all defaults as one list */
232 Token
**defaults
; /* parameter default pointers */
233 int ndefs
; /* number of default parameters */
235 int prepend
; /* label prepend state */
239 int linecount
; /* number of lines within expansion */
241 int64_t def_depth
; /* current number of definition pairs deep */
242 int64_t cur_depth
; /* current number of expansions */
243 int64_t max_depth
; /* maximum number of expansions allowed */
245 int state
; /* condition state */
246 bool ignoring
; /* ignoring definition lines */
250 * Store the invocation of an expansion.
252 * The `prev' field is for the `istk->expansion` linked-list.
254 * When an expansion is being expanded, `params', `iline', `nparam',
255 * `paramlen', `rotate' and `unique' are local to the invocation.
258 ExpInv
*prev
; /* previous invocation */
259 ExpDef
*def
; /* pointer to expansion definition */
260 char *name
; /* invocation name */
261 Line
*label
; /* pointer to label */
262 char *label_text
; /* pointer to label text */
263 Line
*current
; /* pointer to current line in invocation */
265 Token
**params
; /* actual parameters */
266 Token
*iline
; /* invocation line */
272 int lineno
; /* current line number in expansion */
273 int linnum
; /* line number at invocation */
274 int relno
; /* relative line number at invocation */
275 enum pp_exp_type type
; /* expansion type */
280 * To handle an arbitrary level of file inclusion, we maintain a
281 * stack (ie linked list) of these things.
294 * Include search path. This is simply a list of strings which get
295 * prepended, in turn, to the name of an include file, in an
296 * attempt to find the file if it's not in the current directory.
304 * Conditional assembly: we maintain a separate stack of these for
305 * each level of file inclusion. (The only reason we keep the
306 * stacks separate is to ensure that a stray `%endif' in a file
307 * included from within the true branch of a `%if' won't terminate
308 * it and cause confusion: instead, rightly, it'll cause an error.)
312 * These states are for use just after %if or %elif: IF_TRUE
313 * means the condition has evaluated to truth so we are
314 * currently emitting, whereas IF_FALSE means we are not
315 * currently emitting but will start doing so if a %else comes
316 * up. In these states, all directives are admissible: %elif,
317 * %else and %endif. (And of course %if.)
322 * These states come up after a %else: ELSE_TRUE means we're
323 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
324 * any %elif or %else will cause an error.
329 * These states mean that we're not emitting now, and also that
330 * nothing until %endif will be emitted at all. COND_DONE is
331 * used when we've had our moment of emission
332 * and have now started seeing %elifs. COND_NEVER is used when
333 * the condition construct in question is contained within a
334 * non-emitting branch of a larger condition construct,
335 * or if there is an error.
342 * These defines are used as the possible return values for do_directive
344 #define NO_DIRECTIVE_FOUND 0
345 #define DIRECTIVE_FOUND 1
348 * This define sets the upper limit for smacro and expansions
350 #define DEADMAN_LIMIT (1 << 20)
353 #define REP_LIMIT ((INT64_C(1) << 62))
356 * Condition codes. Note that we use c_ prefix not C_ because C_ is
357 * used in nasm.h for the "real" condition codes. At _this_ level,
358 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
359 * ones, so we need a different enum...
361 static const char * const conditions
[] = {
362 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
363 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
364 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
367 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
368 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
369 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_RCXZ
, c_S
, c_Z
,
372 static const enum pp_conds inverse_ccs
[] = {
373 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
374 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
,
375 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, -1, c_NS
, c_NZ
378 /* For TASM compatibility we need to be able to recognise TASM compatible
379 * conditional compilation directives. Using the NASM pre-processor does
380 * not work, so we look for them specifically from the following list and
381 * then jam in the equivalent NASM directive into the input stream.
385 TM_ARG
, TM_ELIF
, TM_ELSE
, TM_ENDIF
, TM_IF
, TM_IFDEF
, TM_IFDIFI
,
386 TM_IFNDEF
, TM_INCLUDE
, TM_LOCAL
389 static const char * const tasm_directives
[] = {
390 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
391 "ifndef", "include", "local"
394 static int StackSize
= 4;
395 static char *StackPointer
= "ebp";
396 static int ArgOffset
= 8;
397 static int LocalOffset
= 0;
399 static Context
*cstk
;
400 static Include
*istk
;
401 static IncPath
*ipath
;
403 static int pass
; /* HACK: pass 0 = generate dependencies only */
404 static StrList
**dephead
, **deptail
; /* Dependency list */
406 static uint64_t unique
; /* unique identifier numbers */
409 static bool do_predef
;
411 static ListGen
*list
;
414 * The current set of expansion definitions we have defined.
416 static struct hash_table expdefs
;
419 * The current set of single-line macros we have defined.
421 static struct hash_table smacros
;
424 * Linked List of all active expansion definitions
426 struct ExpDef
*expansions
;
429 * The expansion we are currently defining
431 static ExpDef
*defining
;
433 static uint64_t nested_mac_count
;
434 static uint64_t nested_rep_count
;
437 * Linked-list of lines to preprocess, prior to cleanup
440 static bool in_final
= false;
443 * The number of macro parameters to allocate space for at a time.
445 #define PARAM_DELTA 16
448 * The standard macro set: defined in macros.c in the array nasm_stdmac.
449 * This gives our position in the macro set, when we're processing it.
451 static macros_t
*stdmacpos
;
454 * The extra standard macros that come from the object format, if
457 static macros_t
*extrastdmac
;
458 static bool any_extrastdmac
;
461 * Tokens are allocated in blocks to improve speed
463 #define TOKEN_BLOCKSIZE 4096
464 static Token
*freeTokens
;
470 static Blocks blocks
;
473 * Forward declarations.
475 static Token
*expand_mmac_params(Token
* tline
);
476 static Token
*expand_smacro(Token
* tline
);
477 static Token
*expand_id(Token
* tline
);
478 static Context
*get_ctx(const char *name
, const char **namep
);
479 static void make_tok_num(Token
* tok
, int64_t val
);
480 static void error(int severity
, const char *fmt
, ...);
481 static void error_precond(int severity
, const char *fmt
, ...);
482 static void *new_Block(size_t size
);
483 static void delete_Blocks(void);
484 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
485 const char *text
, int txtlen
);
486 static Token
*copy_Token(Token
* tline
);
487 static Token
*delete_Token(Token
* t
);
488 static Line
*new_Line(void);
489 static ExpDef
*new_ExpDef(int exp_type
);
490 static ExpInv
*new_ExpInv(int exp_type
, ExpDef
*ed
);
493 * Macros for safe checking of token pointers, avoid *(NULL)
495 #define tok_type_(x,t) ((x) && (x)->type == (t))
496 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
497 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
498 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
501 * A few helpers for single macros
504 /* We might be not smacro parameter at all */
505 static bool is_smacro_param(Token
*t
)
507 return t
->type
>= TOK_SMAC_PARAM
;
510 /* smacro parameters are counted in a special way */
511 static int smacro_get_param_idx(Token
*t
)
513 return t
->type
- TOK_SMAC_PARAM
;
516 /* encode smacro parameter index */
517 static int smacro_set_param_idx(Token
*t
, unsigned int index
)
519 return t
->type
= TOK_SMAC_PARAM
+ index
;
524 #define stringify(x) #x
526 #define nasm_trace(msg, ...) printf("(%s:%d): " msg "\n", __func__, __LINE__, ##__VA_ARGS__)
527 #define nasm_dump_token(t) nasm_raw_dump_token(t, __FILE__, __LINE__, __func__);
528 #define nasm_dump_stream(t) nasm_raw_dump_stream(t, __FILE__, __LINE__, __func__);
530 /* FIXME: we really need some compound type here instead of inplace code */
531 static const char *nasm_get_tok_type_str(enum pp_token_type type
)
533 #define SWITCH_TOK_NAME(type) \
535 return stringify(type)
538 SWITCH_TOK_NAME(TOK_NONE
);
539 SWITCH_TOK_NAME(TOK_WHITESPACE
);
540 SWITCH_TOK_NAME(TOK_COMMENT
);
541 SWITCH_TOK_NAME(TOK_ID
);
542 SWITCH_TOK_NAME(TOK_PREPROC_ID
);
543 SWITCH_TOK_NAME(TOK_STRING
);
544 SWITCH_TOK_NAME(TOK_NUMBER
);
545 SWITCH_TOK_NAME(TOK_FLOAT
);
546 SWITCH_TOK_NAME(TOK_SMAC_END
);
547 SWITCH_TOK_NAME(TOK_OTHER
);
548 SWITCH_TOK_NAME(TOK_INTERNAL_STRING
);
549 SWITCH_TOK_NAME(TOK_PREPROC_Q
);
550 SWITCH_TOK_NAME(TOK_PREPROC_QQ
);
551 SWITCH_TOK_NAME(TOK_PASTE
);
552 SWITCH_TOK_NAME(TOK_INDIRECT
);
553 SWITCH_TOK_NAME(TOK_SMAC_PARAM
);
554 SWITCH_TOK_NAME(TOK_MAX
);
560 static void nasm_raw_dump_token(Token
*token
, const char *file
, int line
, const char *func
)
562 printf("---[%s (%s:%d): %p]---\n", func
, file
, line
, (void *)token
);
565 list_for_each(t
, token
) {
567 printf("'%s'(%s) ", t
->text
,
568 nasm_get_tok_type_str(t
->type
));
574 static void nasm_raw_dump_stream(Token
*token
, const char *file
, int line
, const char *func
)
576 printf("---[%s (%s:%d): %p]---\n", func
, file
, line
, (void *)token
);
579 list_for_each(t
, token
)
580 printf("%s", t
->text
? t
->text
: " ");
586 #define nasm_trace(msg, ...)
587 #define nasm_dump_token(t)
588 #define nasm_dump_stream(t)
592 * nasm_unquote with error if the string contains NUL characters.
593 * If the string contains NUL characters, issue an error and return
594 * the C len, i.e. truncate at the NUL.
596 static size_t nasm_unquote_cstr(char *qstr
, enum preproc_token directive
)
598 size_t len
= nasm_unquote(qstr
, NULL
);
599 size_t clen
= strlen(qstr
);
602 error(ERR_NONFATAL
, "NUL character in `%s' directive",
603 pp_directives
[directive
]);
609 * In-place reverse a list of tokens.
611 static Token
*reverse_tokens(Token
*t
)
615 list_reverse(t
, prev
, next
);
621 * Handle TASM specific directives, which do not contain a % in
622 * front of them. We do it here because I could not find any other
623 * place to do it for the moment, and it is a hack (ideally it would
624 * be nice to be able to use the NASM pre-processor to do it).
626 static char *check_tasm_directive(char *line
)
628 int32_t i
, j
, k
, m
, len
;
629 char *p
, *q
, *oldline
, oldchar
;
631 p
= nasm_skip_spaces(line
);
633 /* Binary search for the directive name */
635 j
= ARRAY_SIZE(tasm_directives
);
636 q
= nasm_skip_word(p
);
643 m
= nasm_stricmp(p
, tasm_directives
[k
]);
645 /* We have found a directive, so jam a % in front of it
646 * so that NASM will then recognise it as one if it's own.
651 line
= nasm_malloc(len
+ 2);
653 if (k
== TM_IFDIFI
) {
655 * NASM does not recognise IFDIFI, so we convert
656 * it to %if 0. This is not used in NASM
657 * compatible code, but does need to parse for the
658 * TASM macro package.
660 strcpy(line
+ 1, "if 0");
662 memcpy(line
+ 1, p
, len
+ 1);
677 * The pre-preprocessing stage... This function translates line
678 * number indications as they emerge from GNU cpp (`# lineno "file"
679 * flags') into NASM preprocessor line number indications (`%line
682 static char *prepreproc(char *line
)
685 char *fname
, *oldline
;
687 if (line
[0] == '#' && line
[1] == ' ') {
690 lineno
= atoi(fname
);
691 fname
+= strspn(fname
, "0123456789 ");
694 fnlen
= strcspn(fname
, "\"");
695 line
= nasm_malloc(20 + fnlen
);
696 snprintf(line
, 20 + fnlen
, "%%line %d %.*s", lineno
, fnlen
, fname
);
699 if (tasm_compatible_mode
)
700 return check_tasm_directive(line
);
705 * Free a linked list of tokens.
707 static void free_tlist(Token
* list
)
710 list
= delete_Token(list
);
714 * Free a linked list of lines.
716 static void free_llist(Line
* list
)
719 list_for_each_safe(l
, tmp
, list
) {
720 free_tlist(l
->first
);
728 static void free_expdef(ExpDef
* ed
)
731 free_tlist(ed
->dlist
);
732 nasm_free(ed
->defaults
);
733 free_llist(ed
->line
);
740 static void free_expinv(ExpInv
* ei
)
743 nasm_free(ei
->label_text
);
748 * Free all currently defined macros, and free the hash tables
750 static void free_smacro_table(struct hash_table
*smt
)
754 struct hash_tbl_node
*it
= NULL
;
756 while ((s
= hash_iterate(smt
, &it
, &key
)) != NULL
) {
757 nasm_free((void *)key
);
758 list_for_each_safe(s
, tmp
, s
) {
760 free_tlist(s
->expansion
);
767 static void free_expdef_table(struct hash_table
*edt
)
771 struct hash_tbl_node
*it
= NULL
;
774 while ((ed
= hash_iterate(edt
, &it
, &key
)) != NULL
) {
775 nasm_free((void *)key
);
776 list_for_each_safe(ed
,tmp
, ed
)
782 static void free_macros(void)
784 free_smacro_table(&smacros
);
785 free_expdef_table(&expdefs
);
789 * Initialize the hash tables
791 static void init_macros(void)
793 hash_init(&smacros
, HASH_LARGE
);
794 hash_init(&expdefs
, HASH_LARGE
);
798 * Pop the context stack.
800 static void ctx_pop(void)
805 free_smacro_table(&c
->localmac
);
811 * Search for a key in the hash index; adding it if necessary
812 * (in which case we initialize the data pointer to NULL.)
815 hash_findi_add(struct hash_table
*hash
, const char *str
)
817 struct hash_insert hi
;
821 r
= hash_findi(hash
, str
, &hi
);
825 strx
= nasm_strdup(str
); /* Use a more efficient allocator here? */
826 return hash_add(&hi
, strx
, NULL
);
830 * Like hash_findi, but returns the data element rather than a pointer
831 * to it. Used only when not adding a new element, hence no third
835 hash_findix(struct hash_table
*hash
, const char *str
)
839 p
= hash_findi(hash
, str
, NULL
);
840 return p
? *p
: NULL
;
844 * read line from standard macros set,
845 * if there no more left -- return NULL
847 static char *line_from_stdmac(void)
850 const unsigned char *p
= stdmacpos
;
859 len
+= pp_directives_len
[c
- 0x80] + 1;
864 line
= nasm_malloc(len
+ 1);
866 while ((c
= *stdmacpos
++)) {
868 memcpy(q
, pp_directives
[c
- 0x80], pp_directives_len
[c
- 0x80]);
869 q
+= pp_directives_len
[c
- 0x80];
879 /* This was the last of the standard macro chain... */
881 if (any_extrastdmac
) {
882 stdmacpos
= extrastdmac
;
883 any_extrastdmac
= false;
884 } else if (do_predef
) {
887 Token
*head
, **tail
, *t
;
890 * Nasty hack: here we push the contents of
891 * `predef' on to the top-level expansion stack,
892 * since this is the most convenient way to
893 * implement the pre-include and pre-define
896 list_for_each(pd
, predef
) {
899 list_for_each(t
, pd
->first
) {
900 *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
901 tail
= &(*tail
)->next
;
906 ei
= new_ExpInv(EXP_PREDEF
, NULL
);
909 ei
->prev
= istk
->expansion
;
910 istk
->expansion
= ei
;
919 #define BUF_DELTA 512
921 * Read a line from the top file in istk, handling multiple CR/LFs
922 * at the end of the line read, and handling spurious ^Zs. Will
923 * return lines from the standard macro set if this has not already
926 static char *read_line(void)
928 char *buffer
, *p
, *q
;
929 int bufsize
, continued_count
;
932 * standart macros set (predefined) goes first
934 p
= line_from_stdmac();
939 * regular read from a file
942 buffer
= nasm_malloc(BUF_DELTA
);
946 q
= fgets(p
, bufsize
- (p
- buffer
), istk
->fp
);
950 if (p
> buffer
&& p
[-1] == '\n') {
952 * Convert backslash-CRLF line continuation sequences into
953 * nothing at all (for DOS and Windows)
955 if (((p
- 2) > buffer
) && (p
[-3] == '\\') && (p
[-2] == '\r')) {
961 * Also convert backslash-LF line continuation sequences into
962 * nothing at all (for Unix)
964 else if (((p
- 1) > buffer
) && (p
[-2] == '\\')) {
972 if (p
- buffer
> bufsize
- 10) {
973 int32_t offset
= p
- buffer
;
974 bufsize
+= BUF_DELTA
;
975 buffer
= nasm_realloc(buffer
, bufsize
);
976 p
= buffer
+ offset
; /* prevent stale-pointer problems */
980 if (!q
&& p
== buffer
) {
985 src_set_linnum(src_get_linnum() + istk
->lineinc
+
986 (continued_count
* istk
->lineinc
));
989 * Play safe: remove CRs as well as LFs, if any of either are
990 * present at the end of the line.
992 while (--p
>= buffer
&& (*p
== '\n' || *p
== '\r'))
996 * Handle spurious ^Z, which may be inserted into source files
997 * by some file transfer utilities.
999 buffer
[strcspn(buffer
, "\032")] = '\0';
1001 list
->line(LIST_READ
, buffer
);
1007 * Tokenize a line of text. This is a very simple process since we
1008 * don't need to parse the value out of e.g. numeric tokens: we
1009 * simply split one string into many.
1011 static Token
*tokenize(char *line
)
1014 enum pp_token_type type
;
1016 Token
*t
, **tail
= &list
;
1017 bool verbose
= true;
1019 nasm_trace("Tokenize for '%s'", line
);
1021 if ((defining
!= NULL
) && (defining
->ignoring
== true)) {
1029 if (*p
== '+' && !nasm_isdigit(p
[1])) {
1032 } else if (nasm_isdigit(*p
) ||
1033 ((*p
== '-' || *p
== '+') && nasm_isdigit(p
[1]))) {
1037 while (nasm_isdigit(*p
));
1038 type
= TOK_PREPROC_ID
;
1039 } else if (*p
== '{') {
1041 while (*p
&& *p
!= '}') {
1048 type
= TOK_PREPROC_ID
;
1049 } else if (*p
== '[') {
1051 line
+= 2; /* Skip the leading %[ */
1053 while (lvl
&& (c
= *p
++)) {
1065 p
= nasm_skip_string(p
- 1) + 1;
1075 error(ERR_NONFATAL
, "unterminated %[ construct");
1076 type
= TOK_INDIRECT
;
1077 } else if (*p
== '?') {
1078 type
= TOK_PREPROC_Q
; /* %? */
1081 type
= TOK_PREPROC_QQ
; /* %?? */
1084 } else if (*p
== '!') {
1085 type
= TOK_PREPROC_ID
;
1090 } while (isidchar(*p
));
1091 } else if (*p
== '\'' || *p
== '\"' || *p
== '`') {
1092 p
= nasm_skip_string(p
);
1096 error(ERR_NONFATAL
|ERR_PASS1
, "unterminated %! string");
1098 /* %! without string or identifier */
1099 type
= TOK_OTHER
; /* Legacy behavior... */
1101 } else if (isidchar(*p
) ||
1102 ((*p
== '!' || *p
== '%' || *p
== '$') &&
1107 while (isidchar(*p
));
1108 type
= TOK_PREPROC_ID
;
1114 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
1117 while (*p
&& isidchar(*p
))
1119 } else if (*p
== '\'' || *p
== '"' || *p
== '`') {
1124 p
= nasm_skip_string(p
);
1128 } else if(verbose
) {
1129 error(ERR_WARNING
|ERR_PASS1
, "unterminated string");
1130 /* Handling unterminated strings by UNV */
1133 } else if (p
[0] == '$' && p
[1] == '$') {
1134 type
= TOK_OTHER
; /* TOKEN_BASE */
1136 } else if (isnumstart(*p
)) {
1137 bool is_hex
= false;
1138 bool is_float
= false;
1154 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
1156 if (*p
== '+' || *p
== '-') {
1158 * e can only be followed by +/- if it is either a
1159 * prefixed hex number or a floating-point number
1164 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
1166 } else if (c
== 'P' || c
== 'p') {
1168 if (*p
== '+' || *p
== '-')
1170 } else if (isnumchar(c
) || c
== '_')
1171 ; /* just advance */
1172 else if (c
== '.') {
1174 * we need to deal with consequences of the legacy
1175 * parser, like "1.nolist" being two tokens
1176 * (TOK_NUMBER, TOK_ID) here; at least give it
1177 * a shot for now. In the future, we probably need
1178 * a flex-based scanner with proper pattern matching
1179 * to do it as well as it can be done. Nothing in
1180 * the world is going to help the person who wants
1181 * 0x123.p16 interpreted as two tokens, though.
1187 if (nasm_isdigit(*r
) || (is_hex
&& nasm_isxdigit(*r
)) ||
1188 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
1189 (*r
== 'p' || *r
== 'P')) {
1193 break; /* Terminate the token */
1197 p
--; /* Point to first character beyond number */
1199 if (p
== line
+1 && *line
== '$') {
1200 type
= TOK_OTHER
; /* TOKEN_HERE */
1202 if (has_e
&& !is_hex
) {
1203 /* 1e13 is floating-point, but 1e13h is not */
1207 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
1209 } else if (nasm_isspace(*p
)) {
1210 type
= TOK_WHITESPACE
;
1211 p
= nasm_skip_spaces(p
);
1213 * Whitespace just before end-of-line is discarded by
1214 * pretending it's a comment; whitespace just before a
1215 * comment gets lumped into the comment.
1217 if (!*p
|| *p
== ';') {
1222 } else if (*p
== ';') {
1228 * Anything else is an operator of some kind. We check
1229 * for all the double-character operators (>>, <<, //,
1230 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1231 * else is a single-character operator.
1234 if ((p
[0] == '>' && p
[1] == '>') ||
1235 (p
[0] == '<' && p
[1] == '<') ||
1236 (p
[0] == '/' && p
[1] == '/') ||
1237 (p
[0] == '<' && p
[1] == '=') ||
1238 (p
[0] == '>' && p
[1] == '=') ||
1239 (p
[0] == '=' && p
[1] == '=') ||
1240 (p
[0] == '!' && p
[1] == '=') ||
1241 (p
[0] == '<' && p
[1] == '>') ||
1242 (p
[0] == '&' && p
[1] == '&') ||
1243 (p
[0] == '|' && p
[1] == '|') ||
1244 (p
[0] == '^' && p
[1] == '^')) {
1250 /* Handling unterminated string by UNV */
1253 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1254 t->text[p-line] = *line;
1258 if (type
!= TOK_COMMENT
) {
1259 *tail
= t
= new_Token(NULL
, type
, line
, p
- line
);
1265 nasm_dump_token(list
);
1271 * this function allocates a new managed block of memory and
1272 * returns a pointer to the block. The managed blocks are
1273 * deleted only all at once by the delete_Blocks function.
1275 static void *new_Block(size_t size
)
1277 Blocks
*b
= &blocks
;
1279 /* first, get to the end of the linked list */
1283 /* now allocate the requested chunk */
1284 b
->chunk
= nasm_malloc(size
);
1286 /* now allocate a new block for the next request */
1287 b
->next
= nasm_zalloc(sizeof(Blocks
));
1293 * this function deletes all managed blocks of memory
1295 static void delete_Blocks(void)
1297 Blocks
*a
, *b
= &blocks
;
1300 * keep in mind that the first block, pointed to by blocks
1301 * is a static and not dynamically allocated, so we don't
1305 nasm_free(b
->chunk
);
1314 * this function creates a new Token and passes a pointer to it
1315 * back to the caller. It sets the type and text elements, and
1316 * also the a.mac and next elements to NULL.
1318 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
1319 const char *text
, int txtlen
)
1325 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1326 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1327 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1328 freeTokens
[i
].next
= NULL
;
1331 freeTokens
= t
->next
;
1335 if (type
== TOK_WHITESPACE
|| !text
) {
1339 txtlen
= strlen(text
);
1340 t
->text
= nasm_malloc(txtlen
+1);
1341 memcpy(t
->text
, text
, txtlen
);
1342 t
->text
[txtlen
] = '\0';
1347 static Token
*copy_Token(Token
* tline
)
1349 Token
*t
, *tt
, *first
= NULL
, *prev
= NULL
;
1351 for (tt
= tline
; tt
!= NULL
; tt
= tt
->next
) {
1353 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1354 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1355 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1356 freeTokens
[i
].next
= NULL
;
1359 freeTokens
= t
->next
;
1361 t
->text
= tt
->text
? nasm_strdup(tt
->text
) : NULL
;
1362 t
->a
.mac
= tt
->a
.mac
;
1363 t
->a
.len
= tt
->a
.len
;
1375 static Token
*delete_Token(Token
* t
)
1377 Token
*next
= t
->next
;
1379 t
->next
= freeTokens
;
1385 * Convert a line of tokens back into text.
1386 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1387 * will be transformed into ..@ctxnum.xxx
1389 static char *detoken(Token
* tlist
, bool expand_locals
)
1396 list_for_each(t
, tlist
) {
1397 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
1402 if (*v
== '\'' || *v
== '\"' || *v
== '`') {
1403 size_t len
= nasm_unquote(v
, NULL
);
1404 size_t clen
= strlen(v
);
1407 error(ERR_NONFATAL
| ERR_PASS1
,
1408 "NUL character in %! string");
1414 char *p
= getenv(v
);
1416 error(ERR_NONFATAL
| ERR_PASS1
,
1417 "nonexistent environment variable `%s'", v
);
1420 t
->text
= nasm_strdup(p
);
1425 /* Expand local macros here and not during preprocessing */
1426 if (expand_locals
&&
1427 t
->type
== TOK_PREPROC_ID
&& t
->text
&&
1428 t
->text
[0] == '%' && t
->text
[1] == '$') {
1431 Context
*ctx
= get_ctx(t
->text
, &q
);
1434 snprintf(buffer
, sizeof(buffer
), "..@%"PRIu32
".", ctx
->number
);
1435 p
= nasm_strcat(buffer
, q
);
1441 /* Expand %? and %?? directives */
1442 if ((istk
->expansion
!= NULL
) &&
1443 ((t
->type
== TOK_PREPROC_Q
) ||
1444 (t
->type
== TOK_PREPROC_QQ
))) {
1446 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
){
1447 if (ei
->type
== EXP_MMACRO
) {
1449 if (t
->type
== TOK_PREPROC_Q
) {
1450 t
->text
= nasm_strdup(ei
->name
);
1452 t
->text
= nasm_strdup(ei
->def
->name
);
1459 if (t
->type
== TOK_WHITESPACE
)
1462 len
+= strlen(t
->text
);
1465 p
= line
= nasm_malloc(len
+ 1);
1467 list_for_each(t
, tlist
) {
1468 if (t
->type
== TOK_WHITESPACE
) {
1470 } else if (t
->text
) {
1482 * Initialize a new Line
1484 static inline Line
*new_Line(void)
1486 return (Line
*)nasm_zalloc(sizeof(Line
));
1491 * Initialize a new Expansion Definition
1493 static ExpDef
*new_ExpDef(int exp_type
)
1495 ExpDef
*ed
= (ExpDef
*)nasm_zalloc(sizeof(ExpDef
));
1496 ed
->type
= exp_type
;
1497 ed
->casesense
= true;
1498 ed
->state
= COND_NEVER
;
1505 * Initialize a new Expansion Instance
1507 static ExpInv
*new_ExpInv(int exp_type
, ExpDef
*ed
)
1509 ExpInv
*ei
= (ExpInv
*)nasm_zalloc(sizeof(ExpInv
));
1510 ei
->type
= exp_type
;
1512 ei
->unique
= ++unique
;
1514 if ((istk
->mmac_depth
< 1) &&
1515 (istk
->expansion
== NULL
) &&
1517 (ed
->type
!= EXP_MMACRO
) &&
1518 (ed
->type
!= EXP_REP
) &&
1519 (ed
->type
!= EXP_WHILE
)) {
1520 ei
->linnum
= src_get_linnum();
1521 src_set_linnum(ei
->linnum
- ed
->linecount
- 1);
1525 if ((istk
->expansion
== NULL
) ||
1526 (ei
->type
== EXP_MMACRO
)) {
1529 ei
->relno
= istk
->expansion
->lineno
;
1531 ei
->relno
-= (ed
->linecount
+ 1);
1538 * A scanner, suitable for use by the expression evaluator, which
1539 * operates on a line of Tokens. Expects a pointer to a pointer to
1540 * the first token in the line to be passed in as its private_data
1543 * FIX: This really needs to be unified with stdscan.
1545 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1547 Token
**tlineptr
= private_data
;
1549 char ourcopy
[MAX_KEYWORD
+1], *p
, *r
, *s
;
1553 *tlineptr
= tline
? tline
->next
: NULL
;
1554 } while (tline
&& (tline
->type
== TOK_WHITESPACE
||
1555 tline
->type
== TOK_COMMENT
));
1558 return tokval
->t_type
= TOKEN_EOS
;
1560 tokval
->t_charptr
= tline
->text
;
1562 if (tline
->text
[0] == '$' && !tline
->text
[1])
1563 return tokval
->t_type
= TOKEN_HERE
;
1564 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[2])
1565 return tokval
->t_type
= TOKEN_BASE
;
1567 if (tline
->type
== TOK_ID
) {
1568 p
= tokval
->t_charptr
= tline
->text
;
1570 tokval
->t_charptr
++;
1571 return tokval
->t_type
= TOKEN_ID
;
1574 for (r
= p
, s
= ourcopy
; *r
; r
++) {
1575 if (r
>= p
+MAX_KEYWORD
)
1576 return tokval
->t_type
= TOKEN_ID
; /* Not a keyword */
1577 *s
++ = nasm_tolower(*r
);
1580 /* right, so we have an identifier sitting in temp storage. now,
1581 * is it actually a register or instruction name, or what? */
1582 return nasm_token_hash(ourcopy
, tokval
);
1585 if (tline
->type
== TOK_NUMBER
) {
1587 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
1588 tokval
->t_charptr
= tline
->text
;
1590 return tokval
->t_type
= TOKEN_ERRNUM
;
1592 return tokval
->t_type
= TOKEN_NUM
;
1595 if (tline
->type
== TOK_FLOAT
) {
1596 return tokval
->t_type
= TOKEN_FLOAT
;
1599 if (tline
->type
== TOK_STRING
) {
1602 bq
= tline
->text
[0];
1603 tokval
->t_charptr
= tline
->text
;
1604 tokval
->t_inttwo
= nasm_unquote(tline
->text
, &ep
);
1606 if (ep
[0] != bq
|| ep
[1] != '\0')
1607 return tokval
->t_type
= TOKEN_ERRSTR
;
1609 return tokval
->t_type
= TOKEN_STR
;
1612 if (tline
->type
== TOK_OTHER
) {
1613 if (!strcmp(tline
->text
, "<<"))
1614 return tokval
->t_type
= TOKEN_SHL
;
1615 if (!strcmp(tline
->text
, ">>"))
1616 return tokval
->t_type
= TOKEN_SHR
;
1617 if (!strcmp(tline
->text
, "//"))
1618 return tokval
->t_type
= TOKEN_SDIV
;
1619 if (!strcmp(tline
->text
, "%%"))
1620 return tokval
->t_type
= TOKEN_SMOD
;
1621 if (!strcmp(tline
->text
, "=="))
1622 return tokval
->t_type
= TOKEN_EQ
;
1623 if (!strcmp(tline
->text
, "<>"))
1624 return tokval
->t_type
= TOKEN_NE
;
1625 if (!strcmp(tline
->text
, "!="))
1626 return tokval
->t_type
= TOKEN_NE
;
1627 if (!strcmp(tline
->text
, "<="))
1628 return tokval
->t_type
= TOKEN_LE
;
1629 if (!strcmp(tline
->text
, ">="))
1630 return tokval
->t_type
= TOKEN_GE
;
1631 if (!strcmp(tline
->text
, "&&"))
1632 return tokval
->t_type
= TOKEN_DBL_AND
;
1633 if (!strcmp(tline
->text
, "^^"))
1634 return tokval
->t_type
= TOKEN_DBL_XOR
;
1635 if (!strcmp(tline
->text
, "||"))
1636 return tokval
->t_type
= TOKEN_DBL_OR
;
1640 * We have no other options: just return the first character of
1643 return tokval
->t_type
= tline
->text
[0];
1647 * Compare a string to the name of an existing macro; this is a
1648 * simple wrapper which calls either strcmp or nasm_stricmp
1649 * depending on the value of the `casesense' parameter.
1651 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
1653 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
1657 * Compare a string to the name of an existing macro; this is a
1658 * simple wrapper which calls either strcmp or nasm_stricmp
1659 * depending on the value of the `casesense' parameter.
1661 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
1663 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
1667 * Return the Context structure associated with a %$ token. Return
1668 * NULL, having _already_ reported an error condition, if the
1669 * context stack isn't deep enough for the supplied number of $
1672 * If "namep" is non-NULL, set it to the pointer to the macro name
1673 * tail, i.e. the part beyond %$...
1675 static Context
*get_ctx(const char *name
, const char **namep
)
1683 if (!name
|| name
[0] != '%' || name
[1] != '$')
1687 error(ERR_NONFATAL
, "`%s': context stack is empty", name
);
1694 while (ctx
&& *name
== '$') {
1701 error(ERR_NONFATAL
, "`%s': context stack is only"
1702 " %d level%s deep", name
, i
, (i
== 1 ? "" : "s"));
1713 * Check to see if a file is already in a string list
1715 static bool in_list(const StrList
*list
, const char *str
)
1718 if (!strcmp(list
->str
, str
))
1726 * Open an include file. This routine must always return a valid
1727 * file pointer if it returns - it's responsible for throwing an
1728 * ERR_FATAL and bombing out completely if not. It should also try
1729 * the include path one by one until it finds the file or reaches
1730 * the end of the path.
1732 static FILE *inc_fopen(const char *file
, StrList
**dhead
, StrList
***dtail
,
1737 IncPath
*ip
= ipath
;
1738 int len
= strlen(file
);
1739 size_t prefix_len
= 0;
1743 sl
= nasm_malloc(prefix_len
+len
+1+sizeof sl
->next
);
1745 memcpy(sl
->str
, prefix
, prefix_len
);
1746 memcpy(sl
->str
+prefix_len
, file
, len
+1);
1747 fp
= fopen(sl
->str
, "r");
1748 if (fp
&& dhead
&& !in_list(*dhead
, sl
->str
)) {
1765 prefix_len
= strlen(prefix
);
1767 /* -MG given and file not found */
1768 if (dhead
&& !in_list(*dhead
, file
)) {
1769 sl
= nasm_malloc(len
+1+sizeof sl
->next
);
1771 strcpy(sl
->str
, file
);
1779 error(ERR_FATAL
, "unable to open include file `%s'", file
);
1784 * Determine if we should warn on defining a single-line macro of
1785 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1786 * return true if _any_ single-line macro of that name is defined.
1787 * Otherwise, will return true if a single-line macro with either
1788 * `nparam' or no parameters is defined.
1790 * If a macro with precisely the right number of parameters is
1791 * defined, or nparam is -1, the address of the definition structure
1792 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1793 * is NULL, no action will be taken regarding its contents, and no
1796 * Note that this is also called with nparam zero to resolve
1799 * If you already know which context macro belongs to, you can pass
1800 * the context pointer as first parameter; if you won't but name begins
1801 * with %$ the context will be automatically computed. If all_contexts
1802 * is true, macro will be searched in outer contexts as well.
1805 smacro_defined(Context
* ctx
, const char *name
, int nparam
, SMacro
** defn
,
1808 struct hash_table
*smtbl
;
1812 smtbl
= &ctx
->localmac
;
1813 } else if (name
[0] == '%' && name
[1] == '$') {
1815 ctx
= get_ctx(name
, &name
);
1817 return false; /* got to return _something_ */
1818 smtbl
= &ctx
->localmac
;
1822 m
= (SMacro
*) hash_findix(smtbl
, name
);
1825 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
1826 (nparam
<= 0 || m
->nparam
== 0 || nparam
== (int) m
->nparam
)) {
1828 if (nparam
== (int) m
->nparam
|| nparam
== -1)
1842 * Count and mark off the parameters in a multi-line macro call.
1843 * This is called both from within the multi-line macro expansion
1844 * code, and also to mark off the default parameters when provided
1845 * in a %macro definition line.
1847 static void count_mmac_params(Token
* t
, int *nparam
, Token
*** params
)
1849 int paramsize
, brace
;
1851 *nparam
= paramsize
= 0;
1854 /* +1: we need space for the final NULL */
1855 if (*nparam
+1 >= paramsize
) {
1856 paramsize
+= PARAM_DELTA
;
1857 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
1861 if (tok_is_(t
, "{"))
1863 (*params
)[(*nparam
)++] = t
;
1864 while (tok_isnt_(t
, brace
? "}" : ","))
1866 if (t
) { /* got a comma/brace */
1870 * Now we've found the closing brace, look further
1874 if (tok_isnt_(t
, ",")) {
1876 "braces do not enclose all of macro parameter");
1877 while (tok_isnt_(t
, ","))
1881 t
= t
->next
; /* eat the comma */
1888 * Determine whether one of the various `if' conditions is true or
1891 * We must free the tline we get passed.
1893 static bool if_condition(Token
* tline
, enum preproc_token ct
)
1895 enum pp_conditional i
= PP_COND(ct
);
1897 Token
*t
, *tt
, **tptr
, *origline
;
1898 struct tokenval tokval
;
1900 enum pp_token_type needtype
;
1907 j
= false; /* have we matched yet? */
1912 if (tline
->type
!= TOK_ID
) {
1914 "`%s' expects context identifiers", pp_directives
[ct
]);
1915 free_tlist(origline
);
1918 if (cstk
&& cstk
->name
&& !nasm_stricmp(tline
->text
, cstk
->name
))
1920 tline
= tline
->next
;
1925 j
= false; /* have we matched yet? */
1928 if (!tline
|| (tline
->type
!= TOK_ID
&&
1929 (tline
->type
!= TOK_PREPROC_ID
||
1930 tline
->text
[1] != '$'))) {
1932 "`%s' expects macro identifiers", pp_directives
[ct
]);
1935 if (smacro_defined(NULL
, tline
->text
, 0, NULL
, true))
1937 tline
= tline
->next
;
1943 tline
= expand_smacro(tline
);
1944 j
= false; /* have we matched yet? */
1947 if (!tline
|| (tline
->type
!= TOK_ID
&&
1948 tline
->type
!= TOK_STRING
&&
1949 (tline
->type
!= TOK_PREPROC_ID
||
1950 tline
->text
[1] != '!'))) {
1952 "`%s' expects environment variable names",
1957 if (tline
->type
== TOK_PREPROC_ID
)
1958 p
+= 2; /* Skip leading %! */
1959 if (*p
== '\'' || *p
== '\"' || *p
== '`')
1960 nasm_unquote_cstr(p
, ct
);
1963 tline
= tline
->next
;
1970 tline
= expand_smacro(tline
);
1972 while (tok_isnt_(tt
, ","))
1976 "`%s' expects two comma-separated arguments",
1981 j
= true; /* assume equality unless proved not */
1982 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1983 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1984 error(ERR_NONFATAL
, "`%s': more than one comma on line",
1988 if (t
->type
== TOK_WHITESPACE
) {
1992 if (tt
->type
== TOK_WHITESPACE
) {
1996 if (tt
->type
!= t
->type
) {
1997 j
= false; /* found mismatching tokens */
2000 /* When comparing strings, need to unquote them first */
2001 if (t
->type
== TOK_STRING
) {
2002 size_t l1
= nasm_unquote(t
->text
, NULL
);
2003 size_t l2
= nasm_unquote(tt
->text
, NULL
);
2009 if (mmemcmp(t
->text
, tt
->text
, l1
, i
== PPC_IFIDN
)) {
2013 } else if (mstrcmp(tt
->text
, t
->text
, i
== PPC_IFIDN
) != 0) {
2014 j
= false; /* found mismatching tokens */
2021 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
2022 j
= false; /* trailing gunk on one end or other */
2028 ExpDef searching
, *ed
;
2031 tline
= expand_id(tline
);
2032 if (!tok_type_(tline
, TOK_ID
)) {
2034 "`%s' expects a macro name", pp_directives
[ct
]);
2037 memset(&searching
, 0, sizeof(searching
));
2038 searching
.name
= nasm_strdup(tline
->text
);
2039 searching
.casesense
= true;
2040 searching
.nparam_max
= INT_MAX
;
2041 tline
= expand_smacro(tline
->next
);
2044 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2046 "`%s' expects a parameter count or nothing",
2049 searching
.nparam_min
= searching
.nparam_max
=
2050 readnum(tline
->text
, &j
);
2053 "unable to parse parameter count `%s'",
2056 if (tline
&& tok_is_(tline
->next
, "-")) {
2057 tline
= tline
->next
->next
;
2058 if (tok_is_(tline
, "*"))
2059 searching
.nparam_max
= INT_MAX
;
2060 else if (!tok_type_(tline
, TOK_NUMBER
))
2062 "`%s' expects a parameter count after `-'",
2065 searching
.nparam_max
= readnum(tline
->text
, &j
);
2068 "unable to parse parameter count `%s'",
2070 if (searching
.nparam_min
> searching
.nparam_max
)
2072 "minimum parameter count exceeds maximum");
2075 if (tline
&& tok_is_(tline
->next
, "+")) {
2076 tline
= tline
->next
;
2077 searching
.plus
= true;
2079 ed
= (ExpDef
*) hash_findix(&expdefs
, searching
.name
);
2080 while (ed
!= NULL
) {
2081 if (!strcmp(ed
->name
, searching
.name
) &&
2082 (ed
->nparam_min
<= searching
.nparam_max
|| searching
.plus
) &&
2083 (searching
.nparam_min
<= ed
->nparam_max
|| ed
->plus
)) {
2089 if (tline
&& tline
->next
)
2090 error(ERR_WARNING
|ERR_PASS1
,
2091 "trailing garbage after %%ifmacro ignored");
2092 nasm_free(searching
.name
);
2101 needtype
= TOK_NUMBER
;
2104 needtype
= TOK_STRING
;
2108 t
= tline
= expand_smacro(tline
);
2110 while (tok_type_(t
, TOK_WHITESPACE
) ||
2111 (needtype
== TOK_NUMBER
&&
2112 tok_type_(t
, TOK_OTHER
) &&
2113 (t
->text
[0] == '-' || t
->text
[0] == '+') &&
2117 j
= tok_type_(t
, needtype
);
2121 t
= tline
= expand_smacro(tline
);
2122 while (tok_type_(t
, TOK_WHITESPACE
))
2127 t
= t
->next
; /* Skip the actual token */
2128 while (tok_type_(t
, TOK_WHITESPACE
))
2130 j
= !t
; /* Should be nothing left */
2135 t
= tline
= expand_smacro(tline
);
2136 while (tok_type_(t
, TOK_WHITESPACE
))
2139 j
= !t
; /* Should be empty */
2143 t
= tline
= expand_smacro(tline
);
2145 tokval
.t_type
= TOKEN_INVALID
;
2146 evalresult
= evaluate(ppscan
, tptr
, &tokval
,
2147 NULL
, pass
| CRITICAL
, error
, NULL
);
2151 error(ERR_WARNING
|ERR_PASS1
,
2152 "trailing garbage after expression ignored");
2153 if (!is_simple(evalresult
)) {
2155 "non-constant value given to `%s'", pp_directives
[ct
]);
2158 j
= reloc_value(evalresult
) != 0;
2163 "preprocessor directive `%s' not yet implemented",
2168 free_tlist(origline
);
2169 return j
^ PP_NEGATIVE(ct
);
2172 free_tlist(origline
);
2177 * Common code for defining an smacro
2179 static bool define_smacro(Context
*ctx
, const char *mname
, bool casesense
,
2180 int nparam
, Token
*expansion
)
2182 SMacro
*smac
, **smhead
;
2183 struct hash_table
*smtbl
;
2185 if (smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
)) {
2187 error(ERR_WARNING
|ERR_PASS1
,
2188 "single-line macro `%s' defined both with and"
2189 " without parameters", mname
);
2191 * Some instances of the old code considered this a failure,
2192 * some others didn't. What is the right thing to do here?
2194 free_tlist(expansion
);
2195 return false; /* Failure */
2198 * We're redefining, so we have to take over an
2199 * existing SMacro structure. This means freeing
2200 * what was already in it.
2202 nasm_free(smac
->name
);
2203 free_tlist(smac
->expansion
);
2206 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2207 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
2208 smac
= nasm_zalloc(sizeof(SMacro
));
2209 smac
->next
= *smhead
;
2212 smac
->name
= nasm_strdup(mname
);
2213 smac
->casesense
= casesense
;
2214 smac
->nparam
= nparam
;
2215 smac
->expansion
= expansion
;
2216 smac
->in_progress
= false;
2217 return true; /* Success */
2221 * Undefine an smacro
2223 static void undef_smacro(Context
*ctx
, const char *mname
)
2225 SMacro
**smhead
, *s
, **sp
;
2226 struct hash_table
*smtbl
;
2228 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
2229 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
2233 * We now have a macro name... go hunt for it.
2236 while ((s
= *sp
) != NULL
) {
2237 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
2240 free_tlist(s
->expansion
);
2250 * Parse a mmacro specification.
2252 static bool parse_mmacro_spec(Token
*tline
, ExpDef
*def
, const char *directive
)
2256 tline
= tline
->next
;
2258 tline
= expand_id(tline
);
2259 if (!tok_type_(tline
, TOK_ID
)) {
2260 error(ERR_NONFATAL
, "`%s' expects a macro name", directive
);
2264 def
->name
= nasm_strdup(tline
->text
);
2266 def
->nolist
= false;
2267 // def->in_progress = 0;
2268 // def->rep_nest = NULL;
2269 def
->nparam_min
= 0;
2270 def
->nparam_max
= 0;
2272 tline
= expand_smacro(tline
->next
);
2274 if (!tok_type_(tline
, TOK_NUMBER
)) {
2275 error(ERR_NONFATAL
, "`%s' expects a parameter count", directive
);
2277 def
->nparam_min
= def
->nparam_max
=
2278 readnum(tline
->text
, &err
);
2281 "unable to parse parameter count `%s'", tline
->text
);
2283 if (tline
&& tok_is_(tline
->next
, "-")) {
2284 tline
= tline
->next
->next
;
2285 if (tok_is_(tline
, "*")) {
2286 def
->nparam_max
= INT_MAX
;
2287 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
2289 "`%s' expects a parameter count after `-'", directive
);
2291 def
->nparam_max
= readnum(tline
->text
, &err
);
2293 error(ERR_NONFATAL
, "unable to parse parameter count `%s'",
2296 if (def
->nparam_min
> def
->nparam_max
) {
2297 error(ERR_NONFATAL
, "minimum parameter count exceeds maximum");
2301 if (tline
&& tok_is_(tline
->next
, "+")) {
2302 tline
= tline
->next
;
2305 if (tline
&& tok_type_(tline
->next
, TOK_ID
) &&
2306 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
2307 tline
= tline
->next
;
2312 * Handle default parameters.
2314 if (tline
&& tline
->next
) {
2315 def
->dlist
= tline
->next
;
2317 count_mmac_params(def
->dlist
, &def
->ndefs
, &def
->defaults
);
2320 def
->defaults
= NULL
;
2324 if (def
->defaults
&& def
->ndefs
> def
->nparam_max
- def
->nparam_min
&&
2326 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MDP
,
2327 "too many default macro parameters");
2334 * Decode a size directive
2336 static int parse_size(const char *str
) {
2337 static const char *size_names
[] =
2338 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2339 static const int sizes
[] =
2340 { 0, 1, 4, 16, 8, 10, 2, 32 };
2342 return sizes
[bsii(str
, size_names
, ARRAY_SIZE(size_names
))+1];
2346 * find and process preprocessor directive in passed line
2347 * Find out if a line contains a preprocessor directive, and deal
2350 * If a directive _is_ found, it is the responsibility of this routine
2351 * (and not the caller) to free_tlist() the line.
2353 * @param tline a pointer to the current tokeninzed line linked list
2354 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2357 static int do_directive(Token
* tline
)
2359 enum preproc_token i
;
2372 Token
*t
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
2373 struct tokenval tokval
;
2375 ExpDef
*ed
, *eed
, **edhead
;
2384 if (!tline
|| !tok_type_(tline
, TOK_PREPROC_ID
) ||
2385 (tline
->text
[1] == '%' || tline
->text
[1] == '$'
2386 || tline
->text
[1] == '!'))
2387 return NO_DIRECTIVE_FOUND
;
2389 i
= pp_token_hash(tline
->text
);
2393 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2394 error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2396 return NO_DIRECTIVE_FOUND
; /* didn't get it */
2399 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2400 /* Directive to tell NASM what the default stack size is. The
2401 * default is for a 16-bit stack, and this can be overriden with
2404 tline
= tline
->next
;
2405 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2406 tline
= tline
->next
;
2407 if (!tline
|| tline
->type
!= TOK_ID
) {
2408 error(ERR_NONFATAL
, "`%%stacksize' missing size parameter");
2409 free_tlist(origline
);
2410 return DIRECTIVE_FOUND
;
2412 if (nasm_stricmp(tline
->text
, "flat") == 0) {
2413 /* All subsequent ARG directives are for a 32-bit stack */
2415 StackPointer
= "ebp";
2418 } else if (nasm_stricmp(tline
->text
, "flat64") == 0) {
2419 /* All subsequent ARG directives are for a 64-bit stack */
2421 StackPointer
= "rbp";
2424 } else if (nasm_stricmp(tline
->text
, "large") == 0) {
2425 /* All subsequent ARG directives are for a 16-bit stack,
2426 * far function call.
2429 StackPointer
= "bp";
2432 } else if (nasm_stricmp(tline
->text
, "small") == 0) {
2433 /* All subsequent ARG directives are for a 16-bit stack,
2434 * far function call. We don't support near functions.
2437 StackPointer
= "bp";
2441 error(ERR_NONFATAL
, "`%%stacksize' invalid size type");
2442 free_tlist(origline
);
2443 return DIRECTIVE_FOUND
;
2445 free_tlist(origline
);
2446 return DIRECTIVE_FOUND
;
2449 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2450 /* TASM like ARG directive to define arguments to functions, in
2451 * the following form:
2453 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2457 char *arg
, directive
[256];
2458 int size
= StackSize
;
2460 /* Find the argument name */
2461 tline
= tline
->next
;
2462 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2463 tline
= tline
->next
;
2464 if (!tline
|| tline
->type
!= TOK_ID
) {
2465 error(ERR_NONFATAL
, "`%%arg' missing argument parameter");
2466 free_tlist(origline
);
2467 return DIRECTIVE_FOUND
;
2471 /* Find the argument size type */
2472 tline
= tline
->next
;
2473 if (!tline
|| tline
->type
!= TOK_OTHER
2474 || tline
->text
[0] != ':') {
2476 "Syntax error processing `%%arg' directive");
2477 free_tlist(origline
);
2478 return DIRECTIVE_FOUND
;
2480 tline
= tline
->next
;
2481 if (!tline
|| tline
->type
!= TOK_ID
) {
2482 error(ERR_NONFATAL
, "`%%arg' missing size type parameter");
2483 free_tlist(origline
);
2484 return DIRECTIVE_FOUND
;
2487 /* Allow macro expansion of type parameter */
2488 tt
= tokenize(tline
->text
);
2489 tt
= expand_smacro(tt
);
2490 size
= parse_size(tt
->text
);
2493 "Invalid size type for `%%arg' missing directive");
2495 free_tlist(origline
);
2496 return DIRECTIVE_FOUND
;
2500 /* Round up to even stack slots */
2501 size
= ALIGN(size
, StackSize
);
2503 /* Now define the macro for the argument */
2504 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
2505 arg
, StackPointer
, offset
);
2506 do_directive(tokenize(directive
));
2509 /* Move to the next argument in the list */
2510 tline
= tline
->next
;
2511 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2512 tline
= tline
->next
;
2513 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2515 free_tlist(origline
);
2516 return DIRECTIVE_FOUND
;
2519 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2520 /* TASM like LOCAL directive to define local variables for a
2521 * function, in the following form:
2523 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2525 * The '= LocalSize' at the end is ignored by NASM, but is
2526 * required by TASM to define the local parameter size (and used
2527 * by the TASM macro package).
2529 offset
= LocalOffset
;
2531 char *local
, directive
[256];
2532 int size
= StackSize
;
2534 /* Find the argument name */
2535 tline
= tline
->next
;
2536 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2537 tline
= tline
->next
;
2538 if (!tline
|| tline
->type
!= TOK_ID
) {
2540 "`%%local' missing argument parameter");
2541 free_tlist(origline
);
2542 return DIRECTIVE_FOUND
;
2544 local
= tline
->text
;
2546 /* Find the argument size type */
2547 tline
= tline
->next
;
2548 if (!tline
|| tline
->type
!= TOK_OTHER
2549 || tline
->text
[0] != ':') {
2551 "Syntax error processing `%%local' directive");
2552 free_tlist(origline
);
2553 return DIRECTIVE_FOUND
;
2555 tline
= tline
->next
;
2556 if (!tline
|| tline
->type
!= TOK_ID
) {
2558 "`%%local' missing size type parameter");
2559 free_tlist(origline
);
2560 return DIRECTIVE_FOUND
;
2563 /* Allow macro expansion of type parameter */
2564 tt
= tokenize(tline
->text
);
2565 tt
= expand_smacro(tt
);
2566 size
= parse_size(tt
->text
);
2569 "Invalid size type for `%%local' missing directive");
2571 free_tlist(origline
);
2572 return DIRECTIVE_FOUND
;
2576 /* Round up to even stack slots */
2577 size
= ALIGN(size
, StackSize
);
2579 offset
+= size
; /* Negative offset, increment before */
2581 /* Now define the macro for the argument */
2582 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
2583 local
, StackPointer
, offset
);
2584 do_directive(tokenize(directive
));
2586 /* Now define the assign to setup the enter_c macro correctly */
2587 snprintf(directive
, sizeof(directive
),
2588 "%%assign %%$localsize %%$localsize+%d", size
);
2589 do_directive(tokenize(directive
));
2591 /* Move to the next argument in the list */
2592 tline
= tline
->next
;
2593 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2594 tline
= tline
->next
;
2595 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2596 LocalOffset
= offset
;
2597 free_tlist(origline
);
2598 return DIRECTIVE_FOUND
;
2601 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2603 error(ERR_WARNING
|ERR_PASS1
,
2604 "trailing garbage after `%%clear' ignored");
2607 free_tlist(origline
);
2608 return DIRECTIVE_FOUND
;
2611 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2612 t
= tline
->next
= expand_smacro(tline
->next
);
2614 if (!t
|| (t
->type
!= TOK_STRING
&&
2615 t
->type
!= TOK_INTERNAL_STRING
)) {
2616 error(ERR_NONFATAL
, "`%%depend' expects a file name");
2617 free_tlist(origline
);
2618 return DIRECTIVE_FOUND
; /* but we did _something_ */
2621 error(ERR_WARNING
|ERR_PASS1
,
2622 "trailing garbage after `%%depend' ignored");
2624 if (t
->type
!= TOK_INTERNAL_STRING
)
2625 nasm_unquote_cstr(p
, i
);
2626 if (dephead
&& !in_list(*dephead
, p
)) {
2627 StrList
*sl
= nasm_malloc(strlen(p
)+1+sizeof sl
->next
);
2631 deptail
= &sl
->next
;
2633 free_tlist(origline
);
2634 return DIRECTIVE_FOUND
;
2637 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2638 t
= tline
->next
= expand_smacro(tline
->next
);
2641 if (!t
|| (t
->type
!= TOK_STRING
&&
2642 t
->type
!= TOK_INTERNAL_STRING
)) {
2643 error(ERR_NONFATAL
, "`%%include' expects a file name");
2644 free_tlist(origline
);
2645 return DIRECTIVE_FOUND
; /* but we did _something_ */
2648 error(ERR_WARNING
|ERR_PASS1
,
2649 "trailing garbage after `%%include' ignored");
2651 if (t
->type
!= TOK_INTERNAL_STRING
)
2652 nasm_unquote_cstr(p
, i
);
2653 inc
= nasm_zalloc(sizeof(Include
));
2655 inc
->fp
= inc_fopen(p
, dephead
, &deptail
, pass
== 0);
2657 /* -MG given but file not found */
2660 inc
->fname
= src_set_fname(nasm_strdup(p
));
2661 inc
->lineno
= src_set_linnum(0);
2663 inc
->expansion
= NULL
;
2665 list
->uplevel(LIST_INCLUDE
);
2667 free_tlist(origline
);
2668 return DIRECTIVE_FOUND
;
2671 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2673 static macros_t
*use_pkg
;
2674 const char *pkg_macro
= NULL
;
2676 tline
= tline
->next
;
2678 tline
= expand_id(tline
);
2680 if (!tline
|| (tline
->type
!= TOK_STRING
&&
2681 tline
->type
!= TOK_INTERNAL_STRING
&&
2682 tline
->type
!= TOK_ID
)) {
2683 error(ERR_NONFATAL
, "`%%use' expects a package name");
2684 free_tlist(origline
);
2685 return DIRECTIVE_FOUND
; /* but we did _something_ */
2688 error(ERR_WARNING
|ERR_PASS1
,
2689 "trailing garbage after `%%use' ignored");
2690 if (tline
->type
== TOK_STRING
)
2691 nasm_unquote_cstr(tline
->text
, i
);
2692 use_pkg
= nasm_stdmac_find_package(tline
->text
);
2694 error(ERR_NONFATAL
, "unknown `%%use' package: %s", tline
->text
);
2696 pkg_macro
= (char *)use_pkg
+ 1; /* The first string will be <%define>__USE_*__ */
2697 if (use_pkg
&& ! smacro_defined(NULL
, pkg_macro
, 0, NULL
, true)) {
2698 /* Not already included, go ahead and include it */
2699 stdmacpos
= use_pkg
;
2701 free_tlist(origline
);
2702 return DIRECTIVE_FOUND
;
2707 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2708 tline
= tline
->next
;
2710 tline
= expand_id(tline
);
2712 if (!tok_type_(tline
, TOK_ID
)) {
2713 error(ERR_NONFATAL
, "`%s' expects a context identifier",
2715 free_tlist(origline
);
2716 return DIRECTIVE_FOUND
; /* but we did _something_ */
2719 error(ERR_WARNING
|ERR_PASS1
,
2720 "trailing garbage after `%s' ignored",
2722 p
= nasm_strdup(tline
->text
);
2724 p
= NULL
; /* Anonymous */
2728 ctx
= nasm_zalloc(sizeof(Context
));
2730 hash_init(&ctx
->localmac
, HASH_SMALL
);
2732 ctx
->number
= unique
++;
2737 error(ERR_NONFATAL
, "`%s': context stack is empty",
2739 } else if (i
== PP_POP
) {
2740 if (p
&& (!cstk
->name
|| nasm_stricmp(p
, cstk
->name
)))
2741 error(ERR_NONFATAL
, "`%%pop' in wrong context: %s, "
2743 cstk
->name
? cstk
->name
: "anonymous", p
);
2748 nasm_free(cstk
->name
);
2754 free_tlist(origline
);
2755 return DIRECTIVE_FOUND
;
2757 severity
= ERR_FATAL
;
2760 severity
= ERR_NONFATAL
;
2763 severity
= ERR_WARNING
|ERR_WARN_USER
;
2767 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
2769 /* Only error out if this is the final pass */
2770 if (pass
!= 2 && i
!= PP_FATAL
)
2771 return DIRECTIVE_FOUND
;
2773 tline
->next
= expand_smacro(tline
->next
);
2774 tline
= tline
->next
;
2776 t
= tline
? tline
->next
: NULL
;
2778 if (tok_type_(tline
, TOK_STRING
) && !t
) {
2779 /* The line contains only a quoted string */
2781 nasm_unquote(p
, NULL
); /* Ignore NUL character truncation */
2782 error(severity
, "%s", p
);
2784 /* Not a quoted string, or more than a quoted string */
2785 p
= detoken(tline
, false);
2786 error(severity
, "%s", p
);
2789 free_tlist(origline
);
2790 return DIRECTIVE_FOUND
;
2794 if (defining
!= NULL
) {
2795 if (defining
->type
== EXP_IF
) {
2796 defining
->def_depth
++;
2798 return NO_DIRECTIVE_FOUND
;
2800 if ((istk
->expansion
!= NULL
) &&
2801 (istk
->expansion
->emitting
== false)) {
2804 j
= if_condition(tline
->next
, i
);
2805 tline
->next
= NULL
; /* it got freed */
2806 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
2808 ed
= new_ExpDef(EXP_IF
);
2810 ed
->ignoring
= ((ed
->state
== COND_IF_TRUE
) ? false : true);
2811 ed
->prev
= defining
;
2813 free_tlist(origline
);
2814 return DIRECTIVE_FOUND
;
2817 if (defining
!= NULL
) {
2818 if ((defining
->type
!= EXP_IF
) || (defining
->def_depth
> 0)) {
2819 return NO_DIRECTIVE_FOUND
;
2822 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2823 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2825 switch (defining
->state
) {
2827 defining
->state
= COND_DONE
;
2828 defining
->ignoring
= true;
2833 defining
->ignoring
= true;
2836 case COND_ELSE_TRUE
:
2837 case COND_ELSE_FALSE
:
2838 error_precond(ERR_WARNING
|ERR_PASS1
,
2839 "`%%elif' after `%%else' ignored");
2840 defining
->state
= COND_NEVER
;
2841 defining
->ignoring
= true;
2846 * IMPORTANT: In the case of %if, we will already have
2847 * called expand_mmac_params(); however, if we're
2848 * processing an %elif we must have been in a
2849 * non-emitting mode, which would have inhibited
2850 * the normal invocation of expand_mmac_params().
2851 * Therefore, we have to do it explicitly here.
2853 j
= if_condition(expand_mmac_params(tline
->next
), i
);
2854 tline
->next
= NULL
; /* it got freed */
2856 j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2857 defining
->ignoring
= ((defining
->state
== COND_IF_TRUE
) ? false : true);
2860 free_tlist(origline
);
2861 return DIRECTIVE_FOUND
;
2864 if (defining
!= NULL
) {
2865 if ((defining
->type
!= EXP_IF
) || (defining
->def_depth
> 0)) {
2866 return NO_DIRECTIVE_FOUND
;
2870 error_precond(ERR_WARNING
|ERR_PASS1
,
2871 "trailing garbage after `%%else' ignored");
2872 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2873 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2875 switch (defining
->state
) {
2878 defining
->state
= COND_ELSE_FALSE
;
2879 defining
->ignoring
= true;
2883 defining
->ignoring
= true;
2887 defining
->state
= COND_ELSE_TRUE
;
2888 defining
->ignoring
= false;
2891 case COND_ELSE_TRUE
:
2892 case COND_ELSE_FALSE
:
2893 error_precond(ERR_WARNING
|ERR_PASS1
,
2894 "`%%else' after `%%else' ignored.");
2895 defining
->state
= COND_NEVER
;
2896 defining
->ignoring
= true;
2899 free_tlist(origline
);
2900 return DIRECTIVE_FOUND
;
2903 if (defining
!= NULL
) {
2904 if (defining
->type
== EXP_IF
) {
2905 if (defining
->def_depth
> 0) {
2906 defining
->def_depth
--;
2907 return NO_DIRECTIVE_FOUND
;
2910 return NO_DIRECTIVE_FOUND
;
2914 error_precond(ERR_WARNING
|ERR_PASS1
,
2915 "trailing garbage after `%%endif' ignored");
2916 if ((defining
== NULL
) || (defining
->type
!= EXP_IF
)) {
2917 error(ERR_NONFATAL
, "`%%endif': no matching `%%if'");
2918 return DIRECTIVE_FOUND
;
2921 defining
= ed
->prev
;
2922 ed
->prev
= expansions
;
2924 ei
= new_ExpInv(EXP_IF
, ed
);
2925 ei
->current
= ed
->line
;
2926 ei
->emitting
= true;
2927 ei
->prev
= istk
->expansion
;
2928 istk
->expansion
= ei
;
2929 free_tlist(origline
);
2930 return DIRECTIVE_FOUND
;
2936 if (defining
!= NULL
) {
2937 if (defining
->type
== EXP_MMACRO
) {
2938 defining
->def_depth
++;
2940 return NO_DIRECTIVE_FOUND
;
2942 ed
= new_ExpDef(EXP_MMACRO
);
2944 (i
== PP_RMACRO
) || (i
== PP_IRMACRO
) ? DEADMAN_LIMIT
: 0;
2945 ed
->casesense
= (i
== PP_MACRO
) || (i
== PP_RMACRO
);
2946 if (!parse_mmacro_spec(tline
, ed
, pp_directives
[i
])) {
2949 return DIRECTIVE_FOUND
;
2953 ed
->max_depth
= (ed
->max_depth
+ 1);
2954 ed
->ignoring
= false;
2955 ed
->prev
= defining
;
2958 eed
= (ExpDef
*) hash_findix(&expdefs
, ed
->name
);
2960 if (!strcmp(eed
->name
, ed
->name
) &&
2961 (eed
->nparam_min
<= ed
->nparam_max
|| ed
->plus
) &&
2962 (ed
->nparam_min
<= eed
->nparam_max
|| eed
->plus
)) {
2963 error(ERR_WARNING
|ERR_PASS1
,
2964 "redefining multi-line macro `%s'", ed
->name
);
2965 return DIRECTIVE_FOUND
;
2969 free_tlist(origline
);
2970 return DIRECTIVE_FOUND
;
2974 if (defining
!= NULL
) {
2975 if (defining
->type
== EXP_MMACRO
) {
2976 if (defining
->def_depth
> 0) {
2977 defining
->def_depth
--;
2978 return NO_DIRECTIVE_FOUND
;
2981 return NO_DIRECTIVE_FOUND
;
2984 if (!(defining
) || (defining
->type
!= EXP_MMACRO
)) {
2985 error(ERR_NONFATAL
, "`%s': not defining a macro", tline
->text
);
2986 return DIRECTIVE_FOUND
;
2988 edhead
= (ExpDef
**) hash_findi_add(&expdefs
, defining
->name
);
2989 defining
->next
= *edhead
;
2992 defining
= ed
->prev
;
2993 ed
->prev
= expansions
;
2996 free_tlist(origline
);
2997 return DIRECTIVE_FOUND
;
3000 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3002 * We must search along istk->expansion until we hit a
3003 * macro invocation. Then we disable the emitting state(s)
3004 * between exitmacro and endmacro.
3006 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3007 if(ei
->type
== EXP_MMACRO
) {
3014 * Set all invocations leading back to the macro
3015 * invocation to a non-emitting state.
3017 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3018 eei
->emitting
= false;
3020 eei
->emitting
= false;
3022 error(ERR_NONFATAL
, "`%%exitmacro' not within `%%macro' block");
3024 free_tlist(origline
);
3025 return DIRECTIVE_FOUND
;
3029 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3034 spec
.casesense
= (i
== PP_UNMACRO
);
3035 if (!parse_mmacro_spec(tline
, &spec
, pp_directives
[i
])) {
3036 return DIRECTIVE_FOUND
;
3038 ed_p
= (ExpDef
**) hash_findi(&expdefs
, spec
.name
, NULL
);
3039 while (ed_p
&& *ed_p
) {
3041 if (ed
->casesense
== spec
.casesense
&&
3042 !mstrcmp(ed
->name
, spec
.name
, spec
.casesense
) &&
3043 ed
->nparam_min
== spec
.nparam_min
&&
3044 ed
->nparam_max
== spec
.nparam_max
&&
3045 ed
->plus
== spec
.plus
) {
3046 if (ed
->cur_depth
> 0) {
3047 error(ERR_NONFATAL
, "`%s' ignored on active macro",
3058 free_tlist(origline
);
3059 free_tlist(spec
.dlist
);
3060 return DIRECTIVE_FOUND
;
3064 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3065 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
3066 tline
= tline
->next
;
3068 free_tlist(origline
);
3069 error(ERR_NONFATAL
, "`%%rotate' missing rotate count");
3070 return DIRECTIVE_FOUND
;
3072 t
= expand_smacro(tline
->next
);
3074 free_tlist(origline
);
3077 tokval
.t_type
= TOKEN_INVALID
;
3079 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3082 return DIRECTIVE_FOUND
;
3084 error(ERR_WARNING
|ERR_PASS1
,
3085 "trailing garbage after expression ignored");
3086 if (!is_simple(evalresult
)) {
3087 error(ERR_NONFATAL
, "non-constant value given to `%%rotate'");
3088 return DIRECTIVE_FOUND
;
3090 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3091 if (ei
->type
== EXP_MMACRO
) {
3096 error(ERR_NONFATAL
, "`%%rotate' invoked outside a macro call");
3097 } else if (ei
->nparam
== 0) {
3099 "`%%rotate' invoked within macro without parameters");
3101 int rotate
= ei
->rotate
+ reloc_value(evalresult
);
3103 rotate
%= (int)ei
->nparam
;
3105 rotate
+= ei
->nparam
;
3106 ei
->rotate
= rotate
;
3108 return DIRECTIVE_FOUND
;
3111 if (defining
!= NULL
) {
3112 if (defining
->type
== EXP_REP
) {
3113 defining
->def_depth
++;
3115 return NO_DIRECTIVE_FOUND
;
3119 tline
= tline
->next
;
3120 } while (tok_type_(tline
, TOK_WHITESPACE
));
3122 if (tok_type_(tline
, TOK_ID
) &&
3123 nasm_stricmp(tline
->text
, ".nolist") == 0) {
3126 tline
= tline
->next
;
3127 } while (tok_type_(tline
, TOK_WHITESPACE
));
3131 t
= expand_smacro(tline
);
3133 tokval
.t_type
= TOKEN_INVALID
;
3135 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3137 free_tlist(origline
);
3138 return DIRECTIVE_FOUND
;
3141 error(ERR_WARNING
|ERR_PASS1
,
3142 "trailing garbage after expression ignored");
3143 if (!is_simple(evalresult
)) {
3144 error(ERR_NONFATAL
, "non-constant value given to `%%rep'");
3145 return DIRECTIVE_FOUND
;
3147 count
= reloc_value(evalresult
);
3148 if (count
>= REP_LIMIT
) {
3149 error(ERR_NONFATAL
, "`%%rep' value exceeds limit");
3154 error(ERR_NONFATAL
, "`%%rep' expects a repeat count");
3157 free_tlist(origline
);
3158 ed
= new_ExpDef(EXP_REP
);
3159 ed
->nolist
= nolist
;
3162 ed
->max_depth
= (count
- 1);
3163 ed
->ignoring
= false;
3164 ed
->prev
= defining
;
3166 return DIRECTIVE_FOUND
;
3169 if (defining
!= NULL
) {
3170 if (defining
->type
== EXP_REP
) {
3171 if (defining
->def_depth
> 0) {
3172 defining
->def_depth
--;
3173 return NO_DIRECTIVE_FOUND
;
3176 return NO_DIRECTIVE_FOUND
;
3179 if ((defining
== NULL
) || (defining
->type
!= EXP_REP
)) {
3180 error(ERR_NONFATAL
, "`%%endrep': no matching `%%rep'");
3181 return DIRECTIVE_FOUND
;
3185 * Now we have a "macro" defined - although it has no name
3186 * and we won't be entering it in the hash tables - we must
3187 * push a macro-end marker for it on to istk->expansion.
3188 * After that, it will take care of propagating itself (a
3189 * macro-end marker line for a macro which is really a %rep
3190 * block will cause the macro to be re-expanded, complete
3191 * with another macro-end marker to ensure the process
3192 * continues) until the whole expansion is forcibly removed
3193 * from istk->expansion by a %exitrep.
3196 defining
= ed
->prev
;
3197 ed
->prev
= expansions
;
3199 ei
= new_ExpInv(EXP_REP
, ed
);
3200 ei
->current
= ed
->line
;
3201 ei
->emitting
= ((ed
->max_depth
> 0) ? true : false);
3202 list
->uplevel(ed
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
3203 ei
->prev
= istk
->expansion
;
3204 istk
->expansion
= ei
;
3205 free_tlist(origline
);
3206 return DIRECTIVE_FOUND
;
3209 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3211 * We must search along istk->expansion until we hit a
3212 * rep invocation. Then we disable the emitting state(s)
3213 * between exitrep and endrep.
3215 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3216 if (ei
->type
== EXP_REP
) {
3223 * Set all invocations leading back to the rep
3224 * invocation to a non-emitting state.
3226 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3227 eei
->emitting
= false;
3229 eei
->emitting
= false;
3230 eei
->current
= NULL
;
3231 eei
->def
->cur_depth
= eei
->def
->max_depth
;
3233 error(ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
3235 free_tlist(origline
);
3236 return DIRECTIVE_FOUND
;
3242 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3243 casesense
= (i
== PP_DEFINE
|| i
== PP_XDEFINE
);
3245 tline
= tline
->next
;
3247 tline
= expand_id(tline
);
3248 if (!tline
|| (tline
->type
!= TOK_ID
&&
3249 (tline
->type
!= TOK_PREPROC_ID
||
3250 tline
->text
[1] != '$'))) {
3251 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3253 free_tlist(origline
);
3254 return DIRECTIVE_FOUND
;
3257 ctx
= get_ctx(tline
->text
, &mname
);
3259 param_start
= tline
= tline
->next
;
3262 /* Expand the macro definition now for %xdefine and %ixdefine */
3263 if ((i
== PP_XDEFINE
) || (i
== PP_IXDEFINE
))
3264 tline
= expand_smacro(tline
);
3266 if (tok_is_(tline
, "(")) {
3268 * This macro has parameters.
3271 tline
= tline
->next
;
3275 error(ERR_NONFATAL
, "parameter identifier expected");
3276 free_tlist(origline
);
3277 return DIRECTIVE_FOUND
;
3279 if (tline
->type
!= TOK_ID
) {
3281 "`%s': parameter identifier expected",
3283 free_tlist(origline
);
3284 return DIRECTIVE_FOUND
;
3287 smacro_set_param_idx(tline
, nparam
);
3290 tline
= tline
->next
;
3292 if (tok_is_(tline
, ",")) {
3293 tline
= tline
->next
;
3295 if (!tok_is_(tline
, ")")) {
3297 "`)' expected to terminate macro template");
3298 free_tlist(origline
);
3299 return DIRECTIVE_FOUND
;
3305 tline
= tline
->next
;
3307 if (tok_type_(tline
, TOK_WHITESPACE
))
3308 last
= tline
, tline
= tline
->next
;
3313 if (t
->type
== TOK_ID
) {
3314 list_for_each(tt
, param_start
)
3315 if (is_smacro_param(tt
) &&
3316 !strcmp(tt
->text
, t
->text
))
3320 t
->next
= macro_start
;
3325 * Good. We now have a macro name, a parameter count, and a
3326 * token list (in reverse order) for an expansion. We ought
3327 * to be OK just to create an SMacro, store it, and let
3328 * free_tlist have the rest of the line (which we have
3329 * carefully re-terminated after chopping off the expansion
3332 define_smacro(ctx
, mname
, casesense
, nparam
, macro_start
);
3333 free_tlist(origline
);
3334 return DIRECTIVE_FOUND
;
3337 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3338 tline
= tline
->next
;
3340 tline
= expand_id(tline
);
3341 if (!tline
|| (tline
->type
!= TOK_ID
&&
3342 (tline
->type
!= TOK_PREPROC_ID
||
3343 tline
->text
[1] != '$'))) {
3344 error(ERR_NONFATAL
, "`%%undef' expects a macro identifier");
3345 free_tlist(origline
);
3346 return DIRECTIVE_FOUND
;
3349 error(ERR_WARNING
|ERR_PASS1
,
3350 "trailing garbage after macro name ignored");
3353 /* Find the context that symbol belongs to */
3354 ctx
= get_ctx(tline
->text
, &mname
);
3355 undef_smacro(ctx
, mname
);
3356 free_tlist(origline
);
3357 return DIRECTIVE_FOUND
;
3361 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3362 casesense
= (i
== PP_DEFSTR
);
3364 tline
= tline
->next
;
3366 tline
= expand_id(tline
);
3367 if (!tline
|| (tline
->type
!= TOK_ID
&&
3368 (tline
->type
!= TOK_PREPROC_ID
||
3369 tline
->text
[1] != '$'))) {
3370 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
3372 free_tlist(origline
);
3373 return DIRECTIVE_FOUND
;
3376 ctx
= get_ctx(tline
->text
, &mname
);
3378 tline
= expand_smacro(tline
->next
);
3381 while (tok_type_(tline
, TOK_WHITESPACE
))
3382 tline
= delete_Token(tline
);
3384 p
= detoken(tline
, false);
3385 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3386 macro_start
->text
= nasm_quote(p
, strlen(p
));
3387 macro_start
->type
= TOK_STRING
;
3391 * We now have a macro name, an implicit parameter count of
3392 * zero, and a string token to use as an expansion. Create
3393 * and store an SMacro.
3395 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3396 free_tlist(origline
);
3397 return DIRECTIVE_FOUND
;
3401 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3402 casesense
= (i
== PP_DEFTOK
);
3404 tline
= tline
->next
;
3406 tline
= expand_id(tline
);
3407 if (!tline
|| (tline
->type
!= TOK_ID
&&
3408 (tline
->type
!= TOK_PREPROC_ID
||
3409 tline
->text
[1] != '$'))) {
3411 "`%s' expects a macro identifier as first parameter",
3413 free_tlist(origline
);
3414 return DIRECTIVE_FOUND
;
3416 ctx
= get_ctx(tline
->text
, &mname
);
3418 tline
= expand_smacro(tline
->next
);
3422 while (tok_type_(t
, TOK_WHITESPACE
))
3424 /* t should now point to the string */
3425 if (!tok_type_(t
, TOK_STRING
)) {
3427 "`%s` requires string as second parameter",
3430 free_tlist(origline
);
3431 return DIRECTIVE_FOUND
;
3435 * Convert the string to a token stream. Note that smacros
3436 * are stored with the token stream reversed, so we have to
3437 * reverse the output of tokenize().
3439 nasm_unquote_cstr(t
->text
, i
);
3440 macro_start
= reverse_tokens(tokenize(t
->text
));
3443 * We now have a macro name, an implicit parameter count of
3444 * zero, and a numeric token to use as an expansion. Create
3445 * and store an SMacro.
3447 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3449 free_tlist(origline
);
3450 return DIRECTIVE_FOUND
;
3453 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3456 StrList
*xsl
= NULL
;
3457 StrList
**xst
= &xsl
;
3461 tline
= tline
->next
;
3463 tline
= expand_id(tline
);
3464 if (!tline
|| (tline
->type
!= TOK_ID
&&
3465 (tline
->type
!= TOK_PREPROC_ID
||
3466 tline
->text
[1] != '$'))) {
3468 "`%%pathsearch' expects a macro identifier as first parameter");
3469 free_tlist(origline
);
3470 return DIRECTIVE_FOUND
;
3472 ctx
= get_ctx(tline
->text
, &mname
);
3474 tline
= expand_smacro(tline
->next
);
3478 while (tok_type_(t
, TOK_WHITESPACE
))
3481 if (!t
|| (t
->type
!= TOK_STRING
&&
3482 t
->type
!= TOK_INTERNAL_STRING
)) {
3483 error(ERR_NONFATAL
, "`%%pathsearch' expects a file name");
3485 free_tlist(origline
);
3486 return DIRECTIVE_FOUND
; /* but we did _something_ */
3489 error(ERR_WARNING
|ERR_PASS1
,
3490 "trailing garbage after `%%pathsearch' ignored");
3492 if (t
->type
!= TOK_INTERNAL_STRING
)
3493 nasm_unquote(p
, NULL
);
3495 fp
= inc_fopen(p
, &xsl
, &xst
, true);
3498 fclose(fp
); /* Don't actually care about the file */
3500 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3501 macro_start
->text
= nasm_quote(p
, strlen(p
));
3502 macro_start
->type
= TOK_STRING
;
3506 * We now have a macro name, an implicit parameter count of
3507 * zero, and a string token to use as an expansion. Create
3508 * and store an SMacro.
3510 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3512 free_tlist(origline
);
3513 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 "`%%strlen' expects a macro identifier as first parameter");
3528 free_tlist(origline
);
3529 return DIRECTIVE_FOUND
;
3531 ctx
= get_ctx(tline
->text
, &mname
);
3533 tline
= expand_smacro(tline
->next
);
3537 while (tok_type_(t
, TOK_WHITESPACE
))
3539 /* t should now point to the string */
3540 if (!tok_type_(t
, TOK_STRING
)) {
3542 "`%%strlen` requires string as second parameter");
3544 free_tlist(origline
);
3545 return DIRECTIVE_FOUND
;
3548 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3549 make_tok_num(macro_start
, nasm_unquote(t
->text
, NULL
));
3552 * We now have a macro name, an implicit parameter count of
3553 * zero, and a numeric token to use as an expansion. Create
3554 * and store an SMacro.
3556 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3558 free_tlist(origline
);
3559 return DIRECTIVE_FOUND
;
3562 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3565 tline
= tline
->next
;
3567 tline
= expand_id(tline
);
3568 if (!tline
|| (tline
->type
!= TOK_ID
&&
3569 (tline
->type
!= TOK_PREPROC_ID
||
3570 tline
->text
[1] != '$'))) {
3572 "`%%strcat' expects a macro identifier as first parameter");
3573 free_tlist(origline
);
3574 return DIRECTIVE_FOUND
;
3576 ctx
= get_ctx(tline
->text
, &mname
);
3578 tline
= expand_smacro(tline
->next
);
3582 list_for_each(t
, tline
) {
3584 case TOK_WHITESPACE
:
3587 len
+= t
->a
.len
= nasm_unquote(t
->text
, NULL
);
3590 if (!strcmp(t
->text
, ",")) /* permit comma separators */
3592 /* else fall through */
3595 "non-string passed to `%%strcat' (%d)", t
->type
);
3597 free_tlist(origline
);
3598 return DIRECTIVE_FOUND
;
3602 p
= pp
= nasm_malloc(len
);
3603 list_for_each(t
, tline
) {
3604 if (t
->type
== TOK_STRING
) {
3605 memcpy(p
, t
->text
, t
->a
.len
);
3611 * We now have a macro name, an implicit parameter count of
3612 * zero, and a numeric token to use as an expansion. Create
3613 * and store an SMacro.
3615 macro_start
= new_Token(NULL
, TOK_STRING
, NULL
, 0);
3616 macro_start
->text
= nasm_quote(pp
, len
);
3618 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3620 free_tlist(origline
);
3621 return DIRECTIVE_FOUND
;
3624 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3626 int64_t start
, count
;
3631 tline
= tline
->next
;
3633 tline
= expand_id(tline
);
3634 if (!tline
|| (tline
->type
!= TOK_ID
&&
3635 (tline
->type
!= TOK_PREPROC_ID
||
3636 tline
->text
[1] != '$'))) {
3638 "`%%substr' expects a macro identifier as first parameter");
3639 free_tlist(origline
);
3640 return DIRECTIVE_FOUND
;
3642 ctx
= get_ctx(tline
->text
, &mname
);
3644 tline
= expand_smacro(tline
->next
);
3647 if (tline
) /* skip expanded id */
3649 while (tok_type_(t
, TOK_WHITESPACE
))
3652 /* t should now point to the string */
3653 if (!tok_type_(t
, TOK_STRING
)) {
3655 "`%%substr` requires string as second parameter");
3657 free_tlist(origline
);
3658 return DIRECTIVE_FOUND
;
3663 tokval
.t_type
= TOKEN_INVALID
;
3664 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3668 free_tlist(origline
);
3669 return DIRECTIVE_FOUND
;
3670 } else if (!is_simple(evalresult
)) {
3671 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3673 free_tlist(origline
);
3674 return DIRECTIVE_FOUND
;
3676 start
= evalresult
->value
- 1;
3678 while (tok_type_(tt
, TOK_WHITESPACE
))
3681 count
= 1; /* Backwards compatibility: one character */
3683 tokval
.t_type
= TOKEN_INVALID
;
3684 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3688 free_tlist(origline
);
3689 return DIRECTIVE_FOUND
;
3690 } else if (!is_simple(evalresult
)) {
3691 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3693 free_tlist(origline
);
3694 return DIRECTIVE_FOUND
;
3696 count
= evalresult
->value
;
3699 len
= nasm_unquote(t
->text
, NULL
);
3700 /* make start and count being in range */
3704 count
= len
+ count
+ 1 - start
;
3705 if (start
+ count
> (int64_t)len
)
3706 count
= len
- start
;
3707 if (!len
|| count
< 0 || start
>=(int64_t)len
)
3708 start
= -1, count
= 0; /* empty string */
3710 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3711 macro_start
->text
= nasm_quote((start
< 0) ? "" : t
->text
+ start
, count
);
3712 macro_start
->type
= TOK_STRING
;
3715 * We now have a macro name, an implicit parameter count of
3716 * zero, and a numeric token to use as an expansion. Create
3717 * and store an SMacro.
3719 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3721 free_tlist(origline
);
3722 return DIRECTIVE_FOUND
;
3727 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3728 casesense
= (i
== PP_ASSIGN
);
3730 tline
= tline
->next
;
3732 tline
= expand_id(tline
);
3733 if (!tline
|| (tline
->type
!= TOK_ID
&&
3734 (tline
->type
!= TOK_PREPROC_ID
||
3735 tline
->text
[1] != '$'))) {
3737 "`%%%sassign' expects a macro identifier",
3738 (i
== PP_IASSIGN
? "i" : ""));
3739 free_tlist(origline
);
3740 return DIRECTIVE_FOUND
;
3742 ctx
= get_ctx(tline
->text
, &mname
);
3744 tline
= expand_smacro(tline
->next
);
3749 tokval
.t_type
= TOKEN_INVALID
;
3751 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3754 free_tlist(origline
);
3755 return DIRECTIVE_FOUND
;
3759 error(ERR_WARNING
|ERR_PASS1
,
3760 "trailing garbage after expression ignored");
3762 if (!is_simple(evalresult
)) {
3764 "non-constant value given to `%%%sassign'",
3765 (i
== PP_IASSIGN
? "i" : ""));
3766 free_tlist(origline
);
3767 return DIRECTIVE_FOUND
;
3770 macro_start
= nasm_zalloc(sizeof(*macro_start
));
3771 make_tok_num(macro_start
, reloc_value(evalresult
));
3774 * We now have a macro name, an implicit parameter count of
3775 * zero, and a numeric token to use as an expansion. Create
3776 * and store an SMacro.
3778 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3779 free_tlist(origline
);
3780 return DIRECTIVE_FOUND
;
3783 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3785 * Syntax is `%line nnn[+mmm] [filename]'
3787 tline
= tline
->next
;
3789 if (!tok_type_(tline
, TOK_NUMBER
)) {
3790 error(ERR_NONFATAL
, "`%%line' expects line number");
3791 free_tlist(origline
);
3792 return DIRECTIVE_FOUND
;
3794 k
= readnum(tline
->text
, &err
);
3796 tline
= tline
->next
;
3797 if (tok_is_(tline
, "+")) {
3798 tline
= tline
->next
;
3799 if (!tok_type_(tline
, TOK_NUMBER
)) {
3800 error(ERR_NONFATAL
, "`%%line' expects line increment");
3801 free_tlist(origline
);
3802 return DIRECTIVE_FOUND
;
3804 m
= readnum(tline
->text
, &err
);
3805 tline
= tline
->next
;
3811 nasm_free(src_set_fname(detoken(tline
, false)));
3813 free_tlist(origline
);
3814 return DIRECTIVE_FOUND
;
3817 if (defining
!= NULL
) {
3818 if (defining
->type
== EXP_WHILE
) {
3819 defining
->def_depth
++;
3821 return NO_DIRECTIVE_FOUND
;
3824 if ((istk
->expansion
!= NULL
) &&
3825 (istk
->expansion
->emitting
== false)) {
3829 l
->first
= copy_Token(tline
->next
);
3830 j
= if_condition(tline
->next
, i
);
3831 tline
->next
= NULL
; /* it got freed */
3832 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
3834 ed
= new_ExpDef(EXP_WHILE
);
3837 ed
->max_depth
= DEADMAN_LIMIT
;
3838 ed
->ignoring
= ((ed
->state
== COND_IF_TRUE
) ? false : true);
3839 if (ed
->ignoring
== false) {
3842 } else if (l
!= NULL
) {
3843 delete_Token(l
->first
);
3847 ed
->prev
= defining
;
3849 free_tlist(origline
);
3850 return DIRECTIVE_FOUND
;
3853 if (defining
!= NULL
) {
3854 if (defining
->type
== EXP_WHILE
) {
3855 if (defining
->def_depth
> 0) {
3856 defining
->def_depth
--;
3857 return NO_DIRECTIVE_FOUND
;
3860 return NO_DIRECTIVE_FOUND
;
3863 if (tline
->next
!= NULL
) {
3864 error_precond(ERR_WARNING
|ERR_PASS1
,
3865 "trailing garbage after `%%endwhile' ignored");
3867 if ((defining
== NULL
) || (defining
->type
!= EXP_WHILE
)) {
3868 error(ERR_NONFATAL
, "`%%endwhile': no matching `%%while'");
3869 return DIRECTIVE_FOUND
;
3872 defining
= ed
->prev
;
3873 if (ed
->ignoring
== false) {
3874 ed
->prev
= expansions
;
3876 ei
= new_ExpInv(EXP_WHILE
, ed
);
3877 ei
->current
= ed
->line
->next
;
3878 ei
->emitting
= true;
3879 ei
->prev
= istk
->expansion
;
3880 istk
->expansion
= ei
;
3884 free_tlist(origline
);
3885 return DIRECTIVE_FOUND
;
3888 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3890 * We must search along istk->expansion until we hit a
3891 * while invocation. Then we disable the emitting state(s)
3892 * between exitwhile and endwhile.
3894 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
3895 if (ei
->type
== EXP_WHILE
) {
3902 * Set all invocations leading back to the while
3903 * invocation to a non-emitting state.
3905 for (eei
= istk
->expansion
; eei
!= ei
; eei
= eei
->prev
) {
3906 eei
->emitting
= false;
3908 eei
->emitting
= false;
3909 eei
->current
= NULL
;
3910 eei
->def
->cur_depth
= eei
->def
->max_depth
;
3912 error(ERR_NONFATAL
, "`%%exitwhile' not within `%%while' block");
3914 free_tlist(origline
);
3915 return DIRECTIVE_FOUND
;
3918 if (defining
!= NULL
) {
3919 if (defining
->type
== EXP_COMMENT
) {
3920 defining
->def_depth
++;
3922 return NO_DIRECTIVE_FOUND
;
3924 ed
= new_ExpDef(EXP_COMMENT
);
3925 ed
->ignoring
= true;
3926 ed
->prev
= defining
;
3928 free_tlist(origline
);
3929 return DIRECTIVE_FOUND
;
3932 if (defining
!= NULL
) {
3933 if (defining
->type
== EXP_COMMENT
) {
3934 if (defining
->def_depth
> 0) {
3935 defining
->def_depth
--;
3936 return NO_DIRECTIVE_FOUND
;
3939 return NO_DIRECTIVE_FOUND
;
3942 if ((defining
== NULL
) || (defining
->type
!= EXP_COMMENT
)) {
3943 error(ERR_NONFATAL
, "`%%endcomment': no matching `%%comment'");
3944 return DIRECTIVE_FOUND
;
3947 defining
= ed
->prev
;
3949 free_tlist(origline
);
3950 return DIRECTIVE_FOUND
;
3953 if (defining
!= NULL
) return NO_DIRECTIVE_FOUND
;
3954 if (in_final
!= false) {
3955 error(ERR_FATAL
, "`%%final' cannot be used recursively");
3957 tline
= tline
->next
;
3959 if (tline
== NULL
) {
3960 error(ERR_NONFATAL
, "`%%final' expects at least one parameter");
3963 l
->first
= copy_Token(tline
);
3967 free_tlist(origline
);
3968 return DIRECTIVE_FOUND
;
3972 "preprocessor directive `%s' not yet implemented",
3974 return DIRECTIVE_FOUND
;
3979 * Ensure that a macro parameter contains a condition code and
3980 * nothing else. Return the condition code index if so, or -1
3983 static int find_cc(Token
* t
)
3989 return -1; /* Probably a %+ without a space */
3992 if (t
->type
!= TOK_ID
)
3996 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
4000 j
= ARRAY_SIZE(conditions
);
4003 m
= nasm_stricmp(t
->text
, conditions
[k
]);
4018 static bool paste_tokens(Token
**head
, const struct tokseq_match
*m
,
4019 int mnum
, bool handle_paste_tokens
)
4021 Token
**tail
, *t
, *tt
;
4023 bool did_paste
= false;
4027 nasm_dump_stream(*head
);
4028 nasm_dump_token(*head
);
4030 /* Now handle token pasting... */
4033 while ((t
= *tail
) && (tt
= t
->next
)) {
4035 case TOK_WHITESPACE
:
4036 if (tt
->type
== TOK_WHITESPACE
) {
4037 /* Zap adjacent whitespace tokens */
4038 t
->next
= delete_Token(tt
);
4040 /* Do not advance paste_head here */
4044 case TOK_PASTE
: /* %+ */
4045 if (handle_paste_tokens
) {
4046 /* Zap %+ and whitespace tokens to the right */
4047 while (t
&& (t
->type
== TOK_WHITESPACE
||
4048 t
->type
== TOK_PASTE
))
4049 t
= *tail
= delete_Token(t
);
4050 if (!t
) { /* Dangling %+ term */
4052 (*paste_head
)->next
= NULL
;
4060 while (tok_type_(tt
, TOK_WHITESPACE
))
4061 tt
= t
->next
= delete_Token(tt
);
4063 tmp
= nasm_strcat(t
->text
, tt
->text
);
4065 tt
= delete_Token(tt
);
4066 t
= *tail
= tokenize(tmp
);
4072 t
->next
= tt
; /* Attach the remaining token chain */
4079 /* else fall through */
4082 * Concatenation of tokens might look nontrivial
4083 * but in real it's pretty simple -- the caller
4084 * prepares the masks of token types to be concatenated
4085 * and we simply find matched sequences and slip
4088 for (i
= 0; i
< mnum
; i
++) {
4089 if (PP_CONCAT_MASK(t
->type
) & m
[i
].mask_head
) {
4093 while (tt
&& (PP_CONCAT_MASK(tt
->type
) & m
[i
].mask_tail
)) {
4094 len
+= strlen(tt
->text
);
4098 nasm_dump_token(tt
);
4101 * Now tt points to the first token after
4102 * the potential paste area...
4104 if (tt
!= t
->next
) {
4105 /* We have at least two tokens... */
4106 len
+= strlen(t
->text
);
4107 p
= tmp
= nasm_malloc(len
+1);
4110 p
= strchr(p
, '\0');
4111 t
= delete_Token(t
);
4113 t
= *tail
= tokenize(tmp
);
4119 t
->next
= tt
; /* Attach the remaining token chain */
4127 if (i
>= mnum
) { /* no match */
4129 if (!tok_type_(t
->next
, TOK_WHITESPACE
))
4139 * expands to a list of tokens from %{x:y}
4141 static Token
*expand_mmac_params_range(ExpInv
*ei
, Token
*tline
, Token
***last
)
4143 Token
*t
= tline
, **tt
, *tm
, *head
;
4147 pos
= strchr(tline
->text
, ':');
4150 lst
= atoi(pos
+ 1);
4151 fst
= atoi(tline
->text
+ 1);
4154 * only macros params are accounted so
4155 * if someone passes %0 -- we reject such
4158 if (lst
== 0 || fst
== 0)
4161 /* the values should be sane */
4162 if ((fst
> (int)ei
->nparam
|| fst
< (-(int)ei
->nparam
)) ||
4163 (lst
> (int)ei
->nparam
|| lst
< (-(int)ei
->nparam
)))
4166 fst
= fst
< 0 ? fst
+ (int)ei
->nparam
+ 1: fst
;
4167 lst
= lst
< 0 ? lst
+ (int)ei
->nparam
+ 1: lst
;
4169 /* counted from zero */
4173 * it will be at least one token
4175 tm
= ei
->params
[(fst
+ ei
->rotate
) % ei
->nparam
];
4176 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4177 head
= t
, tt
= &t
->next
;
4179 for (i
= fst
+ 1; i
<= lst
; i
++) {
4180 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
4181 *tt
= t
, tt
= &t
->next
;
4182 j
= (i
+ ei
->rotate
) % ei
->nparam
;
4184 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4185 *tt
= t
, tt
= &t
->next
;
4188 for (i
= fst
- 1; i
>= lst
; i
--) {
4189 t
= new_Token(NULL
, TOK_OTHER
, ",", 0);
4190 *tt
= t
, tt
= &t
->next
;
4191 j
= (i
+ ei
->rotate
) % ei
->nparam
;
4193 t
= new_Token(NULL
, tm
->type
, tm
->text
, 0);
4194 *tt
= t
, tt
= &t
->next
;
4202 error(ERR_NONFATAL
, "`%%{%s}': macro parameters out of range",
4208 * Expand MMacro-local things: parameter references (%0, %n, %+n,
4209 * %-n) and MMacro-local identifiers (%%foo) as well as
4210 * macro indirection (%[...]) and range (%{..:..}).
4212 static Token
*expand_mmac_params(Token
* tline
)
4214 Token
*t
, *tt
, **tail
, *thead
;
4215 bool changed
= false;
4221 nasm_dump_stream(tline
);
4224 if (tline
->type
== TOK_PREPROC_ID
&&
4225 (((tline
->text
[1] == '+' || tline
->text
[1] == '-') && tline
->text
[2]) ||
4226 (tline
->text
[1] >= '0' && tline
->text
[1] <= '9') ||
4227 tline
->text
[1] == '%')) {
4229 int type
= 0, cc
; /* type = 0 to placate optimisers */
4236 tline
= tline
->next
;
4238 for (ei
= istk
->expansion
; ei
!= NULL
; ei
= ei
->prev
) {
4239 if (ei
->type
== EXP_MMACRO
) {
4244 error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
4246 pos
= strchr(t
->text
, ':');
4248 switch (t
->text
[1]) {
4250 * We have to make a substitution of one of the
4251 * forms %1, %-1, %+1, %%foo, %0.
4254 if ((strlen(t
->text
) > 2) && (t
->text
[2] == '0')) {
4256 text
= nasm_strdup(ei
->label_text
);
4259 snprintf(tmpbuf
, sizeof(tmpbuf
), "%d", ei
->nparam
);
4260 text
= nasm_strdup(tmpbuf
);
4265 snprintf(tmpbuf
, sizeof(tmpbuf
), "..@%"PRIu64
".",
4267 text
= nasm_strcat(tmpbuf
, t
->text
+ 2);
4270 n
= atoi(t
->text
+ 2) - 1;
4271 if (n
>= ei
->nparam
)
4275 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4281 "macro parameter %d is not a condition code",
4286 if (inverse_ccs
[cc
] == -1) {
4288 "condition code `%s' is not invertible",
4292 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
4296 n
= atoi(t
->text
+ 2) - 1;
4297 if (n
>= ei
->nparam
)
4301 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4307 "macro parameter %d is not a condition code",
4312 text
= nasm_strdup(conditions
[cc
]);
4316 n
= atoi(t
->text
+ 1) - 1;
4317 if (n
>= ei
->nparam
)
4321 n
= (n
+ ei
->rotate
) % ei
->nparam
;
4325 for (i
= 0; i
< ei
->paramlen
[n
]; i
++) {
4326 *tail
= new_Token(NULL
, tt
->type
, tt
->text
, 0);
4327 tail
= &(*tail
)->next
;
4331 text
= NULL
; /* we've done it here */
4336 * seems we have a parameters range here
4338 Token
*head
, **last
;
4339 head
= expand_mmac_params_range(ei
, t
, &last
);
4360 } else if (tline
->type
== TOK_INDIRECT
) {
4362 tline
= tline
->next
;
4363 tt
= tokenize(t
->text
);
4364 tt
= expand_mmac_params(tt
);
4365 tt
= expand_smacro(tt
);
4368 tt
->a
.mac
= NULL
; /* Necessary? */
4376 tline
= tline
->next
;
4384 const struct tokseq_match t
[] = {
4386 PP_CONCAT_MASK(TOK_ID
) |
4387 PP_CONCAT_MASK(TOK_FLOAT
), /* head */
4388 PP_CONCAT_MASK(TOK_ID
) |
4389 PP_CONCAT_MASK(TOK_NUMBER
) |
4390 PP_CONCAT_MASK(TOK_FLOAT
) |
4391 PP_CONCAT_MASK(TOK_OTHER
) /* tail */
4394 PP_CONCAT_MASK(TOK_NUMBER
), /* head */
4395 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4398 paste_tokens(&thead
, t
, ARRAY_SIZE(t
), false);
4401 nasm_dump_token(thead
);
4407 * Expand all single-line macro calls made in the given line.
4408 * Return the expanded version of the line. The original is deemed
4409 * to be destroyed in the process. (In reality we'll just move
4410 * Tokens from input to output a lot of the time, rather than
4411 * actually bothering to destroy and replicate.)
4414 static Token
*expand_smacro(Token
* tline
)
4416 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
4417 SMacro
*head
= NULL
, *m
;
4420 unsigned int nparam
, sparam
;
4422 Token
*org_tline
= tline
;
4425 int deadman
= DEADMAN_LIMIT
;
4429 * Trick: we should avoid changing the start token pointer since it can
4430 * be contained in "next" field of other token. Because of this
4431 * we allocate a copy of first token and work with it; at the end of
4432 * routine we copy it back
4435 tline
= new_Token(org_tline
->next
, org_tline
->type
,
4436 org_tline
->text
, 0);
4437 tline
->a
.mac
= org_tline
->a
.mac
;
4438 nasm_free(org_tline
->text
);
4439 org_tline
->text
= NULL
;
4442 expanded
= true; /* Always expand %+ at least once */
4448 while (tline
) { /* main token loop */
4450 error(ERR_NONFATAL
, "interminable macro recursion");
4454 if ((mname
= tline
->text
)) {
4455 /* if this token is a local macro, look in local context */
4456 if (tline
->type
== TOK_ID
) {
4457 head
= (SMacro
*)hash_findix(&smacros
, mname
);
4458 } else if (tline
->type
== TOK_PREPROC_ID
) {
4459 ctx
= get_ctx(mname
, &mname
);
4460 head
= ctx
? (SMacro
*)hash_findix(&ctx
->localmac
, mname
) : NULL
;
4465 * We've hit an identifier. As in is_mmacro below, we first
4466 * check whether the identifier is a single-line macro at
4467 * all, then think about checking for parameters if
4470 list_for_each(m
, head
) {
4471 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
4478 if (m
->nparam
== 0) {
4480 * Simple case: the macro is parameterless. Discard the
4481 * one token that the macro call took, and push the
4482 * expansion back on the to-do stack.
4484 if (!m
->expansion
) {
4485 if (!strcmp("__FILE__", m
->name
)) {
4488 src_get(&num
, &file
);
4489 tline
->text
= nasm_quote(file
, strlen(file
));
4490 tline
->type
= TOK_STRING
;
4494 if (!strcmp("__LINE__", m
->name
)) {
4495 nasm_free(tline
->text
);
4496 make_tok_num(tline
, src_get_linnum());
4499 if (!strcmp("__BITS__", m
->name
)) {
4500 nasm_free(tline
->text
);
4501 make_tok_num(tline
, globalbits
);
4504 tline
= delete_Token(tline
);
4509 * Complicated case: at least one macro with this name
4510 * exists and takes parameters. We must find the
4511 * parameters in the call, count them, find the SMacro
4512 * that corresponds to that form of the macro call, and
4513 * substitute for the parameters when we expand. What a
4516 /*tline = tline->next;
4517 skip_white_(tline); */
4520 while (tok_type_(t
, TOK_SMAC_END
)) {
4521 t
->a
.mac
->in_progress
= false;
4523 t
= tline
->next
= delete_Token(t
);
4526 } while (tok_type_(tline
, TOK_WHITESPACE
));
4527 if (!tok_is_(tline
, "(")) {
4529 * This macro wasn't called with parameters: ignore
4530 * the call. (Behaviour borrowed from gnu cpp.)
4539 sparam
= PARAM_DELTA
;
4540 params
= nasm_malloc(sparam
* sizeof(Token
*));
4541 params
[0] = tline
->next
;
4542 paramsize
= nasm_malloc(sparam
* sizeof(int));
4544 while (true) { /* parameter loop */
4546 * For some unusual expansions
4547 * which concatenates function call
4550 while (tok_type_(t
, TOK_SMAC_END
)) {
4551 t
->a
.mac
->in_progress
= false;
4553 t
= tline
->next
= delete_Token(t
);
4559 "macro call expects terminating `)'");
4562 if (tline
->type
== TOK_WHITESPACE
4564 if (paramsize
[nparam
])
4567 params
[nparam
] = tline
->next
;
4568 continue; /* parameter loop */
4570 if (tline
->type
== TOK_OTHER
4571 && tline
->text
[1] == 0) {
4572 char ch
= tline
->text
[0];
4573 if (ch
== ',' && !paren
&& brackets
<= 0) {
4574 if (++nparam
>= sparam
) {
4575 sparam
+= PARAM_DELTA
;
4576 params
= nasm_realloc(params
,
4577 sparam
* sizeof(Token
*));
4578 paramsize
= nasm_realloc(paramsize
,
4579 sparam
* sizeof(int));
4581 params
[nparam
] = tline
->next
;
4582 paramsize
[nparam
] = 0;
4584 continue; /* parameter loop */
4587 (brackets
> 0 || (brackets
== 0 &&
4588 !paramsize
[nparam
])))
4590 if (!(brackets
++)) {
4591 params
[nparam
] = tline
->next
;
4592 continue; /* parameter loop */
4595 if (ch
== '}' && brackets
> 0)
4596 if (--brackets
== 0) {
4598 continue; /* parameter loop */
4600 if (ch
== '(' && !brackets
)
4602 if (ch
== ')' && brackets
<= 0)
4608 error(ERR_NONFATAL
, "braces do not "
4609 "enclose all of macro parameter");
4611 paramsize
[nparam
] += white
+ 1;
4613 } /* parameter loop */
4615 while (m
&& (m
->nparam
!= nparam
||
4616 mstrcmp(m
->name
, mname
,
4620 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4621 "macro `%s' exists, "
4622 "but not taking %d parameters",
4623 mstart
->text
, nparam
);
4626 if (m
&& m
->in_progress
)
4628 if (!m
) { /* in progess or didn't find '(' or wrong nparam */
4630 * Design question: should we handle !tline, which
4631 * indicates missing ')' here, or expand those
4632 * macros anyway, which requires the (t) test a few
4636 nasm_free(paramsize
);
4640 * Expand the macro: we are placed on the last token of the
4641 * call, so that we can easily split the call from the
4642 * following tokens. We also start by pushing an SMAC_END
4643 * token for the cycle removal.
4650 tt
= new_Token(tline
, TOK_SMAC_END
, NULL
, 0);
4652 m
->in_progress
= true;
4654 list_for_each(t
, m
->expansion
) {
4655 if (is_smacro_param(t
)) {
4656 Token
*pcopy
= tline
, **ptail
= &pcopy
;
4660 idx
= smacro_get_param_idx(t
);
4664 * We need smacro paramters appended.
4666 for (i
= paramsize
[idx
]; i
> 0; i
--) {
4667 *ptail
= new_Token(tline
, ttt
->type
, ttt
->text
, 0);
4668 ptail
= &(*ptail
)->next
;
4673 } else if (t
->type
== TOK_PREPROC_Q
) {
4674 tt
= new_Token(tline
, TOK_ID
, mname
, 0);
4676 } else if (t
->type
== TOK_PREPROC_QQ
) {
4677 tt
= new_Token(tline
, TOK_ID
, m
->name
, 0);
4680 tt
= new_Token(tline
, t
->type
, t
->text
, 0);
4686 * Having done that, get rid of the macro call, and clean
4687 * up the parameters.
4690 nasm_free(paramsize
);
4693 continue; /* main token loop */
4698 if (tline
->type
== TOK_SMAC_END
) {
4699 tline
->a
.mac
->in_progress
= false;
4700 tline
= delete_Token(tline
);
4703 tline
= tline
->next
;
4711 * Now scan the entire line and look for successive TOK_IDs that resulted
4712 * after expansion (they can't be produced by tokenize()). The successive
4713 * TOK_IDs should be concatenated.
4714 * Also we look for %+ tokens and concatenate the tokens before and after
4715 * them (without white spaces in between).
4718 const struct tokseq_match t
[] = {
4720 PP_CONCAT_MASK(TOK_ID
) |
4721 PP_CONCAT_MASK(TOK_PREPROC_ID
), /* head */
4722 PP_CONCAT_MASK(TOK_ID
) |
4723 PP_CONCAT_MASK(TOK_PREPROC_ID
) |
4724 PP_CONCAT_MASK(TOK_NUMBER
) /* tail */
4727 if (paste_tokens(&thead
, t
, ARRAY_SIZE(t
), true)) {
4729 * If we concatenated something, *and* we had previously expanded
4730 * an actual macro, scan the lines again for macros...
4741 *org_tline
= *thead
;
4742 /* since we just gave text to org_line, don't free it */
4744 delete_Token(thead
);
4746 /* the expression expanded to empty line;
4747 we can't return NULL for some reasons
4748 we just set the line to a single WHITESPACE token. */
4749 memset(org_tline
, 0, sizeof(*org_tline
));
4750 org_tline
->text
= NULL
;
4751 org_tline
->type
= TOK_WHITESPACE
;
4760 * Similar to expand_smacro but used exclusively with macro identifiers
4761 * right before they are fetched in. The reason is that there can be
4762 * identifiers consisting of several subparts. We consider that if there
4763 * are more than one element forming the name, user wants a expansion,
4764 * otherwise it will be left as-is. Example:
4768 * the identifier %$abc will be left as-is so that the handler for %define
4769 * will suck it and define the corresponding value. Other case:
4771 * %define _%$abc cde
4773 * In this case user wants name to be expanded *before* %define starts
4774 * working, so we'll expand %$abc into something (if it has a value;
4775 * otherwise it will be left as-is) then concatenate all successive
4778 static Token
*expand_id(Token
* tline
)
4780 Token
*cur
, *oldnext
= NULL
;
4782 if (!tline
|| !tline
->next
)
4787 (cur
->next
->type
== TOK_ID
||
4788 cur
->next
->type
== TOK_PREPROC_ID
||
4789 cur
->next
->type
== TOK_NUMBER
))
4792 /* If identifier consists of just one token, don't expand */
4797 oldnext
= cur
->next
; /* Detach the tail past identifier */
4798 cur
->next
= NULL
; /* so that expand_smacro stops here */
4801 tline
= expand_smacro(tline
);
4804 /* expand_smacro possibly changhed tline; re-scan for EOL */
4806 while (cur
&& cur
->next
)
4809 cur
->next
= oldnext
;
4816 * Determine whether the given line constitutes a multi-line macro
4817 * call, and return the ExpDef structure called if so. Doesn't have
4818 * to check for an initial label - that's taken care of in
4819 * expand_mmacro - but must check numbers of parameters. Guaranteed
4820 * to be called with tline->type == TOK_ID, so the putative macro
4821 * name is easy to find.
4823 static ExpDef
*is_mmacro(Token
* tline
, Token
*** params_array
)
4829 head
= (ExpDef
*) hash_findix(&expdefs
, tline
->text
);
4832 * Efficiency: first we see if any macro exists with the given
4833 * name. If not, we can return NULL immediately. _Then_ we
4834 * count the parameters, and then we look further along the
4835 * list if necessary to find the proper ExpDef.
4837 list_for_each(ed
, head
) {
4838 if (!mstrcmp(ed
->name
, tline
->text
, ed
->casesense
))
4845 * OK, we have a potential macro. Count and demarcate the
4848 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
4851 * So we know how many parameters we've got. Find the ExpDef
4852 * structure that handles this number.
4855 if (ed
->nparam_min
<= nparam
4856 && (ed
->plus
|| nparam
<= ed
->nparam_max
)) {
4858 * It's right, and we can use it. Add its default
4859 * parameters to the end of our list if necessary.
4861 if (ed
->defaults
&& nparam
< ed
->nparam_min
+ ed
->ndefs
) {
4863 nasm_realloc(params
,
4864 ((ed
->nparam_min
+ ed
->ndefs
+
4865 1) * sizeof(*params
)));
4866 while (nparam
< ed
->nparam_min
+ ed
->ndefs
) {
4867 params
[nparam
] = ed
->defaults
[nparam
- ed
->nparam_min
];
4872 * If we've gone over the maximum parameter count (and
4873 * we're in Plus mode), ignore parameters beyond
4876 if (ed
->plus
&& nparam
> ed
->nparam_max
)
4877 nparam
= ed
->nparam_max
;
4879 * Then terminate the parameter list, and leave.
4881 if (!params
) { /* need this special case */
4882 params
= nasm_malloc(sizeof(*params
));
4885 params
[nparam
] = NULL
;
4886 *params_array
= params
;
4890 * This one wasn't right: look for the next one with the
4893 list_for_each(ed
, ed
->next
) {
4894 if (!mstrcmp(ed
->name
, tline
->text
, ed
->casesense
))
4900 * After all that, we didn't find one with the right number of
4901 * parameters. Issue a warning, and fail to expand the macro.
4903 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4904 "macro `%s' exists, but not taking %d parameters",
4905 tline
->text
, nparam
);
4911 * Expand the multi-line macro call made by the given line, if
4912 * there is one to be expanded. If there is, push the expansion on
4913 * istk->expansion and return true. Otherwise return false.
4915 static bool expand_mmacro(Token
* tline
)
4917 Token
*label
= NULL
;
4918 int dont_prepend
= 0;
4923 int i
, nparam
, *paramlen
;
4928 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4929 if (!tok_type_(t
, TOK_ID
) && !tok_type_(t
, TOK_PREPROC_ID
))
4931 ed
= is_mmacro(t
, ¶ms
);
4937 * We have an id which isn't a macro call. We'll assume
4938 * it might be a label; we'll also check to see if a
4939 * colon follows it. Then, if there's another id after
4940 * that lot, we'll check it again for macro-hood.
4944 if (tok_type_(t
, TOK_WHITESPACE
))
4945 last
= t
, t
= t
->next
;
4946 if (tok_is_(t
, ":")) {
4948 last
= t
, t
= t
->next
;
4949 if (tok_type_(t
, TOK_WHITESPACE
))
4950 last
= t
, t
= t
->next
;
4952 if (!tok_type_(t
, TOK_ID
) || !(ed
= is_mmacro(t
, ¶ms
)))
4960 * Fix up the parameters: this involves stripping leading and
4961 * trailing whitespace, then stripping braces if they are
4964 for (nparam
= 0; params
[nparam
]; nparam
++)
4966 paramlen
= nparam
? nasm_malloc(nparam
* sizeof(*paramlen
)) : NULL
;
4968 for (i
= 0; params
[i
]; i
++) {
4970 int comma
= (!ed
->plus
|| i
< nparam
- 1);
4974 if (tok_is_(t
, "{"))
4975 t
= t
->next
, brace
= true, comma
= false;
4979 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
4980 break; /* ... because we have hit a comma */
4981 if (comma
&& t
->type
== TOK_WHITESPACE
4982 && tok_is_(t
->next
, ","))
4983 break; /* ... or a space then a comma */
4984 if (brace
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "}"))
4985 break; /* ... or a brace */
4991 if (ed
->cur_depth
>= ed
->max_depth
) {
4992 if (ed
->max_depth
> 1) {
4994 "reached maximum macro recursion depth of %i for %s",
4995 ed
->max_depth
,ed
->name
);
5003 * OK, we have found a ExpDef structure representing a
5004 * previously defined mmacro. Create an expansion invocation
5005 * and point it back to the expansion definition. Substitution of
5006 * parameter tokens and macro-local tokens doesn't get done
5007 * until the single-line macro substitution process; this is
5008 * because delaying them allows us to change the semantics
5009 * later through %rotate.
5011 ei
= new_ExpInv(EXP_MMACRO
, ed
);
5012 ei
->name
= nasm_strdup(mname
);
5013 //ei->label = label;
5014 //ei->label_text = detoken(label, false);
5015 ei
->current
= ed
->line
;
5016 ei
->emitting
= true;
5017 //ei->iline = tline;
5018 ei
->params
= params
;
5019 ei
->nparam
= nparam
;
5021 ei
->paramlen
= paramlen
;
5024 ei
->prev
= istk
->expansion
;
5025 istk
->expansion
= ei
;
5028 * Special case: detect %00 on first invocation; if found,
5029 * avoid emitting any labels that precede the mmacro call.
5030 * ed->prepend is set to -1 when %00 is detected, else 1.
5032 if (ed
->prepend
== 0) {
5033 for (l
= ed
->line
; l
!= NULL
; l
= l
->next
) {
5034 for (t
= l
->first
; t
!= NULL
; t
= t
->next
) {
5035 if ((t
->type
== TOK_PREPROC_ID
) &&
5036 (strlen(t
->text
) == 3) &&
5037 (t
->text
[1] == '0') && (t
->text
[2] == '0')) {
5042 if (dont_prepend
< 0)
5045 ed
->prepend
= ((dont_prepend
< 0) ? -1 : 1);
5049 * If we had a label, push it on as the first line of
5050 * the macro expansion.
5052 if (label
!= NULL
) {
5053 if (ed
->prepend
< 0) {
5054 ei
->label_text
= detoken(label
, false);
5056 if (dont_prepend
== 0) {
5058 while (t
->next
!= NULL
) {
5061 t
->next
= new_Token(NULL
, TOK_OTHER
, ":", 0);
5064 l
->first
= copy_Token(label
);
5065 l
->next
= ei
->current
;
5070 list
->uplevel(ed
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
5076 /* The function that actually does the error reporting */
5077 static void verror(int severity
, const char *fmt
, va_list arg
)
5081 vsnprintf(buff
, sizeof(buff
), fmt
, arg
);
5083 if (istk
&& istk
->mmac_depth
> 0) {
5084 ExpInv
*ei
= istk
->expansion
;
5085 int lineno
= ei
->lineno
;
5087 if (ei
->type
== EXP_MMACRO
)
5089 lineno
+= ei
->relno
;
5092 nasm_error(severity
, "(%s:%d) %s", ei
->def
->name
,
5095 nasm_error(severity
, "%s", buff
);
5100 * Since preprocessor always operate only on the line that didn't
5101 * arrived yet, we should always use ERR_OFFBY1.
5103 static void error(int severity
, const char *fmt
, ...)
5107 verror(severity
, fmt
, arg
);
5112 * Because %else etc are evaluated in the state context
5113 * of the previous branch, errors might get lost with error():
5114 * %if 0 ... %else trailing garbage ... %endif
5115 * So %else etc should report errors with this function.
5117 static void error_precond(int severity
, const char *fmt
, ...)
5121 /* Only ignore the error if it's really in a dead branch */
5122 if ((istk
!= NULL
) &&
5123 (istk
->expansion
!= NULL
) &&
5124 (istk
->expansion
->type
== EXP_IF
) &&
5125 (istk
->expansion
->def
->state
== COND_NEVER
))
5129 verror(severity
, fmt
, arg
);
5134 pp_reset(char *file
, int apass
, ListGen
* listgen
, StrList
**deplist
)
5139 istk
= nasm_zalloc(sizeof(Include
));
5140 istk
->fp
= fopen(file
, "r");
5141 src_set_fname(nasm_strdup(file
));
5145 error(ERR_FATAL
|ERR_NOFILE
, "unable to open input file `%s'",
5150 nested_mac_count
= 0;
5151 nested_rep_count
= 0;
5154 if (tasm_compatible_mode
)
5155 stdmacpos
= nasm_stdmac
;
5157 stdmacpos
= nasm_stdmac_after_tasm
;
5158 any_extrastdmac
= extrastdmac
&& *extrastdmac
;
5163 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
5164 * The caller, however, will also pass in 3 for preprocess-only so
5165 * we can set __PASS__ accordingly.
5167 pass
= apass
> 2 ? 2 : apass
;
5169 dephead
= deptail
= deplist
;
5171 StrList
*sl
= nasm_malloc(strlen(file
)+1+sizeof sl
->next
);
5173 strcpy(sl
->str
, file
);
5175 deptail
= &sl
->next
;
5179 * Define the __PASS__ macro. This is defined here unlike
5180 * all the other builtins, because it is special -- it varies between
5183 t
= nasm_zalloc(sizeof(*t
));
5184 make_tok_num(t
, apass
);
5185 define_smacro(NULL
, "__PASS__", true, 0, t
);
5188 static char *pp_getline(void)
5199 * Fetch a tokenized line, either from the expansion
5200 * buffer or from the input file.
5204 while (1) { /* until we get a line we can use */
5206 * Fetch a tokenized line from the expansion buffer
5208 if (istk
->expansion
!= NULL
) {
5209 ei
= istk
->expansion
;
5210 if (ei
->current
!= NULL
) {
5211 if (ei
->emitting
== false) {
5216 ei
->current
= l
->next
;
5218 tline
= copy_Token(l
->first
);
5219 if (((ei
->type
== EXP_REP
) ||
5220 (ei
->type
== EXP_MMACRO
) ||
5221 (ei
->type
== EXP_WHILE
))
5222 && (ei
->def
->nolist
== false)) {
5223 char *p
= detoken(tline
, false);
5224 list
->line(LIST_MACRO
, p
);
5227 if (ei
->linnum
> -1) {
5228 src_set_linnum(src_get_linnum() + 1);
5231 } else if ((ei
->type
== EXP_REP
) &&
5232 (ei
->def
->cur_depth
< ei
->def
->max_depth
)) {
5233 ei
->def
->cur_depth
++;
5234 ei
->current
= ei
->def
->line
;
5237 } else if ((ei
->type
== EXP_WHILE
) &&
5238 (ei
->def
->cur_depth
< ei
->def
->max_depth
)) {
5239 ei
->current
= ei
->def
->line
;
5241 tline
= copy_Token(ei
->current
->first
);
5242 j
= if_condition(tline
, PP_WHILE
);
5244 j
= (((j
< 0) ? COND_NEVER
: j
) ? COND_IF_TRUE
: COND_IF_FALSE
);
5245 if (j
== COND_IF_TRUE
) {
5246 ei
->current
= ei
->current
->next
;
5247 ei
->def
->cur_depth
++;
5249 ei
->emitting
= false;
5251 ei
->def
->cur_depth
= ei
->def
->max_depth
;
5255 istk
->expansion
= ei
->prev
;
5258 if ((ei
->emitting
== true) &&
5259 (ed
->max_depth
== DEADMAN_LIMIT
) &&
5260 (ed
->cur_depth
== DEADMAN_LIMIT
)
5262 error(ERR_FATAL
, "runaway expansion detected, aborting");
5264 if (ed
->cur_depth
> 0) {
5266 } else if (ed
->type
!= EXP_MMACRO
) {
5267 expansions
= ed
->prev
;
5270 if ((ei
->type
== EXP_REP
) ||
5271 (ei
->type
== EXP_MMACRO
) ||
5272 (ei
->type
== EXP_WHILE
)) {
5273 list
->downlevel(LIST_MACRO
);
5274 if (ei
->type
== EXP_MMACRO
) {
5279 if (ei
->linnum
> -1) {
5280 src_set_linnum(ei
->linnum
);
5288 * Read in line from input and tokenize
5291 if (line
) { /* from the current input file */
5292 line
= prepreproc(line
);
5293 tline
= tokenize(line
);
5299 * The current file has ended; work down the istk
5304 if (i
->expansion
!= NULL
) {
5306 "end of file while still in an expansion");
5308 /* only set line and file name if there's a next node */
5310 src_set_linnum(i
->lineno
);
5311 nasm_free(src_set_fname(nasm_strdup(i
->fname
)));
5313 if ((i
->next
== NULL
) && (finals
!= NULL
)) {
5315 ei
= new_ExpInv(EXP_FINAL
, NULL
);
5316 ei
->emitting
= true;
5317 ei
->current
= finals
;
5318 istk
->expansion
= ei
;
5323 list
->downlevel(LIST_INCLUDE
);
5335 if (defining
== NULL
)
5336 tline
= expand_mmac_params(tline
);
5339 * Check the line to see if it's a preprocessor directive.
5341 if (do_directive(tline
) == DIRECTIVE_FOUND
) {
5343 } else if (defining
!= NULL
) {
5345 * We're defining an expansion. We emit nothing at all,
5346 * and just shove the tokenized line on to the definition.
5348 if (defining
->ignoring
== false) {
5349 Line
*l
= new_Line();
5351 if (defining
->line
== NULL
) {
5355 defining
->last
->next
= l
;
5361 defining
->linecount
++;
5363 } else if ((istk
->expansion
!= NULL
) &&
5364 (istk
->expansion
->emitting
!= true)) {
5366 * We're in a non-emitting branch of an expansion.
5367 * Emit nothing at all, not even a blank line: when we
5368 * emerge from the expansion we'll give a line-number
5369 * directive so we keep our place correctly.
5374 tline
= expand_smacro(tline
);
5375 if (expand_mmacro(tline
) != true) {
5377 * De-tokenize the line again, and emit it.
5379 line
= detoken(tline
, true);
5390 static void pp_cleanup(int pass
)
5392 if (defining
!= NULL
) {
5393 error(ERR_NONFATAL
, "end of file while still defining an expansion");
5394 while (defining
!= NULL
) {
5395 ExpDef
*ed
= defining
;
5396 defining
= ed
->prev
;
5401 while (cstk
!= NULL
)
5404 while (istk
!= NULL
) {
5408 nasm_free(i
->fname
);
5409 while (i
->expansion
!= NULL
) {
5410 ExpInv
*ei
= i
->expansion
;
5411 i
->expansion
= ei
->prev
;
5418 nasm_free(src_set_fname(NULL
));
5423 while ((i
= ipath
)) {
5431 void pp_include_path(char *path
)
5433 IncPath
*i
= nasm_zalloc(sizeof(IncPath
));
5436 i
->path
= nasm_strdup(path
);
5448 void pp_pre_include(char *fname
)
5450 Token
*inc
, *space
, *name
;
5453 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
5454 space
= new_Token(name
, TOK_WHITESPACE
, NULL
, 0);
5455 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
5463 void pp_pre_define(char *definition
)
5469 equals
= strchr(definition
, '=');
5470 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5471 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
5474 space
->next
= tokenize(definition
);
5484 void pp_pre_undefine(char *definition
)
5489 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
5490 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
5491 space
->next
= tokenize(definition
);
5500 * This function is used to assist with "runtime" preprocessor
5501 * directives, e.g. pp_runtime("%define __BITS__ 64");
5503 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
5504 * PASS A VALID STRING TO THIS FUNCTION!!!!!
5507 void pp_runtime(char *definition
)
5511 def
= tokenize(definition
);
5512 if (do_directive(def
) == NO_DIRECTIVE_FOUND
)
5517 void pp_extra_stdmac(macros_t
*macros
)
5519 extrastdmac
= macros
;
5522 static void make_tok_num(Token
* tok
, int64_t val
)
5525 snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
5526 tok
->text
= nasm_strdup(numbuf
);
5527 tok
->type
= TOK_NUMBER
;
5530 struct preproc_ops nasmpp
= {