1 /* preproc.c macro preprocessor for the Netwide Assembler
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the license given in the file "LICENSE"
6 * distributed in the NASM archive.
8 * initial version 18/iii/97 by Simon Tatham
11 /* Typical flow of text through preproc
13 * pp_getline gets tokenized lines, either
15 * from a macro expansion
19 * read_line gets raw text from stdmacpos, or predef, or current input file
20 * tokenize converts to tokens
23 * expand_mmac_params is used to expand %1 etc., unless a macro is being
24 * defined or a false conditional is being processed
25 * (%0, %1, %+1, %-1, %%foo
27 * do_directive checks for directives
29 * expand_smacro is used to expand single line macros
31 * expand_mmacro is used to expand multi-line macros
33 * detoken is used to convert the line back to text
56 typedef struct SMacro SMacro
;
57 typedef struct MMacro MMacro
;
58 typedef struct Context Context
;
59 typedef struct Token Token
;
60 typedef struct Blocks Blocks
;
61 typedef struct Line Line
;
62 typedef struct Include Include
;
63 typedef struct Cond Cond
;
64 typedef struct IncPath IncPath
;
67 * Note on the storage of both SMacro and MMacros: the hash table
68 * indexes them case-insensitively, and we then have to go through a
69 * linked list of potential case aliases (and, for MMacros, parameter
70 * ranges); this is to preserve the matching semantics of the earlier
71 * code. If the number of case aliases for a specific macro is a
72 * performance issue, you may want to reconsider your coding style.
76 * Store the definition of a single-line macro.
88 * Store the definition of a multi-line macro. This is also used to
89 * store the interiors of `%rep...%endrep' blocks, which are
90 * effectively self-re-invoking multi-line macros which simply
91 * don't have a name or bother to appear in the hash tables. %rep
92 * blocks are signified by having a NULL `name' field.
94 * In a MMacro describing a `%rep' block, the `in_progress' field
95 * isn't merely boolean, but gives the number of repeats left to
98 * The `next' field is used for storing MMacros in hash tables; the
99 * `next_active' field is for stacking them on istk entries.
101 * When a MMacro is being expanded, `params', `iline', `nparam',
102 * `paramlen', `rotate' and `unique' are local to the invocation.
107 int nparam_min
, nparam_max
;
109 bool plus
; /* is the last parameter greedy? */
110 bool nolist
; /* is this macro listing-inhibited? */
112 Token
*dlist
; /* All defaults as one list */
113 Token
**defaults
; /* Parameter default pointers */
114 int ndefs
; /* number of default parameters */
118 MMacro
*rep_nest
; /* used for nesting %rep */
119 Token
**params
; /* actual parameters */
120 Token
*iline
; /* invocation line */
121 unsigned int nparam
, rotate
;
124 int lineno
; /* Current line number on expansion */
128 * The context stack is composed of a linked list of these.
133 struct hash_table localmac
;
138 * This is the internal form which we break input lines up into.
139 * Typically stored in linked lists.
141 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
142 * necessarily used as-is, but is intended to denote the number of
143 * the substituted parameter. So in the definition
145 * %define a(x,y) ( (x) & ~(y) )
147 * the token representing `x' will have its type changed to
148 * TOK_SMAC_PARAM, but the one representing `y' will be
151 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
152 * which doesn't need quotes around it. Used in the pre-include
153 * mechanism as an alternative to trying to find a sensible type of
154 * quote to use on the filename we were passed.
157 TOK_NONE
= 0, TOK_WHITESPACE
, TOK_COMMENT
, TOK_ID
,
158 TOK_PREPROC_ID
, TOK_STRING
,
159 TOK_NUMBER
, TOK_FLOAT
, TOK_SMAC_END
, TOK_OTHER
,
161 TOK_PREPROC_Q
, TOK_PREPROC_QQ
,
162 TOK_SMAC_PARAM
, /* MUST BE LAST IN THE LIST!!! */
163 TOK_MAX
= INT_MAX
/* Keep compiler from reducing the range */
169 SMacro
*mac
; /* associated macro for TOK_SMAC_END */
170 enum pp_token_type type
;
174 * Multi-line macro definitions are stored as a linked list of
175 * these, which is essentially a container to allow several linked
178 * Note that in this module, linked lists are treated as stacks
179 * wherever possible. For this reason, Lines are _pushed_ on to the
180 * `expansion' field in MMacro structures, so that the linked list,
181 * if walked, would give the macro lines in reverse order; this
182 * means that we can walk the list when expanding a macro, and thus
183 * push the lines on to the `expansion' field in _istk_ in reverse
184 * order (so that when popped back off they are in the right
185 * order). It may seem cockeyed, and it relies on my design having
186 * an even number of steps in, but it works...
188 * Some of these structures, rather than being actual lines, are
189 * markers delimiting the end of the expansion of a given macro.
190 * This is for use in the cycle-tracking and %rep-handling code.
191 * Such structures have `finishes' non-NULL, and `first' NULL. All
192 * others have `finishes' NULL, but `first' may still be NULL if
202 * To handle an arbitrary level of file inclusion, we maintain a
203 * stack (ie linked list) of these things.
212 MMacro
*mstk
; /* stack of active macros/reps */
216 * Include search path. This is simply a list of strings which get
217 * prepended, in turn, to the name of an include file, in an
218 * attempt to find the file if it's not in the current directory.
226 * Conditional assembly: we maintain a separate stack of these for
227 * each level of file inclusion. (The only reason we keep the
228 * stacks separate is to ensure that a stray `%endif' in a file
229 * included from within the true branch of a `%if' won't terminate
230 * it and cause confusion: instead, rightly, it'll cause an error.)
238 * These states are for use just after %if or %elif: IF_TRUE
239 * means the condition has evaluated to truth so we are
240 * currently emitting, whereas IF_FALSE means we are not
241 * currently emitting but will start doing so if a %else comes
242 * up. In these states, all directives are admissible: %elif,
243 * %else and %endif. (And of course %if.)
245 COND_IF_TRUE
, COND_IF_FALSE
,
247 * These states come up after a %else: ELSE_TRUE means we're
248 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
249 * any %elif or %else will cause an error.
251 COND_ELSE_TRUE
, COND_ELSE_FALSE
,
253 * This state means that we're not emitting now, and also that
254 * nothing until %endif will be emitted at all. It's for use in
255 * two circumstances: (i) when we've had our moment of emission
256 * and have now started seeing %elifs, and (ii) when the
257 * condition construct in question is contained within a
258 * non-emitting branch of a larger condition construct.
262 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
265 * These defines are used as the possible return values for do_directive
267 #define NO_DIRECTIVE_FOUND 0
268 #define DIRECTIVE_FOUND 1
271 * Condition codes. Note that we use c_ prefix not C_ because C_ is
272 * used in nasm.h for the "real" condition codes. At _this_ level,
273 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
274 * ones, so we need a different enum...
276 static const char * const conditions
[] = {
277 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
278 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
279 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
282 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
283 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
284 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_RCXZ
, c_S
, c_Z
,
287 static const enum pp_conds inverse_ccs
[] = {
288 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
289 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
,
290 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, -1, c_NS
, c_NZ
296 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
297 static int is_condition(enum preproc_token arg
)
299 return PP_IS_COND(arg
) || (arg
== PP_ELSE
) || (arg
== PP_ENDIF
);
302 /* For TASM compatibility we need to be able to recognise TASM compatible
303 * conditional compilation directives. Using the NASM pre-processor does
304 * not work, so we look for them specifically from the following list and
305 * then jam in the equivalent NASM directive into the input stream.
309 TM_ARG
, TM_ELIF
, TM_ELSE
, TM_ENDIF
, TM_IF
, TM_IFDEF
, TM_IFDIFI
,
310 TM_IFNDEF
, TM_INCLUDE
, TM_LOCAL
313 static const char * const tasm_directives
[] = {
314 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
315 "ifndef", "include", "local"
318 static int StackSize
= 4;
319 static char *StackPointer
= "ebp";
320 static int ArgOffset
= 8;
321 static int LocalOffset
= 0;
323 static Context
*cstk
;
324 static Include
*istk
;
325 static IncPath
*ipath
= NULL
;
327 static efunc _error
; /* Pointer to client-provided error reporting function */
328 static evalfunc evaluate
;
330 static int pass
; /* HACK: pass 0 = generate dependencies only */
331 static StrList
**dephead
, **deptail
; /* Dependency list */
333 static uint64_t unique
; /* unique identifier numbers */
335 static Line
*predef
= NULL
;
337 static ListGen
*list
;
340 * The current set of multi-line macros we have defined.
342 static struct hash_table mmacros
;
345 * The current set of single-line macros we have defined.
347 static struct hash_table smacros
;
350 * The multi-line macro we are currently defining, or the %rep
351 * block we are currently reading, if any.
353 static MMacro
*defining
;
356 * The number of macro parameters to allocate space for at a time.
358 #define PARAM_DELTA 16
361 * The standard macro set: defined in macros.c in the array nasm_stdmac.
362 * This gives our position in the macro set, when we're processing it.
364 static const char * const *stdmacpos
;
367 * The extra standard macros that come from the object format, if
370 static const char * const *extrastdmac
= NULL
;
371 bool any_extrastdmac
;
374 * Tokens are allocated in blocks to improve speed
376 #define TOKEN_BLOCKSIZE 4096
377 static Token
*freeTokens
= NULL
;
383 static Blocks blocks
= { NULL
, NULL
};
386 * Forward declarations.
388 static Token
*expand_mmac_params(Token
* tline
);
389 static Token
*expand_smacro(Token
* tline
);
390 static Token
*expand_id(Token
* tline
);
391 static Context
*get_ctx(char *name
, bool all_contexts
);
392 static void make_tok_num(Token
* tok
, int64_t val
);
393 static void error(int severity
, const char *fmt
, ...);
394 static void *new_Block(size_t size
);
395 static void delete_Blocks(void);
396 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
397 const char *text
, int txtlen
);
398 static Token
*delete_Token(Token
* t
);
401 * Macros for safe checking of token pointers, avoid *(NULL)
403 #define tok_type_(x,t) ((x) && (x)->type == (t))
404 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
405 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
406 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
408 /* Handle TASM specific directives, which do not contain a % in
409 * front of them. We do it here because I could not find any other
410 * place to do it for the moment, and it is a hack (ideally it would
411 * be nice to be able to use the NASM pre-processor to do it).
413 static char *check_tasm_directive(char *line
)
415 int32_t i
, j
, k
, m
, len
;
416 char *p
= line
, *oldline
, oldchar
;
418 /* Skip whitespace */
419 while (isspace(*p
) && *p
!= 0)
422 /* Binary search for the directive name */
424 j
= elements(tasm_directives
);
426 while (!isspace(p
[len
]) && p
[len
] != 0)
433 m
= nasm_stricmp(p
, tasm_directives
[k
]);
435 /* We have found a directive, so jam a % in front of it
436 * so that NASM will then recognise it as one if it's own.
441 line
= nasm_malloc(len
+ 2);
443 if (k
== TM_IFDIFI
) {
444 /* NASM does not recognise IFDIFI, so we convert it to
445 * %ifdef BOGUS. This is not used in NASM comaptible
446 * code, but does need to parse for the TASM macro
449 strcpy(line
+ 1, "ifdef BOGUS");
451 memcpy(line
+ 1, p
, len
+ 1);
466 * The pre-preprocessing stage... This function translates line
467 * number indications as they emerge from GNU cpp (`# lineno "file"
468 * flags') into NASM preprocessor line number indications (`%line
471 static char *prepreproc(char *line
)
474 char *fname
, *oldline
;
476 if (line
[0] == '#' && line
[1] == ' ') {
479 lineno
= atoi(fname
);
480 fname
+= strspn(fname
, "0123456789 ");
483 fnlen
= strcspn(fname
, "\"");
484 line
= nasm_malloc(20 + fnlen
);
485 snprintf(line
, 20 + fnlen
, "%%line %d %.*s", lineno
, fnlen
, fname
);
488 if (tasm_compatible_mode
)
489 return check_tasm_directive(line
);
494 * Free a linked list of tokens.
496 static void free_tlist(Token
* list
)
499 list
= delete_Token(list
);
504 * Free a linked list of lines.
506 static void free_llist(Line
* list
)
512 free_tlist(l
->first
);
520 static void free_mmacro(MMacro
* m
)
523 free_tlist(m
->dlist
);
524 nasm_free(m
->defaults
);
525 free_llist(m
->expansion
);
530 * Free all currently defined macros, and free the hash tables
532 static void free_smacro_table(struct hash_table
*smt
)
536 struct hash_tbl_node
*it
= NULL
;
538 while ((s
= hash_iterate(smt
, &it
, &key
)) != NULL
) {
539 nasm_free((void *)key
);
541 SMacro
*ns
= s
->next
;
543 free_tlist(s
->expansion
);
551 static void free_mmacro_table(struct hash_table
*mmt
)
555 struct hash_tbl_node
*it
= NULL
;
558 while ((m
= hash_iterate(mmt
, &it
, &key
)) != NULL
) {
559 nasm_free((void *)key
);
561 MMacro
*nm
= m
->next
;
569 static void free_macros(void)
571 free_smacro_table(&smacros
);
572 free_mmacro_table(&mmacros
);
576 * Initialize the hash tables
578 static void init_macros(void)
580 hash_init(&smacros
, HASH_LARGE
);
581 hash_init(&mmacros
, HASH_LARGE
);
585 * Pop the context stack.
587 static void ctx_pop(void)
592 free_smacro_table(&c
->localmac
);
598 * Search for a key in the hash index; adding it if necessary
599 * (in which case we initialize the data pointer to NULL.)
602 hash_findi_add(struct hash_table
*hash
, const char *str
)
604 struct hash_insert hi
;
608 r
= hash_findi(hash
, str
, &hi
);
612 strx
= nasm_strdup(str
); /* Use a more efficient allocator here? */
613 return hash_add(&hi
, strx
, NULL
);
617 * Like hash_findi, but returns the data element rather than a pointer
618 * to it. Used only when not adding a new element, hence no third
622 hash_findix(struct hash_table
*hash
, const char *str
)
626 p
= hash_findi(hash
, str
, NULL
);
627 return p
? *p
: NULL
;
630 #define BUF_DELTA 512
632 * Read a line from the top file in istk, handling multiple CR/LFs
633 * at the end of the line read, and handling spurious ^Zs. Will
634 * return lines from the standard macro set if this has not already
637 static char *read_line(void)
639 char *buffer
, *p
, *q
;
640 int bufsize
, continued_count
;
644 char *ret
= nasm_strdup(*stdmacpos
++);
645 if (!*stdmacpos
&& any_extrastdmac
) {
646 stdmacpos
= extrastdmac
;
647 any_extrastdmac
= false;
651 * Nasty hack: here we push the contents of `predef' on
652 * to the top-level expansion stack, since this is the
653 * most convenient way to implement the pre-include and
654 * pre-define features.
658 Token
*head
, **tail
, *t
;
660 for (pd
= predef
; pd
; pd
= pd
->next
) {
663 for (t
= pd
->first
; t
; t
= t
->next
) {
664 *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
665 tail
= &(*tail
)->next
;
667 l
= nasm_malloc(sizeof(Line
));
668 l
->next
= istk
->expansion
;
681 buffer
= nasm_malloc(BUF_DELTA
);
685 q
= fgets(p
, bufsize
- (p
- buffer
), istk
->fp
);
689 if (p
> buffer
&& p
[-1] == '\n') {
690 /* Convert backslash-CRLF line continuation sequences into
691 nothing at all (for DOS and Windows) */
692 if (((p
- 2) > buffer
) && (p
[-3] == '\\') && (p
[-2] == '\r')) {
697 /* Also convert backslash-LF line continuation sequences into
698 nothing at all (for Unix) */
699 else if (((p
- 1) > buffer
) && (p
[-2] == '\\')) {
707 if (p
- buffer
> bufsize
- 10) {
708 int32_t offset
= p
- buffer
;
709 bufsize
+= BUF_DELTA
;
710 buffer
= nasm_realloc(buffer
, bufsize
);
711 p
= buffer
+ offset
; /* prevent stale-pointer problems */
715 if (!q
&& p
== buffer
) {
720 src_set_linnum(src_get_linnum() + istk
->lineinc
+
721 (continued_count
* istk
->lineinc
));
724 * Play safe: remove CRs as well as LFs, if any of either are
725 * present at the end of the line.
727 while (--p
>= buffer
&& (*p
== '\n' || *p
== '\r'))
731 * Handle spurious ^Z, which may be inserted into source files
732 * by some file transfer utilities.
734 buffer
[strcspn(buffer
, "\032")] = '\0';
736 list
->line(LIST_READ
, buffer
);
742 * Tokenize a line of text. This is a very simple process since we
743 * don't need to parse the value out of e.g. numeric tokens: we
744 * simply split one string into many.
746 static Token
*tokenize(char *line
)
749 enum pp_token_type type
;
751 Token
*t
, **tail
= &list
;
758 ((*p
== '-' || *p
== '+') && isdigit(p
[1])) ||
759 ((*p
== '+') && (isspace(p
[1]) || !p
[1]))) {
764 type
= TOK_PREPROC_ID
;
765 } else if (*p
== '{') {
767 while (*p
&& *p
!= '}') {
774 type
= TOK_PREPROC_ID
;
775 } else if (*p
== '?') {
776 type
= TOK_PREPROC_Q
; /* %? */
779 type
= TOK_PREPROC_QQ
; /* %?? */
782 } else if (isidchar(*p
) ||
783 ((*p
== '!' || *p
== '%' || *p
== '$') &&
788 while (isidchar(*p
));
789 type
= TOK_PREPROC_ID
;
795 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
798 while (*p
&& isidchar(*p
))
800 } else if (*p
== '\'' || *p
== '"' || *p
== '`') {
805 p
= nasm_skip_string(p
);
810 error(ERR_WARNING
, "unterminated string");
811 /* Handling unterminated strings by UNV */
814 } else if (isnumstart(*p
)) {
816 bool is_float
= false;
832 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
834 if (*p
== '+' || *p
== '-') {
835 /* e can only be followed by +/- if it is either a
836 prefixed hex number or a floating-point number */
840 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
842 } else if (c
== 'P' || c
== 'p') {
844 if (*p
== '+' || *p
== '-')
846 } else if (isnumchar(c
) || c
== '_')
849 /* we need to deal with consequences of the legacy
850 parser, like "1.nolist" being two tokens
851 (TOK_NUMBER, TOK_ID) here; at least give it
852 a shot for now. In the future, we probably need
853 a flex-based scanner with proper pattern matching
854 to do it as well as it can be done. Nothing in
855 the world is going to help the person who wants
856 0x123.p16 interpreted as two tokens, though. */
861 if (isdigit(*r
) || (is_hex
&& isxdigit(*r
)) ||
862 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
863 (*r
== 'p' || *r
== 'P')) {
867 break; /* Terminate the token */
871 p
--; /* Point to first character beyond number */
873 if (has_e
&& !is_hex
) {
874 /* 1e13 is floating-point, but 1e13h is not */
878 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
879 } else if (isspace(*p
)) {
880 type
= TOK_WHITESPACE
;
882 while (*p
&& isspace(*p
))
885 * Whitespace just before end-of-line is discarded by
886 * pretending it's a comment; whitespace just before a
887 * comment gets lumped into the comment.
889 if (!*p
|| *p
== ';') {
894 } else if (*p
== ';') {
900 * Anything else is an operator of some kind. We check
901 * for all the double-character operators (>>, <<, //,
902 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
903 * else is a single-character operator.
906 if ((p
[0] == '>' && p
[1] == '>') ||
907 (p
[0] == '<' && p
[1] == '<') ||
908 (p
[0] == '/' && p
[1] == '/') ||
909 (p
[0] == '<' && p
[1] == '=') ||
910 (p
[0] == '>' && p
[1] == '=') ||
911 (p
[0] == '=' && p
[1] == '=') ||
912 (p
[0] == '!' && p
[1] == '=') ||
913 (p
[0] == '<' && p
[1] == '>') ||
914 (p
[0] == '&' && p
[1] == '&') ||
915 (p
[0] == '|' && p
[1] == '|') ||
916 (p
[0] == '^' && p
[1] == '^')) {
922 /* Handling unterminated string by UNV */
925 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
926 t->text[p-line] = *line;
930 if (type
!= TOK_COMMENT
) {
931 *tail
= t
= new_Token(NULL
, type
, line
, p
- line
);
940 * this function allocates a new managed block of memory and
941 * returns a pointer to the block. The managed blocks are
942 * deleted only all at once by the delete_Blocks function.
944 static void *new_Block(size_t size
)
948 /* first, get to the end of the linked list */
951 /* now allocate the requested chunk */
952 b
->chunk
= nasm_malloc(size
);
954 /* now allocate a new block for the next request */
955 b
->next
= nasm_malloc(sizeof(Blocks
));
956 /* and initialize the contents of the new block */
957 b
->next
->next
= NULL
;
958 b
->next
->chunk
= NULL
;
963 * this function deletes all managed blocks of memory
965 static void delete_Blocks(void)
967 Blocks
*a
, *b
= &blocks
;
970 * keep in mind that the first block, pointed to by blocks
971 * is a static and not dynamically allocated, so we don't
985 * this function creates a new Token and passes a pointer to it
986 * back to the caller. It sets the type and text elements, and
987 * also the mac and next elements to NULL.
989 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
990 const char *text
, int txtlen
)
995 if (freeTokens
== NULL
) {
996 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
997 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
998 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
999 freeTokens
[i
].next
= NULL
;
1002 freeTokens
= t
->next
;
1006 if (type
== TOK_WHITESPACE
|| text
== NULL
) {
1010 txtlen
= strlen(text
);
1011 t
->text
= nasm_malloc(txtlen
+1);
1012 memcpy(t
->text
, text
, txtlen
);
1013 t
->text
[txtlen
] = '\0';
1018 static Token
*delete_Token(Token
* t
)
1020 Token
*next
= t
->next
;
1022 t
->next
= freeTokens
;
1028 * Convert a line of tokens back into text.
1029 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1030 * will be transformed into ..@ctxnum.xxx
1032 static char *detoken(Token
* tlist
, bool expand_locals
)
1040 for (t
= tlist
; t
; t
= t
->next
) {
1041 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
1042 char *p
= getenv(t
->text
+ 2);
1045 t
->text
= nasm_strdup(p
);
1049 /* Expand local macros here and not during preprocessing */
1050 if (expand_locals
&&
1051 t
->type
== TOK_PREPROC_ID
&& t
->text
&&
1052 t
->text
[0] == '%' && t
->text
[1] == '$') {
1053 Context
*ctx
= get_ctx(t
->text
, false);
1056 char *p
, *q
= t
->text
+ 2;
1058 q
+= strspn(q
, "$");
1059 snprintf(buffer
, sizeof(buffer
), "..@%"PRIu32
".", ctx
->number
);
1060 p
= nasm_strcat(buffer
, q
);
1065 if (t
->type
== TOK_WHITESPACE
) {
1067 } else if (t
->text
) {
1068 len
+= strlen(t
->text
);
1071 p
= line
= nasm_malloc(len
+ 1);
1072 for (t
= tlist
; t
; t
= t
->next
) {
1073 if (t
->type
== TOK_WHITESPACE
) {
1075 } else if (t
->text
) {
1086 * A scanner, suitable for use by the expression evaluator, which
1087 * operates on a line of Tokens. Expects a pointer to a pointer to
1088 * the first token in the line to be passed in as its private_data
1091 * FIX: This really needs to be unified with stdscan.
1093 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1095 Token
**tlineptr
= private_data
;
1097 char ourcopy
[MAX_KEYWORD
+1], *p
, *r
, *s
;
1101 *tlineptr
= tline
? tline
->next
: NULL
;
1103 while (tline
&& (tline
->type
== TOK_WHITESPACE
||
1104 tline
->type
== TOK_COMMENT
));
1107 return tokval
->t_type
= TOKEN_EOS
;
1109 tokval
->t_charptr
= tline
->text
;
1111 if (tline
->text
[0] == '$' && !tline
->text
[1])
1112 return tokval
->t_type
= TOKEN_HERE
;
1113 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[2])
1114 return tokval
->t_type
= TOKEN_BASE
;
1116 if (tline
->type
== TOK_ID
) {
1117 p
= tokval
->t_charptr
= tline
->text
;
1119 tokval
->t_charptr
++;
1120 return tokval
->t_type
= TOKEN_ID
;
1123 for (r
= p
, s
= ourcopy
; *r
; r
++) {
1124 if (r
>= p
+MAX_KEYWORD
)
1125 return tokval
->t_type
= TOKEN_ID
; /* Not a keyword */
1129 /* right, so we have an identifier sitting in temp storage. now,
1130 * is it actually a register or instruction name, or what? */
1131 return nasm_token_hash(ourcopy
, tokval
);
1134 if (tline
->type
== TOK_NUMBER
) {
1136 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
1138 return tokval
->t_type
= TOKEN_ERRNUM
; /* some malformation occurred */
1139 tokval
->t_charptr
= tline
->text
;
1140 return tokval
->t_type
= TOKEN_NUM
;
1143 if (tline
->type
== TOK_FLOAT
) {
1144 return tokval
->t_type
= TOKEN_FLOAT
;
1147 if (tline
->type
== TOK_STRING
) {
1153 bq
= tline
->text
[0];
1154 l
= nasm_unquote(tline
->text
, &ep
);
1155 if (ep
[0] != bq
|| ep
[1] != '\0')
1159 return tokval
->t_type
= TOKEN_ERRNUM
;
1161 tokval
->t_integer
= readstrnum(tline
->text
, l
, &rn_warn
);
1163 error(ERR_WARNING
| ERR_PASS1
, "character constant too long");
1164 tokval
->t_charptr
= NULL
;
1165 return tokval
->t_type
= TOKEN_NUM
;
1168 if (tline
->type
== TOK_OTHER
) {
1169 if (!strcmp(tline
->text
, "<<"))
1170 return tokval
->t_type
= TOKEN_SHL
;
1171 if (!strcmp(tline
->text
, ">>"))
1172 return tokval
->t_type
= TOKEN_SHR
;
1173 if (!strcmp(tline
->text
, "//"))
1174 return tokval
->t_type
= TOKEN_SDIV
;
1175 if (!strcmp(tline
->text
, "%%"))
1176 return tokval
->t_type
= TOKEN_SMOD
;
1177 if (!strcmp(tline
->text
, "=="))
1178 return tokval
->t_type
= TOKEN_EQ
;
1179 if (!strcmp(tline
->text
, "<>"))
1180 return tokval
->t_type
= TOKEN_NE
;
1181 if (!strcmp(tline
->text
, "!="))
1182 return tokval
->t_type
= TOKEN_NE
;
1183 if (!strcmp(tline
->text
, "<="))
1184 return tokval
->t_type
= TOKEN_LE
;
1185 if (!strcmp(tline
->text
, ">="))
1186 return tokval
->t_type
= TOKEN_GE
;
1187 if (!strcmp(tline
->text
, "&&"))
1188 return tokval
->t_type
= TOKEN_DBL_AND
;
1189 if (!strcmp(tline
->text
, "^^"))
1190 return tokval
->t_type
= TOKEN_DBL_XOR
;
1191 if (!strcmp(tline
->text
, "||"))
1192 return tokval
->t_type
= TOKEN_DBL_OR
;
1196 * We have no other options: just return the first character of
1199 return tokval
->t_type
= tline
->text
[0];
1203 * Compare a string to the name of an existing macro; this is a
1204 * simple wrapper which calls either strcmp or nasm_stricmp
1205 * depending on the value of the `casesense' parameter.
1207 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
1209 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
1213 * Compare a string to the name of an existing macro; this is a
1214 * simple wrapper which calls either strcmp or nasm_stricmp
1215 * depending on the value of the `casesense' parameter.
1217 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
1219 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
1223 * Return the Context structure associated with a %$ token. Return
1224 * NULL, having _already_ reported an error condition, if the
1225 * context stack isn't deep enough for the supplied number of $
1227 * If all_contexts == true, contexts that enclose current are
1228 * also scanned for such smacro, until it is found; if not -
1229 * only the context that directly results from the number of $'s
1230 * in variable's name.
1232 static Context
*get_ctx(char *name
, bool all_contexts
)
1238 if (!name
|| name
[0] != '%' || name
[1] != '$')
1242 error(ERR_NONFATAL
, "`%s': context stack is empty", name
);
1246 for (i
= strspn(name
+ 2, "$"), ctx
= cstk
; (i
> 0) && ctx
; i
--) {
1248 /* i--; Lino - 02/25/02 */
1251 error(ERR_NONFATAL
, "`%s': context stack is only"
1252 " %d level%s deep", name
, i
- 1, (i
== 2 ? "" : "s"));
1259 /* Search for this smacro in found context */
1260 m
= hash_findix(&ctx
->localmac
, name
);
1262 if (!mstrcmp(m
->name
, name
, m
->casesense
))
1273 * Check to see if a file is already in a string list
1275 static bool in_list(const StrList
*list
, const char *str
)
1278 if (!strcmp(list
->str
, str
))
1286 * Open an include file. This routine must always return a valid
1287 * file pointer if it returns - it's responsible for throwing an
1288 * ERR_FATAL and bombing out completely if not. It should also try
1289 * the include path one by one until it finds the file or reaches
1290 * the end of the path.
1292 static FILE *inc_fopen(const char *file
, StrList
**dhead
, StrList
***dtail
,
1297 IncPath
*ip
= ipath
;
1298 int len
= strlen(file
);
1299 size_t prefix_len
= 0;
1303 sl
= nasm_malloc(prefix_len
+len
+1+sizeof sl
->next
);
1304 memcpy(sl
->str
, prefix
, prefix_len
);
1305 memcpy(sl
->str
+prefix_len
, file
, len
+1);
1306 fp
= fopen(sl
->str
, "r");
1307 if (fp
&& dhead
&& !in_list(*dhead
, sl
->str
)) {
1325 prefix_len
= strlen(prefix
);
1327 /* -MG given and file not found */
1328 if (dhead
&& !in_list(*dhead
, file
)) {
1329 sl
= nasm_malloc(len
+1+sizeof sl
->next
);
1331 strcpy(sl
->str
, file
);
1339 error(ERR_FATAL
, "unable to open include file `%s'", file
);
1340 return NULL
; /* never reached - placate compilers */
1344 * Determine if we should warn on defining a single-line macro of
1345 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1346 * return true if _any_ single-line macro of that name is defined.
1347 * Otherwise, will return true if a single-line macro with either
1348 * `nparam' or no parameters is defined.
1350 * If a macro with precisely the right number of parameters is
1351 * defined, or nparam is -1, the address of the definition structure
1352 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1353 * is NULL, no action will be taken regarding its contents, and no
1356 * Note that this is also called with nparam zero to resolve
1359 * If you already know which context macro belongs to, you can pass
1360 * the context pointer as first parameter; if you won't but name begins
1361 * with %$ the context will be automatically computed. If all_contexts
1362 * is true, macro will be searched in outer contexts as well.
1365 smacro_defined(Context
* ctx
, char *name
, int nparam
, SMacro
** defn
,
1368 struct hash_table
*smtbl
;
1372 smtbl
= &ctx
->localmac
;
1373 } else if (name
[0] == '%' && name
[1] == '$') {
1375 ctx
= get_ctx(name
, false);
1377 return false; /* got to return _something_ */
1378 smtbl
= &ctx
->localmac
;
1382 m
= (SMacro
*) hash_findix(smtbl
, name
);
1385 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
1386 (nparam
<= 0 || m
->nparam
== 0 || nparam
== (int) m
->nparam
)) {
1388 if (nparam
== (int) m
->nparam
|| nparam
== -1)
1402 * Count and mark off the parameters in a multi-line macro call.
1403 * This is called both from within the multi-line macro expansion
1404 * code, and also to mark off the default parameters when provided
1405 * in a %macro definition line.
1407 static void count_mmac_params(Token
* t
, int *nparam
, Token
*** params
)
1409 int paramsize
, brace
;
1411 *nparam
= paramsize
= 0;
1414 if (*nparam
>= paramsize
) {
1415 paramsize
+= PARAM_DELTA
;
1416 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
1420 if (tok_is_(t
, "{"))
1422 (*params
)[(*nparam
)++] = t
;
1423 while (tok_isnt_(t
, brace
? "}" : ","))
1425 if (t
) { /* got a comma/brace */
1429 * Now we've found the closing brace, look further
1433 if (tok_isnt_(t
, ",")) {
1435 "braces do not enclose all of macro parameter");
1436 while (tok_isnt_(t
, ","))
1440 t
= t
->next
; /* eat the comma */
1447 * Determine whether one of the various `if' conditions is true or
1450 * We must free the tline we get passed.
1452 static bool if_condition(Token
* tline
, enum preproc_token ct
)
1454 enum pp_conditional i
= PP_COND(ct
);
1456 Token
*t
, *tt
, **tptr
, *origline
;
1457 struct tokenval tokval
;
1459 enum pp_token_type needtype
;
1465 j
= false; /* have we matched yet? */
1466 while (cstk
&& tline
) {
1468 if (!tline
|| tline
->type
!= TOK_ID
) {
1470 "`%s' expects context identifiers", pp_directives
[ct
]);
1471 free_tlist(origline
);
1474 if (!nasm_stricmp(tline
->text
, cstk
->name
))
1476 tline
= tline
->next
;
1481 j
= false; /* have we matched yet? */
1484 if (!tline
|| (tline
->type
!= TOK_ID
&&
1485 (tline
->type
!= TOK_PREPROC_ID
||
1486 tline
->text
[1] != '$'))) {
1488 "`%s' expects macro identifiers", pp_directives
[ct
]);
1491 if (smacro_defined(NULL
, tline
->text
, 0, NULL
, true))
1493 tline
= tline
->next
;
1499 tline
= expand_smacro(tline
);
1501 while (tok_isnt_(tt
, ","))
1505 "`%s' expects two comma-separated arguments",
1510 j
= true; /* assume equality unless proved not */
1511 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1512 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1513 error(ERR_NONFATAL
, "`%s': more than one comma on line",
1517 if (t
->type
== TOK_WHITESPACE
) {
1521 if (tt
->type
== TOK_WHITESPACE
) {
1525 if (tt
->type
!= t
->type
) {
1526 j
= false; /* found mismatching tokens */
1529 /* When comparing strings, need to unquote them first */
1530 if (t
->type
== TOK_STRING
) {
1531 size_t l1
= nasm_unquote(t
->text
, NULL
);
1532 size_t l2
= nasm_unquote(tt
->text
, NULL
);
1538 if (mmemcmp(t
->text
, tt
->text
, l1
, i
== PPC_IFIDN
)) {
1542 } else if (mstrcmp(tt
->text
, t
->text
, i
== PPC_IFIDN
) != 0) {
1543 j
= false; /* found mismatching tokens */
1550 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
1551 j
= false; /* trailing gunk on one end or other */
1557 MMacro searching
, *mmac
;
1559 tline
= tline
->next
;
1561 tline
= expand_id(tline
);
1562 if (!tok_type_(tline
, TOK_ID
)) {
1564 "`%s' expects a macro name", pp_directives
[ct
]);
1567 searching
.name
= nasm_strdup(tline
->text
);
1568 searching
.casesense
= true;
1569 searching
.plus
= false;
1570 searching
.nolist
= false;
1571 searching
.in_progress
= 0;
1572 searching
.rep_nest
= NULL
;
1573 searching
.nparam_min
= 0;
1574 searching
.nparam_max
= INT_MAX
;
1575 tline
= expand_smacro(tline
->next
);
1578 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
1580 "`%s' expects a parameter count or nothing",
1583 searching
.nparam_min
= searching
.nparam_max
=
1584 readnum(tline
->text
, &j
);
1587 "unable to parse parameter count `%s'",
1590 if (tline
&& tok_is_(tline
->next
, "-")) {
1591 tline
= tline
->next
->next
;
1592 if (tok_is_(tline
, "*"))
1593 searching
.nparam_max
= INT_MAX
;
1594 else if (!tok_type_(tline
, TOK_NUMBER
))
1596 "`%s' expects a parameter count after `-'",
1599 searching
.nparam_max
= readnum(tline
->text
, &j
);
1602 "unable to parse parameter count `%s'",
1604 if (searching
.nparam_min
> searching
.nparam_max
)
1606 "minimum parameter count exceeds maximum");
1609 if (tline
&& tok_is_(tline
->next
, "+")) {
1610 tline
= tline
->next
;
1611 searching
.plus
= true;
1613 mmac
= (MMacro
*) hash_findix(&mmacros
, searching
.name
);
1615 if (!strcmp(mmac
->name
, searching
.name
) &&
1616 (mmac
->nparam_min
<= searching
.nparam_max
1618 && (searching
.nparam_min
<= mmac
->nparam_max
1625 nasm_free(searching
.name
);
1634 needtype
= TOK_NUMBER
;
1637 needtype
= TOK_STRING
;
1641 t
= tline
= expand_smacro(tline
);
1643 while (tok_type_(t
, TOK_WHITESPACE
) ||
1644 (needtype
== TOK_NUMBER
&&
1645 tok_type_(t
, TOK_OTHER
) &&
1646 (t
->text
[0] == '-' || t
->text
[0] == '+') &&
1650 j
= tok_type_(t
, needtype
);
1654 t
= tline
= expand_smacro(tline
);
1655 while (tok_type_(t
, TOK_WHITESPACE
))
1660 t
= t
->next
; /* Skip the actual token */
1661 while (tok_type_(t
, TOK_WHITESPACE
))
1663 j
= !t
; /* Should be nothing left */
1668 t
= tline
= expand_smacro(tline
);
1669 while (tok_type_(t
, TOK_WHITESPACE
))
1672 j
= !t
; /* Should be empty */
1676 t
= tline
= expand_smacro(tline
);
1678 tokval
.t_type
= TOKEN_INVALID
;
1679 evalresult
= evaluate(ppscan
, tptr
, &tokval
,
1680 NULL
, pass
| CRITICAL
, error
, NULL
);
1685 "trailing garbage after expression ignored");
1686 if (!is_simple(evalresult
)) {
1688 "non-constant value given to `%s'", pp_directives
[ct
]);
1691 j
= reloc_value(evalresult
) != 0;
1696 "preprocessor directive `%s' not yet implemented",
1701 free_tlist(origline
);
1702 return j
^ PP_NEGATIVE(ct
);
1705 free_tlist(origline
);
1710 * Expand macros in a string. Used in %error directives (and it should
1711 * almost certainly be removed from there, too.)
1713 * First tokenize the string, apply "expand_smacro" and then de-tokenize back.
1714 * The returned variable should ALWAYS be freed after usage.
1716 void expand_macros_in_string(char **p
)
1718 Token
*line
= tokenize(*p
);
1719 line
= expand_smacro(line
);
1720 *p
= detoken(line
, false);
1724 * Common code for defining an smacro
1726 static bool define_smacro(Context
*ctx
, char *mname
, bool casesense
,
1727 int nparam
, Token
*expansion
)
1729 SMacro
*smac
, **smhead
;
1730 struct hash_table
*smtbl
;
1732 if (smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
)) {
1735 "single-line macro `%s' defined both with and"
1736 " without parameters", mname
);
1738 /* Some instances of the old code considered this a failure,
1739 some others didn't. What is the right thing to do here? */
1740 free_tlist(expansion
);
1741 return false; /* Failure */
1744 * We're redefining, so we have to take over an
1745 * existing SMacro structure. This means freeing
1746 * what was already in it.
1748 nasm_free(smac
->name
);
1749 free_tlist(smac
->expansion
);
1752 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
1753 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
1754 smac
= nasm_malloc(sizeof(SMacro
));
1755 smac
->next
= *smhead
;
1758 smac
->name
= nasm_strdup(mname
);
1759 smac
->casesense
= casesense
;
1760 smac
->nparam
= nparam
;
1761 smac
->expansion
= expansion
;
1762 smac
->in_progress
= false;
1763 return true; /* Success */
1767 * Undefine an smacro
1769 static void undef_smacro(Context
*ctx
, const char *mname
)
1771 SMacro
**smhead
, *s
, **sp
;
1772 struct hash_table
*smtbl
;
1774 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
1775 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
1779 * We now have a macro name... go hunt for it.
1782 while ((s
= *sp
) != NULL
) {
1783 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
1786 free_tlist(s
->expansion
);
1796 * Decode a size directive
1798 static int parse_size(const char *str
) {
1799 static const char *size_names
[] =
1800 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
1801 static const int sizes
[] =
1802 { 0, 1, 4, 16, 8, 10, 2, 32 };
1804 return sizes
[bsii(str
, size_names
, elements(size_names
))+1];
1808 * find and process preprocessor directive in passed line
1809 * Find out if a line contains a preprocessor directive, and deal
1812 * If a directive _is_ found, it is the responsibility of this routine
1813 * (and not the caller) to free_tlist() the line.
1815 * @param tline a pointer to the current tokeninzed line linked list
1816 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
1819 static int do_directive(Token
* tline
)
1821 enum preproc_token i
;
1833 MMacro
*mmac
, **mmhead
;
1834 Token
*t
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
1836 struct tokenval tokval
;
1838 MMacro
*tmp_defining
; /* Used when manipulating rep_nest */
1844 if (!tline
|| !tok_type_(tline
, TOK_PREPROC_ID
) ||
1845 (tline
->text
[1] == '%' || tline
->text
[1] == '$'
1846 || tline
->text
[1] == '!'))
1847 return NO_DIRECTIVE_FOUND
;
1849 i
= pp_token_hash(tline
->text
);
1852 * If we're in a non-emitting branch of a condition construct,
1853 * or walking to the end of an already terminated %rep block,
1854 * we should ignore all directives except for condition
1857 if (((istk
->conds
&& !emitting(istk
->conds
->state
)) ||
1858 (istk
->mstk
&& !istk
->mstk
->in_progress
)) && !is_condition(i
)) {
1859 return NO_DIRECTIVE_FOUND
;
1863 * If we're defining a macro or reading a %rep block, we should
1864 * ignore all directives except for %macro/%imacro (which
1865 * generate an error), %endm/%endmacro, and (only if we're in a
1866 * %rep block) %endrep. If we're in a %rep block, another %rep
1867 * causes an error, so should be let through.
1869 if (defining
&& i
!= PP_MACRO
&& i
!= PP_IMACRO
&&
1870 i
!= PP_ENDMACRO
&& i
!= PP_ENDM
&&
1871 (defining
->name
|| (i
!= PP_ENDREP
&& i
!= PP_REP
))) {
1872 return NO_DIRECTIVE_FOUND
;
1877 error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
1879 return NO_DIRECTIVE_FOUND
; /* didn't get it */
1882 /* Directive to tell NASM what the default stack size is. The
1883 * default is for a 16-bit stack, and this can be overriden with
1885 * the following form:
1887 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1889 tline
= tline
->next
;
1890 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1891 tline
= tline
->next
;
1892 if (!tline
|| tline
->type
!= TOK_ID
) {
1893 error(ERR_NONFATAL
, "`%%stacksize' missing size parameter");
1894 free_tlist(origline
);
1895 return DIRECTIVE_FOUND
;
1897 if (nasm_stricmp(tline
->text
, "flat") == 0) {
1898 /* All subsequent ARG directives are for a 32-bit stack */
1900 StackPointer
= "ebp";
1903 } else if (nasm_stricmp(tline
->text
, "flat64") == 0) {
1904 /* All subsequent ARG directives are for a 64-bit stack */
1906 StackPointer
= "rbp";
1909 } else if (nasm_stricmp(tline
->text
, "large") == 0) {
1910 /* All subsequent ARG directives are for a 16-bit stack,
1911 * far function call.
1914 StackPointer
= "bp";
1917 } else if (nasm_stricmp(tline
->text
, "small") == 0) {
1918 /* All subsequent ARG directives are for a 16-bit stack,
1919 * far function call. We don't support near functions.
1922 StackPointer
= "bp";
1926 error(ERR_NONFATAL
, "`%%stacksize' invalid size type");
1927 free_tlist(origline
);
1928 return DIRECTIVE_FOUND
;
1930 free_tlist(origline
);
1931 return DIRECTIVE_FOUND
;
1934 /* TASM like ARG directive to define arguments to functions, in
1935 * the following form:
1937 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1941 char *arg
, directive
[256];
1942 int size
= StackSize
;
1944 /* Find the argument name */
1945 tline
= tline
->next
;
1946 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1947 tline
= tline
->next
;
1948 if (!tline
|| tline
->type
!= TOK_ID
) {
1949 error(ERR_NONFATAL
, "`%%arg' missing argument parameter");
1950 free_tlist(origline
);
1951 return DIRECTIVE_FOUND
;
1955 /* Find the argument size type */
1956 tline
= tline
->next
;
1957 if (!tline
|| tline
->type
!= TOK_OTHER
1958 || tline
->text
[0] != ':') {
1960 "Syntax error processing `%%arg' directive");
1961 free_tlist(origline
);
1962 return DIRECTIVE_FOUND
;
1964 tline
= tline
->next
;
1965 if (!tline
|| tline
->type
!= TOK_ID
) {
1966 error(ERR_NONFATAL
, "`%%arg' missing size type parameter");
1967 free_tlist(origline
);
1968 return DIRECTIVE_FOUND
;
1971 /* Allow macro expansion of type parameter */
1972 tt
= tokenize(tline
->text
);
1973 tt
= expand_smacro(tt
);
1974 size
= parse_size(tt
->text
);
1977 "Invalid size type for `%%arg' missing directive");
1979 free_tlist(origline
);
1980 return DIRECTIVE_FOUND
;
1984 /* Round up to even stack slots */
1985 size
= (size
+StackSize
-1) & ~(StackSize
-1);
1987 /* Now define the macro for the argument */
1988 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
1989 arg
, StackPointer
, offset
);
1990 do_directive(tokenize(directive
));
1993 /* Move to the next argument in the list */
1994 tline
= tline
->next
;
1995 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1996 tline
= tline
->next
;
1997 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
1999 free_tlist(origline
);
2000 return DIRECTIVE_FOUND
;
2003 /* TASM like LOCAL directive to define local variables for a
2004 * function, in the following form:
2006 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2008 * The '= LocalSize' at the end is ignored by NASM, but is
2009 * required by TASM to define the local parameter size (and used
2010 * by the TASM macro package).
2012 offset
= LocalOffset
;
2014 char *local
, directive
[256];
2015 int size
= StackSize
;
2017 /* Find the argument name */
2018 tline
= tline
->next
;
2019 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2020 tline
= tline
->next
;
2021 if (!tline
|| tline
->type
!= TOK_ID
) {
2023 "`%%local' missing argument parameter");
2024 free_tlist(origline
);
2025 return DIRECTIVE_FOUND
;
2027 local
= tline
->text
;
2029 /* Find the argument size type */
2030 tline
= tline
->next
;
2031 if (!tline
|| tline
->type
!= TOK_OTHER
2032 || tline
->text
[0] != ':') {
2034 "Syntax error processing `%%local' directive");
2035 free_tlist(origline
);
2036 return DIRECTIVE_FOUND
;
2038 tline
= tline
->next
;
2039 if (!tline
|| tline
->type
!= TOK_ID
) {
2041 "`%%local' missing size type parameter");
2042 free_tlist(origline
);
2043 return DIRECTIVE_FOUND
;
2046 /* Allow macro expansion of type parameter */
2047 tt
= tokenize(tline
->text
);
2048 tt
= expand_smacro(tt
);
2049 size
= parse_size(tt
->text
);
2052 "Invalid size type for `%%local' missing directive");
2054 free_tlist(origline
);
2055 return DIRECTIVE_FOUND
;
2059 /* Round up to even stack slots */
2060 size
= (size
+StackSize
-1) & ~(StackSize
-1);
2062 offset
+= size
; /* Negative offset, increment before */
2064 /* Now define the macro for the argument */
2065 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
2066 local
, StackPointer
, offset
);
2067 do_directive(tokenize(directive
));
2069 /* Now define the assign to setup the enter_c macro correctly */
2070 snprintf(directive
, sizeof(directive
),
2071 "%%assign %%$localsize %%$localsize+%d", size
);
2072 do_directive(tokenize(directive
));
2074 /* Move to the next argument in the list */
2075 tline
= tline
->next
;
2076 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2077 tline
= tline
->next
;
2078 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2079 LocalOffset
= offset
;
2080 free_tlist(origline
);
2081 return DIRECTIVE_FOUND
;
2085 error(ERR_WARNING
, "trailing garbage after `%%clear' ignored");
2088 free_tlist(origline
);
2089 return DIRECTIVE_FOUND
;
2092 t
= tline
->next
= expand_smacro(tline
->next
);
2094 if (!t
|| (t
->type
!= TOK_STRING
&&
2095 t
->type
!= TOK_INTERNAL_STRING
)) {
2096 error(ERR_NONFATAL
, "`%%depend' expects a file name");
2097 free_tlist(origline
);
2098 return DIRECTIVE_FOUND
; /* but we did _something_ */
2102 "trailing garbage after `%%depend' ignored");
2104 if (t
->type
!= TOK_INTERNAL_STRING
)
2105 nasm_unquote(p
, NULL
);
2106 if (dephead
&& !in_list(*dephead
, p
)) {
2107 StrList
*sl
= nasm_malloc(strlen(p
)+1+sizeof sl
->next
);
2111 deptail
= &sl
->next
;
2113 free_tlist(origline
);
2114 return DIRECTIVE_FOUND
;
2117 t
= tline
->next
= expand_smacro(tline
->next
);
2120 if (!t
|| (t
->type
!= TOK_STRING
&&
2121 t
->type
!= TOK_INTERNAL_STRING
)) {
2122 error(ERR_NONFATAL
, "`%%include' expects a file name");
2123 free_tlist(origline
);
2124 return DIRECTIVE_FOUND
; /* but we did _something_ */
2128 "trailing garbage after `%%include' ignored");
2130 if (t
->type
!= TOK_INTERNAL_STRING
)
2131 nasm_unquote(p
, NULL
);
2132 inc
= nasm_malloc(sizeof(Include
));
2135 inc
->fp
= inc_fopen(p
, dephead
, &deptail
, pass
== 0);
2137 /* -MG given but file not found */
2140 inc
->fname
= src_set_fname(nasm_strdup(p
));
2141 inc
->lineno
= src_set_linnum(0);
2143 inc
->expansion
= NULL
;
2146 list
->uplevel(LIST_INCLUDE
);
2148 free_tlist(origline
);
2149 return DIRECTIVE_FOUND
;
2152 tline
= tline
->next
;
2154 tline
= expand_id(tline
);
2155 if (!tok_type_(tline
, TOK_ID
)) {
2156 error(ERR_NONFATAL
, "`%%push' expects a context identifier");
2157 free_tlist(origline
);
2158 return DIRECTIVE_FOUND
; /* but we did _something_ */
2161 error(ERR_WARNING
, "trailing garbage after `%%push' ignored");
2162 ctx
= nasm_malloc(sizeof(Context
));
2164 hash_init(&ctx
->localmac
, HASH_SMALL
);
2165 ctx
->name
= nasm_strdup(tline
->text
);
2166 ctx
->number
= unique
++;
2168 free_tlist(origline
);
2172 tline
= tline
->next
;
2174 tline
= expand_id(tline
);
2175 if (!tok_type_(tline
, TOK_ID
)) {
2176 error(ERR_NONFATAL
, "`%%repl' expects a context identifier");
2177 free_tlist(origline
);
2178 return DIRECTIVE_FOUND
; /* but we did _something_ */
2181 error(ERR_WARNING
, "trailing garbage after `%%repl' ignored");
2183 error(ERR_NONFATAL
, "`%%repl': context stack is empty");
2185 nasm_free(cstk
->name
);
2186 cstk
->name
= nasm_strdup(tline
->text
);
2188 free_tlist(origline
);
2193 error(ERR_WARNING
, "trailing garbage after `%%pop' ignored");
2195 error(ERR_NONFATAL
, "`%%pop': context stack is already empty");
2198 free_tlist(origline
);
2202 tline
->next
= expand_smacro(tline
->next
);
2203 tline
= tline
->next
;
2205 if (tok_type_(tline
, TOK_STRING
)) {
2207 nasm_unquote(p
, NULL
);
2208 expand_macros_in_string(&p
); /* WHY? */
2209 error(ERR_NONFATAL
, "%s", p
);
2212 p
= detoken(tline
, false);
2213 error(ERR_WARNING
, "%s", p
); /* WARNING!??!! */
2216 free_tlist(origline
);
2220 if (istk
->conds
&& !emitting(istk
->conds
->state
))
2223 j
= if_condition(tline
->next
, i
);
2224 tline
->next
= NULL
; /* it got freed */
2225 j
= j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2227 cond
= nasm_malloc(sizeof(Cond
));
2228 cond
->next
= istk
->conds
;
2231 free_tlist(origline
);
2232 return DIRECTIVE_FOUND
;
2236 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2237 if (emitting(istk
->conds
->state
)
2238 || istk
->conds
->state
== COND_NEVER
)
2239 istk
->conds
->state
= COND_NEVER
;
2242 * IMPORTANT: In the case of %if, we will already have
2243 * called expand_mmac_params(); however, if we're
2244 * processing an %elif we must have been in a
2245 * non-emitting mode, which would have inhibited
2246 * the normal invocation of expand_mmac_params(). Therefore,
2247 * we have to do it explicitly here.
2249 j
= if_condition(expand_mmac_params(tline
->next
), i
);
2250 tline
->next
= NULL
; /* it got freed */
2251 istk
->conds
->state
=
2252 j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2254 free_tlist(origline
);
2255 return DIRECTIVE_FOUND
;
2259 error(ERR_WARNING
, "trailing garbage after `%%else' ignored");
2261 error(ERR_FATAL
, "`%%else': no matching `%%if'");
2262 if (emitting(istk
->conds
->state
)
2263 || istk
->conds
->state
== COND_NEVER
)
2264 istk
->conds
->state
= COND_ELSE_FALSE
;
2266 istk
->conds
->state
= COND_ELSE_TRUE
;
2267 free_tlist(origline
);
2268 return DIRECTIVE_FOUND
;
2272 error(ERR_WARNING
, "trailing garbage after `%%endif' ignored");
2274 error(ERR_FATAL
, "`%%endif': no matching `%%if'");
2276 istk
->conds
= cond
->next
;
2278 free_tlist(origline
);
2279 return DIRECTIVE_FOUND
;
2285 "`%%%smacro': already defining a macro",
2286 (i
== PP_IMACRO
? "i" : ""));
2287 tline
= tline
->next
;
2289 tline
= expand_id(tline
);
2290 if (!tok_type_(tline
, TOK_ID
)) {
2292 "`%%%smacro' expects a macro name",
2293 (i
== PP_IMACRO
? "i" : ""));
2294 return DIRECTIVE_FOUND
;
2296 defining
= nasm_malloc(sizeof(MMacro
));
2297 defining
->name
= nasm_strdup(tline
->text
);
2298 defining
->casesense
= (i
== PP_MACRO
);
2299 defining
->plus
= false;
2300 defining
->nolist
= false;
2301 defining
->in_progress
= 0;
2302 defining
->rep_nest
= NULL
;
2303 tline
= expand_smacro(tline
->next
);
2305 if (!tok_type_(tline
, TOK_NUMBER
)) {
2307 "`%%%smacro' expects a parameter count",
2308 (i
== PP_IMACRO
? "i" : ""));
2309 defining
->nparam_min
= defining
->nparam_max
= 0;
2311 defining
->nparam_min
= defining
->nparam_max
=
2312 readnum(tline
->text
, &err
);
2315 "unable to parse parameter count `%s'", tline
->text
);
2317 if (tline
&& tok_is_(tline
->next
, "-")) {
2318 tline
= tline
->next
->next
;
2319 if (tok_is_(tline
, "*"))
2320 defining
->nparam_max
= INT_MAX
;
2321 else if (!tok_type_(tline
, TOK_NUMBER
))
2323 "`%%%smacro' expects a parameter count after `-'",
2324 (i
== PP_IMACRO
? "i" : ""));
2326 defining
->nparam_max
= readnum(tline
->text
, &err
);
2329 "unable to parse parameter count `%s'",
2331 if (defining
->nparam_min
> defining
->nparam_max
)
2333 "minimum parameter count exceeds maximum");
2336 if (tline
&& tok_is_(tline
->next
, "+")) {
2337 tline
= tline
->next
;
2338 defining
->plus
= true;
2340 if (tline
&& tok_type_(tline
->next
, TOK_ID
) &&
2341 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
2342 tline
= tline
->next
;
2343 defining
->nolist
= true;
2345 mmac
= (MMacro
*) hash_findix(&mmacros
, defining
->name
);
2347 if (!strcmp(mmac
->name
, defining
->name
) &&
2348 (mmac
->nparam_min
<= defining
->nparam_max
2350 && (defining
->nparam_min
<= mmac
->nparam_max
2353 "redefining multi-line macro `%s'", defining
->name
);
2359 * Handle default parameters.
2361 if (tline
&& tline
->next
) {
2362 defining
->dlist
= tline
->next
;
2364 count_mmac_params(defining
->dlist
, &defining
->ndefs
,
2365 &defining
->defaults
);
2367 defining
->dlist
= NULL
;
2368 defining
->defaults
= NULL
;
2370 defining
->expansion
= NULL
;
2371 free_tlist(origline
);
2372 return DIRECTIVE_FOUND
;
2377 error(ERR_NONFATAL
, "`%s': not defining a macro", tline
->text
);
2378 return DIRECTIVE_FOUND
;
2380 mmhead
= (MMacro
**) hash_findi_add(&mmacros
, defining
->name
);
2381 defining
->next
= *mmhead
;
2384 free_tlist(origline
);
2385 return DIRECTIVE_FOUND
;
2388 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
2389 tline
= tline
->next
;
2390 if (tline
->next
== NULL
) {
2391 free_tlist(origline
);
2392 error(ERR_NONFATAL
, "`%%rotate' missing rotate count");
2393 return DIRECTIVE_FOUND
;
2395 t
= expand_smacro(tline
->next
);
2397 free_tlist(origline
);
2400 tokval
.t_type
= TOKEN_INVALID
;
2402 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
2405 return DIRECTIVE_FOUND
;
2408 "trailing garbage after expression ignored");
2409 if (!is_simple(evalresult
)) {
2410 error(ERR_NONFATAL
, "non-constant value given to `%%rotate'");
2411 return DIRECTIVE_FOUND
;
2414 while (mmac
&& !mmac
->name
) /* avoid mistaking %reps for macros */
2415 mmac
= mmac
->next_active
;
2417 error(ERR_NONFATAL
, "`%%rotate' invoked outside a macro call");
2418 } else if (mmac
->nparam
== 0) {
2420 "`%%rotate' invoked within macro without parameters");
2422 int rotate
= mmac
->rotate
+ reloc_value(evalresult
);
2424 rotate
%= (int)mmac
->nparam
;
2426 rotate
+= mmac
->nparam
;
2428 mmac
->rotate
= rotate
;
2430 return DIRECTIVE_FOUND
;
2435 tline
= tline
->next
;
2436 } while (tok_type_(tline
, TOK_WHITESPACE
));
2438 if (tok_type_(tline
, TOK_ID
) &&
2439 nasm_stricmp(tline
->text
, ".nolist") == 0) {
2442 tline
= tline
->next
;
2443 } while (tok_type_(tline
, TOK_WHITESPACE
));
2447 t
= expand_smacro(tline
);
2449 tokval
.t_type
= TOKEN_INVALID
;
2451 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
2453 free_tlist(origline
);
2454 return DIRECTIVE_FOUND
;
2458 "trailing garbage after expression ignored");
2459 if (!is_simple(evalresult
)) {
2460 error(ERR_NONFATAL
, "non-constant value given to `%%rep'");
2461 return DIRECTIVE_FOUND
;
2463 count
= reloc_value(evalresult
) + 1;
2465 error(ERR_NONFATAL
, "`%%rep' expects a repeat count");
2468 free_tlist(origline
);
2470 tmp_defining
= defining
;
2471 defining
= nasm_malloc(sizeof(MMacro
));
2472 defining
->name
= NULL
; /* flags this macro as a %rep block */
2473 defining
->casesense
= false;
2474 defining
->plus
= false;
2475 defining
->nolist
= nolist
;
2476 defining
->in_progress
= count
;
2477 defining
->nparam_min
= defining
->nparam_max
= 0;
2478 defining
->defaults
= NULL
;
2479 defining
->dlist
= NULL
;
2480 defining
->expansion
= NULL
;
2481 defining
->next_active
= istk
->mstk
;
2482 defining
->rep_nest
= tmp_defining
;
2483 return DIRECTIVE_FOUND
;
2486 if (!defining
|| defining
->name
) {
2487 error(ERR_NONFATAL
, "`%%endrep': no matching `%%rep'");
2488 return DIRECTIVE_FOUND
;
2492 * Now we have a "macro" defined - although it has no name
2493 * and we won't be entering it in the hash tables - we must
2494 * push a macro-end marker for it on to istk->expansion.
2495 * After that, it will take care of propagating itself (a
2496 * macro-end marker line for a macro which is really a %rep
2497 * block will cause the macro to be re-expanded, complete
2498 * with another macro-end marker to ensure the process
2499 * continues) until the whole expansion is forcibly removed
2500 * from istk->expansion by a %exitrep.
2502 l
= nasm_malloc(sizeof(Line
));
2503 l
->next
= istk
->expansion
;
2504 l
->finishes
= defining
;
2506 istk
->expansion
= l
;
2508 istk
->mstk
= defining
;
2510 list
->uplevel(defining
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
2511 tmp_defining
= defining
;
2512 defining
= defining
->rep_nest
;
2513 free_tlist(origline
);
2514 return DIRECTIVE_FOUND
;
2518 * We must search along istk->expansion until we hit a
2519 * macro-end marker for a macro with no name. Then we set
2520 * its `in_progress' flag to 0.
2522 for (l
= istk
->expansion
; l
; l
= l
->next
)
2523 if (l
->finishes
&& !l
->finishes
->name
)
2527 l
->finishes
->in_progress
= 0;
2529 error(ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
2530 free_tlist(origline
);
2531 return DIRECTIVE_FOUND
;
2537 casesense
= (i
== PP_DEFINE
|| i
== PP_XDEFINE
);
2539 tline
= tline
->next
;
2541 tline
= expand_id(tline
);
2542 if (!tline
|| (tline
->type
!= TOK_ID
&&
2543 (tline
->type
!= TOK_PREPROC_ID
||
2544 tline
->text
[1] != '$'))) {
2545 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
2547 free_tlist(origline
);
2548 return DIRECTIVE_FOUND
;
2551 ctx
= get_ctx(tline
->text
, false);
2553 mname
= tline
->text
;
2555 param_start
= tline
= tline
->next
;
2558 /* Expand the macro definition now for %xdefine and %ixdefine */
2559 if ((i
== PP_XDEFINE
) || (i
== PP_IXDEFINE
))
2560 tline
= expand_smacro(tline
);
2562 if (tok_is_(tline
, "(")) {
2564 * This macro has parameters.
2567 tline
= tline
->next
;
2571 error(ERR_NONFATAL
, "parameter identifier expected");
2572 free_tlist(origline
);
2573 return DIRECTIVE_FOUND
;
2575 if (tline
->type
!= TOK_ID
) {
2577 "`%s': parameter identifier expected",
2579 free_tlist(origline
);
2580 return DIRECTIVE_FOUND
;
2582 tline
->type
= TOK_SMAC_PARAM
+ nparam
++;
2583 tline
= tline
->next
;
2585 if (tok_is_(tline
, ",")) {
2586 tline
= tline
->next
;
2589 if (!tok_is_(tline
, ")")) {
2591 "`)' expected to terminate macro template");
2592 free_tlist(origline
);
2593 return DIRECTIVE_FOUND
;
2598 tline
= tline
->next
;
2600 if (tok_type_(tline
, TOK_WHITESPACE
))
2601 last
= tline
, tline
= tline
->next
;
2606 if (t
->type
== TOK_ID
) {
2607 for (tt
= param_start
; tt
; tt
= tt
->next
)
2608 if (tt
->type
>= TOK_SMAC_PARAM
&&
2609 !strcmp(tt
->text
, t
->text
))
2613 t
->next
= macro_start
;
2618 * Good. We now have a macro name, a parameter count, and a
2619 * token list (in reverse order) for an expansion. We ought
2620 * to be OK just to create an SMacro, store it, and let
2621 * free_tlist have the rest of the line (which we have
2622 * carefully re-terminated after chopping off the expansion
2625 define_smacro(ctx
, mname
, casesense
, nparam
, macro_start
);
2626 free_tlist(origline
);
2627 return DIRECTIVE_FOUND
;
2630 tline
= tline
->next
;
2632 tline
= expand_id(tline
);
2633 if (!tline
|| (tline
->type
!= TOK_ID
&&
2634 (tline
->type
!= TOK_PREPROC_ID
||
2635 tline
->text
[1] != '$'))) {
2636 error(ERR_NONFATAL
, "`%%undef' expects a macro identifier");
2637 free_tlist(origline
);
2638 return DIRECTIVE_FOUND
;
2642 "trailing garbage after macro name ignored");
2645 /* Find the context that symbol belongs to */
2646 ctx
= get_ctx(tline
->text
, false);
2647 undef_smacro(ctx
, tline
->text
);
2648 free_tlist(origline
);
2649 return DIRECTIVE_FOUND
;
2653 casesense
= (i
== PP_DEFSTR
);
2655 tline
= tline
->next
;
2657 tline
= expand_id(tline
);
2658 if (!tline
|| (tline
->type
!= TOK_ID
&&
2659 (tline
->type
!= TOK_PREPROC_ID
||
2660 tline
->text
[1] != '$'))) {
2661 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
2663 free_tlist(origline
);
2664 return DIRECTIVE_FOUND
;
2667 ctx
= get_ctx(tline
->text
, false);
2669 mname
= tline
->text
;
2671 tline
= expand_smacro(tline
->next
);
2674 while (tok_type_(tline
, TOK_WHITESPACE
))
2675 tline
= delete_Token(tline
);
2677 p
= detoken(tline
, false);
2678 macro_start
= nasm_malloc(sizeof(*macro_start
));
2679 macro_start
->next
= NULL
;
2680 macro_start
->text
= nasm_quote(p
, strlen(p
));
2681 macro_start
->type
= TOK_STRING
;
2682 macro_start
->mac
= NULL
;
2686 * We now have a macro name, an implicit parameter count of
2687 * zero, and a string token to use as an expansion. Create
2688 * and store an SMacro.
2690 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
2691 free_tlist(origline
);
2692 return DIRECTIVE_FOUND
;
2697 StrList
*xsl
= NULL
;
2698 StrList
**xst
= &xsl
;
2702 tline
= tline
->next
;
2704 tline
= expand_id(tline
);
2705 if (!tline
|| (tline
->type
!= TOK_ID
&&
2706 (tline
->type
!= TOK_PREPROC_ID
||
2707 tline
->text
[1] != '$'))) {
2709 "`%%pathsearch' expects a macro identifier as first parameter");
2710 free_tlist(origline
);
2711 return DIRECTIVE_FOUND
;
2713 ctx
= get_ctx(tline
->text
, false);
2715 mname
= tline
->text
;
2717 tline
= expand_smacro(tline
->next
);
2721 while (tok_type_(t
, TOK_WHITESPACE
))
2724 if (!t
|| (t
->type
!= TOK_STRING
&&
2725 t
->type
!= TOK_INTERNAL_STRING
)) {
2726 error(ERR_NONFATAL
, "`%%pathsearch' expects a file name");
2728 free_tlist(origline
);
2729 return DIRECTIVE_FOUND
; /* but we did _something_ */
2733 "trailing garbage after `%%pathsearch' ignored");
2735 if (t
->type
!= TOK_INTERNAL_STRING
)
2736 nasm_unquote(p
, NULL
);
2738 fp
= inc_fopen(p
, &xsl
, &xst
, true);
2741 fclose(fp
); /* Don't actually care about the file */
2743 macro_start
= nasm_malloc(sizeof(*macro_start
));
2744 macro_start
->next
= NULL
;
2745 macro_start
->text
= nasm_quote(p
, strlen(p
));
2746 macro_start
->type
= TOK_STRING
;
2747 macro_start
->mac
= NULL
;
2752 * We now have a macro name, an implicit parameter count of
2753 * zero, and a string token to use as an expansion. Create
2754 * and store an SMacro.
2756 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
2758 free_tlist(origline
);
2759 return DIRECTIVE_FOUND
;
2765 tline
= tline
->next
;
2767 tline
= expand_id(tline
);
2768 if (!tline
|| (tline
->type
!= TOK_ID
&&
2769 (tline
->type
!= TOK_PREPROC_ID
||
2770 tline
->text
[1] != '$'))) {
2772 "`%%strlen' expects a macro identifier as first parameter");
2773 free_tlist(origline
);
2774 return DIRECTIVE_FOUND
;
2776 ctx
= get_ctx(tline
->text
, false);
2778 mname
= tline
->text
;
2780 tline
= expand_smacro(tline
->next
);
2784 while (tok_type_(t
, TOK_WHITESPACE
))
2786 /* t should now point to the string */
2787 if (t
->type
!= TOK_STRING
) {
2789 "`%%strlen` requires string as second parameter");
2791 free_tlist(origline
);
2792 return DIRECTIVE_FOUND
;
2795 macro_start
= nasm_malloc(sizeof(*macro_start
));
2796 macro_start
->next
= NULL
;
2797 make_tok_num(macro_start
, nasm_unquote(t
->text
, NULL
));
2798 macro_start
->mac
= NULL
;
2801 * We now have a macro name, an implicit parameter count of
2802 * zero, and a numeric token to use as an expansion. Create
2803 * and store an SMacro.
2805 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
2807 free_tlist(origline
);
2808 return DIRECTIVE_FOUND
;
2817 tline
= tline
->next
;
2819 tline
= expand_id(tline
);
2820 if (!tline
|| (tline
->type
!= TOK_ID
&&
2821 (tline
->type
!= TOK_PREPROC_ID
||
2822 tline
->text
[1] != '$'))) {
2824 "`%%substr' expects a macro identifier as first parameter");
2825 free_tlist(origline
);
2826 return DIRECTIVE_FOUND
;
2828 ctx
= get_ctx(tline
->text
, false);
2830 mname
= tline
->text
;
2832 tline
= expand_smacro(tline
->next
);
2836 while (tok_type_(t
, TOK_WHITESPACE
))
2839 /* t should now point to the string */
2840 if (t
->type
!= TOK_STRING
) {
2842 "`%%substr` requires string as second parameter");
2844 free_tlist(origline
);
2845 return DIRECTIVE_FOUND
;
2850 tokval
.t_type
= TOKEN_INVALID
;
2851 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
2855 free_tlist(origline
);
2856 return DIRECTIVE_FOUND
;
2857 } else if (!is_simple(evalresult
)) {
2858 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
2860 free_tlist(origline
);
2861 return DIRECTIVE_FOUND
;
2863 a1
= evalresult
->value
-1;
2865 while (tok_type_(tt
, TOK_WHITESPACE
))
2868 a2
= 1; /* Backwards compatibility: one character */
2870 tokval
.t_type
= TOKEN_INVALID
;
2871 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
2875 free_tlist(origline
);
2876 return DIRECTIVE_FOUND
;
2877 } else if (!is_simple(evalresult
)) {
2878 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
2880 free_tlist(origline
);
2881 return DIRECTIVE_FOUND
;
2883 a2
= evalresult
->value
;
2886 len
= nasm_unquote(t
->text
, NULL
);
2889 if (a1
+a2
> (int64_t)len
)
2892 macro_start
= nasm_malloc(sizeof(*macro_start
));
2893 macro_start
->next
= NULL
;
2894 macro_start
->text
= nasm_quote((a1
< 0) ? "" : t
->text
+a1
, a2
);
2895 macro_start
->type
= TOK_STRING
;
2896 macro_start
->mac
= NULL
;
2899 * We now have a macro name, an implicit parameter count of
2900 * zero, and a numeric token to use as an expansion. Create
2901 * and store an SMacro.
2903 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
2905 free_tlist(origline
);
2906 return DIRECTIVE_FOUND
;
2911 casesense
= (i
== PP_ASSIGN
);
2913 tline
= tline
->next
;
2915 tline
= expand_id(tline
);
2916 if (!tline
|| (tline
->type
!= TOK_ID
&&
2917 (tline
->type
!= TOK_PREPROC_ID
||
2918 tline
->text
[1] != '$'))) {
2920 "`%%%sassign' expects a macro identifier",
2921 (i
== PP_IASSIGN
? "i" : ""));
2922 free_tlist(origline
);
2923 return DIRECTIVE_FOUND
;
2925 ctx
= get_ctx(tline
->text
, false);
2927 mname
= tline
->text
;
2929 tline
= expand_smacro(tline
->next
);
2934 tokval
.t_type
= TOKEN_INVALID
;
2936 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
2939 free_tlist(origline
);
2940 return DIRECTIVE_FOUND
;
2945 "trailing garbage after expression ignored");
2947 if (!is_simple(evalresult
)) {
2949 "non-constant value given to `%%%sassign'",
2950 (i
== PP_IASSIGN
? "i" : ""));
2951 free_tlist(origline
);
2952 return DIRECTIVE_FOUND
;
2955 macro_start
= nasm_malloc(sizeof(*macro_start
));
2956 macro_start
->next
= NULL
;
2957 make_tok_num(macro_start
, reloc_value(evalresult
));
2958 macro_start
->mac
= NULL
;
2961 * We now have a macro name, an implicit parameter count of
2962 * zero, and a numeric token to use as an expansion. Create
2963 * and store an SMacro.
2965 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
2966 free_tlist(origline
);
2967 return DIRECTIVE_FOUND
;
2971 * Syntax is `%line nnn[+mmm] [filename]'
2973 tline
= tline
->next
;
2975 if (!tok_type_(tline
, TOK_NUMBER
)) {
2976 error(ERR_NONFATAL
, "`%%line' expects line number");
2977 free_tlist(origline
);
2978 return DIRECTIVE_FOUND
;
2980 k
= readnum(tline
->text
, &err
);
2982 tline
= tline
->next
;
2983 if (tok_is_(tline
, "+")) {
2984 tline
= tline
->next
;
2985 if (!tok_type_(tline
, TOK_NUMBER
)) {
2986 error(ERR_NONFATAL
, "`%%line' expects line increment");
2987 free_tlist(origline
);
2988 return DIRECTIVE_FOUND
;
2990 m
= readnum(tline
->text
, &err
);
2991 tline
= tline
->next
;
2997 nasm_free(src_set_fname(detoken(tline
, false)));
2999 free_tlist(origline
);
3000 return DIRECTIVE_FOUND
;
3004 "preprocessor directive `%s' not yet implemented",
3008 return DIRECTIVE_FOUND
;
3012 * Ensure that a macro parameter contains a condition code and
3013 * nothing else. Return the condition code index if so, or -1
3016 static int find_cc(Token
* t
)
3022 return -1; /* Probably a %+ without a space */
3025 if (t
->type
!= TOK_ID
)
3029 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
3033 j
= elements(conditions
);
3036 m
= nasm_stricmp(t
->text
, conditions
[k
]);
3052 * Expand MMacro-local things: parameter references (%0, %n, %+n,
3053 * %-n) and MMacro-local identifiers (%%foo).
3055 static Token
*expand_mmac_params(Token
* tline
)
3057 Token
*t
, *tt
, **tail
, *thead
;
3063 if (tline
->type
== TOK_PREPROC_ID
&&
3064 (((tline
->text
[1] == '+' || tline
->text
[1] == '-')
3065 && tline
->text
[2]) || tline
->text
[1] == '%'
3066 || (tline
->text
[1] >= '0' && tline
->text
[1] <= '9'))) {
3068 int type
= 0, cc
; /* type = 0 to placate optimisers */
3075 tline
= tline
->next
;
3078 while (mac
&& !mac
->name
) /* avoid mistaking %reps for macros */
3079 mac
= mac
->next_active
;
3081 error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
3083 switch (t
->text
[1]) {
3085 * We have to make a substitution of one of the
3086 * forms %1, %-1, %+1, %%foo, %0.
3090 snprintf(tmpbuf
, sizeof(tmpbuf
), "%d", mac
->nparam
);
3091 text
= nasm_strdup(tmpbuf
);
3095 snprintf(tmpbuf
, sizeof(tmpbuf
), "..@%"PRIu64
".",
3097 text
= nasm_strcat(tmpbuf
, t
->text
+ 2);
3100 n
= atoi(t
->text
+ 2) - 1;
3101 if (n
>= mac
->nparam
)
3104 if (mac
->nparam
> 1)
3105 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3106 tt
= mac
->params
[n
];
3111 "macro parameter %d is not a condition code",
3116 if (inverse_ccs
[cc
] == -1) {
3118 "condition code `%s' is not invertible",
3123 nasm_strdup(conditions
[inverse_ccs
[cc
]]);
3127 n
= atoi(t
->text
+ 2) - 1;
3128 if (n
>= mac
->nparam
)
3131 if (mac
->nparam
> 1)
3132 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3133 tt
= mac
->params
[n
];
3138 "macro parameter %d is not a condition code",
3143 text
= nasm_strdup(conditions
[cc
]);
3147 n
= atoi(t
->text
+ 1) - 1;
3148 if (n
>= mac
->nparam
)
3151 if (mac
->nparam
> 1)
3152 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3153 tt
= mac
->params
[n
];
3156 for (i
= 0; i
< mac
->paramlen
[n
]; i
++) {
3157 *tail
= new_Token(NULL
, tt
->type
, tt
->text
, 0);
3158 tail
= &(*tail
)->next
;
3162 text
= NULL
; /* we've done it here */
3178 tline
= tline
->next
;
3185 for (; t
&& (tt
= t
->next
) != NULL
; t
= t
->next
)
3187 case TOK_WHITESPACE
:
3188 if (tt
->type
== TOK_WHITESPACE
) {
3189 t
->next
= delete_Token(tt
);
3193 if (tt
->type
== TOK_ID
|| tt
->type
== TOK_NUMBER
) {
3194 char *tmp
= nasm_strcat(t
->text
, tt
->text
);
3197 t
->next
= delete_Token(tt
);
3201 if (tt
->type
== TOK_NUMBER
) {
3202 char *tmp
= nasm_strcat(t
->text
, tt
->text
);
3205 t
->next
= delete_Token(tt
);
3216 * Expand all single-line macro calls made in the given line.
3217 * Return the expanded version of the line. The original is deemed
3218 * to be destroyed in the process. (In reality we'll just move
3219 * Tokens from input to output a lot of the time, rather than
3220 * actually bothering to destroy and replicate.)
3222 #define DEADMAN_LIMIT (1 << 20)
3224 static Token
*expand_smacro(Token
* tline
)
3226 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
3227 struct hash_table
*smtbl
;
3228 SMacro
*head
= NULL
, *m
;
3231 unsigned int nparam
, sparam
;
3232 int brackets
, rescan
;
3233 Token
*org_tline
= tline
;
3236 int deadman
= DEADMAN_LIMIT
;
3239 * Trick: we should avoid changing the start token pointer since it can
3240 * be contained in "next" field of other token. Because of this
3241 * we allocate a copy of first token and work with it; at the end of
3242 * routine we copy it back
3246 new_Token(org_tline
->next
, org_tline
->type
, org_tline
->text
,
3248 tline
->mac
= org_tline
->mac
;
3249 nasm_free(org_tline
->text
);
3250 org_tline
->text
= NULL
;
3257 while (tline
) { /* main token loop */
3259 error(ERR_NONFATAL
, "interminable macro recursion");
3263 if ((mname
= tline
->text
)) {
3264 /* if this token is a local macro, look in local context */
3267 if (tline
->type
== TOK_ID
|| tline
->type
== TOK_PREPROC_ID
) {
3268 ctx
= get_ctx(mname
, true);
3270 smtbl
= &ctx
->localmac
;
3272 head
= (SMacro
*) hash_findix(smtbl
, mname
);
3275 * We've hit an identifier. As in is_mmacro below, we first
3276 * check whether the identifier is a single-line macro at
3277 * all, then think about checking for parameters if
3280 for (m
= head
; m
; m
= m
->next
)
3281 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
3287 if (m
->nparam
== 0) {
3289 * Simple case: the macro is parameterless. Discard the
3290 * one token that the macro call took, and push the
3291 * expansion back on the to-do stack.
3293 if (!m
->expansion
) {
3294 if (!strcmp("__FILE__", m
->name
)) {
3297 src_get(&num
, &file
);
3298 tline
->text
= nasm_quote(file
, strlen(file
));
3299 tline
->type
= TOK_STRING
;
3303 if (!strcmp("__LINE__", m
->name
)) {
3304 nasm_free(tline
->text
);
3305 make_tok_num(tline
, src_get_linnum());
3308 if (!strcmp("__BITS__", m
->name
)) {
3309 nasm_free(tline
->text
);
3310 make_tok_num(tline
, globalbits
);
3313 tline
= delete_Token(tline
);
3318 * Complicated case: at least one macro with this name
3319 * exists and takes parameters. We must find the
3320 * parameters in the call, count them, find the SMacro
3321 * that corresponds to that form of the macro call, and
3322 * substitute for the parameters when we expand. What a
3325 /*tline = tline->next;
3326 skip_white_(tline); */
3329 while (tok_type_(t
, TOK_SMAC_END
)) {
3330 t
->mac
->in_progress
= false;
3332 t
= tline
->next
= delete_Token(t
);
3335 } while (tok_type_(tline
, TOK_WHITESPACE
));
3336 if (!tok_is_(tline
, "(")) {
3338 * This macro wasn't called with parameters: ignore
3339 * the call. (Behaviour borrowed from gnu cpp.)
3348 sparam
= PARAM_DELTA
;
3349 params
= nasm_malloc(sparam
* sizeof(Token
*));
3350 params
[0] = tline
->next
;
3351 paramsize
= nasm_malloc(sparam
* sizeof(int));
3353 while (true) { /* parameter loop */
3355 * For some unusual expansions
3356 * which concatenates function call
3359 while (tok_type_(t
, TOK_SMAC_END
)) {
3360 t
->mac
->in_progress
= false;
3362 t
= tline
->next
= delete_Token(t
);
3368 "macro call expects terminating `)'");
3371 if (tline
->type
== TOK_WHITESPACE
3373 if (paramsize
[nparam
])
3376 params
[nparam
] = tline
->next
;
3377 continue; /* parameter loop */
3379 if (tline
->type
== TOK_OTHER
3380 && tline
->text
[1] == 0) {
3381 char ch
= tline
->text
[0];
3382 if (ch
== ',' && !paren
&& brackets
<= 0) {
3383 if (++nparam
>= sparam
) {
3384 sparam
+= PARAM_DELTA
;
3385 params
= nasm_realloc(params
,
3390 nasm_realloc(paramsize
,
3394 params
[nparam
] = tline
->next
;
3395 paramsize
[nparam
] = 0;
3397 continue; /* parameter loop */
3400 (brackets
> 0 || (brackets
== 0 &&
3401 !paramsize
[nparam
])))
3403 if (!(brackets
++)) {
3404 params
[nparam
] = tline
->next
;
3405 continue; /* parameter loop */
3408 if (ch
== '}' && brackets
> 0)
3409 if (--brackets
== 0) {
3411 continue; /* parameter loop */
3413 if (ch
== '(' && !brackets
)
3415 if (ch
== ')' && brackets
<= 0)
3421 error(ERR_NONFATAL
, "braces do not "
3422 "enclose all of macro parameter");
3424 paramsize
[nparam
] += white
+ 1;
3426 } /* parameter loop */
3428 while (m
&& (m
->nparam
!= nparam
||
3429 mstrcmp(m
->name
, mname
,
3433 error(ERR_WARNING
| ERR_WARN_MNP
,
3434 "macro `%s' exists, "
3435 "but not taking %d parameters",
3436 mstart
->text
, nparam
);
3439 if (m
&& m
->in_progress
)
3441 if (!m
) { /* in progess or didn't find '(' or wrong nparam */
3443 * Design question: should we handle !tline, which
3444 * indicates missing ')' here, or expand those
3445 * macros anyway, which requires the (t) test a few
3449 nasm_free(paramsize
);
3453 * Expand the macro: we are placed on the last token of the
3454 * call, so that we can easily split the call from the
3455 * following tokens. We also start by pushing an SMAC_END
3456 * token for the cycle removal.
3463 tt
= new_Token(tline
, TOK_SMAC_END
, NULL
, 0);
3465 m
->in_progress
= true;
3467 for (t
= m
->expansion
; t
; t
= t
->next
) {
3468 if (t
->type
>= TOK_SMAC_PARAM
) {
3469 Token
*pcopy
= tline
, **ptail
= &pcopy
;
3473 ttt
= params
[t
->type
- TOK_SMAC_PARAM
];
3474 for (i
= paramsize
[t
->type
- TOK_SMAC_PARAM
];
3477 new_Token(tline
, ttt
->type
, ttt
->text
,
3483 } else if (t
->type
== TOK_PREPROC_Q
) {
3484 tt
= new_Token(tline
, TOK_ID
, mname
, 0);
3486 } else if (t
->type
== TOK_PREPROC_QQ
) {
3487 tt
= new_Token(tline
, TOK_ID
, m
->name
, 0);
3490 tt
= new_Token(tline
, t
->type
, t
->text
, 0);
3496 * Having done that, get rid of the macro call, and clean
3497 * up the parameters.
3500 nasm_free(paramsize
);
3502 continue; /* main token loop */
3507 if (tline
->type
== TOK_SMAC_END
) {
3508 tline
->mac
->in_progress
= false;
3509 tline
= delete_Token(tline
);
3512 tline
= tline
->next
;
3520 * Now scan the entire line and look for successive TOK_IDs that resulted
3521 * after expansion (they can't be produced by tokenize()). The successive
3522 * TOK_IDs should be concatenated.
3523 * Also we look for %+ tokens and concatenate the tokens before and after
3524 * them (without white spaces in between).
3529 while (t
&& t
->type
!= TOK_ID
&& t
->type
!= TOK_PREPROC_ID
)
3533 if (t
->next
->type
== TOK_ID
||
3534 t
->next
->type
== TOK_PREPROC_ID
||
3535 t
->next
->type
== TOK_NUMBER
) {
3536 char *p
= nasm_strcat(t
->text
, t
->next
->text
);
3538 t
->next
= delete_Token(t
->next
);
3541 } else if (t
->next
->type
== TOK_WHITESPACE
&& t
->next
->next
&&
3542 t
->next
->next
->type
== TOK_PREPROC_ID
&&
3543 strcmp(t
->next
->next
->text
, "%+") == 0) {
3544 /* free the next whitespace, the %+ token and next whitespace */
3546 for (i
= 1; i
<= 3; i
++) {
3548 || (i
!= 2 && t
->next
->type
!= TOK_WHITESPACE
))
3550 t
->next
= delete_Token(t
->next
);
3555 /* If we concatenaded something, re-scan the line for macros */
3563 *org_tline
= *thead
;
3564 /* since we just gave text to org_line, don't free it */
3566 delete_Token(thead
);
3568 /* the expression expanded to empty line;
3569 we can't return NULL for some reasons
3570 we just set the line to a single WHITESPACE token. */
3571 memset(org_tline
, 0, sizeof(*org_tline
));
3572 org_tline
->text
= NULL
;
3573 org_tline
->type
= TOK_WHITESPACE
;
3582 * Similar to expand_smacro but used exclusively with macro identifiers
3583 * right before they are fetched in. The reason is that there can be
3584 * identifiers consisting of several subparts. We consider that if there
3585 * are more than one element forming the name, user wants a expansion,
3586 * otherwise it will be left as-is. Example:
3590 * the identifier %$abc will be left as-is so that the handler for %define
3591 * will suck it and define the corresponding value. Other case:
3593 * %define _%$abc cde
3595 * In this case user wants name to be expanded *before* %define starts
3596 * working, so we'll expand %$abc into something (if it has a value;
3597 * otherwise it will be left as-is) then concatenate all successive
3600 static Token
*expand_id(Token
* tline
)
3602 Token
*cur
, *oldnext
= NULL
;
3604 if (!tline
|| !tline
->next
)
3609 (cur
->next
->type
== TOK_ID
||
3610 cur
->next
->type
== TOK_PREPROC_ID
3611 || cur
->next
->type
== TOK_NUMBER
))
3614 /* If identifier consists of just one token, don't expand */
3619 oldnext
= cur
->next
; /* Detach the tail past identifier */
3620 cur
->next
= NULL
; /* so that expand_smacro stops here */
3623 tline
= expand_smacro(tline
);
3626 /* expand_smacro possibly changhed tline; re-scan for EOL */
3628 while (cur
&& cur
->next
)
3631 cur
->next
= oldnext
;
3638 * Determine whether the given line constitutes a multi-line macro
3639 * call, and return the MMacro structure called if so. Doesn't have
3640 * to check for an initial label - that's taken care of in
3641 * expand_mmacro - but must check numbers of parameters. Guaranteed
3642 * to be called with tline->type == TOK_ID, so the putative macro
3643 * name is easy to find.
3645 static MMacro
*is_mmacro(Token
* tline
, Token
*** params_array
)
3651 head
= (MMacro
*) hash_findix(&mmacros
, tline
->text
);
3654 * Efficiency: first we see if any macro exists with the given
3655 * name. If not, we can return NULL immediately. _Then_ we
3656 * count the parameters, and then we look further along the
3657 * list if necessary to find the proper MMacro.
3659 for (m
= head
; m
; m
= m
->next
)
3660 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
3666 * OK, we have a potential macro. Count and demarcate the
3669 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
3672 * So we know how many parameters we've got. Find the MMacro
3673 * structure that handles this number.
3676 if (m
->nparam_min
<= nparam
3677 && (m
->plus
|| nparam
<= m
->nparam_max
)) {
3679 * This one is right. Just check if cycle removal
3680 * prohibits us using it before we actually celebrate...
3682 if (m
->in_progress
) {
3685 "self-reference in multi-line macro `%s'", m
->name
);
3691 * It's right, and we can use it. Add its default
3692 * parameters to the end of our list if necessary.
3694 if (m
->defaults
&& nparam
< m
->nparam_min
+ m
->ndefs
) {
3696 nasm_realloc(params
,
3697 ((m
->nparam_min
+ m
->ndefs
+
3698 1) * sizeof(*params
)));
3699 while (nparam
< m
->nparam_min
+ m
->ndefs
) {
3700 params
[nparam
] = m
->defaults
[nparam
- m
->nparam_min
];
3705 * If we've gone over the maximum parameter count (and
3706 * we're in Plus mode), ignore parameters beyond
3709 if (m
->plus
&& nparam
> m
->nparam_max
)
3710 nparam
= m
->nparam_max
;
3712 * Then terminate the parameter list, and leave.
3714 if (!params
) { /* need this special case */
3715 params
= nasm_malloc(sizeof(*params
));
3718 params
[nparam
] = NULL
;
3719 *params_array
= params
;
3723 * This one wasn't right: look for the next one with the
3726 for (m
= m
->next
; m
; m
= m
->next
)
3727 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
3732 * After all that, we didn't find one with the right number of
3733 * parameters. Issue a warning, and fail to expand the macro.
3735 error(ERR_WARNING
| ERR_WARN_MNP
,
3736 "macro `%s' exists, but not taking %d parameters",
3737 tline
->text
, nparam
);
3743 * Expand the multi-line macro call made by the given line, if
3744 * there is one to be expanded. If there is, push the expansion on
3745 * istk->expansion and return 1. Otherwise return 0.
3747 static int expand_mmacro(Token
* tline
)
3749 Token
*startline
= tline
;
3750 Token
*label
= NULL
;
3751 int dont_prepend
= 0;
3752 Token
**params
, *t
, *mtok
, *tt
;
3755 int i
, nparam
, *paramlen
;
3760 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
3761 if (!tok_type_(t
, TOK_ID
) && !tok_type_(t
, TOK_PREPROC_ID
))
3764 m
= is_mmacro(t
, ¶ms
);
3770 * We have an id which isn't a macro call. We'll assume
3771 * it might be a label; we'll also check to see if a
3772 * colon follows it. Then, if there's another id after
3773 * that lot, we'll check it again for macro-hood.
3777 if (tok_type_(t
, TOK_WHITESPACE
))
3778 last
= t
, t
= t
->next
;
3779 if (tok_is_(t
, ":")) {
3781 last
= t
, t
= t
->next
;
3782 if (tok_type_(t
, TOK_WHITESPACE
))
3783 last
= t
, t
= t
->next
;
3785 if (!tok_type_(t
, TOK_ID
) || (m
= is_mmacro(t
, ¶ms
)) == NULL
)
3793 * Fix up the parameters: this involves stripping leading and
3794 * trailing whitespace, then stripping braces if they are
3797 for (nparam
= 0; params
[nparam
]; nparam
++) ;
3798 paramlen
= nparam
? nasm_malloc(nparam
* sizeof(*paramlen
)) : NULL
;
3800 for (i
= 0; params
[i
]; i
++) {
3802 int comma
= (!m
->plus
|| i
< nparam
- 1);
3806 if (tok_is_(t
, "{"))
3807 t
= t
->next
, brace
= true, comma
= false;
3811 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
3812 break; /* ... because we have hit a comma */
3813 if (comma
&& t
->type
== TOK_WHITESPACE
3814 && tok_is_(t
->next
, ","))
3815 break; /* ... or a space then a comma */
3816 if (brace
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "}"))
3817 break; /* ... or a brace */
3824 * OK, we have a MMacro structure together with a set of
3825 * parameters. We must now go through the expansion and push
3826 * copies of each Line on to istk->expansion. Substitution of
3827 * parameter tokens and macro-local tokens doesn't get done
3828 * until the single-line macro substitution process; this is
3829 * because delaying them allows us to change the semantics
3830 * later through %rotate.
3832 * First, push an end marker on to istk->expansion, mark this
3833 * macro as in progress, and set up its invocation-specific
3836 ll
= nasm_malloc(sizeof(Line
));
3837 ll
->next
= istk
->expansion
;
3840 istk
->expansion
= ll
;
3842 m
->in_progress
= true;
3847 m
->paramlen
= paramlen
;
3848 m
->unique
= unique
++;
3851 m
->next_active
= istk
->mstk
;
3854 for (l
= m
->expansion
; l
; l
= l
->next
) {
3857 ll
= nasm_malloc(sizeof(Line
));
3858 ll
->finishes
= NULL
;
3859 ll
->next
= istk
->expansion
;
3860 istk
->expansion
= ll
;
3863 for (t
= l
->first
; t
; t
= t
->next
) {
3867 tt
= *tail
= new_Token(NULL
, TOK_ID
, mname
, 0);
3869 case TOK_PREPROC_QQ
:
3870 tt
= *tail
= new_Token(NULL
, TOK_ID
, m
->name
, 0);
3872 case TOK_PREPROC_ID
:
3873 if (t
->text
[1] == '0' && t
->text
[2] == '0') {
3881 tt
= *tail
= new_Token(NULL
, x
->type
, x
->text
, 0);
3890 * If we had a label, push it on as the first line of
3891 * the macro expansion.
3894 if (dont_prepend
< 0)
3895 free_tlist(startline
);
3897 ll
= nasm_malloc(sizeof(Line
));
3898 ll
->finishes
= NULL
;
3899 ll
->next
= istk
->expansion
;
3900 istk
->expansion
= ll
;
3901 ll
->first
= startline
;
3902 if (!dont_prepend
) {
3904 label
= label
->next
;
3905 label
->next
= tt
= new_Token(NULL
, TOK_OTHER
, ":", 0);
3910 list
->uplevel(m
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
3916 * Since preprocessor always operate only on the line that didn't
3917 * arrived yet, we should always use ERR_OFFBY1. Also since user
3918 * won't want to see same error twice (preprocessing is done once
3919 * per pass) we will want to show errors only during pass one.
3921 static void error(int severity
, const char *fmt
, ...)
3926 /* If we're in a dead branch of IF or something like it, ignore the error */
3927 if (istk
&& istk
->conds
&& !emitting(istk
->conds
->state
))
3931 vsnprintf(buff
, sizeof(buff
), fmt
, arg
);
3934 if (istk
&& istk
->mstk
&& istk
->mstk
->name
)
3935 _error(severity
| ERR_PASS1
, "(%s:%d) %s", istk
->mstk
->name
,
3936 istk
->mstk
->lineno
, buff
);
3938 _error(severity
| ERR_PASS1
, "%s", buff
);
3942 pp_reset(char *file
, int apass
, efunc errfunc
, evalfunc eval
,
3943 ListGen
* listgen
, StrList
**deplist
)
3947 istk
= nasm_malloc(sizeof(Include
));
3950 istk
->expansion
= NULL
;
3952 istk
->fp
= fopen(file
, "r");
3954 src_set_fname(nasm_strdup(file
));
3958 error(ERR_FATAL
| ERR_NOFILE
, "unable to open input file `%s'",
3963 if (tasm_compatible_mode
) {
3964 stdmacpos
= nasm_stdmac
;
3966 stdmacpos
= nasm_stdmac_after_tasm
;
3968 any_extrastdmac
= (extrastdmac
!= NULL
);
3972 dephead
= deptail
= deplist
;
3974 StrList
*sl
= nasm_malloc(strlen(file
)+1+sizeof sl
->next
);
3976 strcpy(sl
->str
, file
);
3978 deptail
= &sl
->next
;
3982 static char *pp_getline(void)
3989 * Fetch a tokenized line, either from the macro-expansion
3990 * buffer or from the input file.
3993 while (istk
->expansion
&& istk
->expansion
->finishes
) {
3994 Line
*l
= istk
->expansion
;
3995 if (!l
->finishes
->name
&& l
->finishes
->in_progress
> 1) {
3999 * This is a macro-end marker for a macro with no
4000 * name, which means it's not really a macro at all
4001 * but a %rep block, and the `in_progress' field is
4002 * more than 1, meaning that we still need to
4003 * repeat. (1 means the natural last repetition; 0
4004 * means termination by %exitrep.) We have
4005 * therefore expanded up to the %endrep, and must
4006 * push the whole block on to the expansion buffer
4007 * again. We don't bother to remove the macro-end
4008 * marker: we'd only have to generate another one
4011 l
->finishes
->in_progress
--;
4012 for (l
= l
->finishes
->expansion
; l
; l
= l
->next
) {
4013 Token
*t
, *tt
, **tail
;
4015 ll
= nasm_malloc(sizeof(Line
));
4016 ll
->next
= istk
->expansion
;
4017 ll
->finishes
= NULL
;
4021 for (t
= l
->first
; t
; t
= t
->next
) {
4022 if (t
->text
|| t
->type
== TOK_WHITESPACE
) {
4024 new_Token(NULL
, t
->type
, t
->text
, 0);
4029 istk
->expansion
= ll
;
4033 * Check whether a `%rep' was started and not ended
4034 * within this macro expansion. This can happen and
4035 * should be detected. It's a fatal error because
4036 * I'm too confused to work out how to recover
4042 "defining with name in expansion");
4043 else if (istk
->mstk
->name
)
4045 "`%%rep' without `%%endrep' within"
4046 " expansion of macro `%s'",
4051 * FIXME: investigate the relationship at this point between
4052 * istk->mstk and l->finishes
4055 MMacro
*m
= istk
->mstk
;
4056 istk
->mstk
= m
->next_active
;
4059 * This was a real macro call, not a %rep, and
4060 * therefore the parameter information needs to
4063 nasm_free(m
->params
);
4064 free_tlist(m
->iline
);
4065 nasm_free(m
->paramlen
);
4066 l
->finishes
->in_progress
= false;
4070 istk
->expansion
= l
->next
;
4072 list
->downlevel(LIST_MACRO
);
4075 while (1) { /* until we get a line we can use */
4077 if (istk
->expansion
) { /* from a macro expansion */
4079 Line
*l
= istk
->expansion
;
4081 istk
->mstk
->lineno
++;
4083 istk
->expansion
= l
->next
;
4085 p
= detoken(tline
, false);
4086 list
->line(LIST_MACRO
, p
);
4091 if (line
) { /* from the current input file */
4092 line
= prepreproc(line
);
4093 tline
= tokenize(line
);
4098 * The current file has ended; work down the istk
4105 "expected `%%endif' before end of file");
4106 /* only set line and file name if there's a next node */
4108 src_set_linnum(i
->lineno
);
4109 nasm_free(src_set_fname(i
->fname
));
4112 list
->downlevel(LIST_INCLUDE
);
4120 * We must expand MMacro parameters and MMacro-local labels
4121 * _before_ we plunge into directive processing, to cope
4122 * with things like `%define something %1' such as STRUC
4123 * uses. Unless we're _defining_ a MMacro, in which case
4124 * those tokens should be left alone to go into the
4125 * definition; and unless we're in a non-emitting
4126 * condition, in which case we don't want to meddle with
4129 if (!defining
&& !(istk
->conds
&& !emitting(istk
->conds
->state
)))
4130 tline
= expand_mmac_params(tline
);
4133 * Check the line to see if it's a preprocessor directive.
4135 if (do_directive(tline
) == DIRECTIVE_FOUND
) {
4137 } else if (defining
) {
4139 * We're defining a multi-line macro. We emit nothing
4141 * shove the tokenized line on to the macro definition.
4143 Line
*l
= nasm_malloc(sizeof(Line
));
4144 l
->next
= defining
->expansion
;
4146 l
->finishes
= false;
4147 defining
->expansion
= l
;
4149 } else if (istk
->conds
&& !emitting(istk
->conds
->state
)) {
4151 * We're in a non-emitting branch of a condition block.
4152 * Emit nothing at all, not even a blank line: when we
4153 * emerge from the condition we'll give a line-number
4154 * directive so we keep our place correctly.
4158 } else if (istk
->mstk
&& !istk
->mstk
->in_progress
) {
4160 * We're in a %rep block which has been terminated, so
4161 * we're walking through to the %endrep without
4162 * emitting anything. Emit nothing at all, not even a
4163 * blank line: when we emerge from the %rep block we'll
4164 * give a line-number directive so we keep our place
4170 tline
= expand_smacro(tline
);
4171 if (!expand_mmacro(tline
)) {
4173 * De-tokenize the line again, and emit it.
4175 line
= detoken(tline
, true);
4179 continue; /* expand_mmacro calls free_tlist */
4187 static void pp_cleanup(int pass
)
4190 error(ERR_NONFATAL
, "end of file while still defining macro `%s'",
4192 free_mmacro(defining
);
4201 nasm_free(i
->fname
);
4212 void pp_include_path(char *path
)
4216 i
= nasm_malloc(sizeof(IncPath
));
4217 i
->path
= path
? nasm_strdup(path
) : NULL
;
4220 if (ipath
!= NULL
) {
4222 while (j
->next
!= NULL
)
4230 void pp_pre_include(char *fname
)
4232 Token
*inc
, *space
, *name
;
4235 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
4236 space
= new_Token(name
, TOK_WHITESPACE
, NULL
, 0);
4237 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
4239 l
= nasm_malloc(sizeof(Line
));
4242 l
->finishes
= false;
4246 void pp_pre_define(char *definition
)
4252 equals
= strchr(definition
, '=');
4253 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
4254 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
4257 space
->next
= tokenize(definition
);
4261 l
= nasm_malloc(sizeof(Line
));
4264 l
->finishes
= false;
4268 void pp_pre_undefine(char *definition
)
4273 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
4274 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
4275 space
->next
= tokenize(definition
);
4277 l
= nasm_malloc(sizeof(Line
));
4280 l
->finishes
= false;
4285 * Added by Keith Kanios:
4287 * This function is used to assist with "runtime" preprocessor
4288 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
4290 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
4291 * PASS A VALID STRING TO THIS FUNCTION!!!!!
4294 void pp_runtime(char *definition
)
4298 def
= tokenize(definition
);
4299 if(do_directive(def
) == NO_DIRECTIVE_FOUND
)
4304 void pp_extra_stdmac(const char **macros
)
4306 extrastdmac
= macros
;
4309 static void make_tok_num(Token
* tok
, int64_t val
)
4312 snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
4313 tok
->text
= nasm_strdup(numbuf
);
4314 tok
->type
= TOK_NUMBER
;