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
20 typedef struct SMacro SMacro
;
21 typedef struct MMacro MMacro
;
22 typedef struct Context Context
;
23 typedef struct Token Token
;
24 typedef struct Line Line
;
25 typedef struct Include Include
;
26 typedef struct Cond Cond
;
27 typedef struct IncPath IncPath
;
30 * Store the definition of a single-line macro.
42 * Store the definition of a multi-line macro.
48 int nparam_min
, nparam_max
;
49 int plus
; /* is the last parameter greedy? */
50 int nolist
; /* is this macro listing-inhibited? */
52 Token
**defaults
, *dlist
;
57 * The context stack is composed of a linked list of these.
67 * This is the internal form which we break input lines up into.
68 * Typically stored in linked lists.
70 * TOK_PS_OTHER is a token type used internally within
71 * expand_smacro(), to denote a token which has already been
72 * checked for being a potential macro, but may still be a context-
75 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
76 * necessarily used as-is, but is intended to denote the number of
77 * the substituted parameter. So in the definition
79 * %define a(x,y) ( (x) & ~(y) )
81 * the token representing `x' will have its type changed to
82 * TOK_SMAC_PARAM, but the one representing `y' will be
85 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
86 * which doesn't need quotes around it. Used in the pre-include
87 * mechanism as an alternative to trying to find a sensible type of
88 * quote to use on the filename we were passed.
93 SMacro
*mac
; /* associated macro for TOK_MAC_END */
97 TOK_WHITESPACE
= 1, TOK_COMMENT
, TOK_ID
, TOK_PREPROC_ID
, TOK_STRING
,
98 TOK_NUMBER
, TOK_SMAC_END
, TOK_OTHER
, TOK_PS_OTHER
, TOK_SMAC_PARAM
,
103 * Multi-line macro definitions are stored as a linked list of
104 * these, which is essentially a container to allow several linked
107 * Note that in this module, linked lists are treated as stacks
108 * wherever possible. For this reason, Lines are _pushed_ on to the
109 * `expansion' field in MMacro structures, so that the linked list,
110 * if walked, would give the macro lines in reverse order; this
111 * means that we can walk the list when expanding a macro, and thus
112 * push the lines on to the `expansion' field in _istk_ in reverse
113 * order (so that when popped back off they are in the right
114 * order). It may seem cockeyed, and it relies on my design having
115 * an even number of steps in, but it works...
117 * Some of these structures, rather than being actual lines, are
118 * markers delimiting the end of the expansion of a given macro.
119 * This is for use in the cycle-tracking code. Such structures have
120 * `finishes' non-NULL, and `first' NULL. All others have
121 * `finishes' NULL, but `first' may still be NULL if the line is
131 * To handle an arbitrary level of file inclusion, we maintain a
132 * stack (ie linked list) of these things.
144 * Include search path. This is simply a list of strings which get
145 * prepended, in turn, to the name of an include file, in an
146 * attempt to find the file if it's not in the current directory.
154 * Conditional assembly: we maintain a separate stack of these for
155 * each level of file inclusion. (The only reason we keep the
156 * stacks separate is to ensure that a stray `%endif' in a file
157 * included from within the true branch of a `%if' won't terminate
158 * it and cause confusion: instead, rightly, it'll cause an error.)
166 * These states are for use just after %if or %elif: IF_TRUE
167 * means the condition has evaluated to truth so we are
168 * currently emitting, whereas IF_FALSE means we are not
169 * currently emitting but will start doing so if a %else comes
170 * up. In these states, all directives are admissible: %elif,
171 * %else and %endif. (And of course %if.)
173 COND_IF_TRUE
, COND_IF_FALSE
,
175 * These states come up after a %else: ELSE_TRUE means we're
176 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
177 * any %elif or %else will cause an error.
179 COND_ELSE_TRUE
, COND_ELSE_FALSE
,
181 * This state means that we're not emitting now, and also that
182 * nothing until %endif will be emitted at all. It's for use in
183 * two circumstances: (i) when we've had our moment of emission
184 * and have now started seeing %elifs, and (ii) when the
185 * condition construct in question is contained within a
186 * non-emitting branch of a larger condition construct.
190 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
193 * Condition codes. Note that we use c_ prefix not C_ because C_ is
194 * used in nasm.h for the "real" condition codes. At _this_ level,
195 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
196 * ones, so we need a different enum...
198 static char *conditions
[] = {
199 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
200 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
201 "np", "ns", "nz", "o", "p", "pe", "po", "s", "z"
204 c_A
, c_AE
, c_B
, c_BE
, c_C
, c_CXZ
, c_E
, c_ECXZ
, c_G
, c_GE
, c_L
, c_LE
,
205 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, c_NE
, c_NG
, c_NGE
, c_NL
, c_NLE
, c_NO
,
206 c_NP
, c_NS
, c_NZ
, c_O
, c_P
, c_PE
, c_PO
, c_S
, c_Z
208 static int inverse_ccs
[] = {
209 c_NA
, c_NAE
, c_NB
, c_NBE
, c_NC
, -1, c_NE
, -1, c_NG
, c_NGE
, c_NL
, c_NLE
,
210 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
,
211 c_Z
, c_NO
, c_NP
, c_PO
, c_PE
, c_NS
, c_NZ
214 static Context
*cstk
;
215 static Include
*istk
;
216 static IncPath
*ipath
= NULL
;
220 static unsigned long unique
; /* unique identifier numbers */
222 static char *linesync
, *outline
;
224 static Line
*predef
= NULL
;
226 static ListGen
*list
;
229 * The number of hash values we use for the macro lookup tables.
234 * The current set of multi-line macros we have defined.
236 static MMacro
*mmacros
[NHASH
];
239 * The current set of single-line macros we have defined.
241 static SMacro
*smacros
[NHASH
];
244 * The multi-line macro we are currently defining, if any.
246 static MMacro
*defining
;
249 * The number of macro parameters to allocate space for at a time.
251 #define PARAM_DELTA 16
254 * The standard macro set: defined as `static char *stdmac[]'. Also
255 * gives our position in the macro set, when we're processing it.
258 static char **stdmacpos
;
261 * The pre-preprocessing stage... This function translates line
262 * number indications as they emerge from GNU cpp (`# lineno "file"
263 * flags') into NASM preprocessor line number indications (`%line
266 static char *prepreproc(char *line
) {
268 char *fname
, *oldline
;
270 if (line
[0] == '#' && line
[1] == ' ') {
273 lineno
= atoi(fname
);
274 fname
+= strspn(fname
, "0123456789 ");
277 fnlen
= strcspn(fname
, "\"");
278 line
= nasm_malloc(20+fnlen
);
279 sprintf(line
, "%%line %d %.*s", lineno
, fnlen
, fname
);
286 * The hash function for macro lookups. Note that due to some
287 * macros having case-insensitive names, the hash function must be
288 * invariant under case changes. We implement this by applying a
289 * perfectly normal hash function to the uppercase of the string.
291 static int hash(char *s
) {
293 * Powers of three, mod 31.
295 static const int multipliers
[] = {
296 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10,
297 30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21
303 h
+= multipliers
[i
] * (unsigned char) (toupper(*s
));
305 if (++i
>= sizeof(multipliers
)/sizeof(*multipliers
))
313 * Free a linked list of tokens.
315 static void free_tlist (Token
*list
) {
326 * Free a linked list of lines.
328 static void free_llist (Line
*list
) {
333 free_tlist (l
->first
);
339 * Pop the context stack.
341 static void ctx_pop (void) {
351 free_tlist (s
->expansion
);
359 * Generate a line synchronisation comment, to ensure the assembler
360 * knows which source file the current output has really come from.
362 static void line_sync (void) {
364 sprintf(text
, "%%line %d+%d %s",
365 (istk
->expansion
? istk
->lineno
- istk
->lineinc
: istk
->lineno
),
366 (istk
->expansion
? 0 : istk
->lineinc
), istk
->fname
);
369 linesync
= nasm_strdup(text
);
372 #define BUF_DELTA 512
374 * Read a line from the top file in istk, handling multiple CR/LFs
375 * at the end of the line read, and handling spurious ^Zs. Will
376 * return lines from the standard macro set if this has not already
379 static char *read_line (void) {
380 char *buffer
, *p
, *q
;
385 char *ret
= nasm_strdup(*stdmacpos
++);
387 * Nasty hack: here we push the contents of `predef' on
388 * to the top-level expansion stack, since this is the
389 * most convenient way to implement the pre-include and
390 * pre-define features.
394 Token
*head
, **tail
, *t
, *tt
;
396 for (pd
= predef
; pd
; pd
= pd
->next
) {
399 for (t
= pd
->first
; t
; t
= t
->next
) {
400 tt
= *tail
= nasm_malloc(sizeof(Token
));
404 tt
->text
= nasm_strdup(t
->text
);
405 tt
->mac
= t
->mac
; /* always NULL here, in fact */
407 l
= nasm_malloc(sizeof(Line
));
408 l
->next
= istk
->expansion
;
422 buffer
= nasm_malloc(BUF_DELTA
);
425 q
= fgets(p
, bufsize
-(p
-buffer
), istk
->fp
);
429 if (p
> buffer
&& p
[-1] == '\n') {
430 istk
->lineno
+= istk
->lineinc
;
433 if (p
-buffer
> bufsize
-10) {
434 bufsize
+= BUF_DELTA
;
435 buffer
= nasm_realloc(buffer
, bufsize
);
439 if (!q
&& p
== buffer
) {
445 * Play safe: remove CRs as well as LFs, if any of either are
446 * present at the end of the line.
448 while (p
> buffer
&& (p
[-1] == '\n' || p
[-1] == '\r'))
452 * Handle spurious ^Z, which may be inserted into source files
453 * by some file transfer utilities.
455 buffer
[strcspn(buffer
, "\032")] = '\0';
457 list
->line (LIST_READ
, buffer
);
463 * Tokenise a line of text. This is a very simple process since we
464 * don't need to parse the value out of e.g. numeric tokens: we
465 * simply split one string into many.
467 static Token
*tokenise (char *line
) {
471 Token
*t
, **tail
= &list
;
476 (p
[1] == '{' || p
[1] == '!' || (p
[1] == '%' && isidchar(p
[2])) ||
477 p
[1] == '$' || p
[1] == '+' || p
[1] == '-' || isidchar(p
[1]))) {
478 type
= TOK_PREPROC_ID
;
482 while (*p
&& *p
!= '}') {
489 if (*p
== '!' || *p
== '%' || *p
== '$' ||
490 *p
== '+' || *p
== '-') p
++;
491 while (*p
&& isidchar(*p
))
494 } else if (isidstart(*p
)) {
497 while (*p
&& isidchar(*p
))
499 } else if (*p
== '\'' || *p
== '"') {
506 while (*p
&& *p
!= c
)
509 } else if (isnumstart(*p
)) {
515 while (*p
&& isnumchar(*p
))
517 } else if (isspace(*p
)) {
518 type
= TOK_WHITESPACE
;
520 while (*p
&& isspace(*p
))
523 * Whitespace just before end-of-line is discarded by
524 * pretending it's a comment; whitespace just before a
525 * comment gets lumped into the comment.
527 if (!*p
|| *p
== ';') {
531 } else if (*p
== ';') {
536 * Anything else is an operator of some kind; with the
537 * exceptions of >>, <<, // and %%, all operator tokens
538 * are single-character.
542 if ( (c
== '>' || c
== '<' || c
== '/' || c
== '%') && *p
== c
)
545 if (type
!= TOK_COMMENT
) {
546 *tail
= t
= nasm_malloc (sizeof(Token
));
550 t
->text
= nasm_malloc(1+p
-line
);
551 strncpy(t
->text
, line
, p
-line
);
552 t
->text
[p
-line
] = '\0';
561 * Convert a line of tokens back into text.
563 static char *detoken (Token
*tlist
) {
569 for (t
= tlist
; t
; t
= t
->next
) {
570 if (t
->type
== TOK_PREPROC_ID
&& t
->text
[1] == '!') {
571 char *p
= getenv(t
->text
+2);
574 t
->text
= nasm_strdup(p
);
579 len
+= strlen(t
->text
);
581 p
= line
= nasm_malloc(len
+1);
582 for (t
= tlist
; t
; t
= t
->next
) {
593 * Return the Context structure associated with a %$ token. Return
594 * NULL, having _already_ reported an error condition, if the
595 * context stack isn't deep enough for the supplied number of $
598 static Context
*get_ctx (char *name
) {
603 error (ERR_NONFATAL
|ERR_OFFBY1
, "`%s': context stack is empty", name
);
609 while (name
[i
+1] == '$') {
613 error (ERR_NONFATAL
|ERR_OFFBY1
, "`%s': context stack is only"
614 " %d level%s deep", name
, i
-1, (i
==2 ? "" : "s"));
622 * Compare a string to the name of an existing macro; this is a
623 * simple wrapper which calls either strcmp or nasm_stricmp
624 * depending on the value of the `casesense' parameter.
626 static int mstrcmp(char *p
, char *q
, int casesense
) {
627 return casesense
? strcmp(p
,q
) : nasm_stricmp(p
,q
);
631 * Open an include file. This routine must always return a valid
632 * file pointer if it returns - it's responsible for throwing an
633 * ERR_FATAL and bombing out completely if not. It should also try
634 * the include path one by one until it finds the file or reaches
635 * the end of the path.
637 static FILE *inc_fopen(char *file
) {
639 char *prefix
= "", *combine
;
641 int len
= strlen(file
);
644 combine
= nasm_malloc(strlen(prefix
)+len
+1);
645 strcpy(combine
, prefix
);
646 strcat(combine
, file
);
647 fp
= fopen(combine
, "r");
651 prefix
= ip
? ip
->path
: NULL
;
656 error (ERR_FATAL
|ERR_OFFBY1
,
657 "unable to open include file `%s'", file
);
658 return NULL
; /* never reached - placate compilers */
662 * Determine if we should warn on defining a single-line macro of
663 * name `name', with `nparam' parameters. If nparam is 0, will
664 * return TRUE if _any_ single-line macro of that name is defined.
665 * Otherwise, will return TRUE if a single-line macro with either
666 * `nparam' or no parameters is defined.
668 * If a macro with precisely the right number of parameters is
669 * defined, the address of the definition structure will be
670 * returned in `defn'; otherwise NULL will be returned. If `defn'
671 * is NULL, no action will be taken regarding its contents, and no
674 * Note that this is also called with nparam zero to resolve
677 static int smacro_defined (char *name
, int nparam
, SMacro
**defn
) {
682 if (name
[0] == '%' && name
[1] == '$') {
683 ctx
= get_ctx (name
);
685 return FALSE
; /* got to return _something_ */
690 m
= smacros
[hash(name
)];
695 if (!mstrcmp(m
->name
, p
, m
->casesense
) &&
696 (nparam
== 0 || m
->nparam
== 0 || nparam
== m
->nparam
)) {
698 if (nparam
== m
->nparam
)
711 * Count and mark off the parameters in a multi-line macro call.
712 * This is called both from within the multi-line macro expansion
713 * code, and also to mark off the default parameters when provided
714 * in a %macro definition line.
716 static void count_mmac_params (Token
*t
, int *nparam
, Token
***params
) {
717 int paramsize
, brace
;
719 *nparam
= paramsize
= 0;
722 if (*nparam
>= paramsize
) {
723 paramsize
+= PARAM_DELTA
;
724 *params
= nasm_realloc(*params
, sizeof(**params
) * paramsize
);
726 if (t
&& t
->type
== TOK_WHITESPACE
)
729 if (t
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "{"))
731 (*params
)[(*nparam
)++] = t
;
732 while (t
&& (t
->type
!= TOK_OTHER
||
733 strcmp(t
->text
, brace
? "}" : ",")))
735 if (t
) { /* got a comma/brace */
739 * Now we've found the closing brace, look further
742 if (t
&& t
->type
== TOK_WHITESPACE
)
744 if (t
&& (t
->type
!= TOK_OTHER
|| strcmp(t
->text
, ","))) {
745 error (ERR_NONFATAL
|ERR_OFFBY1
,
746 "braces do not enclose all of macro parameter");
747 while (t
&& (t
->type
!= TOK_OTHER
||
748 strcmp(t
->text
, ",")))
752 t
= t
->next
; /* eat the comma */
761 * Find out if a line contains a preprocessor directive, and deal
764 * If a directive _is_ found, the line will never be de-tokenised
765 * as is, so we have carte blanche to fiddle with it and adjust
768 * Return values go like this:
770 * bit 0 is set if a directive was found
771 * bit 1 is set if a blank line should be emitted
772 * bit 2 is set if a re-sync line number comment should be emitted
774 * (bits 1 and 2 are mutually exclusive in that the rest of the
775 * preprocessor doesn't guarantee to be able to handle the case in
776 * which both are set)
778 static int do_directive (Token
*tline
) {
779 static char *directives
[] = {
780 "%clear", "%define", "%elifctx", "%elifdef", "%elifnctx",
781 "%elifndef", "%else", "%endif", "%endm", "%endmacro", "%error",
782 "%idefine", "%ifctx", "%ifdef", "%ifnctx", "%ifndef", "%imacro",
783 "%include", "%line", "%macro", "%pop", "%push", "%repl"
786 PP_CLEAR
, PP_DEFINE
, PP_ELIFCTX
, PP_ELIFDEF
, PP_ELIFNCTX
,
787 PP_ELIFNDEF
, PP_ELSE
, PP_ENDIF
, PP_ENDM
, PP_ENDMACRO
, PP_ERROR
,
788 PP_IDEFINE
, PP_IFCTX
, PP_IFDEF
, PP_IFNCTX
, PP_IFNDEF
, PP_IMACRO
,
789 PP_INCLUDE
, PP_LINE
, PP_MACRO
, PP_POP
, PP_PUSH
, PP_REPL
791 int i
, j
, k
, m
, nparam
;
796 SMacro
*smac
, **smhead
;
798 Token
*t
, *tt
, *param_start
, *macro_start
, *last
;
800 if (tline
&& tline
->type
== TOK_WHITESPACE
)
802 if (!tline
|| tline
->type
!= TOK_PREPROC_ID
||
803 (tline
->text
[1]=='%' || tline
->text
[1]=='$' || tline
->text
[1]=='!'))
807 j
= sizeof(directives
)/sizeof(*directives
);
810 m
= nasm_stricmp(tline
->text
, directives
[k
]);
822 * If we're in a non-emitting branch of a condition construct,
823 * we should ignore all directives except for condition
826 if (istk
->conds
&& !emitting(istk
->conds
->state
) &&
827 i
!= PP_IFCTX
&& i
!= PP_IFDEF
&& i
!= PP_IFNCTX
&& i
!= PP_IFNDEF
&&
828 i
!=PP_ELIFCTX
&& i
!=PP_ELIFDEF
&& i
!=PP_ELIFNCTX
&& i
!=PP_ELIFNDEF
&&
829 i
!= PP_ELSE
&& i
!= PP_ENDIF
)
833 * If we're defining a macro, we should ignore all directives
834 * except for %macro/%imacro (which generate an error) and
837 if (defining
&& i
!= PP_MACRO
&& i
!= PP_IMACRO
&&
838 i
!= PP_ENDMACRO
&& i
!= PP_ENDM
)
842 error(ERR_NONFATAL
|ERR_OFFBY1
, "unknown preprocessor directive `%s'",
844 return 0; /* didn't get it */
851 error(ERR_WARNING
|ERR_OFFBY1
,
852 "trailing garbage after `%%clear' ignored");
853 for (j
=0; j
<NHASH
; j
++) {
855 MMacro
*m
= mmacros
[j
];
856 mmacros
[j
] = mmacros
[j
]->next
;
858 free_tlist (m
->dlist
);
859 free_llist (m
->expansion
);
863 SMacro
*s
= smacros
[j
];
864 smacros
[j
] = smacros
[j
]->next
;
866 free_tlist (s
->expansion
);
874 if (tline
&& tline
->type
== TOK_WHITESPACE
)
876 if (!tline
|| (tline
->type
!= TOK_STRING
&&
877 tline
->type
!= TOK_INTERNAL_STRING
)) {
878 error(ERR_NONFATAL
|ERR_OFFBY1
, "`%%include' expects a file name");
879 return 3; /* but we did _something_ */
882 error(ERR_WARNING
|ERR_OFFBY1
,
883 "trailing garbage after `%%include' ignored");
884 if (tline
->type
!= TOK_INTERNAL_STRING
) {
885 p
= tline
->text
+1; /* point past the quote to the name */
886 p
[strlen(p
)-1] = '\0'; /* remove the trailing quote */
888 p
= tline
->text
; /* internal_string is easier */
889 inc
= nasm_malloc(sizeof(Include
));
892 inc
->fp
= inc_fopen(p
);
893 inc
->fname
= nasm_strdup(p
);
894 inc
->lineno
= inc
->lineinc
= 1;
895 inc
->expansion
= NULL
;
897 list
->uplevel (LIST_INCLUDE
);
902 if (tline
&& tline
->type
== TOK_WHITESPACE
)
904 if (!tline
|| tline
->type
!= TOK_ID
) {
905 error(ERR_NONFATAL
|ERR_OFFBY1
,
906 "`%%push' expects a context identifier");
907 return 3; /* but we did _something_ */
910 error(ERR_WARNING
|ERR_OFFBY1
,
911 "trailing garbage after `%%push' ignored");
912 ctx
= nasm_malloc(sizeof(Context
));
914 ctx
->localmac
= NULL
;
915 ctx
->name
= nasm_strdup(tline
->text
);
916 ctx
->number
= unique
++;
922 if (tline
&& tline
->type
== TOK_WHITESPACE
)
924 if (!tline
|| tline
->type
!= TOK_ID
) {
925 error(ERR_NONFATAL
|ERR_OFFBY1
,
926 "`%%repl' expects a context identifier");
927 return 3; /* but we did _something_ */
930 error(ERR_WARNING
|ERR_OFFBY1
,
931 "trailing garbage after `%%repl' ignored");
933 error(ERR_NONFATAL
|ERR_OFFBY1
,
934 "`%%repl': context stack is empty");
936 nasm_free (cstk
->name
);
937 cstk
->name
= nasm_strdup(tline
->text
);
943 error(ERR_WARNING
|ERR_OFFBY1
,
944 "trailing garbage after `%%pop' ignored");
946 error(ERR_NONFATAL
|ERR_OFFBY1
,
947 "`%%pop': context stack is already empty");
954 if (tline
&& tline
->type
== TOK_WHITESPACE
)
956 if (!tline
|| tline
->type
!= TOK_STRING
) {
957 error(ERR_NONFATAL
|ERR_OFFBY1
,
958 "`%%error' expects an error string");
959 return 3; /* but we did _something_ */
962 error(ERR_WARNING
|ERR_OFFBY1
,
963 "trailing garbage after `%%error' ignored");
964 p
= tline
->text
+1; /* point past the quote to the name */
965 p
[strlen(p
)-1] = '\0'; /* remove the trailing quote */
966 error(ERR_NONFATAL
|ERR_OFFBY1
, "user error: %s", p
);
972 if (istk
->conds
&& !emitting(istk
->conds
->state
))
975 j
= FALSE
; /* have we matched yet? */
977 error(ERR_FATAL
|ERR_OFFBY1
,
978 "`%%if%sctx': context stack is empty",
979 (i
==PP_IFNCTX
? "n" : ""));
981 if (tline
->type
== TOK_WHITESPACE
)
983 if (!tline
|| tline
->type
!= TOK_ID
) {
984 error(ERR_NONFATAL
|ERR_OFFBY1
,
985 "`%%ifctx' expects context identifiers");
986 return 3; /* but we did _something_ */
988 if (!nasm_stricmp(tline
->text
, cstk
->name
))
994 j
= (j
? COND_IF_TRUE
: COND_IF_FALSE
);
996 cond
= nasm_malloc(sizeof(Cond
));
997 cond
->next
= istk
->conds
;
1004 tline
= tline
->next
;
1006 error(ERR_FATAL
|ERR_OFFBY1
, "`%%elif%sctx': no matching `%%if'",
1007 (i
==PP_ELIFNCTX
? "n" : ""));
1008 if (emitting(istk
->conds
->state
) || istk
->conds
->state
== COND_NEVER
)
1009 istk
->conds
->state
= COND_NEVER
;
1011 j
= FALSE
; /* have we matched yet? */
1013 error(ERR_FATAL
|ERR_OFFBY1
,
1014 "`%%elif%sctx': context stack is empty",
1015 (i
==PP_ELIFNCTX
? "n" : ""));
1016 else while (tline
) {
1017 if (tline
->type
== TOK_WHITESPACE
)
1018 tline
= tline
->next
;
1019 if (!tline
|| tline
->type
!= TOK_ID
) {
1020 error(ERR_NONFATAL
|ERR_OFFBY1
,
1021 "`%%elif%sctx' expects context identifiers",
1022 (i
==PP_ELIFNCTX
? "n" : ""));
1023 return 3; /* but we did _something_ */
1025 if (!nasm_stricmp(tline
->text
, cstk
->name
))
1027 tline
= tline
->next
;
1029 if (i
== PP_ELIFNCTX
)
1031 istk
->conds
->state
= (j
? COND_IF_TRUE
: COND_IF_FALSE
);
1037 tline
= tline
->next
;
1038 if (istk
->conds
&& !emitting(istk
->conds
->state
))
1041 j
= FALSE
; /* have we matched yet? */
1043 if (tline
->type
== TOK_WHITESPACE
)
1044 tline
= tline
->next
;
1045 if (!tline
|| (tline
->type
!= TOK_ID
&&
1046 (tline
->type
!= TOK_PREPROC_ID
||
1047 tline
->text
[1] != '$'))) {
1048 error(ERR_NONFATAL
|ERR_OFFBY1
,
1049 "`%%if%sdef' expects macro identifiers",
1050 (i
==PP_ELIFNDEF
? "n" : ""));
1051 return 3; /* but we did _something_ */
1053 if (smacro_defined(tline
->text
, 0, NULL
))
1055 tline
= tline
->next
;
1059 j
= (j
? COND_IF_TRUE
: COND_IF_FALSE
);
1061 cond
= nasm_malloc(sizeof(Cond
));
1062 cond
->next
= istk
->conds
;
1069 tline
= tline
->next
;
1071 error(ERR_FATAL
|ERR_OFFBY1
, "`%%elif%sctx': no matching `%%if'",
1072 (i
==PP_ELIFNCTX
? "n" : ""));
1073 if (emitting(istk
->conds
->state
) || istk
->conds
->state
== COND_NEVER
)
1074 istk
->conds
->state
= COND_NEVER
;
1076 j
= FALSE
; /* have we matched yet? */
1078 if (tline
->type
== TOK_WHITESPACE
)
1079 tline
= tline
->next
;
1080 if (!tline
|| (tline
->type
!= TOK_ID
&&
1081 (tline
->type
!= TOK_PREPROC_ID
||
1082 tline
->text
[1] != '$'))) {
1083 error(ERR_NONFATAL
|ERR_OFFBY1
,
1084 "`%%elif%sdef' expects macro identifiers",
1085 (i
==PP_ELIFNDEF
? "n" : ""));
1086 return 3; /* but we did _something_ */
1088 if (smacro_defined(tline
->text
, 0, NULL
))
1090 tline
= tline
->next
;
1092 if (i
== PP_ELIFNDEF
)
1094 istk
->conds
->state
= (j
? COND_IF_TRUE
: COND_IF_FALSE
);
1100 error(ERR_WARNING
|ERR_OFFBY1
,
1101 "trailing garbage after `%%else' ignored");
1103 error(ERR_FATAL
|ERR_OFFBY1
,
1104 "`%%else': no matching `%%if'");
1105 if (emitting(istk
->conds
->state
) || istk
->conds
->state
== COND_NEVER
)
1106 istk
->conds
->state
= COND_ELSE_FALSE
;
1108 istk
->conds
->state
= COND_ELSE_TRUE
;
1113 error(ERR_WARNING
|ERR_OFFBY1
,
1114 "trailing garbage after `%%endif' ignored");
1116 error(ERR_FATAL
|ERR_OFFBY1
,
1117 "`%%endif': no matching `%%if'");
1119 istk
->conds
= cond
->next
;
1126 error (ERR_FATAL
|ERR_OFFBY1
,
1127 "`%%%smacro': already defining a macro",
1128 (i
== PP_IMACRO
? "i" : ""));
1129 tline
= tline
->next
;
1130 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1131 tline
= tline
->next
;
1132 if (!tline
|| tline
->type
!= TOK_ID
) {
1133 error (ERR_NONFATAL
|ERR_OFFBY1
,
1134 "`%%%smacro' expects a macro name",
1135 (i
== PP_IMACRO
? "i" : ""));
1138 defining
= nasm_malloc(sizeof(MMacro
));
1139 defining
->name
= nasm_strdup(tline
->text
);
1140 defining
->casesense
= (i
== PP_MACRO
);
1141 defining
->plus
= FALSE
;
1142 defining
->nolist
= FALSE
;
1143 defining
->in_progress
= FALSE
;
1144 tline
= tline
->next
;
1145 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1146 tline
= tline
->next
;
1147 if (!tline
|| tline
->type
!= TOK_NUMBER
) {
1148 error (ERR_NONFATAL
|ERR_OFFBY1
,
1149 "`%%%smacro' expects a parameter count",
1150 (i
== PP_IMACRO
? "i" : ""));
1151 defining
->nparam_min
= defining
->nparam_max
= 0;
1153 defining
->nparam_min
= defining
->nparam_max
=
1154 readnum(tline
->text
, &j
);
1156 error (ERR_NONFATAL
|ERR_OFFBY1
,
1157 "unable to parse parameter count `%s'", tline
->text
);
1159 if (tline
&& tline
->next
&& tline
->next
->type
== TOK_OTHER
&&
1160 !strcmp(tline
->next
->text
, "-")) {
1161 tline
= tline
->next
->next
;
1162 if (!tline
|| tline
->type
!= TOK_NUMBER
)
1163 error (ERR_NONFATAL
|ERR_OFFBY1
,
1164 "`%%%smacro' expects a parameter count after `-'",
1165 (i
== PP_IMACRO
? "i" : ""));
1167 defining
->nparam_max
= readnum(tline
->text
, &j
);
1169 error (ERR_NONFATAL
|ERR_OFFBY1
,
1170 "unable to parse parameter count `%s'",
1172 if (defining
->nparam_min
> defining
->nparam_max
)
1173 error (ERR_NONFATAL
|ERR_OFFBY1
,
1174 "minimum parameter count exceeds maximum");
1177 if (tline
&& tline
->next
&& tline
->next
->type
== TOK_OTHER
&&
1178 !strcmp(tline
->next
->text
, "+")) {
1179 tline
= tline
->next
;
1180 defining
->plus
= TRUE
;
1182 if (tline
&& tline
->next
&& tline
->next
->type
== TOK_ID
&&
1183 !nasm_stricmp(tline
->next
->text
, ".nolist")) {
1184 tline
= tline
->next
;
1185 defining
->nolist
= TRUE
;
1187 mmac
= mmacros
[hash(defining
->name
)];
1189 if (!strcmp(mmac
->name
, defining
->name
) &&
1190 (mmac
->nparam_min
<=defining
->nparam_max
|| defining
->plus
) &&
1191 (defining
->nparam_min
<=mmac
->nparam_max
|| mmac
->plus
)) {
1192 error (ERR_WARNING
|ERR_OFFBY1
,
1193 "redefining multi-line macro `%s'", defining
->name
);
1199 * Handle default parameters.
1201 if (tline
&& tline
->next
) {
1204 defining
->dlist
= tline
->next
;
1206 count_mmac_params (defining
->dlist
, &np
, &defining
->defaults
);
1207 want_np
= defining
->nparam_max
- defining
->nparam_min
;
1208 defining
->defaults
= nasm_realloc (defining
->defaults
,
1209 want_np
*sizeof(Token
*));
1210 while (np
< want_np
)
1211 defining
->defaults
[np
++] = NULL
;
1213 defining
->dlist
= NULL
;
1214 defining
->defaults
= NULL
;
1216 defining
->expansion
= NULL
;
1222 error (ERR_NONFATAL
|ERR_OFFBY1
, "`%s': not defining a macro",
1226 k
= hash(defining
->name
);
1227 defining
->next
= mmacros
[k
];
1228 mmacros
[k
] = defining
;
1234 tline
= tline
->next
;
1235 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1236 tline
= tline
->next
;
1237 if (!tline
|| (tline
->type
!= TOK_ID
&&
1238 (tline
->type
!= TOK_PREPROC_ID
||
1239 tline
->text
[1] != '$'))) {
1240 error (ERR_NONFATAL
|ERR_OFFBY1
,
1241 "`%%%sdefine' expects a macro identifier",
1242 (i
== PP_IDEFINE
? "i" : ""));
1245 mname
= tline
->text
;
1246 if (tline
->type
== TOK_ID
) {
1248 smhead
= &smacros
[hash(mname
)];
1250 ctx
= get_ctx (tline
->text
);
1255 p
+= strspn(p
, "$");
1256 smhead
= &ctx
->localmac
;
1260 param_start
= tline
= tline
->next
;
1262 if (tline
&& tline
->type
== TOK_OTHER
&& !strcmp(tline
->text
, "(")) {
1264 * This macro has parameters.
1267 tline
= tline
->next
;
1269 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1270 tline
= tline
->next
;
1272 error (ERR_NONFATAL
|ERR_OFFBY1
,
1273 "parameter identifier expected");
1276 if (tline
->type
!= TOK_ID
) {
1277 error (ERR_NONFATAL
|ERR_OFFBY1
,
1278 "`%s': parameter identifier expected",
1282 tline
->type
= TOK_SMAC_PARAM
+ nparam
++;
1283 tline
= tline
->next
;
1284 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1285 tline
= tline
->next
;
1286 if (tline
&& tline
->type
== TOK_OTHER
&&
1287 !strcmp(tline
->text
, ",")) {
1288 tline
= tline
->next
;
1291 if (!tline
|| tline
->type
!= TOK_OTHER
||
1292 strcmp(tline
->text
, ")")) {
1293 error (ERR_NONFATAL
|ERR_OFFBY1
,
1294 "`)' expected to terminate macro template");
1300 tline
= tline
->next
;
1302 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1303 last
= tline
, tline
= tline
->next
;
1308 if (t
->type
== TOK_ID
) {
1309 for (tt
= param_start
; tt
; tt
= tt
->next
)
1310 if (tt
->type
>= TOK_SMAC_PARAM
&&
1311 !strcmp(tt
->text
, t
->text
))
1315 t
->next
= macro_start
;
1320 * Good. We now have a macro name, a parameter count, and a
1321 * token list (in reverse order) for an expansion. We ought
1322 * to be OK just to create an SMacro, store it, and let
1323 * free_tlist have the rest of the line (which we have
1324 * carefully re-terminated after chopping off the expansion
1327 if (smacro_defined (mname
, nparam
, &smac
)) {
1329 error (ERR_WARNING
|ERR_OFFBY1
,
1330 "single-line macro `%s' defined both with and"
1331 " without parameters", mname
);
1334 * We're redefining, so we have to take over an
1335 * existing SMacro structure. This means freeing
1336 * what was already in it.
1338 nasm_free (smac
->name
);
1339 free_tlist (smac
->expansion
);
1342 smac
= nasm_malloc(sizeof(SMacro
));
1343 smac
->next
= *smhead
;
1346 smac
->name
= nasm_strdup(p
);
1347 smac
->casesense
= (i
== PP_DEFINE
);
1348 smac
->nparam
= nparam
;
1349 smac
->expansion
= macro_start
;
1350 smac
->in_progress
= FALSE
;
1355 * Syntax is `%line nnn[+mmm] [filename]'
1357 tline
= tline
->next
;
1358 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1359 tline
= tline
->next
;
1360 if (!tline
|| tline
->type
!= TOK_NUMBER
) {
1361 error (ERR_NONFATAL
|ERR_OFFBY1
, "`%%line' expects line number");
1364 k
= readnum(tline
->text
, &j
);
1366 tline
= tline
->next
;
1367 if (tline
&& tline
->type
== TOK_OTHER
&& !strcmp(tline
->text
, "+")) {
1368 tline
= tline
->next
;
1369 if (!tline
|| tline
->type
!= TOK_NUMBER
) {
1370 error (ERR_NONFATAL
|ERR_OFFBY1
,
1371 "`%%line' expects line increment");
1374 m
= readnum(tline
->text
, &j
);
1375 tline
= tline
->next
;
1377 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1378 tline
= tline
->next
;
1382 char *s
= detoken(tline
);
1383 nasm_free (istk
->fname
);
1389 error(ERR_FATAL
|ERR_OFFBY1
,
1390 "preprocessor directive `%s' not yet implemented",
1398 * Expand all single-line macro calls made in the given line.
1399 * Return the expanded version of the line. The original is deemed
1400 * to be destroyed in the process. (In reality we'll just move
1401 * Tokens from input to output a lot of the time, rather than
1402 * actually bothering to destroy and replicate.)
1404 static Token
*expand_smacro (Token
*tline
) {
1405 Token
*t
, *tt
, *mstart
, **tail
, *thead
;
1409 int nparam
, sparam
, brackets
;
1416 while (tline
&& tline
->type
!= TOK_ID
&&
1417 (tline
->type
!= TOK_PREPROC_ID
|| tline
->text
[1] != '$')) {
1418 if (tline
->type
== TOK_SMAC_END
) {
1419 tline
->mac
->in_progress
= FALSE
;
1421 tline
= tline
->next
;
1425 tline
= tline
->next
;
1429 if (t
->type
== TOK_PS_OTHER
) {
1431 * If we see a PS_OTHER, we must at the very
1432 * least restore its correct token type. We
1433 * should also check for a %$ token, since this
1434 * is the point at which we expand context-
1438 if (t
->text
[0] == '%' && t
->text
[1] == '$') {
1439 Context
*c
= get_ctx (t
->text
);
1440 char *p
, *q
, buffer
[40];
1444 q
+= strspn(q
, "$");
1445 sprintf(buffer
, "..@%lu.", c
->number
);
1446 p
= nasm_malloc (strlen(buffer
)+strlen(q
)+1);
1449 nasm_free (t
->text
);
1459 * We've hit an identifier. As in is_mmacro below, we first
1460 * check whether the identifier is a single-line macro at
1461 * all, then think about checking for parameters if
1464 if (tline
->type
== TOK_ID
) {
1465 head
= smacros
[hash(tline
->text
)];
1468 Context
*ctx
= get_ctx (tline
->text
);
1471 p
+= strspn(p
, "$");
1472 head
= ctx
->localmac
;
1474 tline
->type
= TOK_OTHER
; /* so it will get copied above */
1478 for (m
= head
; m
; m
= m
->next
)
1479 if (!mstrcmp(m
->name
, p
, m
->casesense
))
1481 if (!m
|| m
->in_progress
) {
1483 * Either we didn't find a macro, so this can't be a
1484 * macro call, or we found a macro which was already in
1485 * progress, in which case we don't _treat_ this as a
1486 * macro call. Copy it through and ignore it.
1488 tline
->type
= TOK_PS_OTHER
; /* so it will get copied above */
1492 if (m
->nparam
== 0) {
1494 * Simple case: the macro is parameterless. Discard the
1495 * one token that the macro call took, and push the
1496 * expansion back on the to-do stack.
1502 * Complicated case: at least one macro with this name
1503 * exists and takes parameters. We must find the
1504 * parameters in the call, count them, find the SMacro
1505 * that corresponds to that form of the macro call, and
1506 * substitute for the parameters when we expand. What a
1509 nparam
= sparam
= 0;
1512 tline
= tline
->next
;
1513 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1514 tline
= tline
->next
;
1515 if (!tline
|| tline
->type
!= TOK_OTHER
||
1516 strcmp(tline
->text
, "(")) {
1518 * This macro wasn't called with parameters: ignore
1519 * the call. (Behaviour borrowed from gnu cpp.)
1522 tline
->type
= TOK_PS_OTHER
;
1525 tline
= tline
->next
;
1527 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1528 tline
= tline
->next
;
1530 error(ERR_NONFATAL
|ERR_OFFBY1
,
1531 "macro call expects terminating `)'");
1534 if (nparam
>= sparam
) {
1535 sparam
+= PARAM_DELTA
;
1536 params
= nasm_realloc (params
, sparam
*sizeof(Token
*));
1537 paramsize
= nasm_realloc (paramsize
, sparam
*sizeof(int));
1539 params
[nparam
] = tline
;
1540 paramsize
[nparam
] = 0;
1542 if (tline
&& tline
->type
== TOK_OTHER
&&
1543 !strcmp(tline
->text
, "{")) {
1544 params
[nparam
] = tline
= tline
->next
;
1545 while (tline
&& (brackets
> 0 ||
1546 tline
->type
!= TOK_OTHER
||
1547 strcmp(tline
->text
, "}"))) {
1548 tline
= tline
->next
;
1549 paramsize
[nparam
]++;
1551 tline
= tline
->next
;
1552 if (tline
&& tline
->type
== TOK_WHITESPACE
)
1553 tline
= tline
->next
;
1554 if (tline
&& (tline
->type
!= TOK_OTHER
||
1555 (strcmp(tline
->text
, ")") &&
1556 strcmp(tline
->text
, ",")))) {
1557 error (ERR_NONFATAL
|ERR_OFFBY1
, "braces do not "
1558 "enclose all of macro parameter");
1560 if (tline
&& tline
->type
== TOK_OTHER
&&
1561 !strcmp(tline
->text
, ","))
1562 tline
= tline
->next
;
1564 while (tline
&& (brackets
> 0 ||
1565 tline
->type
!= TOK_OTHER
||
1566 (strcmp(tline
->text
, ",") &&
1567 strcmp(tline
->text
, ")")))) {
1568 if (tline
->type
== TOK_OTHER
&& !tline
->text
[1])
1569 brackets
+= (tline
->text
[0] == '(' ? 1 :
1570 tline
->text
[0] == ')' ? -1 : 0);
1571 tline
= tline
->next
;
1572 paramsize
[nparam
]++;
1576 if (tline
&& !strcmp(tline
->text
, ")"))
1578 if (tline
&& !strcmp(tline
->text
, ","))
1579 tline
= tline
->next
;
1581 while (m
&& m
->nparam
!= nparam
) {
1582 while ( (m
= m
->next
) )
1583 if (!strcmp(m
->name
, mstart
->text
))
1587 error (ERR_WARNING
|ERR_OFFBY1
|ERR_WARN_MNP
,
1588 "macro `%s' exists, but not taking %d parameters",
1589 mstart
->text
, nparam
);
1591 nasm_free (paramsize
);
1593 tline
->type
= TOK_PS_OTHER
;
1598 * Expand the macro: we are placed on the last token of the
1599 * call, so that we can easily split the call from the
1600 * following tokens. We also start by pushing an SMAC_END
1601 * token for the cycle removal.
1604 tline
= tline
->next
;
1606 tt
= nasm_malloc(sizeof(Token
));
1607 tt
->type
= TOK_SMAC_END
;
1610 m
->in_progress
= TRUE
;
1613 for (t
= m
->expansion
; t
; t
= t
->next
) {
1614 if (t
->type
>= TOK_SMAC_PARAM
) {
1615 Token
*pcopy
= tline
, **ptail
= &pcopy
;
1619 ttt
= params
[t
->type
- TOK_SMAC_PARAM
];
1620 for (i
=0; i
<paramsize
[t
->type
-TOK_SMAC_PARAM
]; i
++) {
1621 pt
= *ptail
= nasm_malloc(sizeof(Token
));
1624 pt
->text
= nasm_strdup(ttt
->text
);
1625 pt
->type
= ttt
->type
;
1631 tt
= nasm_malloc(sizeof(Token
));
1633 tt
->text
= nasm_strdup(t
->text
);
1641 * Having done that, get rid of the macro call, and clean
1642 * up the parameters.
1645 nasm_free (paramsize
);
1646 free_tlist (mstart
);
1653 * Ensure that a macro parameter contains a condition code and
1654 * nothing else. Return the condition code index if so, or -1
1657 static int find_cc (Token
*t
) {
1661 if (t
&& t
->type
== TOK_WHITESPACE
)
1663 if (t
->type
!= TOK_ID
)
1666 if (tt
&& tt
->type
== TOK_WHITESPACE
)
1668 if (tt
&& (tt
->type
!= TOK_OTHER
|| strcmp(tt
->text
, ",")))
1672 j
= sizeof(conditions
)/sizeof(*conditions
);
1675 m
= nasm_stricmp(t
->text
, conditions
[k
]);
1691 * Determine whether the given line constitutes a multi-line macro
1692 * call, and return the MMacro structure called if so. Doesn't have
1693 * to check for an initial label - that's taken care of in
1694 * expand_mmacro - but must check numbers of parameters. Guaranteed
1695 * to be called with tline->type == TOK_ID, so the putative macro
1696 * name is easy to find.
1698 static MMacro
*is_mmacro (Token
*tline
, Token
***params_array
) {
1703 head
= mmacros
[hash(tline
->text
)];
1706 * Efficiency: first we see if any macro exists with the given
1707 * name. If not, we can return NULL immediately. _Then_ we
1708 * count the parameters, and then we look further along the
1709 * list if necessary to find the proper MMacro.
1711 for (m
= head
; m
; m
= m
->next
)
1712 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
1718 * OK, we have a potential macro. Count and demarcate the
1721 count_mmac_params (tline
->next
, &nparam
, ¶ms
);
1724 * So we know how many parameters we've got. Find the MMacro
1725 * structure that handles this number.
1728 if (m
->nparam_min
<= nparam
&& (m
->plus
|| nparam
<= m
->nparam_max
)) {
1730 * This one is right. Just check if cycle removal
1731 * prohibits us using it before we actually celebrate...
1733 if (m
->in_progress
) {
1734 error (ERR_NONFATAL
|ERR_OFFBY1
,
1735 "self-reference in multi-line macro `%s'",
1741 * It's right, and we can use it. Add its default
1742 * parameters to the end of our list if necessary.
1744 params
= nasm_realloc (params
, (m
->nparam_max
+1)*sizeof(*params
));
1746 while (nparam
< m
->nparam_max
) {
1747 params
[nparam
] = m
->defaults
[nparam
- m
->nparam_min
];
1751 while (nparam
< m
->nparam_max
) {
1752 params
[nparam
] = NULL
;
1757 * Then terminate the parameter list, and leave.
1759 params
[m
->nparam_max
] = NULL
;
1760 *params_array
= params
;
1764 * This one wasn't right: look for the next one with the
1767 for (m
= m
->next
; m
; m
= m
->next
)
1768 if (!mstrcmp(m
->name
, tline
->text
, m
->casesense
))
1773 * After all that, we didn't find one with the right number of
1774 * parameters. Issue a warning, and fail to expand the macro.
1776 error (ERR_WARNING
|ERR_OFFBY1
|ERR_WARN_MNP
,
1777 "macro `%s' exists, but not taking %d parameters",
1778 tline
->text
, nparam
);
1784 * Expand the multi-line macro call made by the given line, if
1785 * there is one to be expanded. If there is, push the expansion on
1786 * istk->expansion and return 1 or 2, as according to whether a
1787 * line sync is needed (2 if it is). Otherwise return 0.
1789 static int expand_mmacro (Token
*tline
) {
1790 Token
*label
= NULL
, **params
, *t
, *tt
, *ttt
, *last
= NULL
;
1793 int i
, n
, nparam
, *paramlen
;
1794 int need_sync
= FALSE
;
1797 if (t
&& t
->type
== TOK_WHITESPACE
)
1799 if (t
&& t
->type
== TOK_ID
) {
1800 m
= is_mmacro (t
, ¶ms
);
1803 * We have an id which isn't a macro call. We'll assume
1804 * it might be a label; we'll also check to see if a
1805 * colon follows it. Then, if there's another id after
1806 * that lot, we'll check it again for macro-hood.
1808 last
= t
, t
= t
->next
;
1809 if (t
&& t
->type
== TOK_WHITESPACE
)
1810 last
= t
, t
= t
->next
;
1811 if (t
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ":"))
1812 last
= t
, t
= t
->next
;
1813 if (t
&& t
->type
== TOK_WHITESPACE
)
1814 last
= t
, t
= t
->next
;
1815 if (t
&& t
->type
== TOK_ID
) {
1816 m
= is_mmacro(t
, ¶ms
);
1829 * If we're not already inside another macro expansion, we'd
1830 * better push a line synchronisation to ensure we stay put on
1833 if (!istk
->expansion
)
1837 * Fix up the parameters: this involves stripping leading and
1838 * trailing whitespace, then stripping braces if they are
1841 for (nparam
= 0; params
[nparam
]; nparam
++);
1842 paramlen
= nparam
? nasm_malloc(nparam
*sizeof(*paramlen
)) : NULL
;
1844 for (i
= 0; params
[i
]; i
++) {
1846 int comma
= (!m
->plus
|| i
< nparam
-1);
1849 if (t
&& t
->type
== TOK_WHITESPACE
)
1851 if (t
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "{"))
1852 t
= t
->next
, brace
= TRUE
, comma
= FALSE
;
1856 if (!t
) /* end of param because EOL */
1858 if (comma
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, ","))
1859 break; /* ... because we have hit a comma */
1860 if (comma
&& t
->type
== TOK_WHITESPACE
&&
1861 t
->next
->type
== TOK_OTHER
&& !strcmp(t
->next
->text
, ","))
1862 break; /* ... or a space then a comma */
1863 if (brace
&& t
->type
== TOK_OTHER
&& !strcmp(t
->text
, "}"))
1864 break; /* ... or a brace */
1871 * OK, we have a MMacro structure together with a set of
1872 * parameters. We must now go through the expansion and push
1873 * _copies_ of each Line on to istk->expansion, having first
1874 * substituted for most % tokens (%1, %+1, %-1, %%foo). Note
1875 * that %$bar, %$$baz, %$$$quux, and so on, do not get
1876 * substituted here but rather have to wait until the
1877 * single-line macro substitution process. This is because they
1878 * don't just crop up in macro definitions, but can appear
1879 * anywhere they like.
1881 * First, push an end marker on to istk->expansion, and mark
1882 * this macro as in progress.
1884 ll
= nasm_malloc(sizeof(Line
));
1885 ll
->next
= istk
->expansion
;
1888 istk
->expansion
= ll
;
1889 m
->in_progress
= TRUE
;
1890 for (l
= m
->expansion
; l
; l
= l
->next
) {
1893 ll
= nasm_malloc(sizeof(Line
));
1894 ll
->next
= istk
->expansion
;
1895 ll
->finishes
= NULL
;
1899 for (t
= l
->first
; t
; t
= t
->next
) {
1901 int type
= 0, cc
; /* type = 0 to placate optimisers */
1904 if (t
->type
== TOK_PREPROC_ID
&&
1905 (t
->text
[1] == '+' || t
->text
[1] == '-' ||
1906 t
->text
[1] == '%' ||
1907 (t
->text
[1] >= '0' && t
->text
[1] <= '9'))) {
1909 * We have to make a substitution of one of the
1910 * forms %1, %-1, %+1, %%foo.
1912 switch (t
->text
[1]) {
1915 sprintf(tmpbuf
, "..@%lu.", unique
);
1916 text
= nasm_malloc(strlen(tmpbuf
)+strlen(t
->text
+2)+1);
1917 strcpy(text
, tmpbuf
);
1918 strcat(text
, t
->text
+2);
1921 n
= atoi(t
->text
+2)-1;
1925 error (ERR_NONFATAL
|ERR_OFFBY1
,
1926 "macro parameter %d is not a condition code",
1931 if (inverse_ccs
[cc
] == -1) {
1932 error (ERR_NONFATAL
|ERR_OFFBY1
,
1933 "condition code `%s' is not invertible",
1937 text
= nasm_strdup(conditions
[inverse_ccs
[cc
]]);
1941 n
= atoi(t
->text
+2)-1;
1945 error (ERR_NONFATAL
|ERR_OFFBY1
,
1946 "macro parameter %d is not a condition code",
1951 text
= nasm_strdup(conditions
[cc
]);
1955 n
= atoi(t
->text
+1)-1;
1958 for (i
=0; i
<paramlen
[n
]; i
++) {
1959 tt
= *tail
= nasm_malloc(sizeof(Token
));
1962 tt
->type
= ttt
->type
;
1963 tt
->text
= nasm_strdup(ttt
->text
);
1968 text
= NULL
; /* we've done it here */
1973 text
= nasm_strdup(t
->text
);
1977 tt
= *tail
= nasm_malloc(sizeof(Token
));
1986 istk
->expansion
= ll
;
1991 * If we had a label, push it on the front of the first line of
1992 * the macro expansion.
1995 last
->next
= istk
->expansion
->first
;
1996 istk
->expansion
->first
= label
;
2003 nasm_free (paramlen
);
2007 list
->uplevel (m
->nolist
? LIST_MACRO_NOLIST
: LIST_MACRO
);
2009 return need_sync
? 2 : 1;
2012 static void pp_reset (char *file
, efunc errfunc
, ListGen
*listgen
) {
2017 linesync
= outline
= NULL
;
2018 istk
= nasm_malloc(sizeof(Include
));
2021 istk
->expansion
= NULL
;
2022 istk
->fp
= fopen(file
, "r");
2023 istk
->fname
= nasm_strdup(file
);
2024 istk
->lineno
= istk
->lineinc
= 1;
2026 error (ERR_FATAL
|ERR_NOFILE
, "unable to open input file `%s'", file
);
2028 for (h
=0; h
<NHASH
; h
++) {
2037 static char *pp_getline (void) {
2050 * Fetch a tokenised line, either from the macro-expansion
2051 * buffer or from the input file.
2054 while (istk
->expansion
&& istk
->expansion
->finishes
) {
2055 Line
*l
= istk
->expansion
;
2056 l
->finishes
->in_progress
= FALSE
;
2057 istk
->expansion
= l
->next
;
2059 list
->downlevel (LIST_MACRO
);
2060 if (!istk
->expansion
)
2063 if (istk
->expansion
) {
2065 Line
*l
= istk
->expansion
;
2067 istk
->expansion
= l
->next
;
2070 list
->line (LIST_MACRO
, p
);
2072 if (!istk
->expansion
)
2078 * The current file has ended; work down the istk
2079 * until we find a file we can read from.
2084 error(ERR_FATAL
, "expected `%%endif' before end of file");
2087 list
->downlevel (LIST_INCLUDE
);
2088 nasm_free (i
->fname
);
2096 line
= prepreproc(line
);
2097 tline
= tokenise(line
);
2102 * Check the line to see if it's a preprocessor directive.
2104 ret
= do_directive(tline
);
2109 if ((ret
& 2) && !stdmacpos
) {/* give a blank line to the output */
2110 outline
= nasm_strdup("");
2115 } else if (defining
) {
2117 * We're defining a multi-line macro. We emit nothing
2118 * at all, not even a blank line (when we finish
2119 * defining the macro, we'll emit a line-number
2120 * directive so that we keep sync properly), and just
2121 * shove the tokenised line on to the macro definition.
2123 Line
*l
= nasm_malloc(sizeof(Line
));
2124 l
->next
= defining
->expansion
;
2126 l
->finishes
= FALSE
;
2127 defining
->expansion
= l
;
2129 } else if (istk
->conds
&& !emitting(istk
->conds
->state
)) {
2131 * We're in a non-emitting branch of a condition block.
2132 * Emit nothing at all, not even a blank line: when we
2133 * emerge from the condition we'll give a line-number
2134 * directive so we keep our place correctly.
2139 tline
= expand_smacro(tline
);
2140 ret
= expand_mmacro(tline
);
2143 * De-tokenise the line again, and emit it.
2145 line
= detoken(tline
);
2152 continue; /* expand_mmacro calls free_tlist */
2158 * Once we're out of this loop, outline _must_ be non-NULL. The
2159 * only question is whether linesync is NULL or not.
2171 static void pp_cleanup (void) {
2175 error (ERR_NONFATAL
, "end of file while still defining macro `%s'",
2177 nasm_free (defining
->name
);
2178 free_tlist (defining
->dlist
);
2179 free_llist (defining
->expansion
);
2180 nasm_free (defining
);
2182 nasm_free (linesync
); /* might just be necessary */
2183 nasm_free (outline
); /* really shouldn't be necessary */
2186 for (h
=0; h
<NHASH
; h
++) {
2187 while (mmacros
[h
]) {
2188 MMacro
*m
= mmacros
[h
];
2189 mmacros
[h
] = mmacros
[h
]->next
;
2190 nasm_free (m
->name
);
2191 free_tlist (m
->dlist
);
2192 free_llist (m
->expansion
);
2195 while (smacros
[h
]) {
2196 SMacro
*s
= smacros
[h
];
2197 smacros
[h
] = smacros
[h
]->next
;
2198 nasm_free (s
->name
);
2199 free_tlist (s
->expansion
);
2207 nasm_free (i
->fname
);
2214 void pp_include_path (char *path
) {
2217 i
= nasm_malloc(sizeof(IncPath
));
2218 i
->path
= nasm_strdup(path
);
2224 void pp_pre_include (char *fname
) {
2225 Token
*inc
, *space
, *name
;
2228 inc
= nasm_malloc(sizeof(Token
));
2229 inc
->next
= space
= nasm_malloc(sizeof(Token
));
2230 space
->next
= name
= nasm_malloc(sizeof(Token
));
2233 inc
->type
= TOK_PREPROC_ID
;
2234 inc
->text
= nasm_strdup("%include");
2235 space
->type
= TOK_WHITESPACE
;
2236 space
->text
= nasm_strdup(" ");
2237 name
->type
= TOK_INTERNAL_STRING
;
2238 name
->text
= nasm_strdup(fname
);
2240 inc
->mac
= space
->mac
= name
->mac
= NULL
;
2242 l
= nasm_malloc(sizeof(Line
));
2245 l
->finishes
= FALSE
;
2249 void pp_pre_define (char *definition
) {
2250 Token
*def
, *space
, *name
;
2254 equals
= strchr(definition
, '=');
2256 def
= nasm_malloc(sizeof(Token
));
2257 def
->next
= space
= nasm_malloc(sizeof(Token
));
2260 space
->next
= name
= tokenise(definition
);
2264 def
->type
= TOK_PREPROC_ID
;
2265 def
->text
= nasm_strdup("%define");
2266 space
->type
= TOK_WHITESPACE
;
2267 space
->text
= nasm_strdup(" ");
2269 def
->mac
= space
->mac
= NULL
;
2271 l
= nasm_malloc(sizeof(Line
));
2274 l
->finishes
= FALSE
;