1 /* preproc.c macro preprocessor for the Netwide Assembler
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the licence given in the file "Licence"
6 * distributed in the NASM archive.
8 * initial version 18/iii/97 by Simon Tatham
21 typedef struct SMacro SMacro
;
22 typedef struct MMacro MMacro
;
23 typedef struct Context Context
;
24 typedef struct Token Token
;
25 typedef struct Line Line
;
26 typedef struct Include Include
;
27 typedef struct Cond Cond
;
28 typedef struct IncPath IncPath
;
31 * Store the definition of a single-line macro.
43 * Store the definition of a multi-line macro. This is also used to
44 * store the interiors of `%rep...%endrep' blocks, which are
45 * effectively self-re-invoking multi-line macros which simply
46 * don't have a name or bother to appear in the hash tables. %rep
47 * blocks are signified by having a NULL `name' field.
49 * In a MMacro describing a `%rep' block, the `in_progress' field
50 * isn't merely boolean, but gives the number of repeats left to
53 * The `next' field is used for storing MMacros in hash tables; the
54 * `next_active' field is for stacking them on istk entries.
56 * When a MMacro is being expanded, `params', `iline', `nparam',
57 * `paramlen', `rotate' and `unique' are local to the invocation.
63 int nparam_min
, nparam_max
;
64 int plus
; /* is the last parameter greedy? */
65 int nolist
; /* is this macro listing-inhibited? */
67 Token
**defaults
, *dlist
;
68 int ndefs
; /* number of default parameters */
72 Token
**params
, *iline
;
73 int nparam
, rotate
, *paramlen
;
78 * The context stack is composed of a linked list of these.
88 * This is the internal form which we break input lines up into.
89 * Typically stored in linked lists.
91 * TOK_PS_OTHER is a token type used internally within
92 * expand_smacro(), to denote a token which has already been
93 * checked for being a potential macro, but may still be a context-
96 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
97 * necessarily used as-is, but is intended to denote the number of
98 * the substituted parameter. So in the definition
100 * %define a(x,y) ( (x) & ~(y) )
102 * the token representing `x' will have its type changed to
103 * TOK_SMAC_PARAM, but the one representing `y' will be
106 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
107 * which doesn't need quotes around it. Used in the pre-include
108 * mechanism as an alternative to trying to find a sensible type of
109 * quote to use on the filename we were passed.
114 SMacro
*mac
; /* associated macro for TOK_SMAC_END */
118 TOK_WHITESPACE
= 1, TOK_COMMENT
, TOK_ID
, TOK_PREPROC_ID
, TOK_STRING
,
119 TOK_NUMBER
, TOK_SMAC_END
, TOK_OTHER
, TOK_PS_OTHER
, TOK_SMAC_PARAM
,
124 * Multi-line macro definitions are stored as a linked list of
125 * these, which is essentially a container to allow several linked
128 * Note that in this module, linked lists are treated as stacks
129 * wherever possible. For this reason, Lines are _pushed_ on to the
130 * `expansion' field in MMacro structures, so that the linked list,
131 * if walked, would give the macro lines in reverse order; this
132 * means that we can walk the list when expanding a macro, and thus
133 * push the lines on to the `expansion' field in _istk_ in reverse
134 * order (so that when popped back off they are in the right
135 * order). It may seem cockeyed, and it relies on my design having
136 * an even number of steps in, but it works...
138 * Some of these structures, rather than being actual lines, are
139 * markers delimiting the end of the expansion of a given macro.
140 * This is for use in the cycle-tracking and %rep-handling code.
141 * Such structures have `finishes' non-NULL, and `first' NULL. All
142 * others have `finishes' NULL, but `first' may still be NULL if
152 * To handle an arbitrary level of file inclusion, we maintain a
153 * stack (ie linked list) of these things.
162 MMacro
*mstk
; /* stack of active macros/reps */
166 * Include search path. This is simply a list of strings which get
167 * prepended, in turn, to the name of an include file, in an
168 * attempt to find the file if it's not in the current directory.
176 * Conditional assembly: we maintain a separate stack of these for
177 * each level of file inclusion. (The only reason we keep the
178 * stacks separate is to ensure that a stray `%endif' in a file
179 * included from within the true branch of a `%if' won't terminate
180 * it and cause confusion: instead, rightly, it'll cause an error.)
188 * These states are for use just after %if or %elif: IF_TRUE
189 * means the condition has evaluated to truth so we are
190 * currently emitting, whereas IF_FALSE means we are not
191 * currently emitting but will start doing so if a %else comes
192 * up. In these states, all directives are admissible: %elif,
193 * %else and %endif. (And of course %if.)
195 COND_IF_TRUE
, COND_IF_FALSE
,
197 * These states come up after a %else: ELSE_TRUE means we're
198 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
199 * any %elif or %else will cause an error.
201 COND_ELSE_TRUE
, COND_ELSE_FALSE
,
203 * This state means that we're not emitting now, and also that
204 * nothing until %endif will be emitted at all. It's for use in
205 * two circumstances: (i) when we've had our moment of emission
206 * and have now started seeing %elifs, and (ii) when the
207 * condition construct in question is contained within a
208 * non-emitting branch of a larger condition construct.
212 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
215 * Condition codes. Note that we use c_ prefix not C_ because C_ is
216 * used in nasm.h for the "real" condition codes. At _this_ level,
217 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
218 * ones, so we need a different enum...
220 static char *conditions
[] = {
221 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
222 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
223 "np", "ns", "nz", "o", "p", "pe", "po", "s", "z"
226 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
227 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
228 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_S
, c_Z
230 static int inverse_ccs
[] = {
231 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
232 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
,
233 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, c_NS
, c_NZ
239 static char *directives
[] = {
240 "%assign", "%clear", "%define", "%elif", "%elifctx", "%elifdef",
241 "%elifid", "%elifidn", "%elifidni", "%elifnctx", "%elifndef",
242 "%elifnid", "%elifnidn", "%elifnidni", "%elifnnum", "%elifnstr",
243 "%elifnum", "%elifstr", "%else", "%endif", "%endm", "%endmacro",
244 "%endrep", "%error", "%exitrep", "%iassign", "%idefine", "%if",
245 "%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifnctx",
246 "%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnnum",
247 "%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include", "%line",
248 "%macro", "%pop", "%push", "%rep", "%repl", "%rotate"
251 PP_ASSIGN
, PP_CLEAR
, PP_DEFINE
, PP_ELIF
, PP_ELIFCTX
, PP_ELIFDEF
,
252 PP_ELIFID
, PP_ELIFIDN
, PP_ELIFIDNI
, PP_ELIFNCTX
, PP_ELIFNDEF
,
253 PP_ELIFNID
, PP_ELIFNIDN
, PP_ELIFNIDNI
, PP_ELIFNNUM
, PP_ELIFNSTR
,
254 PP_ELIFNUM
, PP_ELIFSTR
, PP_ELSE
, PP_ENDIF
, PP_ENDM
, PP_ENDMACRO
,
255 PP_ENDREP
, PP_ERROR
, PP_EXITREP
, PP_IASSIGN
, PP_IDEFINE
, PP_IF
,
256 PP_IFCTX
, PP_IFDEF
, PP_IFID
, PP_IFIDN
, PP_IFIDNI
, PP_IFNCTX
,
257 PP_IFNDEF
, PP_IFNID
, PP_IFNIDN
, PP_IFNIDNI
, PP_IFNNUM
,
258 PP_IFNSTR
, PP_IFNUM
, PP_IFSTR
, PP_IMACRO
, PP_INCLUDE
, PP_LINE
,
259 PP_MACRO
, PP_POP
, PP_PUSH
, PP_REP
, PP_REPL
, PP_ROTATE
263 static Context
*cstk
;
264 static Include
*istk
;
265 static IncPath
*ipath
= NULL
;
268 static evalfunc evaluate
;
272 static unsigned long unique
; /* unique identifier numbers */
274 static char *linesync
, *outline
;
276 static Line
*predef
= NULL
;
278 static ListGen
*list
;
281 * The number of hash values we use for the macro lookup tables.
286 * The current set of multi-line macros we have defined.
288 static MMacro
*mmacros
[NHASH
];
291 * The current set of single-line macros we have defined.
293 static SMacro
*smacros
[NHASH
];
296 * The multi-line macro we are currently defining, or the %rep
297 * block we are currently reading, if any.
299 static MMacro
*defining
;
302 * The number of macro parameters to allocate space for at a time.
304 #define PARAM_DELTA 16
307 * The standard macro set: defined as `static char *stdmac[]'. Also
308 * gives our position in the macro set, when we're processing it.
311 static char **stdmacpos
;
314 * The extra standard macros that come from the object format, if
317 static char **extrastdmac
= NULL
;
321 * Forward declarations.
323 static Token
*expand_smacro (Token
*tline
);
324 static void update_fileline (int which
);
327 * The pre-preprocessing stage... This function translates line
328 * number indications as they emerge from GNU cpp (`# lineno "file"
329 * flags') into NASM preprocessor line number indications (`%line
332 static char *prepreproc(char *line
) {
334 char *fname
, *oldline
;
336 if (line
[0] == '#' && line
[1] == ' ') {
339 lineno
= atoi(fname
);
340 fname
+= strspn(fname
, "0123456789 ");
343 fnlen
= strcspn(fname
, "\"");
344 line
= nasm_malloc(20+fnlen
);
345 sprintf(line
, "%%line %d %.*s", lineno
, fnlen
, fname
);
352 * The hash function for macro lookups. Note that due to some
353 * macros having case-insensitive names, the hash function must be
354 * invariant under case changes. We implement this by applying a
355 * perfectly normal hash function to the uppercase of the string.
357 static int hash(char *s
) {
359 * Powers of three, mod 31.
361 static const int multipliers
[] = {
362 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10,
363 30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21
369 h
+= multipliers
[i
] * (unsigned char) (toupper(*s
));
371 if (++i
>= sizeof(multipliers
)/sizeof(*multipliers
))
379 * Free a linked list of tokens.
381 static void free_tlist (Token
*list
) {
392 * Free a linked list of lines.
394 static void free_llist (Line
*list
) {
399 free_tlist (l
->first
);
405 * Pop the context stack.
407 static void ctx_pop (void) {
417 free_tlist (s
->expansion
);
425 * Generate a line synchronisation comment, to ensure the assembler
426 * knows which source file the current output has really come from.
428 static void line_sync (void) {
429 char text
[30+FILENAME_MAX
];
430 sprintf(text
, "%%line %d+%d %s",
431 (istk
->expansion
? istk
->lineno
- istk
->lineinc
: istk
->lineno
),
432 (istk
->expansion
? 0 : istk
->lineinc
), istk
->fname
);
433 nasm_free (linesync
);
434 linesync
= nasm_strdup(text
);
437 #define BUF_DELTA 512
439 * Read a line from the top file in istk, handling multiple CR/LFs
440 * at the end of the line read, and handling spurious ^Zs. Will
441 * return lines from the standard macro set if this has not already
444 static char *read_line (void) {
445 char *buffer
, *p
, *q
;
450 char *ret
= nasm_strdup(*stdmacpos
++);
451 if (!*stdmacpos
&& any_extrastdmac
) {
452 stdmacpos
= extrastdmac
;
453 any_extrastdmac
= FALSE
;
457 * Nasty hack: here we push the contents of `predef' on
458 * to the top-level expansion stack, since this is the
459 * most convenient way to implement the pre-include and
460 * pre-define features.
464 Token
*head
, **tail
, *t
, *tt
;
466 for (pd
= predef
; pd
; pd
= pd
->next
) {
469 for (t
= pd
->first
; t
; t
= t
->next
) {
470 tt
= *tail
= nasm_malloc(sizeof(Token
));
474 tt
->text
= nasm_strdup(t
->text
);
475 tt
->mac
= t
->mac
; /* always NULL here, in fact */
477 l
= nasm_malloc(sizeof(Line
));
478 l
->next
= istk
->expansion
;
488 update_fileline(3); /* update __FILE__ and __LINE__ */
493 buffer
= nasm_malloc(BUF_DELTA
);
496 q
= fgets(p
, bufsize
-(p
-buffer
), istk
->fp
);
500 if (p
> buffer
&& p
[-1] == '\n') {
501 istk
->lineno
+= istk
->lineinc
;
502 update_fileline(1); /* update __LINE__ only */
505 if (p
-buffer
> bufsize
-10) {
506 bufsize
+= BUF_DELTA
;
507 buffer
= nasm_realloc(buffer
, bufsize
);
511 if (!q
&& p
== buffer
) {
517 * Play safe: remove CRs as well as LFs, if any of either are
518 * present at the end of the line.
520 while (p
> buffer
&& (p
[-1] == '\n' || p
[-1] == '\r'))
524 * Handle spurious ^Z, which may be inserted into source files
525 * by some file transfer utilities.
527 buffer
[strcspn(buffer
, "\032")] = '\0';
529 list
->line (LIST_READ
, buffer
);
535 * Tokenise a line of text. This is a very simple process since we
536 * don't need to parse the value out of e.g. numeric tokens: we
537 * simply split one string into many.
539 static Token
*tokenise (char *line
) {
543 Token
*t
, **tail
= &list
;
548 (p
[1] == '{' || p
[1] == '!' || (p
[1] == '%' && isidchar(p
[2])) ||
549 p
[1] == '$' || p
[1] == '+' || p
[1] == '-' || isidchar(p
[1]))) {
550 type
= TOK_PREPROC_ID
;
554 while (*p
&& *p
!= '}') {
561 if (*p
== '!' || *p
== '%' || *p
== '$' ||
562 *p
== '+' || *p
== '-') p
++;
563 while (*p
&& isidchar(*p
))
566 } else if (isidstart(*p
) || (*p
== '$' && isidstart(p
[1]))) {
569 while (*p
&& isidchar(*p
))
571 } else if (*p
== '\'' || *p
== '"') {
578 while (*p
&& *p
!= c
)
581 } else if (isnumstart(*p
)) {
587 while (*p
&& isnumchar(*p
))
589 } else if (isspace(*p
)) {
590 type
= TOK_WHITESPACE
;
592 while (*p
&& isspace(*p
))
595 * Whitespace just before end-of-line is discarded by
596 * pretending it's a comment; whitespace just before a
597 * comment gets lumped into the comment.
599 if (!*p
|| *p
== ';') {
603 } else if (*p
== ';') {
608 * Anything else is an operator of some kind. We check
609 * for all the double-character operators (>>, <<, //,
610 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
611 * else is a single-character operator.
614 if ((p
[0] == '>' && p
[1] == '>') ||
615 (p
[0] == '<' && p
[1] == '<') ||
616 (p
[0] == '/' && p
[1] == '/') ||
617 (p
[0] == '%' && p
[1] == '%') ||
618 (p
[0] == '<' && p
[1] == '=') ||
619 (p
[0] == '>' && p
[1] == '=') ||
620 (p
[0] == '=' && p
[1] == '=') ||
621 (p
[0] == '!' && p
[1] == '=') ||
622 (p
[0] == '<' && p
[1] == '>') ||
623 (p
[0] == '&' && p
[1] == '&') ||
624 (p
[0] == '|' && p
[1] == '|') ||
625 (p
[0] == '^' && p
[1] == '^'))
629 if (type
!= TOK_COMMENT
) {
630 *tail
= t
= nasm_malloc (sizeof(Token
));
634 t
->text
= nasm_malloc(1+p
-line
);
635 strncpy(t
->text
, line
, p
-line
);
636 t
->text
[p
-line
] = '\0';
645 * Convert a line of tokens back into text.
647 static char *detoken (Token
*tlist
) {
653 for (t
= tlist
; t
; t
= t
->next
) {
654 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
655 char *p
= getenv(t
->text
+2);
658 t
->text
= nasm_strdup(p
);
663 len
+= strlen(t
->text
);
665 p
= line
= nasm_malloc(len
+1);
666 for (t
= tlist
; t
; t
= t
->next
) {
677 * A scanner, suitable for use by the expression evaluator, which
678 * operates on a line of Tokens. Expects a pointer to a pointer to
679 * the first token in the line to be passed in as its private_data
682 static int ppscan(void *private_data
, struct tokenval
*tokval
) {
683 Token
**tlineptr
= private_data
;
688 *tlineptr
= tline
? tline
->next
: NULL
;
689 } while (tline
&& (tline
->type
== TOK_WHITESPACE
||
690 tline
->type
== TOK_COMMENT
));
693 return tokval
->t_type
= TOKEN_EOS
;
695 if (tline
->text
[0] == '$' && !tline
->text
[1])
696 return tokval
->t_type
= TOKEN_HERE
;
697 if (tline
->text
[0] == '$' && tline
->text
[1] == '$' && !tline
->text
[1])
698 return tokval
->t_type
= TOKEN_BASE
;
700 if (tline
->type
== TOK_ID
) {
701 tokval
->t_charptr
= tline
->text
;
702 if (tline
->text
[0] == '$') {
704 return tokval
->t_type
= TOKEN_ID
;
708 * This is the only special case we actually need to worry
709 * about in this restricted context.
711 if (!nasm_stricmp(tline
->text
, "seg"))
712 return tokval
->t_type
= TOKEN_SEG
;
714 return tokval
->t_type
= TOKEN_ID
;
717 if (tline
->type
== TOK_NUMBER
) {
720 tokval
->t_integer
= readnum(tline
->text
, &rn_error
);
722 return tokval
->t_type
= TOKEN_ERRNUM
;
723 tokval
->t_charptr
= NULL
;
724 return tokval
->t_type
= TOKEN_NUM
;
727 if (tline
->type
== TOK_OTHER
) {
728 if (!strcmp(tline
->text
, "<<")) return tokval
->t_type
= TOKEN_SHL
;
729 if (!strcmp(tline
->text
, ">>")) return tokval
->t_type
= TOKEN_SHR
;
730 if (!strcmp(tline
->text
, "//")) return tokval
->t_type
= TOKEN_SDIV
;
731 if (!strcmp(tline
->text
, "%%")) return tokval
->t_type
= TOKEN_SMOD
;
732 if (!strcmp(tline
->text
, "==")) return tokval
->t_type
= TOKEN_EQ
;
733 if (!strcmp(tline
->text
, "<>")) return tokval
->t_type
= TOKEN_NE
;
734 if (!strcmp(tline
->text
, "!=")) return tokval
->t_type
= TOKEN_NE
;
735 if (!strcmp(tline
->text
, "<=")) return tokval
->t_type
= TOKEN_LE
;
736 if (!strcmp(tline
->text
, ">=")) return tokval
->t_type
= TOKEN_GE
;
737 if (!strcmp(tline
->text
, "&&")) return tokval
->t_type
= TOKEN_DBL_AND
;
738 if (!strcmp(tline
->text
, "^^")) return tokval
->t_type
= TOKEN_DBL_XOR
;
739 if (!strcmp(tline
->text
, "||")) return tokval
->t_type
= TOKEN_DBL_OR
;
743 * We have no other options: just return the first character of
746 return tokval
->t_type
= tline
->text
[0];
750 * Return the Context structure associated with a %$ token. Return
751 * NULL, having _already_ reported an error condition, if the
752 * context stack isn't deep enough for the supplied number of $
755 static Context
*get_ctx (char *name
) {
760 error (ERR_NONFATAL
|ERR_OFFBY1
, "`%s': context stack is empty", name
);
766 while (name
[i
+1] == '$') {
770 error (ERR_NONFATAL
|ERR_OFFBY1
, "`%s': context stack is only"
771 " %d level%s deep", name
, i
-1, (i
==2 ? "" : "s"));
779 * Compare a string to the name of an existing macro; this is a
780 * simple wrapper which calls either strcmp or nasm_stricmp
781 * depending on the value of the `casesense' parameter.
783 static int mstrcmp(char *p
, char *q
, int casesense
) {
784 return casesense
? strcmp(p
,q
) : nasm_stricmp(p
,q
);
788 * Open an include file. This routine must always return a valid
789 * file pointer if it returns - it's responsible for throwing an
790 * ERR_FATAL and bombing out completely if not. It should also try
791 * the include path one by one until it finds the file or reaches
792 * the end of the path.
794 static FILE *inc_fopen(char *file
) {
796 char *prefix
= "", *combine
;
798 int len
= strlen(file
);
801 combine
= nasm_malloc(strlen(prefix
)+len
+1);
802 strcpy(combine
, prefix
);
803 strcat(combine
, file
);
804 fp
= fopen(combine
, "r");
808 prefix
= ip
? ip
->path
: NULL
;
813 error (ERR_FATAL
|ERR_OFFBY1
,
814 "unable to open include file `%s'", file
);
815 return NULL
; /* never reached - placate compilers */
819 * Determine if we should warn on defining a single-line macro of
820 * name `name', with `nparam' parameters. If nparam is 0, will
821 * return TRUE if _any_ single-line macro of that name is defined.
822 * Otherwise, will return TRUE if a single-line macro with either
823 * `nparam' or no parameters is defined.
825 * If a macro with precisely the right number of parameters is
826 * defined, the address of the definition structure will be
827 * returned in `defn'; otherwise NULL will be returned. If `defn'
828 * is NULL, no action will be taken regarding its contents, and no
831 * Note that this is also called with nparam zero to resolve
834 static int smacro_defined (char *name
, int nparam
, SMacro
**defn
) {
839 if (name
[0] == '%' && name
[1] == '$') {
840 ctx
= get_ctx (name
);
842 return FALSE
; /* got to return _something_ */
847 m
= smacros
[hash(name
)];
852 if (!mstrcmp(m
->name
, p
, m
->casesense
) &&
853 (nparam
== 0 || m
->nparam
== 0 || nparam
== m
->nparam
)) {
855 if (nparam
== m
->nparam
)
868 * Update the __FILE__ and __LINE__ macros. Specifically, update
869 * __FILE__ if bit 1 of our argument is set, and update __LINE__ if
872 * If the macros don't exist, a `%clear' must have happened, in
873 * which case we should exit quite happily and carry on going. It's
874 * not an error condition.
876 static void update_fileline(int which
) {
880 if ((which
& 3) && smacro_defined ("__FILE__", 0, &sm
) && sm
) {
881 free_tlist(sm
->expansion
);
882 sm
->expansion
= nasm_malloc(sizeof(Token
));
883 sm
->expansion
->next
= NULL
;
884 sm
->expansion
->mac
= NULL
;
885 sm
->expansion
->type
= TOK_STRING
;
886 sm
->expansion
->text
= nasm_malloc(3+strlen(istk
->fname
));
887 /* FIXME: throw an error if both sorts of quote are present */
888 /* Better still, invent a way for us to cope with that case */
889 sprintf(sm
->expansion
->text
, "\"%s\"", istk
->fname
);
892 if ((which
& 1) && smacro_defined ("__LINE__", 0, &sm
) && sm
) {
893 free_tlist(sm
->expansion
);
894 sm
->expansion
= nasm_malloc(sizeof(Token
));
895 sm
->expansion
->next
= NULL
;
896 sm
->expansion
->mac
= NULL
;
897 sm
->expansion
->type
= TOK_NUMBER
;
898 sprintf(num
, "%d", istk
->lineno
- istk
->lineinc
);
899 sm
->expansion
->text
= nasm_strdup(num
);
904 * Count and mark off the parameters in a multi-line macro call.
905 * This is called both from within the multi-line macro expansion
906 * code, and also to mark off the default parameters when provided
907 * in a %macro definition line.
909 static void count_mmac_params (Token
*t
, int *nparam
, Token
***params
) {
910 int paramsize
, brace
;
912 *nparam
= paramsize
= 0;
915 if (*nparam
>= paramsize
) {
916 paramsize
+= PARAM_DELTA
;
917 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
919 if (t
&& t
->type
== TOK_WHITESPACE
)
922 if (t
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "{"))
924 (*params
)[(*nparam
)++] = t
;
925 while (t
&& (t
->type
!= TOK_OTHER
||
926 strcmp(t
->text
, brace
? "}" : ",")))
928 if (t
) { /* got a comma/brace */
932 * Now we've found the closing brace, look further
935 if (t
&& t
->type
== TOK_WHITESPACE
)
937 if (t
&& (t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ","))) {
938 error (ERR_NONFATAL
|ERR_OFFBY1
,
939 "braces do not enclose all of macro parameter");
940 while (t
&& (t
->type
!= TOK_OTHER
||
941 strcmp(t
->text
, ",")))
945 t
= t
->next
; /* eat the comma */
954 * Determine whether one of the various `if' conditions is true or
957 * We must free the tline we get passed.
959 static int if_condition (Token
*tline
, int i
) {
961 Token
*t
, *tt
, **tptr
, *origline
;
962 struct tokenval tokval
;
968 case PP_IFCTX
: case PP_ELIFCTX
:
969 case PP_IFNCTX
: case PP_ELIFNCTX
:
970 j
= FALSE
; /* have we matched yet? */
972 error(ERR_FATAL
|ERR_OFFBY1
,
973 "`%s': context stack is empty", directives
[i
]);
975 if (tline
->type
== TOK_WHITESPACE
)
977 if (!tline
|| tline
->type
!= TOK_ID
) {
978 error(ERR_NONFATAL
|ERR_OFFBY1
,
979 "`%s' expects context identifiers", directives
[i
]);
980 free_tlist (origline
);
983 if (!nasm_stricmp(tline
->text
, cstk
->name
))
987 if (i
== PP_IFNCTX
|| i
== PP_ELIFNCTX
)
989 free_tlist (origline
);
992 case PP_IFDEF
: case PP_ELIFDEF
:
993 case PP_IFNDEF
: case PP_ELIFNDEF
:
994 j
= FALSE
; /* have we matched yet? */
996 if (tline
->type
== TOK_WHITESPACE
)
998 if (!tline
|| (tline
->type
!= TOK_ID
&&
999 (tline
->type
!= TOK_PREPROC_ID
||
1000 tline
->text
[1] != '$'))) {
1001 error(ERR_NONFATAL
|ERR_OFFBY1
,
1002 "`%%if%sdef' expects macro identifiers",
1003 (i
==PP_ELIFNDEF
? "n" : ""));
1004 free_tlist (origline
);
1007 if (smacro_defined(tline
->text
, 0, NULL
))
1009 tline
= tline
->next
;
1011 if (i
== PP_IFNDEF
|| i
== PP_ELIFNDEF
)
1013 free_tlist (origline
);
1016 case PP_IFIDN
: case PP_ELIFIDN
: case PP_IFNIDN
: case PP_ELIFNIDN
:
1017 case PP_IFIDNI
: case PP_ELIFIDNI
: case PP_IFNIDNI
: case PP_ELIFNIDNI
:
1018 tline
= expand_smacro(tline
);
1020 while (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
1023 error(ERR_NONFATAL
, "`%s' expects two comma-separated arguments");
1028 casesense
= (i
== PP_IFIDN
|| i
== PP_ELIFIDN
||
1029 i
== PP_IFNIDN
|| i
== PP_ELIFNIDN
);
1030 j
= TRUE
; /* assume equality unless proved not */
1031 while ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) && tt
) {
1032 if (tt
->type
== TOK_OTHER
&& !strcmp(tt
->text
, ",")) {
1033 error(ERR_NONFATAL
, "`%s': more than one comma on line",
1038 if (t
->type
== TOK_WHITESPACE
) {
1041 } else if (tt
->type
== TOK_WHITESPACE
) {
1044 } else if (tt
->type
!= t
->type
||
1045 (casesense
? strcmp(tt
->text
, t
->text
) :
1046 nasm_stricmp(tt
->text
, t
->text
))) {
1047 j
= FALSE
; /* found mismatching tokens */
1055 if ((t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ",")) || tt
)
1056 j
= FALSE
; /* trailing gunk on one end or other */
1057 if (i
== PP_IFNIDN
|| i
== PP_ELIFNIDN
)
1062 case PP_IFID
: case PP_ELIFID
: case PP_IFNID
: case PP_ELIFNID
:
1063 case PP_IFNUM
: case PP_ELIFNUM
: case PP_IFNNUM
: case PP_ELIFNNUM
:
1064 case PP_IFSTR
: case PP_ELIFSTR
: case PP_IFNSTR
: case PP_ELIFNSTR
:
1065 tline
= expand_smacro(tline
);
1067 while (t
&& t
->type
== TOK_WHITESPACE
)
1069 j
= FALSE
; /* placate optimiser */
1071 case PP_IFID
: case PP_ELIFID
: case PP_IFNID
: case PP_ELIFNID
:
1072 j
= (t
->type
== TOK_ID
);
1074 case PP_IFNUM
: case PP_ELIFNUM
: case PP_IFNNUM
: case PP_ELIFNNUM
:
1075 j
= (t
->type
== TOK_NUMBER
);
1077 case PP_IFSTR
: case PP_ELIFSTR
: case PP_IFNSTR
: case PP_ELIFNSTR
:
1078 j
= (t
->type
== TOK_STRING
);
1081 if (i
== PP_IFNID
|| i
== PP_ELIFNID
||
1082 i
== PP_IFNNUM
|| i
== PP_ELIFNNUM
||
1083 i
== PP_IFNSTR
|| i
== PP_ELIFNSTR
)
1088 case PP_IF
: case PP_ELIF
:
1089 t
= tline
= expand_smacro(tline
);
1091 tokval
.t_type
= TOKEN_INVALID
;
1092 evalresult
= evaluate (ppscan
, tptr
, &tokval
,
1093 NULL
, pass
| 0x10, error
, NULL
);
1098 error(ERR_WARNING
|ERR_OFFBY1
,
1099 "trailing garbage after expression ignored");
1100 if (!is_simple(evalresult
)) {
1101 error(ERR_NONFATAL
|ERR_OFFBY1
,
1102 "non-constant value given to `%s'", directives
[i
]);
1105 return reloc_value(evalresult
) != 0;
1108 error(ERR_FATAL
|ERR_OFFBY1
,
1109 "preprocessor directive `%s' not yet implemented",
1111 free_tlist (origline
);
1112 return -1; /* yeah, right */
1117 * Find out if a line contains a preprocessor directive, and deal
1120 * If a directive _is_ found, we are expected to free_tlist() the
1123 * Return values go like this:
1125 * bit 0 is set if a directive was found (so the line gets freed)
1126 * bit 1 is set if a blank line should be emitted
1127 * bit 2 is set if a re-sync line number comment should be emitted
1129 * (bits 1 and 2 are mutually exclusive in that the rest of the
1130 * preprocessor doesn't guarantee to be able to handle the case in
1131 * which both are set)
1133 static int do_directive (Token
*tline
) {
1134 int i
, j
, k
, m
, nparam
, nolist
;
1139 SMacro
*smac
, **smhead
;
1141 Token
*t
, *tt
, *param_start
, *macro_start
, *last
, **tptr
, *origline
;
1143 struct tokenval tokval
;
1148 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1149 tline
= tline
->next
;
1150 if (!tline
|| tline
->type
!= TOK_PREPROC_ID
||
1151 (tline
->text
[1]=='%' || tline
->text
[1]=='$' || tline
->text
[1]=='!'))
1155 j
= sizeof(directives
)/sizeof(*directives
);
1158 m
= nasm_stricmp(tline
->text
, directives
[k
]);
1170 * If we're in a non-emitting branch of a condition construct,
1171 * or walking to the end of an already terminated %rep block,
1172 * we should ignore all directives except for condition
1175 if (((istk
->conds
&& !emitting(istk
->conds
->state
)) ||
1176 (istk
->mstk
&& !istk
->mstk
->in_progress
)) &&
1177 i
!= PP_IF
&& i
!= PP_ELIF
&&
1178 i
!= PP_IFCTX
&& i
!= PP_ELIFCTX
&&
1179 i
!= PP_IFDEF
&& i
!= PP_ELIFDEF
&&
1180 i
!= PP_IFID
&& i
!= PP_ELIFID
&&
1181 i
!= PP_IFIDN
&& i
!= PP_ELIFIDN
&&
1182 i
!= PP_IFIDNI
&& i
!= PP_ELIFIDNI
&&
1183 i
!= PP_IFNCTX
&& i
!= PP_ELIFNCTX
&&
1184 i
!= PP_IFNDEF
&& i
!= PP_ELIFNDEF
&&
1185 i
!= PP_IFNID
&& i
!= PP_ELIFNID
&&
1186 i
!= PP_IFNIDN
&& i
!= PP_ELIFNIDN
&&
1187 i
!= PP_IFNIDNI
&& i
!= PP_ELIFNIDNI
&&
1188 i
!= PP_IFNNUM
&& i
!= PP_ELIFNNUM
&&
1189 i
!= PP_IFNSTR
&& i
!= PP_ELIFNSTR
&&
1190 i
!= PP_IFNUM
&& i
!= PP_ELIFNUM
&&
1191 i
!= PP_IFSTR
&& i
!= PP_ELIFSTR
&&
1192 i
!= PP_ELSE
&& i
!= PP_ENDIF
)
1196 * If we're defining a macro or reading a %rep block, we should
1197 * ignore all directives except for %macro/%imacro (which
1198 * generate an error), %endm/%endmacro, and (only if we're in a
1199 * %rep block) %endrep.
1201 if (defining
&& i
!= PP_MACRO
&& i
!= PP_IMACRO
&&
1202 i
!= PP_ENDMACRO
&& i
!= PP_ENDM
&&
1203 (defining
->name
|| i
!= PP_ENDREP
))
1207 error(ERR_NONFATAL
|ERR_OFFBY1
, "unknown preprocessor directive `%s'",
1209 return 0; /* didn't get it */
1216 error(ERR_WARNING
|ERR_OFFBY1
,
1217 "trailing garbage after `%%clear' ignored");
1218 for (j
=0; j
<NHASH
; j
++) {
1219 while (mmacros
[j
]) {
1220 MMacro
*m
= mmacros
[j
];
1221 mmacros
[j
] = mmacros
[j
]->next
;
1222 nasm_free (m
->name
);
1223 free_tlist (m
->dlist
);
1224 free_llist (m
->expansion
);
1227 while (smacros
[j
]) {
1228 SMacro
*s
= smacros
[j
];
1229 smacros
[j
] = smacros
[j
]->next
;
1230 nasm_free (s
->name
);
1231 free_tlist (s
->expansion
);
1235 free_tlist (origline
);
1239 tline
= tline
->next
;
1240 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1241 tline
= tline
->next
;
1242 if (!tline
|| (tline
->type
!= TOK_STRING
&&
1243 tline
->type
!= TOK_INTERNAL_STRING
)) {
1244 error(ERR_NONFATAL
|ERR_OFFBY1
, "`%%include' expects a file name");
1245 free_tlist (origline
);
1246 return 3; /* but we did _something_ */
1249 error(ERR_WARNING
|ERR_OFFBY1
,
1250 "trailing garbage after `%%include' ignored");
1251 if (tline
->type
!= TOK_INTERNAL_STRING
) {
1252 p
= tline
->text
+1; /* point past the quote to the name */
1253 p
[strlen(p
)-1] = '\0'; /* remove the trailing quote */
1255 p
= tline
->text
; /* internal_string is easier */
1256 inc
= nasm_malloc(sizeof(Include
));
1259 inc
->fp
= inc_fopen(p
);
1260 inc
->fname
= nasm_strdup(p
);
1261 inc
->lineno
= inc
->lineinc
= 1;
1262 inc
->expansion
= NULL
;
1265 list
->uplevel (LIST_INCLUDE
);
1266 update_fileline(3); /* update __FILE__ and __LINE__ */
1267 free_tlist (origline
);
1271 tline
= tline
->next
;
1272 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1273 tline
= tline
->next
;
1274 if (!tline
|| tline
->type
!= TOK_ID
) {
1275 error(ERR_NONFATAL
|ERR_OFFBY1
,
1276 "`%%push' expects a context identifier");
1277 free_tlist (origline
);
1278 return 3; /* but we did _something_ */
1281 error(ERR_WARNING
|ERR_OFFBY1
,
1282 "trailing garbage after `%%push' ignored");
1283 ctx
= nasm_malloc(sizeof(Context
));
1285 ctx
->localmac
= NULL
;
1286 ctx
->name
= nasm_strdup(tline
->text
);
1287 ctx
->number
= unique
++;
1289 free_tlist (origline
);
1293 tline
= tline
->next
;
1294 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1295 tline
= tline
->next
;
1296 if (!tline
|| tline
->type
!= TOK_ID
) {
1297 error(ERR_NONFATAL
|ERR_OFFBY1
,
1298 "`%%repl' expects a context identifier");
1299 free_tlist (origline
);
1300 return 3; /* but we did _something_ */
1303 error(ERR_WARNING
|ERR_OFFBY1
,
1304 "trailing garbage after `%%repl' ignored");
1306 error(ERR_NONFATAL
|ERR_OFFBY1
,
1307 "`%%repl': context stack is empty");
1309 nasm_free (cstk
->name
);
1310 cstk
->name
= nasm_strdup(tline
->text
);
1312 free_tlist (origline
);
1317 error(ERR_WARNING
|ERR_OFFBY1
,
1318 "trailing garbage after `%%pop' ignored");
1320 error(ERR_NONFATAL
|ERR_OFFBY1
,
1321 "`%%pop': context stack is already empty");
1324 free_tlist (origline
);
1328 tline
= tline
->next
;
1329 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1330 tline
= tline
->next
;
1331 if (!tline
|| tline
->type
!= TOK_STRING
) {
1332 error(ERR_NONFATAL
|ERR_OFFBY1
,
1333 "`%%error' expects an error string");
1334 free_tlist (origline
);
1335 return 3; /* but we did _something_ */
1338 error(ERR_WARNING
|ERR_OFFBY1
,
1339 "trailing garbage after `%%error' ignored");
1340 p
= tline
->text
+1; /* point past the quote to the name */
1341 p
[strlen(p
)-1] = '\0'; /* remove the trailing quote */
1342 error(ERR_NONFATAL
|ERR_OFFBY1
, "user error: %s", p
);
1343 free_tlist (origline
);
1361 if (istk
->conds
&& !emitting(istk
->conds
->state
))
1364 j
= if_condition(tline
->next
, i
);
1365 tline
->next
= NULL
; /* it got freed */
1366 free_tlist (origline
);
1370 j
= j
? COND_IF_TRUE
: COND_IF_FALSE
;
1372 cond
= nasm_malloc(sizeof(Cond
));
1373 cond
->next
= istk
->conds
;
1376 return (j
== COND_IF_TRUE
? 3 : 1);
1394 error(ERR_FATAL
|ERR_OFFBY1
, "`%s': no matching `%%if'",
1396 if (emitting(istk
->conds
->state
) || istk
->conds
->state
== COND_NEVER
)
1397 istk
->conds
->state
= COND_NEVER
;
1399 j
= if_condition(tline
->next
, i
);
1400 tline
->next
= NULL
; /* it got freed */
1401 free_tlist (origline
);
1405 istk
->conds
->state
= j
? COND_IF_TRUE
: COND_IF_FALSE
;
1407 return (istk
->conds
->state
== COND_IF_TRUE
? 5 : 1);
1411 error(ERR_WARNING
|ERR_OFFBY1
,
1412 "trailing garbage after `%%else' ignored");
1414 error(ERR_FATAL
|ERR_OFFBY1
,
1415 "`%%else': no matching `%%if'");
1416 if (emitting(istk
->conds
->state
) || istk
->conds
->state
== COND_NEVER
)
1417 istk
->conds
->state
= COND_ELSE_FALSE
;
1419 istk
->conds
->state
= COND_ELSE_TRUE
;
1420 free_tlist (origline
);
1425 error(ERR_WARNING
|ERR_OFFBY1
,
1426 "trailing garbage after `%%endif' ignored");
1428 error(ERR_FATAL
|ERR_OFFBY1
,
1429 "`%%endif': no matching `%%if'");
1431 istk
->conds
= cond
->next
;
1433 free_tlist (origline
);
1439 error (ERR_FATAL
|ERR_OFFBY1
,
1440 "`%%%smacro': already defining a macro",
1441 (i
== PP_IMACRO
? "i" : ""));
1442 tline
= tline
->next
;
1443 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1444 tline
= tline
->next
;
1445 if (!tline
|| tline
->type
!= TOK_ID
) {
1446 error (ERR_NONFATAL
|ERR_OFFBY1
,
1447 "`%%%smacro' expects a macro name",
1448 (i
== PP_IMACRO
? "i" : ""));
1451 defining
= nasm_malloc(sizeof(MMacro
));
1452 defining
->name
= nasm_strdup(tline
->text
);
1453 defining
->casesense
= (i
== PP_MACRO
);
1454 defining
->plus
= FALSE
;
1455 defining
->nolist
= FALSE
;
1456 defining
->in_progress
= FALSE
;
1457 tline
= tline
->next
;
1458 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1459 tline
= tline
->next
;
1460 if (!tline
|| tline
->type
!= TOK_NUMBER
) {
1461 error (ERR_NONFATAL
|ERR_OFFBY1
,
1462 "`%%%smacro' expects a parameter count",
1463 (i
== PP_IMACRO
? "i" : ""));
1464 defining
->nparam_min
= defining
->nparam_max
= 0;
1466 defining
->nparam_min
= defining
->nparam_max
=
1467 readnum(tline
->text
, &j
);
1469 error (ERR_NONFATAL
|ERR_OFFBY1
,
1470 "unable to parse parameter count `%s'", tline
->text
);
1472 if (tline
&& tline
->next
&& tline
->next
->type
== TOK_OTHER
&&
1473 !strcmp(tline
->next
->text
, "-")) {
1474 tline
= tline
->next
->next
;
1475 if (tline
&& tline
->type
== TOK_OTHER
&&
1476 !strcmp(tline
->text
, "*"))
1477 defining
->nparam_max
= INT_MAX
;
1478 else if (!tline
|| tline
->type
!= TOK_NUMBER
)
1479 error (ERR_NONFATAL
|ERR_OFFBY1
,
1480 "`%%%smacro' expects a parameter count after `-'",
1481 (i
== PP_IMACRO
? "i" : ""));
1483 defining
->nparam_max
= readnum(tline
->text
, &j
);
1485 error (ERR_NONFATAL
|ERR_OFFBY1
,
1486 "unable to parse parameter count `%s'",
1488 if (defining
->nparam_min
> defining
->nparam_max
)
1489 error (ERR_NONFATAL
|ERR_OFFBY1
,
1490 "minimum parameter count exceeds maximum");
1493 if (tline
&& tline
->next
&& tline
->next
->type
== TOK_OTHER
&&
1494 !strcmp(tline
->next
->text
, "+")) {
1495 tline
= tline
->next
;
1496 defining
->plus
= TRUE
;
1498 if (tline
&& tline
->next
&& tline
->next
->type
== TOK_ID
&&
1499 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
1500 tline
= tline
->next
;
1501 defining
->nolist
= TRUE
;
1503 mmac
= mmacros
[hash(defining
->name
)];
1505 if (!strcmp(mmac
->name
, defining
->name
) &&
1506 (mmac
->nparam_min
<=defining
->nparam_max
|| defining
->plus
) &&
1507 (defining
->nparam_min
<=mmac
->nparam_max
|| mmac
->plus
)) {
1508 error (ERR_WARNING
|ERR_OFFBY1
,
1509 "redefining multi-line macro `%s'", defining
->name
);
1515 * Handle default parameters.
1517 if (tline
&& tline
->next
) {
1518 defining
->dlist
= tline
->next
;
1520 count_mmac_params (defining
->dlist
, &defining
->ndefs
,
1521 &defining
->defaults
);
1523 defining
->dlist
= NULL
;
1524 defining
->defaults
= NULL
;
1526 defining
->expansion
= NULL
;
1527 free_tlist (origline
);
1533 error (ERR_NONFATAL
|ERR_OFFBY1
, "`%s': not defining a macro",
1537 k
= hash(defining
->name
);
1538 defining
->next
= mmacros
[k
];
1539 mmacros
[k
] = defining
;
1541 free_tlist (origline
);
1545 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
1546 tline
= tline
->next
;
1547 t
= expand_smacro(tline
->next
);
1549 free_tlist (origline
);
1552 tokval
.t_type
= TOKEN_INVALID
;
1553 evalresult
= evaluate (ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
1558 error(ERR_WARNING
|ERR_OFFBY1
,
1559 "trailing garbage after expression ignored");
1560 if (!is_simple(evalresult
)) {
1561 error(ERR_NONFATAL
|ERR_OFFBY1
,
1562 "non-constant value given to `%%rotate'");
1566 while (mmac
&& !mmac
->name
) /* avoid mistaking %reps for macros */
1567 mmac
= mmac
->next_active
;
1569 error(ERR_NONFATAL
, "`%rotate' invoked outside a macro call");
1570 mmac
->rotate
= mmac
->rotate
+ reloc_value(evalresult
);
1571 if (mmac
->rotate
< 0)
1572 mmac
->rotate
= mmac
->nparam
- (-mmac
->rotate
) % mmac
->nparam
;
1573 mmac
->rotate
%= mmac
->nparam
;
1578 tline
= tline
->next
;
1579 if (tline
->next
&& tline
->next
->type
== TOK_WHITESPACE
)
1580 tline
= tline
->next
;
1581 if (tline
->next
&& tline
->next
->type
== TOK_ID
&&
1582 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
1583 tline
= tline
->next
;
1586 t
= expand_smacro(tline
->next
);
1588 free_tlist (origline
);
1591 tokval
.t_type
= TOKEN_INVALID
;
1592 evalresult
= evaluate (ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
1597 error(ERR_WARNING
|ERR_OFFBY1
,
1598 "trailing garbage after expression ignored");
1599 if (!is_simple(evalresult
)) {
1600 error(ERR_NONFATAL
|ERR_OFFBY1
,
1601 "non-constant value given to `%%rep'");
1604 defining
= nasm_malloc(sizeof(MMacro
));
1605 defining
->name
= NULL
; /* flags this macro as a %rep block */
1606 defining
->casesense
= 0;
1607 defining
->plus
= FALSE
;
1608 defining
->nolist
= nolist
;
1609 defining
->in_progress
= reloc_value(evalresult
) + 1;
1610 defining
->nparam_min
= defining
->nparam_max
= 0;
1611 defining
->expansion
= NULL
;
1612 defining
->next_active
= istk
->mstk
;
1617 error (ERR_NONFATAL
|ERR_OFFBY1
,
1618 "`%%endrep': no matching `%%rep'");
1623 * Now we have a "macro" defined - although it has no name
1624 * and we won't be entering it in the hash tables - we must
1625 * push a macro-end marker for it on to istk->expansion.
1626 * After that, it will take care of propagating itself (a
1627 * macro-end marker line for a macro which is really a %rep
1628 * block will cause the macro to be re-expanded, complete
1629 * with another macro-end marker to ensure the process
1630 * continues) until the whole expansion is forcibly removed
1631 * from istk->expansion by a %exitrep.
1633 l
= nasm_malloc(sizeof(Line
));
1634 l
->next
= istk
->expansion
;
1635 l
->finishes
= defining
;
1637 istk
->expansion
= l
;
1639 istk
->mstk
= defining
;
1641 list
->uplevel (defining
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
1643 free_tlist (origline
);
1644 return 1; /* the expansion will line-sync */
1648 * We must search along istk->expansion until we hit a
1649 * macro-end marker for a macro with no name. Then we set
1650 * its `in_progress' flag to 0.
1652 for (l
= istk
->expansion
; l
; l
= l
->next
)
1653 if (l
->finishes
&& !l
->finishes
->name
)
1656 if (l
->finishes
&& !l
->finishes
->name
)
1657 l
->finishes
->in_progress
= 0;
1659 error (ERR_NONFATAL
, "`%%exitrep' not within `%%rep' block");
1660 free_tlist (origline
);
1661 return 1; /* the end marker will line-sync */
1665 tline
= tline
->next
;
1666 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1667 tline
= tline
->next
;
1668 if (!tline
|| (tline
->type
!= TOK_ID
&&
1669 (tline
->type
!= TOK_PREPROC_ID
||
1670 tline
->text
[1] != '$'))) {
1671 error (ERR_NONFATAL
|ERR_OFFBY1
,
1672 "`%%%sdefine' expects a macro identifier",
1673 (i
== PP_IDEFINE
? "i" : ""));
1674 free_tlist (origline
);
1677 mname
= tline
->text
;
1678 if (tline
->type
== TOK_ID
) {
1680 smhead
= &smacros
[hash(mname
)];
1682 ctx
= get_ctx (tline
->text
);
1687 p
+= strspn(p
, "$");
1688 smhead
= &ctx
->localmac
;
1692 param_start
= tline
= tline
->next
;
1694 if (tline
&& tline
->type
== TOK_OTHER
&& !strcmp(tline
->text
, "(")) {
1696 * This macro has parameters.
1699 tline
= tline
->next
;
1701 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1702 tline
= tline
->next
;
1704 error (ERR_NONFATAL
|ERR_OFFBY1
,
1705 "parameter identifier expected");
1706 free_tlist (origline
);
1709 if (tline
->type
!= TOK_ID
) {
1710 error (ERR_NONFATAL
|ERR_OFFBY1
,
1711 "`%s': parameter identifier expected",
1713 free_tlist (origline
);
1716 tline
->type
= TOK_SMAC_PARAM
+ nparam
++;
1717 tline
= tline
->next
;
1718 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1719 tline
= tline
->next
;
1720 if (tline
&& tline
->type
== TOK_OTHER
&&
1721 !strcmp(tline
->text
, ",")) {
1722 tline
= tline
->next
;
1725 if (!tline
|| tline
->type
!= TOK_OTHER
||
1726 strcmp(tline
->text
, ")")) {
1727 error (ERR_NONFATAL
|ERR_OFFBY1
,
1728 "`)' expected to terminate macro template");
1729 free_tlist (origline
);
1735 tline
= tline
->next
;
1737 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1738 last
= tline
, tline
= tline
->next
;
1743 if (t
->type
== TOK_ID
) {
1744 for (tt
= param_start
; tt
; tt
= tt
->next
)
1745 if (tt
->type
>= TOK_SMAC_PARAM
&&
1746 !strcmp(tt
->text
, t
->text
))
1750 t
->next
= macro_start
;
1755 * Good. We now have a macro name, a parameter count, and a
1756 * token list (in reverse order) for an expansion. We ought
1757 * to be OK just to create an SMacro, store it, and let
1758 * free_tlist have the rest of the line (which we have
1759 * carefully re-terminated after chopping off the expansion
1762 if (smacro_defined (mname
, nparam
, &smac
)) {
1764 error (ERR_WARNING
|ERR_OFFBY1
,
1765 "single-line macro `%s' defined both with and"
1766 " without parameters", mname
);
1769 * We're redefining, so we have to take over an
1770 * existing SMacro structure. This means freeing
1771 * what was already in it.
1773 nasm_free (smac
->name
);
1774 free_tlist (smac
->expansion
);
1777 smac
= nasm_malloc(sizeof(SMacro
));
1778 smac
->next
= *smhead
;
1781 smac
->name
= nasm_strdup(p
);
1782 smac
->casesense
= (i
== PP_DEFINE
);
1783 smac
->nparam
= nparam
;
1784 smac
->expansion
= macro_start
;
1785 smac
->in_progress
= FALSE
;
1786 free_tlist (origline
);
1791 tline
= tline
->next
;
1792 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1793 tline
= tline
->next
;
1794 if (!tline
|| (tline
->type
!= TOK_ID
&&
1795 (tline
->type
!= TOK_PREPROC_ID
||
1796 tline
->text
[1] != '$'))) {
1797 error (ERR_NONFATAL
|ERR_OFFBY1
,
1798 "`%%%sassign' expects a macro identifier",
1799 (i
== PP_IASSIGN
? "i" : ""));
1800 free_tlist (origline
);
1803 mname
= tline
->text
;
1804 if (tline
->type
== TOK_ID
) {
1806 smhead
= &smacros
[hash(mname
)];
1808 ctx
= get_ctx (tline
->text
);
1810 free_tlist (origline
);
1814 p
+= strspn(p
, "$");
1815 smhead
= &ctx
->localmac
;
1819 tline
= tline
->next
;
1822 tline
= expand_smacro (tline
);
1825 tokval
.t_type
= TOKEN_INVALID
;
1826 evalresult
= evaluate (ppscan
, tptr
, &tokval
, NULL
, pass
, error
, NULL
);
1829 free_tlist (origline
);
1834 error(ERR_WARNING
|ERR_OFFBY1
,
1835 "trailing garbage after expression ignored");
1837 if (!is_simple(evalresult
)) {
1838 error(ERR_NONFATAL
|ERR_OFFBY1
,
1839 "non-constant value given to `%%%sassign'",
1840 (i
== PP_IASSIGN
? "i" : ""));
1841 free_tlist (origline
);
1845 macro_start
= nasm_malloc(sizeof(*macro_start
));
1846 macro_start
->next
= NULL
;
1849 sprintf(numbuf
, "%ld", reloc_value(evalresult
));
1850 macro_start
->text
= nasm_strdup(numbuf
);
1852 macro_start
->mac
= NULL
;
1853 macro_start
->type
= TOK_NUMBER
;
1856 * We now have a macro name, an implicit parameter count of
1857 * zero, and a numeric token to use as an expansion. Create
1858 * and store an SMacro.
1860 if (smacro_defined (mname
, 0, &smac
)) {
1862 error (ERR_WARNING
|ERR_OFFBY1
,
1863 "single-line macro `%s' defined both with and"
1864 " without parameters", mname
);
1867 * We're redefining, so we have to take over an
1868 * existing SMacro structure. This means freeing
1869 * what was already in it.
1871 nasm_free (smac
->name
);
1872 free_tlist (smac
->expansion
);
1875 smac
= nasm_malloc(sizeof(SMacro
));
1876 smac
->next
= *smhead
;
1879 smac
->name
= nasm_strdup(p
);
1880 smac
->casesense
= (i
== PP_ASSIGN
);
1882 smac
->expansion
= macro_start
;
1883 smac
->in_progress
= FALSE
;
1884 free_tlist (origline
);
1889 * Syntax is `%line nnn[+mmm] [filename]'
1891 tline
= tline
->next
;
1892 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1893 tline
= tline
->next
;
1894 if (!tline
|| tline
->type
!= TOK_NUMBER
) {
1895 error (ERR_NONFATAL
|ERR_OFFBY1
, "`%%line' expects line number");
1896 free_tlist (origline
);
1899 k
= readnum(tline
->text
, &j
);
1901 tline
= tline
->next
;
1902 if (tline
&& tline
->type
== TOK_OTHER
&& !strcmp(tline
->text
, "+")) {
1903 tline
= tline
->next
;
1904 if (!tline
|| tline
->type
!= TOK_NUMBER
) {
1905 error (ERR_NONFATAL
|ERR_OFFBY1
,
1906 "`%%line' expects line increment");
1907 free_tlist (origline
);
1910 m
= readnum(tline
->text
, &j
);
1911 tline
= tline
->next
;
1913 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1914 tline
= tline
->next
;
1917 update_fileline(3); /* update __FILE__ and __LINE__ */
1919 char *s
= detoken(tline
);
1920 nasm_free (istk
->fname
);
1923 free_tlist (origline
);
1927 error(ERR_FATAL
|ERR_OFFBY1
,
1928 "preprocessor directive `%s' not yet implemented",
1936 * Ensure that a macro parameter contains a condition code and
1937 * nothing else. Return the condition code index if so, or -1
1940 static int find_cc (Token
*t
) {
1944 if (t
&& t
->type
== TOK_WHITESPACE
)
1946 if (t
->type
!= TOK_ID
)
1949 if (tt
&& tt
->type
== TOK_WHITESPACE
)
1951 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
1955 j
= sizeof(conditions
)/sizeof(*conditions
);
1958 m
= nasm_stricmp(t
->text
, conditions
[k
]);
1974 * Expand MMacro-local things: parameter references (%0, %n, %+n,
1975 * %-n) and MMacro-local identifiers (%%foo).
1977 static Token
*expand_mmac_params (Token
*tline
) {
1978 Token
*t
, *tt
, *ttt
, **tail
, *thead
;
1984 if (tline
->type
== TOK_PREPROC_ID
&&
1985 (tline
->text
[1] == '+' || tline
->text
[1] == '-' ||
1986 tline
->text
[1] == '%' ||
1987 (tline
->text
[1] >= '0' && tline
->text
[1] <= '9'))) {
1989 int type
= 0, cc
; /* type = 0 to placate optimisers */
1995 tline
= tline
->next
;
1998 while (mac
&& !mac
->name
) /* avoid mistaking %reps for macros */
1999 mac
= mac
->next_active
;
2001 error(ERR_NONFATAL
, "`%s': not in a macro call", t
->text
);
2002 else switch (t
->text
[1]) {
2004 * We have to make a substitution of one of the
2005 * forms %1, %-1, %+1, %%foo, %0.
2009 sprintf(tmpbuf
, "%d", mac
->nparam
);
2010 text
= nasm_strdup(tmpbuf
);
2014 sprintf(tmpbuf
, "..@%lu.", mac
->unique
);
2015 text
= nasm_malloc(strlen(tmpbuf
)+strlen(t
->text
+2)+1);
2016 strcpy(text
, tmpbuf
);
2017 strcat(text
, t
->text
+2);
2020 n
= atoi(t
->text
+2)-1;
2021 if (n
>= mac
->nparam
)
2024 if (mac
->nparam
> 1)
2025 n
= (n
+ mac
->rotate
) % mac
->nparam
;
2026 tt
= mac
->params
[n
];
2030 error (ERR_NONFATAL
|ERR_OFFBY1
,
2031 "macro parameter %d is not a condition code",
2036 if (inverse_ccs
[cc
] == -1) {
2037 error (ERR_NONFATAL
|ERR_OFFBY1
,
2038 "condition code `%s' is not invertible",
2042 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
2046 n
= atoi(t
->text
+2)-1;
2047 if (n
>= mac
->nparam
)
2050 if (mac
->nparam
> 1)
2051 n
= (n
+ mac
->rotate
) % mac
->nparam
;
2052 tt
= mac
->params
[n
];
2056 error (ERR_NONFATAL
|ERR_OFFBY1
,
2057 "macro parameter %d is not a condition code",
2062 text
= nasm_strdup(conditions
[cc
]);
2066 n
= atoi(t
->text
+1)-1;
2067 if (n
>= mac
->nparam
)
2070 if (mac
->nparam
> 1)
2071 n
= (n
+ mac
->rotate
) % mac
->nparam
;
2072 tt
= mac
->params
[n
];
2075 for (i
=0; i
<mac
->paramlen
[n
]; i
++) {
2076 ttt
= *tail
= nasm_malloc(sizeof(Token
));
2079 ttt
->type
= tt
->type
;
2080 ttt
->text
= nasm_strdup(tt
->text
);
2085 text
= NULL
; /* we've done it here */
2088 nasm_free (t
->text
);
2091 t
= *tail
= nasm_malloc(sizeof(Token
));
2101 tline
= tline
->next
;
2111 * Expand all single-line macro calls made in the given line.
2112 * Return the expanded version of the line. The original is deemed
2113 * to be destroyed in the process. (In reality we'll just move
2114 * Tokens from input to output a lot of the time, rather than
2115 * actually bothering to destroy and replicate.)
2117 static Token
*expand_smacro (Token
*tline
) {
2118 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
2122 int nparam
, sparam
, brackets
;
2129 while (tline
&& tline
->type
!= TOK_ID
&&
2130 (tline
->type
!= TOK_PREPROC_ID
|| tline
->text
[1] != '$')) {
2131 if (tline
->type
== TOK_SMAC_END
) {
2132 tline
->mac
->in_progress
= FALSE
;
2134 tline
= tline
->next
;
2138 tline
= tline
->next
;
2142 if (t
->type
== TOK_PS_OTHER
) {
2144 * If we see a PS_OTHER, we must at the very
2145 * least restore its correct token type. We
2146 * should also check for a %$ token, since this
2147 * is the point at which we expand context-
2151 if (t
->text
[0] == '%' && t
->text
[1] == '$') {
2152 Context
*c
= get_ctx (t
->text
);
2153 char *p
, *q
, buffer
[40];
2157 q
+= strspn(q
, "$");
2158 sprintf(buffer
, "..@%lu.", c
->number
);
2159 p
= nasm_malloc (strlen(buffer
)+strlen(q
)+1);
2162 nasm_free (t
->text
);
2173 * We've hit an identifier. As in is_mmacro below, we first
2174 * check whether the identifier is a single-line macro at
2175 * all, then think about checking for parameters if
2178 if (tline
->type
== TOK_ID
) {
2179 head
= smacros
[hash(tline
->text
)];
2182 Context
*ctx
= get_ctx (tline
->text
);
2185 p
+= strspn(p
, "$");
2186 head
= ctx
->localmac
;
2188 tline
->type
= TOK_OTHER
; /* so it will get copied above */
2192 for (m
= head
; m
; m
= m
->next
)
2193 if (!mstrcmp(m
->name
, p
, m
->casesense
))
2195 if (!m
|| m
->in_progress
) {
2197 * Either we didn't find a macro, so this can't be a
2198 * macro call, or we found a macro which was already in
2199 * progress, in which case we don't _treat_ this as a
2200 * macro call. Copy it through and ignore it.
2202 tline
->type
= TOK_PS_OTHER
; /* so it will get copied above */
2206 if (m
->nparam
== 0) {
2208 * Simple case: the macro is parameterless. Discard the
2209 * one token that the macro call took, and push the
2210 * expansion back on the to-do stack.
2216 * Complicated case: at least one macro with this name
2217 * exists and takes parameters. We must find the
2218 * parameters in the call, count them, find the SMacro
2219 * that corresponds to that form of the macro call, and
2220 * substitute for the parameters when we expand. What a
2223 nparam
= sparam
= 0;
2226 tline
= tline
->next
;
2227 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2228 tline
= tline
->next
;
2229 if (!tline
|| tline
->type
!= TOK_OTHER
||
2230 strcmp(tline
->text
, "(")) {
2232 * This macro wasn't called with parameters: ignore
2233 * the call. (Behaviour borrowed from gnu cpp.)
2236 tline
->type
= TOK_PS_OTHER
;
2239 tline
= tline
->next
;
2241 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2242 tline
= tline
->next
;
2244 error(ERR_NONFATAL
|ERR_OFFBY1
,
2245 "macro call expects terminating `)'");
2248 if (nparam
>= sparam
) {
2249 sparam
+= PARAM_DELTA
;
2250 params
= nasm_realloc (params
, sparam
*sizeof(Token
*));
2251 paramsize
= nasm_realloc (paramsize
, sparam
*sizeof(int));
2253 params
[nparam
] = tline
;
2254 paramsize
[nparam
] = 0;
2256 if (tline
&& tline
->type
== TOK_OTHER
&&
2257 !strcmp(tline
->text
, "{")) {
2258 params
[nparam
] = tline
= tline
->next
;
2259 while (tline
&& (brackets
> 0 ||
2260 tline
->type
!= TOK_OTHER
||
2261 strcmp(tline
->text
, "}"))) {
2262 tline
= tline
->next
;
2263 paramsize
[nparam
]++;
2265 tline
= tline
->next
;
2266 if (tline
&& tline
->type
== TOK_WHITESPACE
)
2267 tline
= tline
->next
;
2268 if (tline
&& (tline
->type
!= TOK_OTHER
||
2269 (strcmp(tline
->text
, ")") &&
2270 strcmp(tline
->text
, ",")))) {
2271 error (ERR_NONFATAL
|ERR_OFFBY1
, "braces do not "
2272 "enclose all of macro parameter");
2274 if (tline
&& tline
->type
== TOK_OTHER
&&
2275 !strcmp(tline
->text
, ","))
2276 tline
= tline
->next
;
2278 while (tline
&& (brackets
> 0 ||
2279 tline
->type
!= TOK_OTHER
||
2280 (strcmp(tline
->text
, ",") &&
2281 strcmp(tline
->text
, ")")))) {
2282 if (tline
->type
== TOK_OTHER
&& !tline
->text
[1])
2283 brackets
+= (tline
->text
[0] == '(' ? 1 :
2284 tline
->text
[0] == ')' ? -1 : 0);
2285 tline
= tline
->next
;
2286 paramsize
[nparam
]++;
2290 if (tline
&& !strcmp(tline
->text
, ")"))
2292 if (tline
&& !strcmp(tline
->text
, ","))
2293 tline
= tline
->next
;
2295 while (m
&& m
->nparam
!= nparam
) {
2296 while ( (m
= m
->next
) )
2297 if (!strcmp(m
->name
, mstart
->text
))
2301 error (ERR_WARNING
|ERR_OFFBY1
|ERR_WARN_MNP
,
2302 "macro `%s' exists, but not taking %d parameters",
2303 mstart
->text
, nparam
);
2305 nasm_free (paramsize
);
2307 tline
->type
= TOK_PS_OTHER
;
2312 * Expand the macro: we are placed on the last token of the
2313 * call, so that we can easily split the call from the
2314 * following tokens. We also start by pushing an SMAC_END
2315 * token for the cycle removal.
2318 tline
= tline
->next
;
2320 tt
= nasm_malloc(sizeof(Token
));
2321 tt
->type
= TOK_SMAC_END
;
2324 m
->in_progress
= TRUE
;
2327 for (t
= m
->expansion
; t
; t
= t
->next
) {
2328 if (t
->type
>= TOK_SMAC_PARAM
) {
2329 Token
*pcopy
= tline
, **ptail
= &pcopy
;
2333 ttt
= params
[t
->type
- TOK_SMAC_PARAM
];
2334 for (i
=0; i
<paramsize
[t
->type
-TOK_SMAC_PARAM
]; i
++) {
2335 pt
= *ptail
= nasm_malloc(sizeof(Token
));
2338 pt
->text
= nasm_strdup(ttt
->text
);
2339 pt
->type
= ttt
->type
;
2345 tt
= nasm_malloc(sizeof(Token
));
2347 tt
->text
= nasm_strdup(t
->text
);
2355 * Having done that, get rid of the macro call, and clean
2356 * up the parameters.
2359 nasm_free (paramsize
);
2360 free_tlist (mstart
);
2367 * Determine whether the given line constitutes a multi-line macro
2368 * call, and return the MMacro structure called if so. Doesn't have
2369 * to check for an initial label - that's taken care of in
2370 * expand_mmacro - but must check numbers of parameters. Guaranteed
2371 * to be called with tline->type == TOK_ID, so the putative macro
2372 * name is easy to find.
2374 static MMacro
*is_mmacro (Token
*tline
, Token
***params_array
) {
2379 head
= mmacros
[hash(tline
->text
)];
2382 * Efficiency: first we see if any macro exists with the given
2383 * name. If not, we can return NULL immediately. _Then_ we
2384 * count the parameters, and then we look further along the
2385 * list if necessary to find the proper MMacro.
2387 for (m
= head
; m
; m
= m
->next
)
2388 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
2394 * OK, we have a potential macro. Count and demarcate the
2397 count_mmac_params (tline
->next
, &nparam
, ¶ms
);
2400 * So we know how many parameters we've got. Find the MMacro
2401 * structure that handles this number.
2404 if (m
->nparam_min
<= nparam
&& (m
->plus
|| nparam
<= m
->nparam_max
)) {
2406 * This one is right. Just check if cycle removal
2407 * prohibits us using it before we actually celebrate...
2409 if (m
->in_progress
) {
2410 error (ERR_NONFATAL
|ERR_OFFBY1
,
2411 "self-reference in multi-line macro `%s'",
2417 * It's right, and we can use it. Add its default
2418 * parameters to the end of our list if necessary.
2420 if (m
->defaults
&& nparam
< m
->nparam_min
+ m
->ndefs
) {
2421 params
= nasm_realloc (params
, ((m
->nparam_min
+m
->ndefs
+1) *
2423 while (nparam
< m
->nparam_min
+ m
->ndefs
) {
2424 params
[nparam
] = m
->defaults
[nparam
- m
->nparam_min
];
2429 * If we've gone over the maximum parameter count (and
2430 * we're in Plus mode), ignore parameters beyond
2433 if (m
->plus
&& nparam
> m
->nparam_max
)
2434 nparam
= m
->nparam_max
;
2436 * Then terminate the parameter list, and leave.
2438 if (!params
) { /* need this special case */
2439 params
= nasm_malloc(sizeof(*params
));
2442 params
[nparam
] = NULL
;
2443 *params_array
= params
;
2447 * This one wasn't right: look for the next one with the
2450 for (m
= m
->next
; m
; m
= m
->next
)
2451 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
2456 * After all that, we didn't find one with the right number of
2457 * parameters. Issue a warning, and fail to expand the macro.
2459 error (ERR_WARNING
|ERR_OFFBY1
|ERR_WARN_MNP
,
2460 "macro `%s' exists, but not taking %d parameters",
2461 tline
->text
, nparam
);
2467 * Expand the multi-line macro call made by the given line, if
2468 * there is one to be expanded. If there is, push the expansion on
2469 * istk->expansion and return 1 or 2, as according to whether a
2470 * line sync is needed (2 if it is). Otherwise return 0.
2472 static int expand_mmacro (Token
*tline
) {
2473 Token
*label
= NULL
, **params
, *t
, *tt
, *last
= NULL
;
2476 int i
, nparam
, *paramlen
;
2477 int need_sync
= FALSE
;
2480 if (t
&& t
->type
== TOK_WHITESPACE
)
2482 if (t
&& t
->type
== TOK_ID
) {
2483 m
= is_mmacro (t
, ¶ms
);
2486 * We have an id which isn't a macro call. We'll assume
2487 * it might be a label; we'll also check to see if a
2488 * colon follows it. Then, if there's another id after
2489 * that lot, we'll check it again for macro-hood.
2491 last
= t
, t
= t
->next
;
2492 if (t
&& t
->type
== TOK_WHITESPACE
)
2493 last
= t
, t
= t
->next
;
2494 if (t
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ":"))
2495 last
= t
, t
= t
->next
;
2496 if (t
&& t
->type
== TOK_WHITESPACE
)
2497 last
= t
, t
= t
->next
;
2498 if (t
&& t
->type
== TOK_ID
) {
2499 m
= is_mmacro(t
, ¶ms
);
2512 * If we're not already inside another macro expansion, we'd
2513 * better push a line synchronisation to ensure we stay put on
2516 if (!istk
->expansion
)
2520 * Fix up the parameters: this involves stripping leading and
2521 * trailing whitespace, then stripping braces if they are
2524 for (nparam
= 0; params
[nparam
]; nparam
++);
2525 paramlen
= nparam
? nasm_malloc(nparam
*sizeof(*paramlen
)) : NULL
;
2527 for (i
= 0; params
[i
]; i
++) {
2529 int comma
= (!m
->plus
|| i
< nparam
-1);
2532 if (t
&& t
->type
== TOK_WHITESPACE
)
2534 if (t
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "{"))
2535 t
= t
->next
, brace
= TRUE
, comma
= FALSE
;
2539 if (!t
) /* end of param because EOL */
2541 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
2542 break; /* ... because we have hit a comma */
2543 if (comma
&& t
->type
== TOK_WHITESPACE
&&
2544 t
->next
->type
== TOK_OTHER
&& !strcmp(t
->next
->text
, ","))
2545 break; /* ... or a space then a comma */
2546 if (brace
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "}"))
2547 break; /* ... or a brace */
2554 * OK, we have a MMacro structure together with a set of
2555 * parameters. We must now go through the expansion and push
2556 * copies of each Line on to istk->expansion. Substitution of
2557 * parameter tokens and macro-local tokens doesn't get done
2558 * until the single-line macro substitution process; this is
2559 * because delaying them allows us to change the semantics
2560 * later through %rotate.
2562 * First, push an end marker on to istk->expansion, mark this
2563 * macro as in progress, and set up its invocation-specific
2566 ll
= nasm_malloc(sizeof(Line
));
2567 ll
->next
= istk
->expansion
;
2570 istk
->expansion
= ll
;
2572 m
->in_progress
= TRUE
;
2577 m
->paramlen
= paramlen
;
2578 m
->unique
= unique
++;
2580 m
->next_active
= istk
->mstk
;
2583 for (l
= m
->expansion
; l
; l
= l
->next
) {
2586 ll
= nasm_malloc(sizeof(Line
));
2587 ll
->next
= istk
->expansion
;
2588 ll
->finishes
= NULL
;
2592 for (t
= l
->first
; t
; t
= t
->next
) {
2593 tt
= *tail
= nasm_malloc(sizeof(Token
));
2597 tt
->text
= nasm_strdup(t
->text
);
2601 istk
->expansion
= ll
;
2606 * If we had a label, push it on the front of the first line of
2607 * the macro expansion. We must check that this doesn't give
2608 * two consecutive TOK_WHITESPACE.
2611 if (last
->type
== TOK_WHITESPACE
&&
2612 istk
->expansion
->first
->type
== TOK_WHITESPACE
) {
2613 Token
*victim
= istk
->expansion
->first
; /* kill this whitespace */
2614 istk
->expansion
->first
= victim
->next
;
2615 nasm_free (victim
->text
);
2618 last
->next
= istk
->expansion
->first
;
2619 istk
->expansion
->first
= label
;
2622 list
->uplevel (m
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
2624 return need_sync
? 2 : 1;
2627 static void pp_reset (char *file
, int apass
, efunc errfunc
, evalfunc eval
,
2633 linesync
= outline
= NULL
;
2634 istk
= nasm_malloc(sizeof(Include
));
2637 istk
->expansion
= NULL
;
2639 istk
->fp
= fopen(file
, "r");
2640 istk
->fname
= nasm_strdup(file
);
2641 istk
->lineno
= istk
->lineinc
= 1;
2643 error (ERR_FATAL
|ERR_NOFILE
, "unable to open input file `%s'", file
);
2645 for (h
=0; h
<NHASH
; h
++) {
2651 any_extrastdmac
= (extrastdmac
!= NULL
);
2657 static char *pp_getline (void) {
2670 * Fetch a tokenised line, either from the macro-expansion
2671 * buffer or from the input file.
2674 while (istk
->expansion
&& istk
->expansion
->finishes
) {
2675 Line
*l
= istk
->expansion
;
2676 if (!l
->finishes
->name
&& l
->finishes
->in_progress
> 1) {
2680 * This is a macro-end marker for a macro with no
2681 * name, which means it's not really a macro at all
2682 * but a %rep block, and the `in_progress' field is
2683 * more than 1, meaning that we still need to
2684 * repeat. (1 means the natural last repetition; 0
2685 * means termination by %exitrep.) We have
2686 * therefore expanded up to the %endrep, and must
2687 * push the whole block on to the expansion buffer
2688 * again. We don't bother to remove the macro-end
2689 * marker: we'd only have to generate another one
2692 l
->finishes
->in_progress
--;
2693 for (l
= l
->finishes
->expansion
; l
; l
= l
->next
) {
2694 Token
*t
, *tt
, **tail
;
2696 ll
= nasm_malloc(sizeof(Line
));
2697 ll
->next
= istk
->expansion
;
2698 ll
->finishes
= NULL
;
2702 for (t
= l
->first
; t
; t
= t
->next
) {
2704 tt
= *tail
= nasm_malloc(sizeof(Token
));
2708 tt
->text
= nasm_strdup(t
->text
);
2713 istk
->expansion
= ll
;
2718 * Check whether a `%rep' was started and not ended
2719 * within this macro expansion. This can happen and
2720 * should be detected. It's a fatal error because
2721 * I'm too confused to work out how to recover
2727 "defining with name in expansion");
2728 else if (!istk
->mstk
->name
)
2729 error (ERR_PANIC
, "istk->mstk has no name but"
2730 " defining is set at end of expansion");
2732 error (ERR_FATAL
, "`%%rep' without `%%endrep' within"
2733 " expansion of macro `%s'", istk
->mstk
->name
);
2736 if (istk
->mstk
->name
) {
2738 * This was a real macro call, not a %rep, and
2739 * therefore the parameter information needs to
2742 nasm_free(istk
->mstk
->params
);
2743 free_tlist(istk
->mstk
->iline
);
2744 nasm_free(istk
->mstk
->paramlen
);
2746 istk
->mstk
= istk
->mstk
->next_active
;
2747 l
->finishes
->in_progress
= FALSE
;
2748 istk
->expansion
= l
->next
;
2750 list
->downlevel (LIST_MACRO
);
2751 if (!istk
->expansion
)
2755 if (istk
->expansion
) {
2757 Line
*l
= istk
->expansion
;
2759 istk
->expansion
= l
->next
;
2762 list
->line (LIST_MACRO
, p
);
2764 if (!istk
->expansion
)
2770 * The current file has ended; work down the istk
2771 * until we find a file we can read from.
2776 error(ERR_FATAL
, "expected `%%endif' before end of file");
2779 list
->downlevel (LIST_INCLUDE
);
2780 nasm_free (i
->fname
);
2786 update_fileline(3); /* update __FILE__ and __LINE__ */
2789 line
= prepreproc(line
);
2790 tline
= tokenise(line
);
2795 * We must expand MMacro parameters and MMacro-local labels
2796 * _before_ we plunge into directive processing, to cope
2797 * with things like `%define something %1' such as STRUC
2798 * uses. Unless we're _defining_ a MMacro, in which case
2799 * those tokens should be left alone to go into the
2803 tline
= expand_mmac_params(tline
);
2806 * Check the line to see if it's a preprocessor directive.
2808 ret
= do_directive(tline
);
2812 if ((ret
& 2) && !stdmacpos
) {/* give a blank line to the output */
2813 outline
= nasm_strdup("");
2818 } else if (defining
) {
2820 * We're defining a multi-line macro. We emit nothing
2821 * at all, not even a blank line (when we finish
2822 * defining the macro, we'll emit a line-number
2823 * directive so that we keep sync properly), and just
2824 * shove the tokenised line on to the macro definition.
2826 Line
*l
= nasm_malloc(sizeof(Line
));
2827 l
->next
= defining
->expansion
;
2829 l
->finishes
= FALSE
;
2830 defining
->expansion
= l
;
2832 } else if (istk
->conds
&& !emitting(istk
->conds
->state
)) {
2834 * We're in a non-emitting branch of a condition block.
2835 * Emit nothing at all, not even a blank line: when we
2836 * emerge from the condition we'll give a line-number
2837 * directive so we keep our place correctly.
2841 } else if (istk
->mstk
&& !istk
->mstk
->in_progress
) {
2843 * We're in a %rep block which has been terminated, so
2844 * we're walking through to the %endrep without
2845 * emitting anything. Emit nothing at all, not even a
2846 * blank line: when we emerge from the %rep block we'll
2847 * give a line-number directive so we keep our place
2853 tline
= expand_smacro(tline
);
2854 ret
= expand_mmacro(tline
);
2857 * De-tokenise the line again, and emit it.
2859 line
= detoken(tline
);
2866 continue; /* expand_mmacro calls free_tlist */
2872 * Once we're out of this loop, outline _must_ be non-NULL. The
2873 * only question is whether linesync is NULL or not.
2885 static void pp_cleanup (void) {
2889 error (ERR_NONFATAL
, "end of file while still defining macro `%s'",
2891 nasm_free (defining
->name
);
2892 free_tlist (defining
->dlist
);
2893 free_llist (defining
->expansion
);
2894 nasm_free (defining
);
2896 nasm_free (linesync
); /* might just be necessary */
2897 nasm_free (outline
); /* really shouldn't be necessary */
2900 for (h
=0; h
<NHASH
; h
++) {
2901 while (mmacros
[h
]) {
2902 MMacro
*m
= mmacros
[h
];
2903 mmacros
[h
] = mmacros
[h
]->next
;
2904 nasm_free (m
->name
);
2905 free_tlist (m
->dlist
);
2906 nasm_free (m
->defaults
);
2907 free_llist (m
->expansion
);
2910 while (smacros
[h
]) {
2911 SMacro
*s
= smacros
[h
];
2912 smacros
[h
] = smacros
[h
]->next
;
2913 nasm_free (s
->name
);
2914 free_tlist (s
->expansion
);
2922 nasm_free (i
->fname
);
2929 void pp_include_path (char *path
) {
2932 i
= nasm_malloc(sizeof(IncPath
));
2933 i
->path
= nasm_strdup(path
);
2939 void pp_pre_include (char *fname
) {
2940 Token
*inc
, *space
, *name
;
2943 inc
= nasm_malloc(sizeof(Token
));
2944 inc
->next
= space
= nasm_malloc(sizeof(Token
));
2945 space
->next
= name
= nasm_malloc(sizeof(Token
));
2948 inc
->type
= TOK_PREPROC_ID
;
2949 inc
->text
= nasm_strdup("%include");
2950 space
->type
= TOK_WHITESPACE
;
2951 space
->text
= nasm_strdup(" ");
2952 name
->type
= TOK_INTERNAL_STRING
;
2953 name
->text
= nasm_strdup(fname
);
2955 inc
->mac
= space
->mac
= name
->mac
= NULL
;
2957 l
= nasm_malloc(sizeof(Line
));
2960 l
->finishes
= FALSE
;
2964 void pp_pre_define (char *definition
) {
2965 Token
*def
, *space
, *name
;
2969 equals
= strchr(definition
, '=');
2971 def
= nasm_malloc(sizeof(Token
));
2972 def
->next
= space
= nasm_malloc(sizeof(Token
));
2975 space
->next
= name
= tokenise(definition
);
2979 def
->type
= TOK_PREPROC_ID
;
2980 def
->text
= nasm_strdup("%define");
2981 space
->type
= TOK_WHITESPACE
;
2982 space
->text
= nasm_strdup(" ");
2984 def
->mac
= space
->mac
= NULL
;
2986 l
= nasm_malloc(sizeof(Line
));
2989 l
->finishes
= FALSE
;
2993 void pp_extra_stdmac (char **macros
) {
2994 extrastdmac
= macros
;