1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2009 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation, Inc.,
10 * 51 Franklin St, Fifth Floor, Boston MA 02110-1301, USA; version 2.1,
11 * or, at your option, any later version, incorporated herein by
14 * Patches submitted to this file are required to be dual licensed
15 * under the LGPL 2.1+ and the 2-clause BSD license:
17 * Copyright 1996-2009 the NASM Authors - All rights reserved.
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following
23 * * Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * * Redistributions in binary form must reproduce the above
26 * copyright notice, this list of conditions and the following
27 * disclaimer in the documentation and/or other materials provided
28 * with the distribution.
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
31 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
32 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
33 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
35 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
37 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
41 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
42 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 * ----------------------------------------------------------------------- */
47 * preproc.c macro preprocessor for the Netwide Assembler
50 /* Typical flow of text through preproc
52 * pp_getline gets tokenized lines, either
54 * from a macro expansion
58 * read_line gets raw text from stdmacpos, or predef, or current input file
59 * tokenize converts to tokens
62 * expand_mmac_params is used to expand %1 etc., unless a macro is being
63 * defined or a false conditional is being processed
64 * (%0, %1, %+1, %-1, %%foo
66 * do_directive checks for directives
68 * expand_smacro is used to expand single line macros
70 * expand_mmacro is used to expand multi-line macros
72 * detoken is used to convert the line back to text
95 typedef struct SMacro SMacro
;
96 typedef struct MMacro MMacro
;
97 typedef struct Context Context
;
98 typedef struct Token Token
;
99 typedef struct Blocks Blocks
;
100 typedef struct Line Line
;
101 typedef struct Include Include
;
102 typedef struct Cond Cond
;
103 typedef struct IncPath IncPath
;
106 * Note on the storage of both SMacro and MMacros: the hash table
107 * indexes them case-insensitively, and we then have to go through a
108 * linked list of potential case aliases (and, for MMacros, parameter
109 * ranges); this is to preserve the matching semantics of the earlier
110 * code. If the number of case aliases for a specific macro is a
111 * performance issue, you may want to reconsider your coding style.
115 * Store the definition of a single-line macro.
127 * Store the definition of a multi-line macro. This is also used to
128 * store the interiors of `%rep...%endrep' blocks, which are
129 * effectively self-re-invoking multi-line macros which simply
130 * don't have a name or bother to appear in the hash tables. %rep
131 * blocks are signified by having a NULL `name' field.
133 * In a MMacro describing a `%rep' block, the `in_progress' field
134 * isn't merely boolean, but gives the number of repeats left to
137 * The `next' field is used for storing MMacros in hash tables; the
138 * `next_active' field is for stacking them on istk entries.
140 * When a MMacro is being expanded, `params', `iline', `nparam',
141 * `paramlen', `rotate' and `unique' are local to the invocation.
146 int nparam_min
, nparam_max
;
148 bool plus
; /* is the last parameter greedy? */
149 bool nolist
; /* is this macro listing-inhibited? */
151 Token
*dlist
; /* All defaults as one list */
152 Token
**defaults
; /* Parameter default pointers */
153 int ndefs
; /* number of default parameters */
157 MMacro
*rep_nest
; /* used for nesting %rep */
158 Token
**params
; /* actual parameters */
159 Token
*iline
; /* invocation line */
160 unsigned int nparam
, rotate
;
163 int lineno
; /* Current line number on expansion */
167 * The context stack is composed of a linked list of these.
172 struct hash_table localmac
;
177 * This is the internal form which we break input lines up into.
178 * Typically stored in linked lists.
180 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
181 * necessarily used as-is, but is intended to denote the number of
182 * the substituted parameter. So in the definition
184 * %define a(x,y) ( (x) & ~(y) )
186 * the token representing `x' will have its type changed to
187 * TOK_SMAC_PARAM, but the one representing `y' will be
190 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
191 * which doesn't need quotes around it. Used in the pre-include
192 * mechanism as an alternative to trying to find a sensible type of
193 * quote to use on the filename we were passed.
196 TOK_NONE
= 0, TOK_WHITESPACE
, TOK_COMMENT
, TOK_ID
,
197 TOK_PREPROC_ID
, TOK_STRING
,
198 TOK_NUMBER
, TOK_FLOAT
, TOK_SMAC_END
, TOK_OTHER
,
200 TOK_PREPROC_Q
, TOK_PREPROC_QQ
,
202 TOK_INDIRECT
, /* %[...] */
203 TOK_SMAC_PARAM
, /* MUST BE LAST IN THE LIST!!! */
204 TOK_MAX
= INT_MAX
/* Keep compiler from reducing the range */
211 SMacro
*mac
; /* associated macro for TOK_SMAC_END */
212 size_t len
; /* scratch length field */
213 } a
; /* Auxiliary data */
214 enum pp_token_type type
;
218 * Multi-line macro definitions are stored as a linked list of
219 * these, which is essentially a container to allow several linked
222 * Note that in this module, linked lists are treated as stacks
223 * wherever possible. For this reason, Lines are _pushed_ on to the
224 * `expansion' field in MMacro structures, so that the linked list,
225 * if walked, would give the macro lines in reverse order; this
226 * means that we can walk the list when expanding a macro, and thus
227 * push the lines on to the `expansion' field in _istk_ in reverse
228 * order (so that when popped back off they are in the right
229 * order). It may seem cockeyed, and it relies on my design having
230 * an even number of steps in, but it works...
232 * Some of these structures, rather than being actual lines, are
233 * markers delimiting the end of the expansion of a given macro.
234 * This is for use in the cycle-tracking and %rep-handling code.
235 * Such structures have `finishes' non-NULL, and `first' NULL. All
236 * others have `finishes' NULL, but `first' may still be NULL if
246 * To handle an arbitrary level of file inclusion, we maintain a
247 * stack (ie linked list) of these things.
256 MMacro
*mstk
; /* stack of active macros/reps */
260 * Include search path. This is simply a list of strings which get
261 * prepended, in turn, to the name of an include file, in an
262 * attempt to find the file if it's not in the current directory.
270 * Conditional assembly: we maintain a separate stack of these for
271 * each level of file inclusion. (The only reason we keep the
272 * stacks separate is to ensure that a stray `%endif' in a file
273 * included from within the true branch of a `%if' won't terminate
274 * it and cause confusion: instead, rightly, it'll cause an error.)
282 * These states are for use just after %if or %elif: IF_TRUE
283 * means the condition has evaluated to truth so we are
284 * currently emitting, whereas IF_FALSE means we are not
285 * currently emitting but will start doing so if a %else comes
286 * up. In these states, all directives are admissible: %elif,
287 * %else and %endif. (And of course %if.)
289 COND_IF_TRUE
, COND_IF_FALSE
,
291 * These states come up after a %else: ELSE_TRUE means we're
292 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
293 * any %elif or %else will cause an error.
295 COND_ELSE_TRUE
, COND_ELSE_FALSE
,
297 * These states mean that we're not emitting now, and also that
298 * nothing until %endif will be emitted at all. COND_DONE is
299 * used when we've had our moment of emission
300 * and have now started seeing %elifs. COND_NEVER is used when
301 * the condition construct in question is contained within a
302 * non-emitting branch of a larger condition construct,
303 * or if there is an error.
305 COND_DONE
, COND_NEVER
307 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
310 * These defines are used as the possible return values for do_directive
312 #define NO_DIRECTIVE_FOUND 0
313 #define DIRECTIVE_FOUND 1
316 * Condition codes. Note that we use c_ prefix not C_ because C_ is
317 * used in nasm.h for the "real" condition codes. At _this_ level,
318 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
319 * ones, so we need a different enum...
321 static const char * const conditions
[] = {
322 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
323 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
324 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
327 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
328 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
329 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_RCXZ
, c_S
, c_Z
,
332 static const enum pp_conds inverse_ccs
[] = {
333 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
334 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
,
335 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, -1, c_NS
, c_NZ
341 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
342 static int is_condition(enum preproc_token arg
)
344 return PP_IS_COND(arg
) || (arg
== PP_ELSE
) || (arg
== PP_ENDIF
);
347 /* For TASM compatibility we need to be able to recognise TASM compatible
348 * conditional compilation directives. Using the NASM pre-processor does
349 * not work, so we look for them specifically from the following list and
350 * then jam in the equivalent NASM directive into the input stream.
354 TM_ARG
, TM_ELIF
, TM_ELSE
, TM_ENDIF
, TM_IF
, TM_IFDEF
, TM_IFDIFI
,
355 TM_IFNDEF
, TM_INCLUDE
, TM_LOCAL
358 static const char * const tasm_directives
[] = {
359 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
360 "ifndef", "include", "local"
363 static int StackSize
= 4;
364 static char *StackPointer
= "ebp";
365 static int ArgOffset
= 8;
366 static int LocalOffset
= 0;
368 static Context
*cstk
;
369 static Include
*istk
;
370 static IncPath
*ipath
= NULL
;
372 static efunc _error
; /* Pointer to client-provided error reporting function */
373 static evalfunc evaluate
;
375 static int pass
; /* HACK: pass 0 = generate dependencies only */
376 static StrList
**dephead
, **deptail
; /* Dependency list */
378 static uint64_t unique
; /* unique identifier numbers */
380 static Line
*predef
= NULL
;
381 static bool do_predef
;
383 static ListGen
*list
;
386 * The current set of multi-line macros we have defined.
388 static struct hash_table mmacros
;
391 * The current set of single-line macros we have defined.
393 static struct hash_table smacros
;
396 * The multi-line macro we are currently defining, or the %rep
397 * block we are currently reading, if any.
399 static MMacro
*defining
;
401 static uint64_t nested_mac_count
;
402 static uint64_t nested_rep_count
;
405 * The number of macro parameters to allocate space for at a time.
407 #define PARAM_DELTA 16
410 * The standard macro set: defined in macros.c in the array nasm_stdmac.
411 * This gives our position in the macro set, when we're processing it.
413 static macros_t
*stdmacpos
;
416 * The extra standard macros that come from the object format, if
419 static macros_t
*extrastdmac
= NULL
;
420 static bool any_extrastdmac
;
423 * Tokens are allocated in blocks to improve speed
425 #define TOKEN_BLOCKSIZE 4096
426 static Token
*freeTokens
= NULL
;
432 static Blocks blocks
= { NULL
, NULL
};
435 * Forward declarations.
437 static Token
*expand_mmac_params(Token
* tline
);
438 static Token
*expand_smacro(Token
* tline
);
439 static Token
*expand_id(Token
* tline
);
440 static Context
*get_ctx(const char *name
, const char **namep
,
442 static void make_tok_num(Token
* tok
, int64_t val
);
443 static void error(int severity
, const char *fmt
, ...);
444 static void error_precond(int severity
, const char *fmt
, ...);
445 static void *new_Block(size_t size
);
446 static void delete_Blocks(void);
447 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
448 const char *text
, int txtlen
);
449 static Token
*delete_Token(Token
* t
);
452 * Macros for safe checking of token pointers, avoid *(NULL)
454 #define tok_type_(x,t) ((x) && (x)->type == (t))
455 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
456 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
457 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
459 /* Handle TASM specific directives, which do not contain a % in
460 * front of them. We do it here because I could not find any other
461 * place to do it for the moment, and it is a hack (ideally it would
462 * be nice to be able to use the NASM pre-processor to do it).
464 static char *check_tasm_directive(char *line
)
466 int32_t i
, j
, k
, m
, len
;
467 char *p
= line
, *oldline
, oldchar
;
469 /* Skip whitespace */
470 while (nasm_isspace(*p
) && *p
!= 0)
473 /* Binary search for the directive name */
475 j
= elements(tasm_directives
);
477 while (!nasm_isspace(p
[len
]) && p
[len
] != 0)
484 m
= nasm_stricmp(p
, tasm_directives
[k
]);
486 /* We have found a directive, so jam a % in front of it
487 * so that NASM will then recognise it as one if it's own.
492 line
= nasm_malloc(len
+ 2);
494 if (k
== TM_IFDIFI
) {
496 * NASM does not recognise IFDIFI, so we convert
497 * it to %if 0. This is not used in NASM
498 * compatible code, but does need to parse for the
499 * TASM macro package.
501 strcpy(line
+ 1, "if 0");
503 memcpy(line
+ 1, p
, len
+ 1);
518 * The pre-preprocessing stage... This function translates line
519 * number indications as they emerge from GNU cpp (`# lineno "file"
520 * flags') into NASM preprocessor line number indications (`%line
523 static char *prepreproc(char *line
)
526 char *fname
, *oldline
;
528 if (line
[0] == '#' && line
[1] == ' ') {
531 lineno
= atoi(fname
);
532 fname
+= strspn(fname
, "0123456789 ");
535 fnlen
= strcspn(fname
, "\"");
536 line
= nasm_malloc(20 + fnlen
);
537 snprintf(line
, 20 + fnlen
, "%%line %d %.*s", lineno
, fnlen
, fname
);
540 if (tasm_compatible_mode
)
541 return check_tasm_directive(line
);
546 * Free a linked list of tokens.
548 static void free_tlist(Token
* list
)
551 list
= delete_Token(list
);
556 * Free a linked list of lines.
558 static void free_llist(Line
* list
)
564 free_tlist(l
->first
);
572 static void free_mmacro(MMacro
* m
)
575 free_tlist(m
->dlist
);
576 nasm_free(m
->defaults
);
577 free_llist(m
->expansion
);
582 * Free all currently defined macros, and free the hash tables
584 static void free_smacro_table(struct hash_table
*smt
)
588 struct hash_tbl_node
*it
= NULL
;
590 while ((s
= hash_iterate(smt
, &it
, &key
)) != NULL
) {
591 nasm_free((void *)key
);
593 SMacro
*ns
= s
->next
;
595 free_tlist(s
->expansion
);
603 static void free_mmacro_table(struct hash_table
*mmt
)
607 struct hash_tbl_node
*it
= NULL
;
610 while ((m
= hash_iterate(mmt
, &it
, &key
)) != NULL
) {
611 nasm_free((void *)key
);
613 MMacro
*nm
= m
->next
;
621 static void free_macros(void)
623 free_smacro_table(&smacros
);
624 free_mmacro_table(&mmacros
);
628 * Initialize the hash tables
630 static void init_macros(void)
632 hash_init(&smacros
, HASH_LARGE
);
633 hash_init(&mmacros
, HASH_LARGE
);
637 * Pop the context stack.
639 static void ctx_pop(void)
644 free_smacro_table(&c
->localmac
);
650 * Search for a key in the hash index; adding it if necessary
651 * (in which case we initialize the data pointer to NULL.)
654 hash_findi_add(struct hash_table
*hash
, const char *str
)
656 struct hash_insert hi
;
660 r
= hash_findi(hash
, str
, &hi
);
664 strx
= nasm_strdup(str
); /* Use a more efficient allocator here? */
665 return hash_add(&hi
, strx
, NULL
);
669 * Like hash_findi, but returns the data element rather than a pointer
670 * to it. Used only when not adding a new element, hence no third
674 hash_findix(struct hash_table
*hash
, const char *str
)
678 p
= hash_findi(hash
, str
, NULL
);
679 return p
? *p
: NULL
;
682 #define BUF_DELTA 512
684 * Read a line from the top file in istk, handling multiple CR/LFs
685 * at the end of the line read, and handling spurious ^Zs. Will
686 * return lines from the standard macro set if this has not already
689 static char *read_line(void)
691 char *buffer
, *p
, *q
;
692 int bufsize
, continued_count
;
696 const unsigned char *p
= stdmacpos
;
701 len
+= pp_directives_len
[c
-0x80]+1;
705 ret
= nasm_malloc(len
+1);
707 while ((c
= *stdmacpos
++)) {
709 memcpy(q
, pp_directives
[c
-0x80], pp_directives_len
[c
-0x80]);
710 q
+= pp_directives_len
[c
-0x80];
720 /* This was the last of the standard macro chain... */
722 if (any_extrastdmac
) {
723 stdmacpos
= extrastdmac
;
724 any_extrastdmac
= false;
725 } else if (do_predef
) {
727 Token
*head
, **tail
, *t
;
730 * Nasty hack: here we push the contents of
731 * `predef' on to the top-level expansion stack,
732 * since this is the most convenient way to
733 * implement the pre-include and pre-define
736 for (pd
= predef
; pd
; pd
= pd
->next
) {
739 for (t
= pd
->first
; t
; t
= t
->next
) {
740 *tail
= new_Token(NULL
, t
->type
, t
->text
, 0);
741 tail
= &(*tail
)->next
;
743 l
= nasm_malloc(sizeof(Line
));
744 l
->next
= istk
->expansion
;
756 buffer
= nasm_malloc(BUF_DELTA
);
760 q
= fgets(p
, bufsize
- (p
- buffer
), istk
->fp
);
764 if (p
> buffer
&& p
[-1] == '\n') {
765 /* Convert backslash-CRLF line continuation sequences into
766 nothing at all (for DOS and Windows) */
767 if (((p
- 2) > buffer
) && (p
[-3] == '\\') && (p
[-2] == '\r')) {
772 /* Also convert backslash-LF line continuation sequences into
773 nothing at all (for Unix) */
774 else if (((p
- 1) > buffer
) && (p
[-2] == '\\')) {
782 if (p
- buffer
> bufsize
- 10) {
783 int32_t offset
= p
- buffer
;
784 bufsize
+= BUF_DELTA
;
785 buffer
= nasm_realloc(buffer
, bufsize
);
786 p
= buffer
+ offset
; /* prevent stale-pointer problems */
790 if (!q
&& p
== buffer
) {
795 src_set_linnum(src_get_linnum() + istk
->lineinc
+
796 (continued_count
* istk
->lineinc
));
799 * Play safe: remove CRs as well as LFs, if any of either are
800 * present at the end of the line.
802 while (--p
>= buffer
&& (*p
== '\n' || *p
== '\r'))
806 * Handle spurious ^Z, which may be inserted into source files
807 * by some file transfer utilities.
809 buffer
[strcspn(buffer
, "\032")] = '\0';
811 list
->line(LIST_READ
, buffer
);
817 * Tokenize a line of text. This is a very simple process since we
818 * don't need to parse the value out of e.g. numeric tokens: we
819 * simply split one string into many.
821 static Token
*tokenize(char *line
)
824 enum pp_token_type type
;
826 Token
*t
, **tail
= &list
;
832 if (*p
== '+' && !nasm_isdigit(p
[1])) {
835 } else if (nasm_isdigit(*p
) ||
836 ((*p
== '-' || *p
== '+') && nasm_isdigit(p
[1]))) {
840 while (nasm_isdigit(*p
));
841 type
= TOK_PREPROC_ID
;
842 } else if (*p
== '{') {
844 while (*p
&& *p
!= '}') {
851 type
= TOK_PREPROC_ID
;
852 } else if (*p
== '[') {
854 line
+= 2; /* Skip the leading %[ */
856 while (lvl
&& (c
= *p
++)) {
868 p
= nasm_skip_string(p
)+1;
878 error(ERR_NONFATAL
, "unterminated %[ construct");
880 } else if (*p
== '?') {
881 type
= TOK_PREPROC_Q
; /* %? */
884 type
= TOK_PREPROC_QQ
; /* %?? */
887 } else if (isidchar(*p
) ||
888 ((*p
== '!' || *p
== '%' || *p
== '$') &&
893 while (isidchar(*p
));
894 type
= TOK_PREPROC_ID
;
900 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
903 while (*p
&& isidchar(*p
))
905 } else if (*p
== '\'' || *p
== '"' || *p
== '`') {
910 p
= nasm_skip_string(p
);
915 error(ERR_WARNING
|ERR_PASS1
, "unterminated string");
916 /* Handling unterminated strings by UNV */
919 } else if (p
[0] == '$' && p
[1] == '$') {
920 type
= TOK_OTHER
; /* TOKEN_BASE */
922 } else if (isnumstart(*p
)) {
924 bool is_float
= false;
940 if (!is_hex
&& (c
== 'e' || c
== 'E')) {
942 if (*p
== '+' || *p
== '-') {
943 /* e can only be followed by +/- if it is either a
944 prefixed hex number or a floating-point number */
948 } else if (c
== 'H' || c
== 'h' || c
== 'X' || c
== 'x') {
950 } else if (c
== 'P' || c
== 'p') {
952 if (*p
== '+' || *p
== '-')
954 } else if (isnumchar(c
) || c
== '_')
957 /* we need to deal with consequences of the legacy
958 parser, like "1.nolist" being two tokens
959 (TOK_NUMBER, TOK_ID) here; at least give it
960 a shot for now. In the future, we probably need
961 a flex-based scanner with proper pattern matching
962 to do it as well as it can be done. Nothing in
963 the world is going to help the person who wants
964 0x123.p16 interpreted as two tokens, though. */
969 if (nasm_isdigit(*r
) || (is_hex
&& nasm_isxdigit(*r
)) ||
970 (!is_hex
&& (*r
== 'e' || *r
== 'E')) ||
971 (*r
== 'p' || *r
== 'P')) {
975 break; /* Terminate the token */
979 p
--; /* Point to first character beyond number */
981 if (p
== line
+1 && *line
== '$') {
982 type
= TOK_OTHER
; /* TOKEN_HERE */
984 if (has_e
&& !is_hex
) {
985 /* 1e13 is floating-point, but 1e13h is not */
989 type
= is_float
? TOK_FLOAT
: TOK_NUMBER
;
991 } else if (nasm_isspace(*p
)) {
992 type
= TOK_WHITESPACE
;
994 while (*p
&& nasm_isspace(*p
))
997 * Whitespace just before end-of-line is discarded by
998 * pretending it's a comment; whitespace just before a
999 * comment gets lumped into the comment.
1001 if (!*p
|| *p
== ';') {
1006 } else if (*p
== ';') {
1012 * Anything else is an operator of some kind. We check
1013 * for all the double-character operators (>>, <<, //,
1014 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1015 * else is a single-character operator.
1018 if ((p
[0] == '>' && p
[1] == '>') ||
1019 (p
[0] == '<' && p
[1] == '<') ||
1020 (p
[0] == '/' && p
[1] == '/') ||
1021 (p
[0] == '<' && p
[1] == '=') ||
1022 (p
[0] == '>' && p
[1] == '=') ||
1023 (p
[0] == '=' && p
[1] == '=') ||
1024 (p
[0] == '!' && p
[1] == '=') ||
1025 (p
[0] == '<' && p
[1] == '>') ||
1026 (p
[0] == '&' && p
[1] == '&') ||
1027 (p
[0] == '|' && p
[1] == '|') ||
1028 (p
[0] == '^' && p
[1] == '^')) {
1034 /* Handling unterminated string by UNV */
1037 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1038 t->text[p-line] = *line;
1042 if (type
!= TOK_COMMENT
) {
1043 *tail
= t
= new_Token(NULL
, type
, line
, p
- line
);
1052 * this function allocates a new managed block of memory and
1053 * returns a pointer to the block. The managed blocks are
1054 * deleted only all at once by the delete_Blocks function.
1056 static void *new_Block(size_t size
)
1058 Blocks
*b
= &blocks
;
1060 /* first, get to the end of the linked list */
1063 /* now allocate the requested chunk */
1064 b
->chunk
= nasm_malloc(size
);
1066 /* now allocate a new block for the next request */
1067 b
->next
= nasm_malloc(sizeof(Blocks
));
1068 /* and initialize the contents of the new block */
1069 b
->next
->next
= NULL
;
1070 b
->next
->chunk
= NULL
;
1075 * this function deletes all managed blocks of memory
1077 static void delete_Blocks(void)
1079 Blocks
*a
, *b
= &blocks
;
1082 * keep in mind that the first block, pointed to by blocks
1083 * is a static and not dynamically allocated, so we don't
1088 nasm_free(b
->chunk
);
1097 * this function creates a new Token and passes a pointer to it
1098 * back to the caller. It sets the type and text elements, and
1099 * also the a.mac and next elements to NULL.
1101 static Token
*new_Token(Token
* next
, enum pp_token_type type
,
1102 const char *text
, int txtlen
)
1107 if (freeTokens
== NULL
) {
1108 freeTokens
= (Token
*) new_Block(TOKEN_BLOCKSIZE
* sizeof(Token
));
1109 for (i
= 0; i
< TOKEN_BLOCKSIZE
- 1; i
++)
1110 freeTokens
[i
].next
= &freeTokens
[i
+ 1];
1111 freeTokens
[i
].next
= NULL
;
1114 freeTokens
= t
->next
;
1118 if (type
== TOK_WHITESPACE
|| text
== NULL
) {
1122 txtlen
= strlen(text
);
1123 t
->text
= nasm_malloc(txtlen
+1);
1124 memcpy(t
->text
, text
, txtlen
);
1125 t
->text
[txtlen
] = '\0';
1130 static Token
*delete_Token(Token
* t
)
1132 Token
*next
= t
->next
;
1134 t
->next
= freeTokens
;
1140 * Convert a line of tokens back into text.
1141 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1142 * will be transformed into ..@ctxnum.xxx
1144 static char *detoken(Token
* tlist
, bool expand_locals
)
1152 for (t
= tlist
; t
; t
= t
->next
) {
1153 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
1154 char *p
= getenv(t
->text
+ 2);
1157 t
->text
= nasm_strdup(p
);
1161 /* Expand local macros here and not during preprocessing */
1162 if (expand_locals
&&
1163 t
->type
== TOK_PREPROC_ID
&& t
->text
&&
1164 t
->text
[0] == '%' && t
->text
[1] == '$') {
1167 Context
*ctx
= get_ctx(t
->text
, &q
, false);
1170 snprintf(buffer
, sizeof(buffer
), "..@%"PRIu32
".", ctx
->number
);
1171 p
= nasm_strcat(buffer
, q
);
1176 if (t
->type
== TOK_WHITESPACE
) {
1178 } else if (t
->text
) {
1179 len
+= strlen(t
->text
);
1182 p
= line
= nasm_malloc(len
+ 1);
1183 for (t
= tlist
; t
; t
= t
->next
) {
1184 if (t
->type
== TOK_WHITESPACE
) {
1186 } else if (t
->text
) {
1197 * A scanner, suitable for use by the expression evaluator, which
1198 * operates on a line of Tokens. Expects a pointer to a pointer to
1199 * the first token in the line to be passed in as its private_data
1202 * FIX: This really needs to be unified with stdscan.
1204 static int ppscan(void *private_data
, struct tokenval
*tokval
)
1206 Token
**tlineptr
= private_data
;
1208 char ourcopy
[MAX_KEYWORD
+1], *p
, *r
, *s
;
1212 *tlineptr
= tline
? tline
->next
: NULL
;
1214 while (tline
&& (tline
->type
== TOK_WHITESPACE
||
1215 tline
->type
== TOK_COMMENT
));
1218 return tokval
->t_type
= TOKEN_EOS
;
1220 tokval
->t_charptr
= tline
->text
;
1222 if (tline
->text
[0] == '$' && !tline
->text
[1])
1223 return tokval
->t_type
= TOKEN_HERE
;
1224 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[2])
1225 return tokval
->t_type
= TOKEN_BASE
;
1227 if (tline
->type
== TOK_ID
) {
1228 p
= tokval
->t_charptr
= tline
->text
;
1230 tokval
->t_charptr
++;
1231 return tokval
->t_type
= TOKEN_ID
;
1234 for (r
= p
, s
= ourcopy
; *r
; r
++) {
1235 if (r
>= p
+MAX_KEYWORD
)
1236 return tokval
->t_type
= TOKEN_ID
; /* Not a keyword */
1237 *s
++ = nasm_tolower(*r
);
1240 /* right, so we have an identifier sitting in temp storage. now,
1241 * is it actually a register or instruction name, or what? */
1242 return nasm_token_hash(ourcopy
, tokval
);
1245 if (tline
->type
== TOK_NUMBER
) {
1247 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
1248 tokval
->t_charptr
= tline
->text
;
1250 return tokval
->t_type
= TOKEN_ERRNUM
;
1252 return tokval
->t_type
= TOKEN_NUM
;
1255 if (tline
->type
== TOK_FLOAT
) {
1256 return tokval
->t_type
= TOKEN_FLOAT
;
1259 if (tline
->type
== TOK_STRING
) {
1262 bq
= tline
->text
[0];
1263 tokval
->t_charptr
= tline
->text
;
1264 tokval
->t_inttwo
= nasm_unquote(tline
->text
, &ep
);
1266 if (ep
[0] != bq
|| ep
[1] != '\0')
1267 return tokval
->t_type
= TOKEN_ERRSTR
;
1269 return tokval
->t_type
= TOKEN_STR
;
1272 if (tline
->type
== TOK_OTHER
) {
1273 if (!strcmp(tline
->text
, "<<"))
1274 return tokval
->t_type
= TOKEN_SHL
;
1275 if (!strcmp(tline
->text
, ">>"))
1276 return tokval
->t_type
= TOKEN_SHR
;
1277 if (!strcmp(tline
->text
, "//"))
1278 return tokval
->t_type
= TOKEN_SDIV
;
1279 if (!strcmp(tline
->text
, "%%"))
1280 return tokval
->t_type
= TOKEN_SMOD
;
1281 if (!strcmp(tline
->text
, "=="))
1282 return tokval
->t_type
= TOKEN_EQ
;
1283 if (!strcmp(tline
->text
, "<>"))
1284 return tokval
->t_type
= TOKEN_NE
;
1285 if (!strcmp(tline
->text
, "!="))
1286 return tokval
->t_type
= TOKEN_NE
;
1287 if (!strcmp(tline
->text
, "<="))
1288 return tokval
->t_type
= TOKEN_LE
;
1289 if (!strcmp(tline
->text
, ">="))
1290 return tokval
->t_type
= TOKEN_GE
;
1291 if (!strcmp(tline
->text
, "&&"))
1292 return tokval
->t_type
= TOKEN_DBL_AND
;
1293 if (!strcmp(tline
->text
, "^^"))
1294 return tokval
->t_type
= TOKEN_DBL_XOR
;
1295 if (!strcmp(tline
->text
, "||"))
1296 return tokval
->t_type
= TOKEN_DBL_OR
;
1300 * We have no other options: just return the first character of
1303 return tokval
->t_type
= tline
->text
[0];
1307 * Compare a string to the name of an existing macro; this is a
1308 * simple wrapper which calls either strcmp or nasm_stricmp
1309 * depending on the value of the `casesense' parameter.
1311 static int mstrcmp(const char *p
, const char *q
, bool casesense
)
1313 return casesense
? strcmp(p
, q
) : nasm_stricmp(p
, q
);
1317 * Compare a string to the name of an existing macro; this is a
1318 * simple wrapper which calls either strcmp or nasm_stricmp
1319 * depending on the value of the `casesense' parameter.
1321 static int mmemcmp(const char *p
, const char *q
, size_t l
, bool casesense
)
1323 return casesense
? memcmp(p
, q
, l
) : nasm_memicmp(p
, q
, l
);
1327 * Return the Context structure associated with a %$ token. Return
1328 * NULL, having _already_ reported an error condition, if the
1329 * context stack isn't deep enough for the supplied number of $
1331 * If all_contexts == true, contexts that enclose current are
1332 * also scanned for such smacro, until it is found; if not -
1333 * only the context that directly results from the number of $'s
1334 * in variable's name.
1336 * If "namep" is non-NULL, set it to the pointer to the macro name
1337 * tail, i.e. the part beyond %$...
1339 static Context
*get_ctx(const char *name
, const char **namep
,
1349 if (!name
|| name
[0] != '%' || name
[1] != '$')
1353 error(ERR_NONFATAL
, "`%s': context stack is empty", name
);
1360 while (ctx
&& *name
== '$') {
1366 error(ERR_NONFATAL
, "`%s': context stack is only"
1367 " %d level%s deep", name
, i
, (i
== 1 ? "" : "s"));
1378 /* Search for this smacro in found context */
1379 m
= hash_findix(&ctx
->localmac
, name
);
1381 if (!mstrcmp(m
->name
, name
, m
->casesense
))
1392 * Check to see if a file is already in a string list
1394 static bool in_list(const StrList
*list
, const char *str
)
1397 if (!strcmp(list
->str
, str
))
1405 * Open an include file. This routine must always return a valid
1406 * file pointer if it returns - it's responsible for throwing an
1407 * ERR_FATAL and bombing out completely if not. It should also try
1408 * the include path one by one until it finds the file or reaches
1409 * the end of the path.
1411 static FILE *inc_fopen(const char *file
, StrList
**dhead
, StrList
***dtail
,
1416 IncPath
*ip
= ipath
;
1417 int len
= strlen(file
);
1418 size_t prefix_len
= 0;
1422 sl
= nasm_malloc(prefix_len
+len
+1+sizeof sl
->next
);
1423 memcpy(sl
->str
, prefix
, prefix_len
);
1424 memcpy(sl
->str
+prefix_len
, file
, len
+1);
1425 fp
= fopen(sl
->str
, "r");
1426 if (fp
&& dhead
&& !in_list(*dhead
, sl
->str
)) {
1444 prefix_len
= strlen(prefix
);
1446 /* -MG given and file not found */
1447 if (dhead
&& !in_list(*dhead
, file
)) {
1448 sl
= nasm_malloc(len
+1+sizeof sl
->next
);
1450 strcpy(sl
->str
, file
);
1458 error(ERR_FATAL
, "unable to open include file `%s'", file
);
1459 return NULL
; /* never reached - placate compilers */
1463 * Determine if we should warn on defining a single-line macro of
1464 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1465 * return true if _any_ single-line macro of that name is defined.
1466 * Otherwise, will return true if a single-line macro with either
1467 * `nparam' or no parameters is defined.
1469 * If a macro with precisely the right number of parameters is
1470 * defined, or nparam is -1, the address of the definition structure
1471 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1472 * is NULL, no action will be taken regarding its contents, and no
1475 * Note that this is also called with nparam zero to resolve
1478 * If you already know which context macro belongs to, you can pass
1479 * the context pointer as first parameter; if you won't but name begins
1480 * with %$ the context will be automatically computed. If all_contexts
1481 * is true, macro will be searched in outer contexts as well.
1484 smacro_defined(Context
* ctx
, const char *name
, int nparam
, SMacro
** defn
,
1487 struct hash_table
*smtbl
;
1491 smtbl
= &ctx
->localmac
;
1492 } else if (name
[0] == '%' && name
[1] == '$') {
1494 ctx
= get_ctx(name
, &name
, false);
1496 return false; /* got to return _something_ */
1497 smtbl
= &ctx
->localmac
;
1501 m
= (SMacro
*) hash_findix(smtbl
, name
);
1504 if (!mstrcmp(m
->name
, name
, m
->casesense
&& nocase
) &&
1505 (nparam
<= 0 || m
->nparam
== 0 || nparam
== (int) m
->nparam
)) {
1507 if (nparam
== (int) m
->nparam
|| nparam
== -1)
1521 * Count and mark off the parameters in a multi-line macro call.
1522 * This is called both from within the multi-line macro expansion
1523 * code, and also to mark off the default parameters when provided
1524 * in a %macro definition line.
1526 static void count_mmac_params(Token
* t
, int *nparam
, Token
*** params
)
1528 int paramsize
, brace
;
1530 *nparam
= paramsize
= 0;
1533 /* +1: we need space for the final NULL */
1534 if (*nparam
+1 >= paramsize
) {
1535 paramsize
+= PARAM_DELTA
;
1536 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
1540 if (tok_is_(t
, "{"))
1542 (*params
)[(*nparam
)++] = t
;
1543 while (tok_isnt_(t
, brace
? "}" : ","))
1545 if (t
) { /* got a comma/brace */
1549 * Now we've found the closing brace, look further
1553 if (tok_isnt_(t
, ",")) {
1555 "braces do not enclose all of macro parameter");
1556 while (tok_isnt_(t
, ","))
1560 t
= t
->next
; /* eat the comma */
1567 * Determine whether one of the various `if' conditions is true or
1570 * We must free the tline we get passed.
1572 static bool if_condition(Token
* tline
, enum preproc_token ct
)
1574 enum pp_conditional i
= PP_COND(ct
);
1576 Token
*t
, *tt
, **tptr
, *origline
;
1577 struct tokenval tokval
;
1579 enum pp_token_type needtype
;
1585 j
= false; /* have we matched yet? */
1590 if (tline
->type
!= TOK_ID
) {
1592 "`%s' expects context identifiers", pp_directives
[ct
]);
1593 free_tlist(origline
);
1596 if (cstk
&& cstk
->name
&& !nasm_stricmp(tline
->text
, cstk
->name
))
1598 tline
= tline
->next
;
1603 j
= false; /* have we matched yet? */
1606 if (!tline
|| (tline
->type
!= TOK_ID
&&
1607 (tline
->type
!= TOK_PREPROC_ID
||
1608 tline
->text
[1] != '$'))) {
1610 "`%s' expects macro identifiers", pp_directives
[ct
]);
1613 if (smacro_defined(NULL
, tline
->text
, 0, NULL
, true))
1615 tline
= tline
->next
;
1621 tline
= expand_smacro(tline
);
1623 while (tok_isnt_(tt
, ","))
1627 "`%s' expects two comma-separated arguments",
1632 j
= true; /* assume equality unless proved not */
1633 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1634 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1635 error(ERR_NONFATAL
, "`%s': more than one comma on line",
1639 if (t
->type
== TOK_WHITESPACE
) {
1643 if (tt
->type
== TOK_WHITESPACE
) {
1647 if (tt
->type
!= t
->type
) {
1648 j
= false; /* found mismatching tokens */
1651 /* When comparing strings, need to unquote them first */
1652 if (t
->type
== TOK_STRING
) {
1653 size_t l1
= nasm_unquote(t
->text
, NULL
);
1654 size_t l2
= nasm_unquote(tt
->text
, NULL
);
1660 if (mmemcmp(t
->text
, tt
->text
, l1
, i
== PPC_IFIDN
)) {
1664 } else if (mstrcmp(tt
->text
, t
->text
, i
== PPC_IFIDN
) != 0) {
1665 j
= false; /* found mismatching tokens */
1672 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
1673 j
= false; /* trailing gunk on one end or other */
1679 MMacro searching
, *mmac
;
1682 tline
= expand_id(tline
);
1683 if (!tok_type_(tline
, TOK_ID
)) {
1685 "`%s' expects a macro name", pp_directives
[ct
]);
1688 searching
.name
= nasm_strdup(tline
->text
);
1689 searching
.casesense
= true;
1690 searching
.plus
= false;
1691 searching
.nolist
= false;
1692 searching
.in_progress
= 0;
1693 searching
.rep_nest
= NULL
;
1694 searching
.nparam_min
= 0;
1695 searching
.nparam_max
= INT_MAX
;
1696 tline
= expand_smacro(tline
->next
);
1699 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
1701 "`%s' expects a parameter count or nothing",
1704 searching
.nparam_min
= searching
.nparam_max
=
1705 readnum(tline
->text
, &j
);
1708 "unable to parse parameter count `%s'",
1711 if (tline
&& tok_is_(tline
->next
, "-")) {
1712 tline
= tline
->next
->next
;
1713 if (tok_is_(tline
, "*"))
1714 searching
.nparam_max
= INT_MAX
;
1715 else if (!tok_type_(tline
, TOK_NUMBER
))
1717 "`%s' expects a parameter count after `-'",
1720 searching
.nparam_max
= readnum(tline
->text
, &j
);
1723 "unable to parse parameter count `%s'",
1725 if (searching
.nparam_min
> searching
.nparam_max
)
1727 "minimum parameter count exceeds maximum");
1730 if (tline
&& tok_is_(tline
->next
, "+")) {
1731 tline
= tline
->next
;
1732 searching
.plus
= true;
1734 mmac
= (MMacro
*) hash_findix(&mmacros
, searching
.name
);
1736 if (!strcmp(mmac
->name
, searching
.name
) &&
1737 (mmac
->nparam_min
<= searching
.nparam_max
1739 && (searching
.nparam_min
<= mmac
->nparam_max
1746 if(tline
&& tline
->next
)
1747 error(ERR_WARNING
|ERR_PASS1
,
1748 "trailing garbage after %%ifmacro ignored");
1749 nasm_free(searching
.name
);
1758 needtype
= TOK_NUMBER
;
1761 needtype
= TOK_STRING
;
1765 t
= tline
= expand_smacro(tline
);
1767 while (tok_type_(t
, TOK_WHITESPACE
) ||
1768 (needtype
== TOK_NUMBER
&&
1769 tok_type_(t
, TOK_OTHER
) &&
1770 (t
->text
[0] == '-' || t
->text
[0] == '+') &&
1774 j
= tok_type_(t
, needtype
);
1778 t
= tline
= expand_smacro(tline
);
1779 while (tok_type_(t
, TOK_WHITESPACE
))
1784 t
= t
->next
; /* Skip the actual token */
1785 while (tok_type_(t
, TOK_WHITESPACE
))
1787 j
= !t
; /* Should be nothing left */
1792 t
= tline
= expand_smacro(tline
);
1793 while (tok_type_(t
, TOK_WHITESPACE
))
1796 j
= !t
; /* Should be empty */
1800 t
= tline
= expand_smacro(tline
);
1802 tokval
.t_type
= TOKEN_INVALID
;
1803 evalresult
= evaluate(ppscan
, tptr
, &tokval
,
1804 NULL
, pass
| CRITICAL
, error
, NULL
);
1808 error(ERR_WARNING
|ERR_PASS1
,
1809 "trailing garbage after expression ignored");
1810 if (!is_simple(evalresult
)) {
1812 "non-constant value given to `%s'", pp_directives
[ct
]);
1815 j
= reloc_value(evalresult
) != 0;
1820 "preprocessor directive `%s' not yet implemented",
1825 free_tlist(origline
);
1826 return j
^ PP_NEGATIVE(ct
);
1829 free_tlist(origline
);
1834 * Common code for defining an smacro
1836 static bool define_smacro(Context
*ctx
, const char *mname
, bool casesense
,
1837 int nparam
, Token
*expansion
)
1839 SMacro
*smac
, **smhead
;
1840 struct hash_table
*smtbl
;
1842 if (smacro_defined(ctx
, mname
, nparam
, &smac
, casesense
)) {
1844 error(ERR_WARNING
|ERR_PASS1
,
1845 "single-line macro `%s' defined both with and"
1846 " without parameters", mname
);
1848 /* Some instances of the old code considered this a failure,
1849 some others didn't. What is the right thing to do here? */
1850 free_tlist(expansion
);
1851 return false; /* Failure */
1854 * We're redefining, so we have to take over an
1855 * existing SMacro structure. This means freeing
1856 * what was already in it.
1858 nasm_free(smac
->name
);
1859 free_tlist(smac
->expansion
);
1862 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
1863 smhead
= (SMacro
**) hash_findi_add(smtbl
, mname
);
1864 smac
= nasm_malloc(sizeof(SMacro
));
1865 smac
->next
= *smhead
;
1868 smac
->name
= nasm_strdup(mname
);
1869 smac
->casesense
= casesense
;
1870 smac
->nparam
= nparam
;
1871 smac
->expansion
= expansion
;
1872 smac
->in_progress
= false;
1873 return true; /* Success */
1877 * Undefine an smacro
1879 static void undef_smacro(Context
*ctx
, const char *mname
)
1881 SMacro
**smhead
, *s
, **sp
;
1882 struct hash_table
*smtbl
;
1884 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
1885 smhead
= (SMacro
**)hash_findi(smtbl
, mname
, NULL
);
1889 * We now have a macro name... go hunt for it.
1892 while ((s
= *sp
) != NULL
) {
1893 if (!mstrcmp(s
->name
, mname
, s
->casesense
)) {
1896 free_tlist(s
->expansion
);
1906 * Parse a mmacro specification.
1908 static bool parse_mmacro_spec(Token
*tline
, MMacro
*def
, const char *directive
)
1912 tline
= tline
->next
;
1914 tline
= expand_id(tline
);
1915 if (!tok_type_(tline
, TOK_ID
)) {
1916 error(ERR_NONFATAL
, "`%s' expects a macro name", directive
);
1920 def
->name
= nasm_strdup(tline
->text
);
1922 def
->nolist
= false;
1923 def
->in_progress
= 0;
1924 def
->rep_nest
= NULL
;
1925 def
->nparam_min
= 0;
1926 def
->nparam_max
= 0;
1928 tline
= expand_smacro(tline
->next
);
1930 if (!tok_type_(tline
, TOK_NUMBER
)) {
1931 error(ERR_NONFATAL
, "`%s' expects a parameter count", directive
);
1933 def
->nparam_min
= def
->nparam_max
=
1934 readnum(tline
->text
, &err
);
1937 "unable to parse parameter count `%s'", tline
->text
);
1939 if (tline
&& tok_is_(tline
->next
, "-")) {
1940 tline
= tline
->next
->next
;
1941 if (tok_is_(tline
, "*")) {
1942 def
->nparam_max
= INT_MAX
;
1943 } else if (!tok_type_(tline
, TOK_NUMBER
)) {
1945 "`%s' expects a parameter count after `-'", directive
);
1947 def
->nparam_max
= readnum(tline
->text
, &err
);
1949 error(ERR_NONFATAL
, "unable to parse parameter count `%s'",
1952 if (def
->nparam_min
> def
->nparam_max
) {
1953 error(ERR_NONFATAL
, "minimum parameter count exceeds maximum");
1957 if (tline
&& tok_is_(tline
->next
, "+")) {
1958 tline
= tline
->next
;
1961 if (tline
&& tok_type_(tline
->next
, TOK_ID
) &&
1962 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
1963 tline
= tline
->next
;
1968 * Handle default parameters.
1970 if (tline
&& tline
->next
) {
1971 def
->dlist
= tline
->next
;
1973 count_mmac_params(def
->dlist
, &def
->ndefs
, &def
->defaults
);
1976 def
->defaults
= NULL
;
1978 def
->expansion
= NULL
;
1981 def
->ndefs
> def
->nparam_max
- def
->nparam_min
&&
1983 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MDP
,
1984 "too many default macro parameters");
1991 * Decode a size directive
1993 static int parse_size(const char *str
) {
1994 static const char *size_names
[] =
1995 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
1996 static const int sizes
[] =
1997 { 0, 1, 4, 16, 8, 10, 2, 32 };
1999 return sizes
[bsii(str
, size_names
, elements(size_names
))+1];
2003 * find and process preprocessor directive in passed line
2004 * Find out if a line contains a preprocessor directive, and deal
2007 * If a directive _is_ found, it is the responsibility of this routine
2008 * (and not the caller) to free_tlist() the line.
2010 * @param tline a pointer to the current tokeninzed line linked list
2011 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2014 static int do_directive(Token
* tline
)
2016 enum preproc_token i
;
2029 MMacro
*mmac
, **mmhead
;
2030 Token
*t
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
2032 struct tokenval tokval
;
2034 MMacro
*tmp_defining
; /* Used when manipulating rep_nest */
2042 if (!tline
|| !tok_type_(tline
, TOK_PREPROC_ID
) ||
2043 (tline
->text
[1] == '%' || tline
->text
[1] == '$'
2044 || tline
->text
[1] == '!'))
2045 return NO_DIRECTIVE_FOUND
;
2047 i
= pp_token_hash(tline
->text
);
2050 * If we're in a non-emitting branch of a condition construct,
2051 * or walking to the end of an already terminated %rep block,
2052 * we should ignore all directives except for condition
2055 if (((istk
->conds
&& !emitting(istk
->conds
->state
)) ||
2056 (istk
->mstk
&& !istk
->mstk
->in_progress
)) && !is_condition(i
)) {
2057 return NO_DIRECTIVE_FOUND
;
2061 * If we're defining a macro or reading a %rep block, we should
2062 * ignore all directives except for %macro/%imacro (which nest),
2063 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2064 * If we're in a %rep block, another %rep nests, so should be let through.
2066 if (defining
&& i
!= PP_MACRO
&& i
!= PP_IMACRO
&&
2067 i
!= PP_ENDMACRO
&& i
!= PP_ENDM
&&
2068 (defining
->name
|| (i
!= PP_ENDREP
&& i
!= PP_REP
))) {
2069 return NO_DIRECTIVE_FOUND
;
2073 if (i
== PP_MACRO
|| i
== PP_IMACRO
) {
2075 return NO_DIRECTIVE_FOUND
;
2076 } else if (nested_mac_count
> 0) {
2077 if (i
== PP_ENDMACRO
) {
2079 return NO_DIRECTIVE_FOUND
;
2082 if (!defining
->name
) {
2085 return NO_DIRECTIVE_FOUND
;
2086 } else if (nested_rep_count
> 0) {
2087 if (i
== PP_ENDREP
) {
2089 return NO_DIRECTIVE_FOUND
;
2097 error(ERR_NONFATAL
, "unknown preprocessor directive `%s'",
2099 return NO_DIRECTIVE_FOUND
; /* didn't get it */
2102 /* Directive to tell NASM what the default stack size is. The
2103 * default is for a 16-bit stack, and this can be overriden with
2105 * the following form:
2107 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2109 tline
= tline
->next
;
2110 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2111 tline
= tline
->next
;
2112 if (!tline
|| tline
->type
!= TOK_ID
) {
2113 error(ERR_NONFATAL
, "`%%stacksize' missing size parameter");
2114 free_tlist(origline
);
2115 return DIRECTIVE_FOUND
;
2117 if (nasm_stricmp(tline
->text
, "flat") == 0) {
2118 /* All subsequent ARG directives are for a 32-bit stack */
2120 StackPointer
= "ebp";
2123 } else if (nasm_stricmp(tline
->text
, "flat64") == 0) {
2124 /* All subsequent ARG directives are for a 64-bit stack */
2126 StackPointer
= "rbp";
2129 } else if (nasm_stricmp(tline
->text
, "large") == 0) {
2130 /* All subsequent ARG directives are for a 16-bit stack,
2131 * far function call.
2134 StackPointer
= "bp";
2137 } else if (nasm_stricmp(tline
->text
, "small") == 0) {
2138 /* All subsequent ARG directives are for a 16-bit stack,
2139 * far function call. We don't support near functions.
2142 StackPointer
= "bp";
2146 error(ERR_NONFATAL
, "`%%stacksize' invalid size type");
2147 free_tlist(origline
);
2148 return DIRECTIVE_FOUND
;
2150 free_tlist(origline
);
2151 return DIRECTIVE_FOUND
;
2154 /* TASM like ARG directive to define arguments to functions, in
2155 * the following form:
2157 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2161 char *arg
, directive
[256];
2162 int size
= StackSize
;
2164 /* Find the argument name */
2165 tline
= tline
->next
;
2166 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2167 tline
= tline
->next
;
2168 if (!tline
|| tline
->type
!= TOK_ID
) {
2169 error(ERR_NONFATAL
, "`%%arg' missing argument parameter");
2170 free_tlist(origline
);
2171 return DIRECTIVE_FOUND
;
2175 /* Find the argument size type */
2176 tline
= tline
->next
;
2177 if (!tline
|| tline
->type
!= TOK_OTHER
2178 || tline
->text
[0] != ':') {
2180 "Syntax error processing `%%arg' directive");
2181 free_tlist(origline
);
2182 return DIRECTIVE_FOUND
;
2184 tline
= tline
->next
;
2185 if (!tline
|| tline
->type
!= TOK_ID
) {
2186 error(ERR_NONFATAL
, "`%%arg' missing size type parameter");
2187 free_tlist(origline
);
2188 return DIRECTIVE_FOUND
;
2191 /* Allow macro expansion of type parameter */
2192 tt
= tokenize(tline
->text
);
2193 tt
= expand_smacro(tt
);
2194 size
= parse_size(tt
->text
);
2197 "Invalid size type for `%%arg' missing directive");
2199 free_tlist(origline
);
2200 return DIRECTIVE_FOUND
;
2204 /* Round up to even stack slots */
2205 size
= (size
+StackSize
-1) & ~(StackSize
-1);
2207 /* Now define the macro for the argument */
2208 snprintf(directive
, sizeof(directive
), "%%define %s (%s+%d)",
2209 arg
, StackPointer
, offset
);
2210 do_directive(tokenize(directive
));
2213 /* Move to the next argument in the list */
2214 tline
= tline
->next
;
2215 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2216 tline
= tline
->next
;
2217 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2219 free_tlist(origline
);
2220 return DIRECTIVE_FOUND
;
2223 /* TASM like LOCAL directive to define local variables for a
2224 * function, in the following form:
2226 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2228 * The '= LocalSize' at the end is ignored by NASM, but is
2229 * required by TASM to define the local parameter size (and used
2230 * by the TASM macro package).
2232 offset
= LocalOffset
;
2234 char *local
, directive
[256];
2235 int size
= StackSize
;
2237 /* Find the argument name */
2238 tline
= tline
->next
;
2239 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2240 tline
= tline
->next
;
2241 if (!tline
|| tline
->type
!= TOK_ID
) {
2243 "`%%local' missing argument parameter");
2244 free_tlist(origline
);
2245 return DIRECTIVE_FOUND
;
2247 local
= tline
->text
;
2249 /* Find the argument size type */
2250 tline
= tline
->next
;
2251 if (!tline
|| tline
->type
!= TOK_OTHER
2252 || tline
->text
[0] != ':') {
2254 "Syntax error processing `%%local' directive");
2255 free_tlist(origline
);
2256 return DIRECTIVE_FOUND
;
2258 tline
= tline
->next
;
2259 if (!tline
|| tline
->type
!= TOK_ID
) {
2261 "`%%local' missing size type parameter");
2262 free_tlist(origline
);
2263 return DIRECTIVE_FOUND
;
2266 /* Allow macro expansion of type parameter */
2267 tt
= tokenize(tline
->text
);
2268 tt
= expand_smacro(tt
);
2269 size
= parse_size(tt
->text
);
2272 "Invalid size type for `%%local' missing directive");
2274 free_tlist(origline
);
2275 return DIRECTIVE_FOUND
;
2279 /* Round up to even stack slots */
2280 size
= (size
+StackSize
-1) & ~(StackSize
-1);
2282 offset
+= size
; /* Negative offset, increment before */
2284 /* Now define the macro for the argument */
2285 snprintf(directive
, sizeof(directive
), "%%define %s (%s-%d)",
2286 local
, StackPointer
, offset
);
2287 do_directive(tokenize(directive
));
2289 /* Now define the assign to setup the enter_c macro correctly */
2290 snprintf(directive
, sizeof(directive
),
2291 "%%assign %%$localsize %%$localsize+%d", size
);
2292 do_directive(tokenize(directive
));
2294 /* Move to the next argument in the list */
2295 tline
= tline
->next
;
2296 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2297 tline
= tline
->next
;
2298 } while (tline
&& tline
->type
== TOK_OTHER
&& tline
->text
[0] == ',');
2299 LocalOffset
= offset
;
2300 free_tlist(origline
);
2301 return DIRECTIVE_FOUND
;
2305 error(ERR_WARNING
|ERR_PASS1
,
2306 "trailing garbage after `%%clear' ignored");
2309 free_tlist(origline
);
2310 return DIRECTIVE_FOUND
;
2313 t
= tline
->next
= expand_smacro(tline
->next
);
2315 if (!t
|| (t
->type
!= TOK_STRING
&&
2316 t
->type
!= TOK_INTERNAL_STRING
)) {
2317 error(ERR_NONFATAL
, "`%%depend' expects a file name");
2318 free_tlist(origline
);
2319 return DIRECTIVE_FOUND
; /* but we did _something_ */
2322 error(ERR_WARNING
|ERR_PASS1
,
2323 "trailing garbage after `%%depend' ignored");
2325 if (t
->type
!= TOK_INTERNAL_STRING
)
2326 nasm_unquote(p
, NULL
);
2327 if (dephead
&& !in_list(*dephead
, p
)) {
2328 StrList
*sl
= nasm_malloc(strlen(p
)+1+sizeof sl
->next
);
2332 deptail
= &sl
->next
;
2334 free_tlist(origline
);
2335 return DIRECTIVE_FOUND
;
2338 t
= tline
->next
= expand_smacro(tline
->next
);
2341 if (!t
|| (t
->type
!= TOK_STRING
&&
2342 t
->type
!= TOK_INTERNAL_STRING
)) {
2343 error(ERR_NONFATAL
, "`%%include' expects a file name");
2344 free_tlist(origline
);
2345 return DIRECTIVE_FOUND
; /* but we did _something_ */
2348 error(ERR_WARNING
|ERR_PASS1
,
2349 "trailing garbage after `%%include' ignored");
2351 if (t
->type
!= TOK_INTERNAL_STRING
)
2352 nasm_unquote(p
, NULL
);
2353 inc
= nasm_malloc(sizeof(Include
));
2356 inc
->fp
= inc_fopen(p
, dephead
, &deptail
, pass
== 0);
2358 /* -MG given but file not found */
2361 inc
->fname
= src_set_fname(nasm_strdup(p
));
2362 inc
->lineno
= src_set_linnum(0);
2364 inc
->expansion
= NULL
;
2367 list
->uplevel(LIST_INCLUDE
);
2369 free_tlist(origline
);
2370 return DIRECTIVE_FOUND
;
2374 static macros_t
*use_pkg
;
2375 const char *pkg_macro
;
2377 tline
= tline
->next
;
2379 tline
= expand_id(tline
);
2381 if (!tline
|| (tline
->type
!= TOK_STRING
&&
2382 tline
->type
!= TOK_INTERNAL_STRING
&&
2383 tline
->type
!= TOK_ID
)) {
2384 error(ERR_NONFATAL
, "`%%use' expects a package name");
2385 free_tlist(origline
);
2386 return DIRECTIVE_FOUND
; /* but we did _something_ */
2389 error(ERR_WARNING
|ERR_PASS1
,
2390 "trailing garbage after `%%use' ignored");
2391 if (tline
->type
== TOK_STRING
)
2392 nasm_unquote(tline
->text
, NULL
);
2393 use_pkg
= nasm_stdmac_find_package(tline
->text
);
2395 error(ERR_NONFATAL
, "unknown `%%use' package: %s", tline
->text
);
2396 /* The first string will be <%define>__USE_*__ */
2397 pkg_macro
= (char *)use_pkg
+ 1;
2398 if (!smacro_defined(NULL
, pkg_macro
, 0, NULL
, true)) {
2399 /* Not already included, go ahead and include it */
2400 stdmacpos
= use_pkg
;
2402 free_tlist(origline
);
2403 return DIRECTIVE_FOUND
;
2408 tline
= tline
->next
;
2410 tline
= expand_id(tline
);
2412 if (!tok_type_(tline
, TOK_ID
)) {
2413 error(ERR_NONFATAL
, "`%s' expects a context identifier",
2415 free_tlist(origline
);
2416 return DIRECTIVE_FOUND
; /* but we did _something_ */
2419 error(ERR_WARNING
|ERR_PASS1
,
2420 "trailing garbage after `%s' ignored",
2422 p
= nasm_strdup(tline
->text
);
2424 p
= NULL
; /* Anonymous */
2428 ctx
= nasm_malloc(sizeof(Context
));
2430 hash_init(&ctx
->localmac
, HASH_SMALL
);
2432 ctx
->number
= unique
++;
2437 error(ERR_NONFATAL
, "`%s': context stack is empty",
2439 } else if (i
== PP_POP
) {
2440 if (p
&& (!cstk
->name
|| nasm_stricmp(p
, cstk
->name
)))
2441 error(ERR_NONFATAL
, "`%%pop' in wrong context: %s, "
2443 cstk
->name
? cstk
->name
: "anonymous", p
);
2448 nasm_free(cstk
->name
);
2454 free_tlist(origline
);
2455 return DIRECTIVE_FOUND
;
2457 severity
= ERR_FATAL
|ERR_NO_SEVERITY
;
2460 severity
= ERR_NONFATAL
|ERR_NO_SEVERITY
;
2463 severity
= ERR_WARNING
|ERR_NO_SEVERITY
|ERR_WARN_USER
;
2468 /* Only error out if this is the final pass */
2469 if (pass
!= 2 && i
!= PP_FATAL
)
2470 return DIRECTIVE_FOUND
;
2472 tline
->next
= expand_smacro(tline
->next
);
2473 tline
= tline
->next
;
2475 t
= tline
? tline
->next
: NULL
;
2477 if (tok_type_(tline
, TOK_STRING
) && !t
) {
2478 /* The line contains only a quoted string */
2480 nasm_unquote(p
, NULL
);
2481 error(severity
, "%s: %s", pp_directives
[i
], p
);
2483 /* Not a quoted string, or more than a quoted string */
2484 p
= detoken(tline
, false);
2485 error(severity
, "%s: %s", pp_directives
[i
], p
);
2488 free_tlist(origline
);
2489 return DIRECTIVE_FOUND
;
2493 if (istk
->conds
&& !emitting(istk
->conds
->state
))
2496 j
= if_condition(tline
->next
, i
);
2497 tline
->next
= NULL
; /* it got freed */
2498 j
= j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2500 cond
= nasm_malloc(sizeof(Cond
));
2501 cond
->next
= istk
->conds
;
2504 free_tlist(origline
);
2505 return DIRECTIVE_FOUND
;
2509 error(ERR_FATAL
, "`%s': no matching `%%if'", pp_directives
[i
]);
2510 switch(istk
->conds
->state
) {
2512 istk
->conds
->state
= COND_DONE
;
2519 case COND_ELSE_TRUE
:
2520 case COND_ELSE_FALSE
:
2521 error_precond(ERR_WARNING
|ERR_PASS1
,
2522 "`%%elif' after `%%else' ignored");
2523 istk
->conds
->state
= COND_NEVER
;
2528 * IMPORTANT: In the case of %if, we will already have
2529 * called expand_mmac_params(); however, if we're
2530 * processing an %elif we must have been in a
2531 * non-emitting mode, which would have inhibited
2532 * the normal invocation of expand_mmac_params().
2533 * Therefore, we have to do it explicitly here.
2535 j
= if_condition(expand_mmac_params(tline
->next
), i
);
2536 tline
->next
= NULL
; /* it got freed */
2537 istk
->conds
->state
=
2538 j
< 0 ? COND_NEVER
: j
? COND_IF_TRUE
: COND_IF_FALSE
;
2541 free_tlist(origline
);
2542 return DIRECTIVE_FOUND
;
2546 error_precond(ERR_WARNING
|ERR_PASS1
,
2547 "trailing garbage after `%%else' ignored");
2549 error(ERR_FATAL
, "`%%else': no matching `%%if'");
2550 switch(istk
->conds
->state
) {
2553 istk
->conds
->state
= COND_ELSE_FALSE
;
2560 istk
->conds
->state
= COND_ELSE_TRUE
;
2563 case COND_ELSE_TRUE
:
2564 case COND_ELSE_FALSE
:
2565 error_precond(ERR_WARNING
|ERR_PASS1
,
2566 "`%%else' after `%%else' ignored.");
2567 istk
->conds
->state
= COND_NEVER
;
2570 free_tlist(origline
);
2571 return DIRECTIVE_FOUND
;
2575 error_precond(ERR_WARNING
|ERR_PASS1
,
2576 "trailing garbage after `%%endif' ignored");
2578 error(ERR_FATAL
, "`%%endif': no matching `%%if'");
2580 istk
->conds
= cond
->next
;
2582 free_tlist(origline
);
2583 return DIRECTIVE_FOUND
;
2589 "`%%%smacro': already defining a macro",
2590 (i
== PP_IMACRO
? "i" : ""));
2591 return DIRECTIVE_FOUND
;
2593 defining
= nasm_malloc(sizeof(MMacro
));
2594 defining
->casesense
= (i
== PP_MACRO
);
2595 if (!parse_mmacro_spec(tline
, defining
, pp_directives
[i
])) {
2596 nasm_free(defining
);
2598 return DIRECTIVE_FOUND
;
2601 mmac
= (MMacro
*) hash_findix(&mmacros
, defining
->name
);
2603 if (!strcmp(mmac
->name
, defining
->name
) &&
2604 (mmac
->nparam_min
<= defining
->nparam_max
2606 && (defining
->nparam_min
<= mmac
->nparam_max
2608 error(ERR_WARNING
|ERR_PASS1
,
2609 "redefining multi-line macro `%s'", defining
->name
);
2610 return DIRECTIVE_FOUND
;
2614 free_tlist(origline
);
2615 return DIRECTIVE_FOUND
;
2619 if (! (defining
&& defining
->name
)) {
2620 error(ERR_NONFATAL
, "`%s': not defining a macro", tline
->text
);
2621 return DIRECTIVE_FOUND
;
2623 mmhead
= (MMacro
**) hash_findi_add(&mmacros
, defining
->name
);
2624 defining
->next
= *mmhead
;
2627 free_tlist(origline
);
2628 return DIRECTIVE_FOUND
;
2636 spec
.casesense
= (i
== PP_UNMACRO
);
2637 if (!parse_mmacro_spec(tline
, &spec
, pp_directives
[i
])) {
2638 return DIRECTIVE_FOUND
;
2640 mmac_p
= (MMacro
**) hash_findi(&mmacros
, spec
.name
, NULL
);
2641 while (mmac_p
&& *mmac_p
) {
2643 if (mmac
->casesense
== spec
.casesense
&&
2644 !mstrcmp(mmac
->name
, spec
.name
, spec
.casesense
) &&
2645 mmac
->nparam_min
== spec
.nparam_min
&&
2646 mmac
->nparam_max
== spec
.nparam_max
&&
2647 mmac
->plus
== spec
.plus
) {
2648 *mmac_p
= mmac
->next
;
2651 mmac_p
= &mmac
->next
;
2654 free_tlist(origline
);
2655 free_tlist(spec
.dlist
);
2656 return DIRECTIVE_FOUND
;
2660 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
2661 tline
= tline
->next
;
2662 if (tline
->next
== NULL
) {
2663 free_tlist(origline
);
2664 error(ERR_NONFATAL
, "`%%rotate' missing rotate count");
2665 return DIRECTIVE_FOUND
;
2667 t
= expand_smacro(tline
->next
);
2669 free_tlist(origline
);
2672 tokval
.t_type
= TOKEN_INVALID
;
2674 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
2677 return DIRECTIVE_FOUND
;
2679 error(ERR_WARNING
|ERR_PASS1
,
2680 "trailing garbage after expression ignored");
2681 if (!is_simple(evalresult
)) {
2682 error(ERR_NONFATAL
, "non-constant value given to `%%rotate'");
2683 return DIRECTIVE_FOUND
;
2686 while (mmac
&& !mmac
->name
) /* avoid mistaking %reps for macros */
2687 mmac
= mmac
->next_active
;
2689 error(ERR_NONFATAL
, "`%%rotate' invoked outside a macro call");
2690 } else if (mmac
->nparam
== 0) {
2692 "`%%rotate' invoked within macro without parameters");
2694 int rotate
= mmac
->rotate
+ reloc_value(evalresult
);
2696 rotate
%= (int)mmac
->nparam
;
2698 rotate
+= mmac
->nparam
;
2700 mmac
->rotate
= rotate
;
2702 return DIRECTIVE_FOUND
;
2707 tline
= tline
->next
;
2708 } while (tok_type_(tline
, TOK_WHITESPACE
));
2710 if (tok_type_(tline
, TOK_ID
) &&
2711 nasm_stricmp(tline
->text
, ".nolist") == 0) {
2714 tline
= tline
->next
;
2715 } while (tok_type_(tline
, TOK_WHITESPACE
));
2719 t
= expand_smacro(tline
);
2721 tokval
.t_type
= TOKEN_INVALID
;
2723 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
2725 free_tlist(origline
);
2726 return DIRECTIVE_FOUND
;
2729 error(ERR_WARNING
|ERR_PASS1
,
2730 "trailing garbage after expression ignored");
2731 if (!is_simple(evalresult
)) {
2732 error(ERR_NONFATAL
, "non-constant value given to `%%rep'");
2733 return DIRECTIVE_FOUND
;
2735 count
= reloc_value(evalresult
) + 1;
2737 error(ERR_NONFATAL
, "`%%rep' expects a repeat count");
2740 free_tlist(origline
);
2742 tmp_defining
= defining
;
2743 defining
= nasm_malloc(sizeof(MMacro
));
2744 defining
->name
= NULL
; /* flags this macro as a %rep block */
2745 defining
->casesense
= false;
2746 defining
->plus
= false;
2747 defining
->nolist
= nolist
;
2748 defining
->in_progress
= count
;
2749 defining
->nparam_min
= defining
->nparam_max
= 0;
2750 defining
->defaults
= NULL
;
2751 defining
->dlist
= NULL
;
2752 defining
->expansion
= NULL
;
2753 defining
->next_active
= istk
->mstk
;
2754 defining
->rep_nest
= tmp_defining
;
2755 return DIRECTIVE_FOUND
;
2758 if (!defining
|| defining
->name
) {
2759 error(ERR_NONFATAL
, "`%%endrep': no matching `%%rep'");
2760 return DIRECTIVE_FOUND
;
2764 * Now we have a "macro" defined - although it has no name
2765 * and we won't be entering it in the hash tables - we must
2766 * push a macro-end marker for it on to istk->expansion.
2767 * After that, it will take care of propagating itself (a
2768 * macro-end marker line for a macro which is really a %rep
2769 * block will cause the macro to be re-expanded, complete
2770 * with another macro-end marker to ensure the process
2771 * continues) until the whole expansion is forcibly removed
2772 * from istk->expansion by a %exitrep.
2774 l
= nasm_malloc(sizeof(Line
));
2775 l
->next
= istk
->expansion
;
2776 l
->finishes
= defining
;
2778 istk
->expansion
= l
;
2780 istk
->mstk
= defining
;
2782 list
->uplevel(defining
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
2783 tmp_defining
= defining
;
2784 defining
= defining
->rep_nest
;
2785 free_tlist(origline
);
2786 return DIRECTIVE_FOUND
;
2790 * We must search along istk->expansion until we hit a
2791 * macro-end marker for a macro with no name. Then we set
2792 * its `in_progress' flag to 0.
2794 for (l
= istk
->expansion
; l
; l
= l
->next
)
2795 if (l
->finishes
&& !l
->finishes
->name
)
2799 l
->finishes
->in_progress
= 1;
2801 error(ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
2802 free_tlist(origline
);
2803 return DIRECTIVE_FOUND
;
2809 casesense
= (i
== PP_DEFINE
|| i
== PP_XDEFINE
);
2811 tline
= tline
->next
;
2813 tline
= expand_id(tline
);
2814 if (!tline
|| (tline
->type
!= TOK_ID
&&
2815 (tline
->type
!= TOK_PREPROC_ID
||
2816 tline
->text
[1] != '$'))) {
2817 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
2819 free_tlist(origline
);
2820 return DIRECTIVE_FOUND
;
2823 ctx
= get_ctx(tline
->text
, &mname
, false);
2825 param_start
= tline
= tline
->next
;
2828 /* Expand the macro definition now for %xdefine and %ixdefine */
2829 if ((i
== PP_XDEFINE
) || (i
== PP_IXDEFINE
))
2830 tline
= expand_smacro(tline
);
2832 if (tok_is_(tline
, "(")) {
2834 * This macro has parameters.
2837 tline
= tline
->next
;
2841 error(ERR_NONFATAL
, "parameter identifier expected");
2842 free_tlist(origline
);
2843 return DIRECTIVE_FOUND
;
2845 if (tline
->type
!= TOK_ID
) {
2847 "`%s': parameter identifier expected",
2849 free_tlist(origline
);
2850 return DIRECTIVE_FOUND
;
2852 tline
->type
= TOK_SMAC_PARAM
+ nparam
++;
2853 tline
= tline
->next
;
2855 if (tok_is_(tline
, ",")) {
2856 tline
= tline
->next
;
2858 if (!tok_is_(tline
, ")")) {
2860 "`)' expected to terminate macro template");
2861 free_tlist(origline
);
2862 return DIRECTIVE_FOUND
;
2868 tline
= tline
->next
;
2870 if (tok_type_(tline
, TOK_WHITESPACE
))
2871 last
= tline
, tline
= tline
->next
;
2876 if (t
->type
== TOK_ID
) {
2877 for (tt
= param_start
; tt
; tt
= tt
->next
)
2878 if (tt
->type
>= TOK_SMAC_PARAM
&&
2879 !strcmp(tt
->text
, t
->text
))
2883 t
->next
= macro_start
;
2888 * Good. We now have a macro name, a parameter count, and a
2889 * token list (in reverse order) for an expansion. We ought
2890 * to be OK just to create an SMacro, store it, and let
2891 * free_tlist have the rest of the line (which we have
2892 * carefully re-terminated after chopping off the expansion
2895 define_smacro(ctx
, mname
, casesense
, nparam
, macro_start
);
2896 free_tlist(origline
);
2897 return DIRECTIVE_FOUND
;
2900 tline
= tline
->next
;
2902 tline
= expand_id(tline
);
2903 if (!tline
|| (tline
->type
!= TOK_ID
&&
2904 (tline
->type
!= TOK_PREPROC_ID
||
2905 tline
->text
[1] != '$'))) {
2906 error(ERR_NONFATAL
, "`%%undef' expects a macro identifier");
2907 free_tlist(origline
);
2908 return DIRECTIVE_FOUND
;
2911 error(ERR_WARNING
|ERR_PASS1
,
2912 "trailing garbage after macro name ignored");
2915 /* Find the context that symbol belongs to */
2916 ctx
= get_ctx(tline
->text
, &mname
, false);
2917 undef_smacro(ctx
, mname
);
2918 free_tlist(origline
);
2919 return DIRECTIVE_FOUND
;
2923 casesense
= (i
== PP_DEFSTR
);
2925 tline
= tline
->next
;
2927 tline
= expand_id(tline
);
2928 if (!tline
|| (tline
->type
!= TOK_ID
&&
2929 (tline
->type
!= TOK_PREPROC_ID
||
2930 tline
->text
[1] != '$'))) {
2931 error(ERR_NONFATAL
, "`%s' expects a macro identifier",
2933 free_tlist(origline
);
2934 return DIRECTIVE_FOUND
;
2937 ctx
= get_ctx(tline
->text
, &mname
, false);
2939 tline
= expand_smacro(tline
->next
);
2942 while (tok_type_(tline
, TOK_WHITESPACE
))
2943 tline
= delete_Token(tline
);
2945 p
= detoken(tline
, false);
2946 macro_start
= nasm_malloc(sizeof(*macro_start
));
2947 macro_start
->next
= NULL
;
2948 macro_start
->text
= nasm_quote(p
, strlen(p
));
2949 macro_start
->type
= TOK_STRING
;
2950 macro_start
->a
.mac
= NULL
;
2954 * We now have a macro name, an implicit parameter count of
2955 * zero, and a string token to use as an expansion. Create
2956 * and store an SMacro.
2958 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
2959 free_tlist(origline
);
2960 return DIRECTIVE_FOUND
;
2965 StrList
*xsl
= NULL
;
2966 StrList
**xst
= &xsl
;
2970 tline
= tline
->next
;
2972 tline
= expand_id(tline
);
2973 if (!tline
|| (tline
->type
!= TOK_ID
&&
2974 (tline
->type
!= TOK_PREPROC_ID
||
2975 tline
->text
[1] != '$'))) {
2977 "`%%pathsearch' expects a macro identifier as first parameter");
2978 free_tlist(origline
);
2979 return DIRECTIVE_FOUND
;
2981 ctx
= get_ctx(tline
->text
, &mname
, false);
2983 tline
= expand_smacro(tline
->next
);
2987 while (tok_type_(t
, TOK_WHITESPACE
))
2990 if (!t
|| (t
->type
!= TOK_STRING
&&
2991 t
->type
!= TOK_INTERNAL_STRING
)) {
2992 error(ERR_NONFATAL
, "`%%pathsearch' expects a file name");
2994 free_tlist(origline
);
2995 return DIRECTIVE_FOUND
; /* but we did _something_ */
2998 error(ERR_WARNING
|ERR_PASS1
,
2999 "trailing garbage after `%%pathsearch' ignored");
3001 if (t
->type
!= TOK_INTERNAL_STRING
)
3002 nasm_unquote(p
, NULL
);
3004 fp
= inc_fopen(p
, &xsl
, &xst
, true);
3007 fclose(fp
); /* Don't actually care about the file */
3009 macro_start
= nasm_malloc(sizeof(*macro_start
));
3010 macro_start
->next
= NULL
;
3011 macro_start
->text
= nasm_quote(p
, strlen(p
));
3012 macro_start
->type
= TOK_STRING
;
3013 macro_start
->a
.mac
= NULL
;
3018 * We now have a macro name, an implicit parameter count of
3019 * zero, and a string token to use as an expansion. Create
3020 * and store an SMacro.
3022 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3024 free_tlist(origline
);
3025 return DIRECTIVE_FOUND
;
3031 tline
= tline
->next
;
3033 tline
= expand_id(tline
);
3034 if (!tline
|| (tline
->type
!= TOK_ID
&&
3035 (tline
->type
!= TOK_PREPROC_ID
||
3036 tline
->text
[1] != '$'))) {
3038 "`%%strlen' expects a macro identifier as first parameter");
3039 free_tlist(origline
);
3040 return DIRECTIVE_FOUND
;
3042 ctx
= get_ctx(tline
->text
, &mname
, false);
3044 tline
= expand_smacro(tline
->next
);
3048 while (tok_type_(t
, TOK_WHITESPACE
))
3050 /* t should now point to the string */
3051 if (t
->type
!= TOK_STRING
) {
3053 "`%%strlen` requires string as second parameter");
3055 free_tlist(origline
);
3056 return DIRECTIVE_FOUND
;
3059 macro_start
= nasm_malloc(sizeof(*macro_start
));
3060 macro_start
->next
= NULL
;
3061 make_tok_num(macro_start
, nasm_unquote(t
->text
, NULL
));
3062 macro_start
->a
.mac
= NULL
;
3065 * We now have a macro name, an implicit parameter count of
3066 * zero, and a numeric token to use as an expansion. Create
3067 * and store an SMacro.
3069 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3071 free_tlist(origline
);
3072 return DIRECTIVE_FOUND
;
3077 tline
= tline
->next
;
3079 tline
= expand_id(tline
);
3080 if (!tline
|| (tline
->type
!= TOK_ID
&&
3081 (tline
->type
!= TOK_PREPROC_ID
||
3082 tline
->text
[1] != '$'))) {
3084 "`%%strcat' expects a macro identifier as first parameter");
3085 free_tlist(origline
);
3086 return DIRECTIVE_FOUND
;
3088 ctx
= get_ctx(tline
->text
, &mname
, false);
3090 tline
= expand_smacro(tline
->next
);
3094 for (t
= tline
; t
; t
= t
->next
) {
3096 case TOK_WHITESPACE
:
3099 len
+= t
->a
.len
= nasm_unquote(t
->text
, NULL
);
3102 if (!strcmp(t
->text
, ",")) /* permit comma separators */
3104 /* else fall through */
3107 "non-string passed to `%%strcat' (%d)", t
->type
);
3109 free_tlist(origline
);
3110 return DIRECTIVE_FOUND
;
3114 p
= pp
= nasm_malloc(len
);
3116 for (t
= tline
; t
; t
= t
->next
) {
3117 if (t
->type
== TOK_STRING
) {
3118 memcpy(p
, t
->text
, t
->a
.len
);
3124 * We now have a macro name, an implicit parameter count of
3125 * zero, and a numeric token to use as an expansion. Create
3126 * and store an SMacro.
3128 macro_start
= new_Token(NULL
, TOK_STRING
, NULL
, 0);
3129 macro_start
->text
= nasm_quote(pp
, len
);
3131 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3133 free_tlist(origline
);
3134 return DIRECTIVE_FOUND
;
3143 tline
= tline
->next
;
3145 tline
= expand_id(tline
);
3146 if (!tline
|| (tline
->type
!= TOK_ID
&&
3147 (tline
->type
!= TOK_PREPROC_ID
||
3148 tline
->text
[1] != '$'))) {
3150 "`%%substr' expects a macro identifier as first parameter");
3151 free_tlist(origline
);
3152 return DIRECTIVE_FOUND
;
3154 ctx
= get_ctx(tline
->text
, &mname
, false);
3156 tline
= expand_smacro(tline
->next
);
3160 while (tok_type_(t
, TOK_WHITESPACE
))
3163 /* t should now point to the string */
3164 if (t
->type
!= TOK_STRING
) {
3166 "`%%substr` requires string as second parameter");
3168 free_tlist(origline
);
3169 return DIRECTIVE_FOUND
;
3174 tokval
.t_type
= TOKEN_INVALID
;
3175 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3179 free_tlist(origline
);
3180 return DIRECTIVE_FOUND
;
3181 } else if (!is_simple(evalresult
)) {
3182 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3184 free_tlist(origline
);
3185 return DIRECTIVE_FOUND
;
3187 a1
= evalresult
->value
-1;
3189 while (tok_type_(tt
, TOK_WHITESPACE
))
3192 a2
= 1; /* Backwards compatibility: one character */
3194 tokval
.t_type
= TOKEN_INVALID
;
3195 evalresult
= evaluate(ppscan
, tptr
, &tokval
, NULL
,
3199 free_tlist(origline
);
3200 return DIRECTIVE_FOUND
;
3201 } else if (!is_simple(evalresult
)) {
3202 error(ERR_NONFATAL
, "non-constant value given to `%%substr`");
3204 free_tlist(origline
);
3205 return DIRECTIVE_FOUND
;
3207 a2
= evalresult
->value
;
3210 len
= nasm_unquote(t
->text
, NULL
);
3213 if (a1
+a2
> (int64_t)len
)
3216 macro_start
= nasm_malloc(sizeof(*macro_start
));
3217 macro_start
->next
= NULL
;
3218 macro_start
->text
= nasm_quote((a1
< 0) ? "" : t
->text
+a1
, a2
);
3219 macro_start
->type
= TOK_STRING
;
3220 macro_start
->a
.mac
= NULL
;
3223 * We now have a macro name, an implicit parameter count of
3224 * zero, and a numeric token to use as an expansion. Create
3225 * and store an SMacro.
3227 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3229 free_tlist(origline
);
3230 return DIRECTIVE_FOUND
;
3235 casesense
= (i
== PP_ASSIGN
);
3237 tline
= tline
->next
;
3239 tline
= expand_id(tline
);
3240 if (!tline
|| (tline
->type
!= TOK_ID
&&
3241 (tline
->type
!= TOK_PREPROC_ID
||
3242 tline
->text
[1] != '$'))) {
3244 "`%%%sassign' expects a macro identifier",
3245 (i
== PP_IASSIGN
? "i" : ""));
3246 free_tlist(origline
);
3247 return DIRECTIVE_FOUND
;
3249 ctx
= get_ctx(tline
->text
, &mname
, false);
3251 tline
= expand_smacro(tline
->next
);
3256 tokval
.t_type
= TOKEN_INVALID
;
3258 evaluate(ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
3261 free_tlist(origline
);
3262 return DIRECTIVE_FOUND
;
3266 error(ERR_WARNING
|ERR_PASS1
,
3267 "trailing garbage after expression ignored");
3269 if (!is_simple(evalresult
)) {
3271 "non-constant value given to `%%%sassign'",
3272 (i
== PP_IASSIGN
? "i" : ""));
3273 free_tlist(origline
);
3274 return DIRECTIVE_FOUND
;
3277 macro_start
= nasm_malloc(sizeof(*macro_start
));
3278 macro_start
->next
= NULL
;
3279 make_tok_num(macro_start
, reloc_value(evalresult
));
3280 macro_start
->a
.mac
= NULL
;
3283 * We now have a macro name, an implicit parameter count of
3284 * zero, and a numeric token to use as an expansion. Create
3285 * and store an SMacro.
3287 define_smacro(ctx
, mname
, casesense
, 0, macro_start
);
3288 free_tlist(origline
);
3289 return DIRECTIVE_FOUND
;
3293 * Syntax is `%line nnn[+mmm] [filename]'
3295 tline
= tline
->next
;
3297 if (!tok_type_(tline
, TOK_NUMBER
)) {
3298 error(ERR_NONFATAL
, "`%%line' expects line number");
3299 free_tlist(origline
);
3300 return DIRECTIVE_FOUND
;
3302 k
= readnum(tline
->text
, &err
);
3304 tline
= tline
->next
;
3305 if (tok_is_(tline
, "+")) {
3306 tline
= tline
->next
;
3307 if (!tok_type_(tline
, TOK_NUMBER
)) {
3308 error(ERR_NONFATAL
, "`%%line' expects line increment");
3309 free_tlist(origline
);
3310 return DIRECTIVE_FOUND
;
3312 m
= readnum(tline
->text
, &err
);
3313 tline
= tline
->next
;
3319 nasm_free(src_set_fname(detoken(tline
, false)));
3321 free_tlist(origline
);
3322 return DIRECTIVE_FOUND
;
3326 "preprocessor directive `%s' not yet implemented",
3328 return DIRECTIVE_FOUND
;
3333 * Ensure that a macro parameter contains a condition code and
3334 * nothing else. Return the condition code index if so, or -1
3337 static int find_cc(Token
* t
)
3343 return -1; /* Probably a %+ without a space */
3346 if (t
->type
!= TOK_ID
)
3350 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
3354 j
= elements(conditions
);
3357 m
= nasm_stricmp(t
->text
, conditions
[k
]);
3372 static bool paste_tokens(Token
**head
, bool handle_paste_tokens
)
3374 Token
**tail
, *t
, *tt
;
3376 bool did_paste
= false;
3379 /* Now handle token pasting... */
3382 while ((t
= *tail
) && (tt
= t
->next
)) {
3384 case TOK_WHITESPACE
:
3385 if (tt
->type
== TOK_WHITESPACE
) {
3386 /* Zap adjacent whitespace tokens */
3387 t
->next
= delete_Token(tt
);
3389 /* Do not advance paste_head here */
3394 case TOK_PREPROC_ID
:
3401 while (tt
&& (tt
->type
== TOK_ID
|| tt
->type
== TOK_PREPROC_ID
||
3402 tt
->type
== TOK_NUMBER
|| tt
->type
== TOK_FLOAT
||
3403 tt
->type
== TOK_OTHER
)) {
3404 len
+= strlen(tt
->text
);
3408 /* Now tt points to the first token after the potential
3410 if (tt
!= t
->next
) {
3411 /* We have at least two tokens... */
3412 len
+= strlen(t
->text
);
3413 p
= tmp
= nasm_malloc(len
+1);
3417 p
= strchr(p
, '\0');
3418 t
= delete_Token(t
);
3421 t
= *tail
= tokenize(tmp
);
3428 t
->next
= tt
; /* Attach the remaining token chain */
3436 case TOK_PASTE
: /* %+ */
3437 if (handle_paste_tokens
) {
3438 /* Zap %+ and whitespace tokens to the right */
3439 while (t
&& (t
->type
== TOK_WHITESPACE
||
3440 t
->type
== TOK_PASTE
))
3441 t
= *tail
= delete_Token(t
);
3442 if (!paste_head
|| !t
)
3443 break; /* Nothing to paste with */
3447 while (tok_type_(tt
, TOK_WHITESPACE
))
3448 tt
= t
->next
= delete_Token(tt
);
3451 tmp
= nasm_strcat(t
->text
, tt
->text
);
3453 tt
= delete_Token(tt
);
3454 t
= *tail
= tokenize(tmp
);
3460 t
->next
= tt
; /* Attach the remaining token chain */
3467 /* else fall through */
3469 tail
= paste_head
= &t
->next
;
3476 * Expand MMacro-local things: parameter references (%0, %n, %+n,
3477 * %-n) and MMacro-local identifiers (%%foo) as well as
3478 * macro indirection (%[...]).
3480 static Token
*expand_mmac_params(Token
* tline
)
3482 Token
*t
, *tt
, **tail
, *thead
;
3483 bool changed
= false;
3489 if (tline
->type
== TOK_PREPROC_ID
&&
3490 (((tline
->text
[1] == '+' || tline
->text
[1] == '-')
3491 && tline
->text
[2]) || tline
->text
[1] == '%'
3492 || (tline
->text
[1] >= '0' && tline
->text
[1] <= '9'))) {
3494 int type
= 0, cc
; /* type = 0 to placate optimisers */
3501 tline
= tline
->next
;
3504 while (mac
&& !mac
->name
) /* avoid mistaking %reps for macros */
3505 mac
= mac
->next_active
;
3507 error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
3509 switch (t
->text
[1]) {
3511 * We have to make a substitution of one of the
3512 * forms %1, %-1, %+1, %%foo, %0.
3516 snprintf(tmpbuf
, sizeof(tmpbuf
), "%d", mac
->nparam
);
3517 text
= nasm_strdup(tmpbuf
);
3521 snprintf(tmpbuf
, sizeof(tmpbuf
), "..@%"PRIu64
".",
3523 text
= nasm_strcat(tmpbuf
, t
->text
+ 2);
3526 n
= atoi(t
->text
+ 2) - 1;
3527 if (n
>= mac
->nparam
)
3530 if (mac
->nparam
> 1)
3531 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3532 tt
= mac
->params
[n
];
3537 "macro parameter %d is not a condition code",
3542 if (inverse_ccs
[cc
] == -1) {
3544 "condition code `%s' is not invertible",
3548 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
3552 n
= atoi(t
->text
+ 2) - 1;
3553 if (n
>= mac
->nparam
)
3556 if (mac
->nparam
> 1)
3557 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3558 tt
= mac
->params
[n
];
3563 "macro parameter %d is not a condition code",
3568 text
= nasm_strdup(conditions
[cc
]);
3572 n
= atoi(t
->text
+ 1) - 1;
3573 if (n
>= mac
->nparam
)
3576 if (mac
->nparam
> 1)
3577 n
= (n
+ mac
->rotate
) % mac
->nparam
;
3578 tt
= mac
->params
[n
];
3581 for (i
= 0; i
< mac
->paramlen
[n
]; i
++) {
3582 *tail
= new_Token(NULL
, tt
->type
, tt
->text
, 0);
3583 tail
= &(*tail
)->next
;
3587 text
= NULL
; /* we've done it here */
3602 } else if (tline
->type
== TOK_INDIRECT
) {
3604 tline
= tline
->next
;
3605 tt
= tokenize(t
->text
);
3606 tt
= expand_mmac_params(tt
);
3607 tt
= expand_smacro(tt
);
3610 tt
->a
.mac
= NULL
; /* Necessary? */
3618 tline
= tline
->next
;
3626 paste_tokens(&thead
, true);
3632 * Expand all single-line macro calls made in the given line.
3633 * Return the expanded version of the line. The original is deemed
3634 * to be destroyed in the process. (In reality we'll just move
3635 * Tokens from input to output a lot of the time, rather than
3636 * actually bothering to destroy and replicate.)
3638 #define DEADMAN_LIMIT (1 << 20)
3640 static Token
*expand_smacro(Token
* tline
)
3642 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
3643 struct hash_table
*smtbl
;
3644 SMacro
*head
= NULL
, *m
;
3647 unsigned int nparam
, sparam
;
3649 Token
*org_tline
= tline
;
3652 int deadman
= DEADMAN_LIMIT
;
3656 * Trick: we should avoid changing the start token pointer since it can
3657 * be contained in "next" field of other token. Because of this
3658 * we allocate a copy of first token and work with it; at the end of
3659 * routine we copy it back
3663 new_Token(org_tline
->next
, org_tline
->type
, org_tline
->text
,
3665 tline
->a
.mac
= org_tline
->a
.mac
;
3666 nasm_free(org_tline
->text
);
3667 org_tline
->text
= NULL
;
3675 while (tline
) { /* main token loop */
3677 error(ERR_NONFATAL
, "interminable macro recursion");
3681 if ((mname
= tline
->text
)) {
3682 /* if this token is a local macro, look in local context */
3683 if (tline
->type
== TOK_ID
|| tline
->type
== TOK_PREPROC_ID
)
3684 ctx
= get_ctx(mname
, &mname
, true);
3687 smtbl
= ctx
? &ctx
->localmac
: &smacros
;
3688 head
= (SMacro
*) hash_findix(smtbl
, mname
);
3691 * We've hit an identifier. As in is_mmacro below, we first
3692 * check whether the identifier is a single-line macro at
3693 * all, then think about checking for parameters if
3696 for (m
= head
; m
; m
= m
->next
)
3697 if (!mstrcmp(m
->name
, mname
, m
->casesense
))
3703 if (m
->nparam
== 0) {
3705 * Simple case: the macro is parameterless. Discard the
3706 * one token that the macro call took, and push the
3707 * expansion back on the to-do stack.
3709 if (!m
->expansion
) {
3710 if (!strcmp("__FILE__", m
->name
)) {
3713 src_get(&num
, &file
);
3714 tline
->text
= nasm_quote(file
, strlen(file
));
3715 tline
->type
= TOK_STRING
;
3719 if (!strcmp("__LINE__", m
->name
)) {
3720 nasm_free(tline
->text
);
3721 make_tok_num(tline
, src_get_linnum());
3724 if (!strcmp("__BITS__", m
->name
)) {
3725 nasm_free(tline
->text
);
3726 make_tok_num(tline
, globalbits
);
3729 tline
= delete_Token(tline
);
3734 * Complicated case: at least one macro with this name
3735 * exists and takes parameters. We must find the
3736 * parameters in the call, count them, find the SMacro
3737 * that corresponds to that form of the macro call, and
3738 * substitute for the parameters when we expand. What a
3741 /*tline = tline->next;
3742 skip_white_(tline); */
3745 while (tok_type_(t
, TOK_SMAC_END
)) {
3746 t
->a
.mac
->in_progress
= false;
3748 t
= tline
->next
= delete_Token(t
);
3751 } while (tok_type_(tline
, TOK_WHITESPACE
));
3752 if (!tok_is_(tline
, "(")) {
3754 * This macro wasn't called with parameters: ignore
3755 * the call. (Behaviour borrowed from gnu cpp.)
3764 sparam
= PARAM_DELTA
;
3765 params
= nasm_malloc(sparam
* sizeof(Token
*));
3766 params
[0] = tline
->next
;
3767 paramsize
= nasm_malloc(sparam
* sizeof(int));
3769 while (true) { /* parameter loop */
3771 * For some unusual expansions
3772 * which concatenates function call
3775 while (tok_type_(t
, TOK_SMAC_END
)) {
3776 t
->a
.mac
->in_progress
= false;
3778 t
= tline
->next
= delete_Token(t
);
3784 "macro call expects terminating `)'");
3787 if (tline
->type
== TOK_WHITESPACE
3789 if (paramsize
[nparam
])
3792 params
[nparam
] = tline
->next
;
3793 continue; /* parameter loop */
3795 if (tline
->type
== TOK_OTHER
3796 && tline
->text
[1] == 0) {
3797 char ch
= tline
->text
[0];
3798 if (ch
== ',' && !paren
&& brackets
<= 0) {
3799 if (++nparam
>= sparam
) {
3800 sparam
+= PARAM_DELTA
;
3801 params
= nasm_realloc(params
,
3806 nasm_realloc(paramsize
,
3810 params
[nparam
] = tline
->next
;
3811 paramsize
[nparam
] = 0;
3813 continue; /* parameter loop */
3816 (brackets
> 0 || (brackets
== 0 &&
3817 !paramsize
[nparam
])))
3819 if (!(brackets
++)) {
3820 params
[nparam
] = tline
->next
;
3821 continue; /* parameter loop */
3824 if (ch
== '}' && brackets
> 0)
3825 if (--brackets
== 0) {
3827 continue; /* parameter loop */
3829 if (ch
== '(' && !brackets
)
3831 if (ch
== ')' && brackets
<= 0)
3837 error(ERR_NONFATAL
, "braces do not "
3838 "enclose all of macro parameter");
3840 paramsize
[nparam
] += white
+ 1;
3842 } /* parameter loop */
3844 while (m
&& (m
->nparam
!= nparam
||
3845 mstrcmp(m
->name
, mname
,
3849 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
3850 "macro `%s' exists, "
3851 "but not taking %d parameters",
3852 mstart
->text
, nparam
);
3855 if (m
&& m
->in_progress
)
3857 if (!m
) { /* in progess or didn't find '(' or wrong nparam */
3859 * Design question: should we handle !tline, which
3860 * indicates missing ')' here, or expand those
3861 * macros anyway, which requires the (t) test a few
3865 nasm_free(paramsize
);
3869 * Expand the macro: we are placed on the last token of the
3870 * call, so that we can easily split the call from the
3871 * following tokens. We also start by pushing an SMAC_END
3872 * token for the cycle removal.
3879 tt
= new_Token(tline
, TOK_SMAC_END
, NULL
, 0);
3881 m
->in_progress
= true;
3883 for (t
= m
->expansion
; t
; t
= t
->next
) {
3884 if (t
->type
>= TOK_SMAC_PARAM
) {
3885 Token
*pcopy
= tline
, **ptail
= &pcopy
;
3889 ttt
= params
[t
->type
- TOK_SMAC_PARAM
];
3890 for (i
= paramsize
[t
->type
- TOK_SMAC_PARAM
];
3893 new_Token(tline
, ttt
->type
, ttt
->text
,
3899 } else if (t
->type
== TOK_PREPROC_Q
) {
3900 tt
= new_Token(tline
, TOK_ID
, mname
, 0);
3902 } else if (t
->type
== TOK_PREPROC_QQ
) {
3903 tt
= new_Token(tline
, TOK_ID
, m
->name
, 0);
3906 tt
= new_Token(tline
, t
->type
, t
->text
, 0);
3912 * Having done that, get rid of the macro call, and clean
3913 * up the parameters.
3916 nasm_free(paramsize
);
3919 continue; /* main token loop */
3924 if (tline
->type
== TOK_SMAC_END
) {
3925 tline
->a
.mac
->in_progress
= false;
3926 tline
= delete_Token(tline
);
3929 tline
= tline
->next
;
3937 * Now scan the entire line and look for successive TOK_IDs that resulted
3938 * after expansion (they can't be produced by tokenize()). The successive
3939 * TOK_IDs should be concatenated.
3940 * Also we look for %+ tokens and concatenate the tokens before and after
3941 * them (without white spaces in between).
3943 if (expanded
&& paste_tokens(&thead
, true)) {
3944 /* If we concatenated something, re-scan the line for macros */
3951 *org_tline
= *thead
;
3952 /* since we just gave text to org_line, don't free it */
3954 delete_Token(thead
);
3956 /* the expression expanded to empty line;
3957 we can't return NULL for some reasons
3958 we just set the line to a single WHITESPACE token. */
3959 memset(org_tline
, 0, sizeof(*org_tline
));
3960 org_tline
->text
= NULL
;
3961 org_tline
->type
= TOK_WHITESPACE
;
3970 * Similar to expand_smacro but used exclusively with macro identifiers
3971 * right before they are fetched in. The reason is that there can be
3972 * identifiers consisting of several subparts. We consider that if there
3973 * are more than one element forming the name, user wants a expansion,
3974 * otherwise it will be left as-is. Example:
3978 * the identifier %$abc will be left as-is so that the handler for %define
3979 * will suck it and define the corresponding value. Other case:
3981 * %define _%$abc cde
3983 * In this case user wants name to be expanded *before* %define starts
3984 * working, so we'll expand %$abc into something (if it has a value;
3985 * otherwise it will be left as-is) then concatenate all successive
3988 static Token
*expand_id(Token
* tline
)
3990 Token
*cur
, *oldnext
= NULL
;
3992 if (!tline
|| !tline
->next
)
3997 (cur
->next
->type
== TOK_ID
||
3998 cur
->next
->type
== TOK_PREPROC_ID
3999 || cur
->next
->type
== TOK_NUMBER
))
4002 /* If identifier consists of just one token, don't expand */
4007 oldnext
= cur
->next
; /* Detach the tail past identifier */
4008 cur
->next
= NULL
; /* so that expand_smacro stops here */
4011 tline
= expand_smacro(tline
);
4014 /* expand_smacro possibly changhed tline; re-scan for EOL */
4016 while (cur
&& cur
->next
)
4019 cur
->next
= oldnext
;
4026 * Determine whether the given line constitutes a multi-line macro
4027 * call, and return the MMacro structure called if so. Doesn't have
4028 * to check for an initial label - that's taken care of in
4029 * expand_mmacro - but must check numbers of parameters. Guaranteed
4030 * to be called with tline->type == TOK_ID, so the putative macro
4031 * name is easy to find.
4033 static MMacro
*is_mmacro(Token
* tline
, Token
*** params_array
)
4039 head
= (MMacro
*) hash_findix(&mmacros
, tline
->text
);
4042 * Efficiency: first we see if any macro exists with the given
4043 * name. If not, we can return NULL immediately. _Then_ we
4044 * count the parameters, and then we look further along the
4045 * list if necessary to find the proper MMacro.
4047 for (m
= head
; m
; m
= m
->next
)
4048 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
4054 * OK, we have a potential macro. Count and demarcate the
4057 count_mmac_params(tline
->next
, &nparam
, ¶ms
);
4060 * So we know how many parameters we've got. Find the MMacro
4061 * structure that handles this number.
4064 if (m
->nparam_min
<= nparam
4065 && (m
->plus
|| nparam
<= m
->nparam_max
)) {
4067 * This one is right. Just check if cycle removal
4068 * prohibits us using it before we actually celebrate...
4070 if (m
->in_progress
) {
4073 "self-reference in multi-line macro `%s'", m
->name
);
4079 * It's right, and we can use it. Add its default
4080 * parameters to the end of our list if necessary.
4082 if (m
->defaults
&& nparam
< m
->nparam_min
+ m
->ndefs
) {
4084 nasm_realloc(params
,
4085 ((m
->nparam_min
+ m
->ndefs
+
4086 1) * sizeof(*params
)));
4087 while (nparam
< m
->nparam_min
+ m
->ndefs
) {
4088 params
[nparam
] = m
->defaults
[nparam
- m
->nparam_min
];
4093 * If we've gone over the maximum parameter count (and
4094 * we're in Plus mode), ignore parameters beyond
4097 if (m
->plus
&& nparam
> m
->nparam_max
)
4098 nparam
= m
->nparam_max
;
4100 * Then terminate the parameter list, and leave.
4102 if (!params
) { /* need this special case */
4103 params
= nasm_malloc(sizeof(*params
));
4106 params
[nparam
] = NULL
;
4107 *params_array
= params
;
4111 * This one wasn't right: look for the next one with the
4114 for (m
= m
->next
; m
; m
= m
->next
)
4115 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
4120 * After all that, we didn't find one with the right number of
4121 * parameters. Issue a warning, and fail to expand the macro.
4123 error(ERR_WARNING
|ERR_PASS1
|ERR_WARN_MNP
,
4124 "macro `%s' exists, but not taking %d parameters",
4125 tline
->text
, nparam
);
4131 * Expand the multi-line macro call made by the given line, if
4132 * there is one to be expanded. If there is, push the expansion on
4133 * istk->expansion and return 1. Otherwise return 0.
4135 static int expand_mmacro(Token
* tline
)
4137 Token
*startline
= tline
;
4138 Token
*label
= NULL
;
4139 int dont_prepend
= 0;
4140 Token
**params
, *t
, *mtok
, *tt
;
4143 int i
, nparam
, *paramlen
;
4148 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4149 if (!tok_type_(t
, TOK_ID
) && !tok_type_(t
, TOK_PREPROC_ID
))
4152 m
= is_mmacro(t
, ¶ms
);
4158 * We have an id which isn't a macro call. We'll assume
4159 * it might be a label; we'll also check to see if a
4160 * colon follows it. Then, if there's another id after
4161 * that lot, we'll check it again for macro-hood.
4165 if (tok_type_(t
, TOK_WHITESPACE
))
4166 last
= t
, t
= t
->next
;
4167 if (tok_is_(t
, ":")) {
4169 last
= t
, t
= t
->next
;
4170 if (tok_type_(t
, TOK_WHITESPACE
))
4171 last
= t
, t
= t
->next
;
4173 if (!tok_type_(t
, TOK_ID
) || (m
= is_mmacro(t
, ¶ms
)) == NULL
)
4181 * Fix up the parameters: this involves stripping leading and
4182 * trailing whitespace, then stripping braces if they are
4185 for (nparam
= 0; params
[nparam
]; nparam
++) ;
4186 paramlen
= nparam
? nasm_malloc(nparam
* sizeof(*paramlen
)) : NULL
;
4188 for (i
= 0; params
[i
]; i
++) {
4190 int comma
= (!m
->plus
|| i
< nparam
- 1);
4194 if (tok_is_(t
, "{"))
4195 t
= t
->next
, brace
= true, comma
= false;
4199 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
4200 break; /* ... because we have hit a comma */
4201 if (comma
&& t
->type
== TOK_WHITESPACE
4202 && tok_is_(t
->next
, ","))
4203 break; /* ... or a space then a comma */
4204 if (brace
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "}"))
4205 break; /* ... or a brace */
4212 * OK, we have a MMacro structure together with a set of
4213 * parameters. We must now go through the expansion and push
4214 * copies of each Line on to istk->expansion. Substitution of
4215 * parameter tokens and macro-local tokens doesn't get done
4216 * until the single-line macro substitution process; this is
4217 * because delaying them allows us to change the semantics
4218 * later through %rotate.
4220 * First, push an end marker on to istk->expansion, mark this
4221 * macro as in progress, and set up its invocation-specific
4224 ll
= nasm_malloc(sizeof(Line
));
4225 ll
->next
= istk
->expansion
;
4228 istk
->expansion
= ll
;
4230 m
->in_progress
= true;
4235 m
->paramlen
= paramlen
;
4236 m
->unique
= unique
++;
4239 m
->next_active
= istk
->mstk
;
4242 for (l
= m
->expansion
; l
; l
= l
->next
) {
4245 ll
= nasm_malloc(sizeof(Line
));
4246 ll
->finishes
= NULL
;
4247 ll
->next
= istk
->expansion
;
4248 istk
->expansion
= ll
;
4251 for (t
= l
->first
; t
; t
= t
->next
) {
4255 tt
= *tail
= new_Token(NULL
, TOK_ID
, mname
, 0);
4257 case TOK_PREPROC_QQ
:
4258 tt
= *tail
= new_Token(NULL
, TOK_ID
, m
->name
, 0);
4260 case TOK_PREPROC_ID
:
4261 if (t
->text
[1] == '0' && t
->text
[2] == '0') {
4269 tt
= *tail
= new_Token(NULL
, x
->type
, x
->text
, 0);
4278 * If we had a label, push it on as the first line of
4279 * the macro expansion.
4282 if (dont_prepend
< 0)
4283 free_tlist(startline
);
4285 ll
= nasm_malloc(sizeof(Line
));
4286 ll
->finishes
= NULL
;
4287 ll
->next
= istk
->expansion
;
4288 istk
->expansion
= ll
;
4289 ll
->first
= startline
;
4290 if (!dont_prepend
) {
4292 label
= label
->next
;
4293 label
->next
= tt
= new_Token(NULL
, TOK_OTHER
, ":", 0);
4298 list
->uplevel(m
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
4303 /* The function that actually does the error reporting */
4304 static void verror(int severity
, const char *fmt
, va_list arg
)
4308 vsnprintf(buff
, sizeof(buff
), fmt
, arg
);
4310 if (istk
&& istk
->mstk
&& istk
->mstk
->name
)
4311 _error(severity
, "(%s:%d) %s", istk
->mstk
->name
,
4312 istk
->mstk
->lineno
, buff
);
4314 _error(severity
, "%s", buff
);
4318 * Since preprocessor always operate only on the line that didn't
4319 * arrived yet, we should always use ERR_OFFBY1.
4321 static void error(int severity
, const char *fmt
, ...)
4325 /* If we're in a dead branch of IF or something like it, ignore the error */
4326 if (istk
&& istk
->conds
&& !emitting(istk
->conds
->state
))
4330 verror(severity
, fmt
, arg
);
4335 * Because %else etc are evaluated in the state context
4336 * of the previous branch, errors might get lost with error():
4337 * %if 0 ... %else trailing garbage ... %endif
4338 * So %else etc should report errors with this function.
4340 static void error_precond(int severity
, const char *fmt
, ...)
4344 /* Only ignore the error if it's really in a dead branch */
4345 if (istk
&& istk
->conds
&& istk
->conds
->state
== COND_NEVER
)
4349 verror(severity
, fmt
, arg
);
4354 pp_reset(char *file
, int apass
, efunc errfunc
, evalfunc eval
,
4355 ListGen
* listgen
, StrList
**deplist
)
4361 istk
= nasm_malloc(sizeof(Include
));
4364 istk
->expansion
= NULL
;
4366 istk
->fp
= fopen(file
, "r");
4368 src_set_fname(nasm_strdup(file
));
4372 error(ERR_FATAL
|ERR_NOFILE
, "unable to open input file `%s'",
4375 nested_mac_count
= 0;
4376 nested_rep_count
= 0;
4379 if (tasm_compatible_mode
) {
4380 stdmacpos
= nasm_stdmac
;
4382 stdmacpos
= nasm_stdmac_after_tasm
;
4384 any_extrastdmac
= extrastdmac
&& *extrastdmac
;
4390 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
4391 * The caller, however, will also pass in 3 for preprocess-only so
4392 * we can set __PASS__ accordingly.
4394 pass
= apass
> 2 ? 2 : apass
;
4396 dephead
= deptail
= deplist
;
4398 StrList
*sl
= nasm_malloc(strlen(file
)+1+sizeof sl
->next
);
4400 strcpy(sl
->str
, file
);
4402 deptail
= &sl
->next
;
4406 * Define the __PASS__ macro. This is defined here unlike
4407 * all the other builtins, because it is special -- it varies between
4410 t
= nasm_malloc(sizeof(*t
));
4412 make_tok_num(t
, apass
);
4414 define_smacro(NULL
, "__PASS__", true, 0, t
);
4417 static char *pp_getline(void)
4424 * Fetch a tokenized line, either from the macro-expansion
4425 * buffer or from the input file.
4428 while (istk
->expansion
&& istk
->expansion
->finishes
) {
4429 Line
*l
= istk
->expansion
;
4430 if (!l
->finishes
->name
&& l
->finishes
->in_progress
> 1) {
4434 * This is a macro-end marker for a macro with no
4435 * name, which means it's not really a macro at all
4436 * but a %rep block, and the `in_progress' field is
4437 * more than 1, meaning that we still need to
4438 * repeat. (1 means the natural last repetition; 0
4439 * means termination by %exitrep.) We have
4440 * therefore expanded up to the %endrep, and must
4441 * push the whole block on to the expansion buffer
4442 * again. We don't bother to remove the macro-end
4443 * marker: we'd only have to generate another one
4446 l
->finishes
->in_progress
--;
4447 for (l
= l
->finishes
->expansion
; l
; l
= l
->next
) {
4448 Token
*t
, *tt
, **tail
;
4450 ll
= nasm_malloc(sizeof(Line
));
4451 ll
->next
= istk
->expansion
;
4452 ll
->finishes
= NULL
;
4456 for (t
= l
->first
; t
; t
= t
->next
) {
4457 if (t
->text
|| t
->type
== TOK_WHITESPACE
) {
4459 new_Token(NULL
, t
->type
, t
->text
, 0);
4464 istk
->expansion
= ll
;
4468 * Check whether a `%rep' was started and not ended
4469 * within this macro expansion. This can happen and
4470 * should be detected. It's a fatal error because
4471 * I'm too confused to work out how to recover
4477 "defining with name in expansion");
4478 else if (istk
->mstk
->name
)
4480 "`%%rep' without `%%endrep' within"
4481 " expansion of macro `%s'",
4486 * FIXME: investigate the relationship at this point between
4487 * istk->mstk and l->finishes
4490 MMacro
*m
= istk
->mstk
;
4491 istk
->mstk
= m
->next_active
;
4494 * This was a real macro call, not a %rep, and
4495 * therefore the parameter information needs to
4498 nasm_free(m
->params
);
4499 free_tlist(m
->iline
);
4500 nasm_free(m
->paramlen
);
4501 l
->finishes
->in_progress
= false;
4505 istk
->expansion
= l
->next
;
4507 list
->downlevel(LIST_MACRO
);
4510 while (1) { /* until we get a line we can use */
4512 if (istk
->expansion
) { /* from a macro expansion */
4514 Line
*l
= istk
->expansion
;
4516 istk
->mstk
->lineno
++;
4518 istk
->expansion
= l
->next
;
4520 p
= detoken(tline
, false);
4521 list
->line(LIST_MACRO
, p
);
4526 if (line
) { /* from the current input file */
4527 line
= prepreproc(line
);
4528 tline
= tokenize(line
);
4533 * The current file has ended; work down the istk
4540 "expected `%%endif' before end of file");
4541 /* only set line and file name if there's a next node */
4543 src_set_linnum(i
->lineno
);
4544 nasm_free(src_set_fname(i
->fname
));
4547 list
->downlevel(LIST_INCLUDE
);
4551 if (istk
->expansion
&& istk
->expansion
->finishes
)
4557 * We must expand MMacro parameters and MMacro-local labels
4558 * _before_ we plunge into directive processing, to cope
4559 * with things like `%define something %1' such as STRUC
4560 * uses. Unless we're _defining_ a MMacro, in which case
4561 * those tokens should be left alone to go into the
4562 * definition; and unless we're in a non-emitting
4563 * condition, in which case we don't want to meddle with
4566 if (!defining
&& !(istk
->conds
&& !emitting(istk
->conds
->state
))
4567 && !(istk
->mstk
&& !istk
->mstk
->in_progress
)) {
4568 tline
= expand_mmac_params(tline
);
4572 * Check the line to see if it's a preprocessor directive.
4574 if (do_directive(tline
) == DIRECTIVE_FOUND
) {
4576 } else if (defining
) {
4578 * We're defining a multi-line macro. We emit nothing
4580 * shove the tokenized line on to the macro definition.
4582 Line
*l
= nasm_malloc(sizeof(Line
));
4583 l
->next
= defining
->expansion
;
4586 defining
->expansion
= l
;
4588 } else if (istk
->conds
&& !emitting(istk
->conds
->state
)) {
4590 * We're in a non-emitting branch of a condition block.
4591 * Emit nothing at all, not even a blank line: when we
4592 * emerge from the condition we'll give a line-number
4593 * directive so we keep our place correctly.
4597 } else if (istk
->mstk
&& !istk
->mstk
->in_progress
) {
4599 * We're in a %rep block which has been terminated, so
4600 * we're walking through to the %endrep without
4601 * emitting anything. Emit nothing at all, not even a
4602 * blank line: when we emerge from the %rep block we'll
4603 * give a line-number directive so we keep our place
4609 tline
= expand_smacro(tline
);
4610 if (!expand_mmacro(tline
)) {
4612 * De-tokenize the line again, and emit it.
4614 line
= detoken(tline
, true);
4618 continue; /* expand_mmacro calls free_tlist */
4626 static void pp_cleanup(int pass
)
4629 if(defining
->name
) {
4631 "end of file while still defining macro `%s'",
4634 error(ERR_NONFATAL
, "end of file while still in %%rep");
4637 free_mmacro(defining
);
4646 nasm_free(i
->fname
);
4651 nasm_free(src_set_fname(NULL
));
4656 while ((i
= ipath
)) {
4665 void pp_include_path(char *path
)
4669 i
= nasm_malloc(sizeof(IncPath
));
4670 i
->path
= path
? nasm_strdup(path
) : NULL
;
4673 if (ipath
!= NULL
) {
4675 while (j
->next
!= NULL
)
4683 void pp_pre_include(char *fname
)
4685 Token
*inc
, *space
, *name
;
4688 name
= new_Token(NULL
, TOK_INTERNAL_STRING
, fname
, 0);
4689 space
= new_Token(name
, TOK_WHITESPACE
, NULL
, 0);
4690 inc
= new_Token(space
, TOK_PREPROC_ID
, "%include", 0);
4692 l
= nasm_malloc(sizeof(Line
));
4699 void pp_pre_define(char *definition
)
4705 equals
= strchr(definition
, '=');
4706 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
4707 def
= new_Token(space
, TOK_PREPROC_ID
, "%define", 0);
4710 space
->next
= tokenize(definition
);
4714 l
= nasm_malloc(sizeof(Line
));
4721 void pp_pre_undefine(char *definition
)
4726 space
= new_Token(NULL
, TOK_WHITESPACE
, NULL
, 0);
4727 def
= new_Token(space
, TOK_PREPROC_ID
, "%undef", 0);
4728 space
->next
= tokenize(definition
);
4730 l
= nasm_malloc(sizeof(Line
));
4738 * Added by Keith Kanios:
4740 * This function is used to assist with "runtime" preprocessor
4741 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
4743 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
4744 * PASS A VALID STRING TO THIS FUNCTION!!!!!
4747 void pp_runtime(char *definition
)
4751 def
= tokenize(definition
);
4752 if(do_directive(def
) == NO_DIRECTIVE_FOUND
)
4757 void pp_extra_stdmac(macros_t
*macros
)
4759 extrastdmac
= macros
;
4762 static void make_tok_num(Token
* tok
, int64_t val
)
4765 snprintf(numbuf
, sizeof(numbuf
), "%"PRId64
"", val
);
4766 tok
->text
= nasm_strdup(numbuf
);
4767 tok
->type
= TOK_NUMBER
;