blob: a62fe858e9f199eb3a81478eb286a54b3e986e33 [file] [log] [blame]
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001/* preproc.c macro preprocessor for the Netwide Assembler
2 *
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.
7 *
8 * initial version 18/iii/97 by Simon Tatham
9 */
10
H. Peter Anvin4836e332002-04-30 20:56:43 +000011/* Typical flow of text through preproc
12 *
13 * pp_getline gets tokenised lines, either
14 *
15 * from a macro expansion
16 *
17 * or
18 * {
19 * read_line gets raw text from stdmacpos, or predef, or current input file
20 * tokenise converts to tokens
21 * }
22 *
23 * expand_mmac_params is used to expand %1 etc., unless a macro is being
24 * defined or a false conditional is being processed
25 * (%0, %1, %+1, %-1, %%foo
26 *
27 * do_directive checks for directives
28 *
29 * expand_smacro is used to expand single line macros
30 *
31 * expand_mmacro is used to expand multi-line macros
32 *
33 * detoken is used to convert the line back to text
34 */
H. Peter Anvineba20a72002-04-30 20:53:55 +000035
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000036#include <stdio.h>
H. Peter Anvinaf535c12002-04-30 20:59:21 +000037#include <stdarg.h>
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000038#include <stdlib.h>
39#include <stddef.h>
40#include <string.h>
41#include <ctype.h>
H. Peter Anvin76690a12002-04-30 20:52:49 +000042#include <limits.h>
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000043
44#include "nasm.h"
45#include "nasmlib.h"
46
47typedef struct SMacro SMacro;
48typedef struct MMacro MMacro;
49typedef struct Context Context;
50typedef struct Token Token;
51typedef struct Line Line;
52typedef struct Include Include;
53typedef struct Cond Cond;
H. Peter Anvin6768eb72002-04-30 20:52:26 +000054typedef struct IncPath IncPath;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000055
56/*
57 * Store the definition of a single-line macro.
58 */
H. Peter Anvin734b1882002-04-30 21:01:08 +000059struct SMacro
60{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000061 SMacro *next;
62 char *name;
63 int casesense;
64 int nparam;
65 int in_progress;
66 Token *expansion;
67};
68
69/*
H. Peter Anvin76690a12002-04-30 20:52:49 +000070 * Store the definition of a multi-line macro. This is also used to
71 * store the interiors of `%rep...%endrep' blocks, which are
72 * effectively self-re-invoking multi-line macros which simply
73 * don't have a name or bother to appear in the hash tables. %rep
74 * blocks are signified by having a NULL `name' field.
75 *
76 * In a MMacro describing a `%rep' block, the `in_progress' field
77 * isn't merely boolean, but gives the number of repeats left to
78 * run.
79 *
80 * The `next' field is used for storing MMacros in hash tables; the
81 * `next_active' field is for stacking them on istk entries.
82 *
83 * When a MMacro is being expanded, `params', `iline', `nparam',
84 * `paramlen', `rotate' and `unique' are local to the invocation.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000085 */
H. Peter Anvin734b1882002-04-30 21:01:08 +000086struct MMacro
87{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000088 MMacro *next;
89 char *name;
90 int casesense;
91 int nparam_min, nparam_max;
H. Peter Anvin734b1882002-04-30 21:01:08 +000092 int plus; /* is the last parameter greedy? */
93 int nolist; /* is this macro listing-inhibited? */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000094 int in_progress;
H. Peter Anvin734b1882002-04-30 21:01:08 +000095 Token *dlist; /* All defaults as one list */
96 Token **defaults; /* Parameter default pointers */
97 int ndefs; /* number of default parameters */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000098 Line *expansion;
H. Peter Anvin76690a12002-04-30 20:52:49 +000099
100 MMacro *next_active;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000101 MMacro *rep_nest; /* used for nesting %rep */
102 Token **params; /* actual parameters */
103 Token *iline; /* invocation line */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000104 int nparam, rotate, *paramlen;
105 unsigned long unique;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000106 int lineno; /* Current line number on expansion */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000107};
108
109/*
110 * The context stack is composed of a linked list of these.
111 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000112struct Context
113{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000114 Context *next;
115 SMacro *localmac;
116 char *name;
117 unsigned long number;
118};
119
120/*
121 * This is the internal form which we break input lines up into.
122 * Typically stored in linked lists.
123 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000124 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
125 * necessarily used as-is, but is intended to denote the number of
126 * the substituted parameter. So in the definition
127 *
128 * %define a(x,y) ( (x) & ~(y) )
129 *
130 * the token representing `x' will have its type changed to
131 * TOK_SMAC_PARAM, but the one representing `y' will be
132 * TOK_SMAC_PARAM+1.
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000133 *
134 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
135 * which doesn't need quotes around it. Used in the pre-include
136 * mechanism as an alternative to trying to find a sensible type of
137 * quote to use on the filename we were passed.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000138 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000139struct Token
140{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000141 Token *next;
142 char *text;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000143 SMacro *mac; /* associated macro for TOK_SMAC_END */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000144 int type;
145};
H. Peter Anvin734b1882002-04-30 21:01:08 +0000146enum
147{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000148 TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000149 TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_SMAC_PARAM,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000150 TOK_INTERNAL_STRING
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000151};
152
153/*
154 * Multi-line macro definitions are stored as a linked list of
155 * these, which is essentially a container to allow several linked
156 * lists of Tokens.
157 *
158 * Note that in this module, linked lists are treated as stacks
159 * wherever possible. For this reason, Lines are _pushed_ on to the
160 * `expansion' field in MMacro structures, so that the linked list,
161 * if walked, would give the macro lines in reverse order; this
162 * means that we can walk the list when expanding a macro, and thus
163 * push the lines on to the `expansion' field in _istk_ in reverse
164 * order (so that when popped back off they are in the right
165 * order). It may seem cockeyed, and it relies on my design having
166 * an even number of steps in, but it works...
167 *
168 * Some of these structures, rather than being actual lines, are
169 * markers delimiting the end of the expansion of a given macro.
H. Peter Anvin76690a12002-04-30 20:52:49 +0000170 * This is for use in the cycle-tracking and %rep-handling code.
171 * Such structures have `finishes' non-NULL, and `first' NULL. All
172 * others have `finishes' NULL, but `first' may still be NULL if
173 * the line is blank.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000174 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000175struct Line
176{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000177 Line *next;
178 MMacro *finishes;
179 Token *first;
180};
181
182/*
183 * To handle an arbitrary level of file inclusion, we maintain a
184 * stack (ie linked list) of these things.
185 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000186struct Include
187{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000188 Include *next;
189 FILE *fp;
190 Cond *conds;
191 Line *expansion;
192 char *fname;
193 int lineno, lineinc;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000194 MMacro *mstk; /* stack of active macros/reps */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000195};
196
197/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000198 * Include search path. This is simply a list of strings which get
199 * prepended, in turn, to the name of an include file, in an
200 * attempt to find the file if it's not in the current directory.
201 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000202struct IncPath
203{
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000204 IncPath *next;
205 char *path;
206};
207
208/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000209 * Conditional assembly: we maintain a separate stack of these for
210 * each level of file inclusion. (The only reason we keep the
211 * stacks separate is to ensure that a stray `%endif' in a file
212 * included from within the true branch of a `%if' won't terminate
213 * it and cause confusion: instead, rightly, it'll cause an error.)
214 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000215struct Cond
216{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000217 Cond *next;
218 int state;
219};
H. Peter Anvin734b1882002-04-30 21:01:08 +0000220enum
221{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000222 /*
223 * These states are for use just after %if or %elif: IF_TRUE
224 * means the condition has evaluated to truth so we are
225 * currently emitting, whereas IF_FALSE means we are not
226 * currently emitting but will start doing so if a %else comes
227 * up. In these states, all directives are admissible: %elif,
228 * %else and %endif. (And of course %if.)
229 */
230 COND_IF_TRUE, COND_IF_FALSE,
231 /*
232 * These states come up after a %else: ELSE_TRUE means we're
233 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
234 * any %elif or %else will cause an error.
235 */
236 COND_ELSE_TRUE, COND_ELSE_FALSE,
237 /*
238 * This state means that we're not emitting now, and also that
239 * nothing until %endif will be emitted at all. It's for use in
240 * two circumstances: (i) when we've had our moment of emission
241 * and have now started seeing %elifs, and (ii) when the
242 * condition construct in question is contained within a
243 * non-emitting branch of a larger condition construct.
244 */
245 COND_NEVER
246};
247#define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
248
249/*
250 * Condition codes. Note that we use c_ prefix not C_ because C_ is
251 * used in nasm.h for the "real" condition codes. At _this_ level,
252 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
253 * ones, so we need a different enum...
254 */
255static char *conditions[] = {
256 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
257 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
258 "np", "ns", "nz", "o", "p", "pe", "po", "s", "z"
259};
H. Peter Anvin734b1882002-04-30 21:01:08 +0000260enum
261{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000262 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
263 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
264 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_S, c_Z
265};
266static int inverse_ccs[] = {
267 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
268 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,
269 c_Z, c_NO, c_NP, c_PO, c_PE, c_NS, c_NZ
270};
271
H. Peter Anvin76690a12002-04-30 20:52:49 +0000272/*
273 * Directive names.
274 */
275static char *directives[] = {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000276 "%arg",
H. Peter Anvin76690a12002-04-30 20:52:49 +0000277 "%assign", "%clear", "%define", "%elif", "%elifctx", "%elifdef",
278 "%elifid", "%elifidn", "%elifidni", "%elifnctx", "%elifndef",
279 "%elifnid", "%elifnidn", "%elifnidni", "%elifnnum", "%elifnstr",
280 "%elifnum", "%elifstr", "%else", "%endif", "%endm", "%endmacro",
281 "%endrep", "%error", "%exitrep", "%iassign", "%idefine", "%if",
282 "%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifnctx",
283 "%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnnum",
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000284 "%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include",
285 "%ixdefine", "%line",
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000286 "%local",
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000287 "%macro", "%pop", "%push", "%rep", "%repl", "%rotate",
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000288 "%stacksize",
H. Peter Anvin734b1882002-04-30 21:01:08 +0000289 "%strlen", "%substr", "%undef", "%xdefine"
H. Peter Anvin76690a12002-04-30 20:52:49 +0000290};
H. Peter Anvin734b1882002-04-30 21:01:08 +0000291enum
292{
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000293 PP_ARG,
H. Peter Anvin76690a12002-04-30 20:52:49 +0000294 PP_ASSIGN, PP_CLEAR, PP_DEFINE, PP_ELIF, PP_ELIFCTX, PP_ELIFDEF,
295 PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFNCTX, PP_ELIFNDEF,
296 PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNNUM, PP_ELIFNSTR,
297 PP_ELIFNUM, PP_ELIFSTR, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO,
298 PP_ENDREP, PP_ERROR, PP_EXITREP, PP_IASSIGN, PP_IDEFINE, PP_IF,
299 PP_IFCTX, PP_IFDEF, PP_IFID, PP_IFIDN, PP_IFIDNI, PP_IFNCTX,
300 PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNNUM,
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000301 PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE,
302 PP_IXDEFINE, PP_LINE,
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000303 PP_LOCAL,
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000304 PP_MACRO, PP_POP, PP_PUSH, PP_REP, PP_REPL, PP_ROTATE,
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000305 PP_STACKSIZE,
H. Peter Anvin734b1882002-04-30 21:01:08 +0000306 PP_STRLEN, PP_SUBSTR, PP_UNDEF, PP_XDEFINE
H. Peter Anvin76690a12002-04-30 20:52:49 +0000307};
308
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000309
310/* For TASM compatibility we need to be able to recognise TASM compatible
311 * conditional compilation directives. Using the NASM pre-processor does
312 * not work, so we look for them specifically from the following list and
313 * then jam in the equivalent NASM directive into the input stream.
314 */
315
316#ifndef MAX
317# define MAX(a,b) ( ((a) > (b)) ? (a) : (b))
318#endif
319
H. Peter Anvin734b1882002-04-30 21:01:08 +0000320enum
321{
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000322 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
323 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
324};
325
326static char *tasm_directives[] = {
327 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
328 "ifndef", "include", "local"
329};
330
331static int StackSize = 4;
332static char *StackPointer = "ebp";
333static int ArgOffset = 8;
334static int LocalOffset = 4;
335
H. Peter Anvin76690a12002-04-30 20:52:49 +0000336
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000337static Context *cstk;
338static Include *istk;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000339static IncPath *ipath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000340
H. Peter Anvin734b1882002-04-30 21:01:08 +0000341static efunc __error; /* Pointer to client-provided error reporting function */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000342static evalfunc evaluate;
343
H. Peter Anvin620515a2002-04-30 20:57:38 +0000344static int pass; /* HACK: pass 0 = generate dependencies only */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000345
H. Peter Anvin734b1882002-04-30 21:01:08 +0000346static unsigned long unique; /* unique identifier numbers */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000347
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000348static Line *predef = NULL;
349
350static ListGen *list;
351
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000352/*
353 * The number of hash values we use for the macro lookup tables.
H. Peter Anvineba20a72002-04-30 20:53:55 +0000354 * FIXME: We should *really* be able to configure this at run time,
355 * or even have the hash table automatically expanding when necessary.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000356 */
357#define NHASH 31
358
359/*
360 * The current set of multi-line macros we have defined.
361 */
362static MMacro *mmacros[NHASH];
363
364/*
365 * The current set of single-line macros we have defined.
366 */
367static SMacro *smacros[NHASH];
368
369/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000370 * The multi-line macro we are currently defining, or the %rep
371 * block we are currently reading, if any.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000372 */
373static MMacro *defining;
374
375/*
376 * The number of macro parameters to allocate space for at a time.
377 */
378#define PARAM_DELTA 16
379
380/*
381 * The standard macro set: defined as `static char *stdmac[]'. Also
382 * gives our position in the macro set, when we're processing it.
383 */
384#include "macros.c"
385static char **stdmacpos;
386
387/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000388 * The extra standard macros that come from the object format, if
389 * any.
390 */
391static char **extrastdmac = NULL;
392int any_extrastdmac;
393
394/*
H. Peter Anvin734b1882002-04-30 21:01:08 +0000395 * Tokens are allocated in blocks to improve speed
396 */
397#define TOKEN_BLOCKSIZE 4096
398static Token *freeTokens = NULL;
399
400/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000401 * Forward declarations.
402 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000403static Token *expand_mmac_params(Token * tline);
404static Token *expand_smacro(Token * tline);
405static Token *expand_id(Token * tline);
406static Context *get_ctx(char *name, int all_contexts);
407static void make_tok_num(Token * tok, long val);
408static void error(int severity, char *fmt, ...);
409static Token *new_Token(Token * next, int type, char *text, int txtlen);
410static Token *delete_Token(Token * t);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000411
412/*
413 * Macros for safe checking of token pointers, avoid *(NULL)
414 */
415#define tok_type_(x,t) ((x) && (x)->type == (t))
416#define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
417#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
418#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
H. Peter Anvin76690a12002-04-30 20:52:49 +0000419
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000420/* Handle TASM specific directives, which do not contain a % in
421 * front of them. We do it here because I could not find any other
422 * place to do it for the moment, and it is a hack (ideally it would
423 * be nice to be able to use the NASM pre-processor to do it).
424 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000425static char *
426check_tasm_directive(char *line)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000427{
428 int i, j, k, m, len;
429 char *p = line, *oldline, oldchar;
430
431 /* Skip whitespace */
432 while (isspace(*p) && *p != 0)
433 p++;
434
435 /* Binary search for the directive name */
436 i = -1;
437 j = sizeof(tasm_directives) / sizeof(*tasm_directives);
438 len = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000439 while (!isspace(p[len]) && p[len] != 0)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000440 len++;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000441 if (len)
442 {
443 oldchar = p[len];
444 p[len] = 0;
445 while (j - i > 1)
446 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000447 k = (j + i) / 2;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000448 m = nasm_stricmp(p, tasm_directives[k]);
449 if (m == 0)
450 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000451 /* We have found a directive, so jam a % in front of it
452 * so that NASM will then recognise it as one if it's own.
453 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000454 p[len] = oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000455 len = strlen(p);
456 oldline = line;
457 line = nasm_malloc(len + 2);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000458 line[0] = '%';
459 if (k == TM_IFDIFI)
460 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000461 /* NASM does not recognise IFDIFI, so we convert it to
462 * %ifdef BOGUS. This is not used in NASM comaptible
463 * code, but does need to parse for the TASM macro
464 * package.
465 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000466 strcpy(line + 1, "ifdef BOGUS");
467 }
468 else
469 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000470 memcpy(line + 1, p, len + 1);
471 }
472 nasm_free(oldline);
473 return line;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000474 }
475 else if (m < 0)
476 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000477 j = k;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000478 }
479 else
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000480 i = k;
481 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000482 p[len] = oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000483 }
484 return line;
485}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000486
H. Peter Anvin76690a12002-04-30 20:52:49 +0000487/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000488 * The pre-preprocessing stage... This function translates line
489 * number indications as they emerge from GNU cpp (`# lineno "file"
490 * flags') into NASM preprocessor line number indications (`%line
491 * lineno file').
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000492 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000493static char *
494prepreproc(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000495{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000496 int lineno, fnlen;
497 char *fname, *oldline;
498
H. Peter Anvin734b1882002-04-30 21:01:08 +0000499 if (line[0] == '#' && line[1] == ' ')
500 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000501 oldline = line;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000502 fname = oldline + 2;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000503 lineno = atoi(fname);
504 fname += strspn(fname, "0123456789 ");
505 if (*fname == '"')
506 fname++;
507 fnlen = strcspn(fname, "\"");
H. Peter Anvin734b1882002-04-30 21:01:08 +0000508 line = nasm_malloc(20 + fnlen);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000509 sprintf(line, "%%line %d %.*s", lineno, fnlen, fname);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000510 nasm_free(oldline);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000511 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000512 if (tasm_compatible_mode)
513 return check_tasm_directive(line);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000514 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000515}
516
517/*
518 * The hash function for macro lookups. Note that due to some
519 * macros having case-insensitive names, the hash function must be
520 * invariant under case changes. We implement this by applying a
521 * perfectly normal hash function to the uppercase of the string.
522 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000523static int
524hash(char *s)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000525{
526 unsigned int h = 0;
527 int i = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000528 /*
529 * Powers of three, mod 31.
530 */
531 static const int multipliers[] = {
532 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10,
533 30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21
534 };
H. Peter Anvineba20a72002-04-30 20:53:55 +0000535
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000536
H. Peter Anvin734b1882002-04-30 21:01:08 +0000537 while (*s)
538 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000539 h += multipliers[i] * (unsigned char) (toupper(*s));
540 s++;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000541 if (++i >= sizeof(multipliers) / sizeof(*multipliers))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000542 i = 0;
543 }
544 h %= NHASH;
545 return h;
546}
547
548/*
549 * Free a linked list of tokens.
550 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000551static void
552free_tlist(Token * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000553{
H. Peter Anvin734b1882002-04-30 21:01:08 +0000554 while (list)
555 {
556 list = delete_Token(list);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000557 }
558}
559
560/*
561 * Free a linked list of lines.
562 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000563static void
564free_llist(Line * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000565{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000566 Line *l;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000567 while (list)
568 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000569 l = list;
570 list = list->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000571 free_tlist(l->first);
572 nasm_free(l);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000573 }
574}
575
576/*
H. Peter Anvineba20a72002-04-30 20:53:55 +0000577 * Free an MMacro
578 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000579static void
580free_mmacro(MMacro * m)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000581{
H. Peter Anvin734b1882002-04-30 21:01:08 +0000582 nasm_free(m->name);
583 free_tlist(m->dlist);
584 nasm_free(m->defaults);
585 free_llist(m->expansion);
586 nasm_free(m);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000587}
588
589/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000590 * Pop the context stack.
591 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000592static void
593ctx_pop(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000594{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000595 Context *c = cstk;
596 SMacro *smac, *s;
597
598 cstk = cstk->next;
599 smac = c->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000600 while (smac)
601 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000602 s = smac;
603 smac = smac->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000604 nasm_free(s->name);
605 free_tlist(s->expansion);
606 nasm_free(s);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000607 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000608 nasm_free(c->name);
609 nasm_free(c);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000610}
611
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000612#define BUF_DELTA 512
613/*
614 * Read a line from the top file in istk, handling multiple CR/LFs
615 * at the end of the line read, and handling spurious ^Zs. Will
616 * return lines from the standard macro set if this has not already
617 * been done.
618 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000619static char *
620read_line(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000621{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000622 char *buffer, *p, *q;
623 int bufsize;
624
H. Peter Anvin734b1882002-04-30 21:01:08 +0000625 if (stdmacpos)
626 {
627 if (*stdmacpos)
628 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000629 char *ret = nasm_strdup(*stdmacpos++);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000630 if (!*stdmacpos && any_extrastdmac)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000631 {
H. Peter Anvin76690a12002-04-30 20:52:49 +0000632 stdmacpos = extrastdmac;
633 any_extrastdmac = FALSE;
634 return ret;
635 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000636 /*
637 * Nasty hack: here we push the contents of `predef' on
638 * to the top-level expansion stack, since this is the
639 * most convenient way to implement the pre-include and
640 * pre-define features.
641 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000642 if (!*stdmacpos)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000643 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000644 Line *pd, *l;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000645 Token *head, **tail, *t;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000646
H. Peter Anvin734b1882002-04-30 21:01:08 +0000647 for (pd = predef; pd; pd = pd->next)
648 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000649 head = NULL;
650 tail = &head;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000651 for (t = pd->first; t; t = t->next)
652 {
653 *tail = new_Token(NULL, t->type, t->text, 0);
654 tail = &(*tail)->next;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000655 }
656 l = nasm_malloc(sizeof(Line));
657 l->next = istk->expansion;
658 l->first = head;
659 l->finishes = FALSE;
660 istk->expansion = l;
661 }
662 }
663 return ret;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000664 }
665 else
666 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000667 stdmacpos = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000668 }
669 }
670
671 bufsize = BUF_DELTA;
672 buffer = nasm_malloc(BUF_DELTA);
673 p = buffer;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000674 while (1)
675 {
676 q = fgets(p, bufsize - (p - buffer), istk->fp);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000677 if (!q)
678 break;
679 p += strlen(p);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000680 if (p > buffer && p[-1] == '\n')
681 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000682 break;
683 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000684 if (p - buffer > bufsize - 10)
685 {
686 long offset = p - buffer;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000687 bufsize += BUF_DELTA;
688 buffer = nasm_realloc(buffer, bufsize);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000689 p = buffer + offset; /* prevent stale-pointer problems */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000690 }
691 }
692
H. Peter Anvin734b1882002-04-30 21:01:08 +0000693 if (!q && p == buffer)
694 {
695 nasm_free(buffer);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000696 return NULL;
697 }
698
H. Peter Anvineba20a72002-04-30 20:53:55 +0000699 src_set_linnum(src_get_linnum() + istk->lineinc);
700
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000701 /*
702 * Play safe: remove CRs as well as LFs, if any of either are
703 * present at the end of the line.
704 */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000705 while (--p >= buffer && (*p == '\n' || *p == '\r'))
706 *p = '\0';
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000707
708 /*
709 * Handle spurious ^Z, which may be inserted into source files
710 * by some file transfer utilities.
711 */
712 buffer[strcspn(buffer, "\032")] = '\0';
713
H. Peter Anvin734b1882002-04-30 21:01:08 +0000714 list->line(LIST_READ, buffer);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000715
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000716 return buffer;
717}
718
719/*
720 * Tokenise a line of text. This is a very simple process since we
721 * don't need to parse the value out of e.g. numeric tokens: we
722 * simply split one string into many.
723 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000724static Token *
725tokenise(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000726{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000727 char *p = line;
728 int type;
729 Token *list = NULL;
730 Token *t, **tail = &list;
731
H. Peter Anvin734b1882002-04-30 21:01:08 +0000732 while (*line)
733 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000734 p = line;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000735 if (*p == '%')
H. Peter Anvineba20a72002-04-30 20:53:55 +0000736 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000737 p++;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000738 if ( isdigit(*p) ||
739 ((*p == '-' || *p == '+') && isdigit(p[1])) ||
740 ((*p == '+') && (isspace(p[1]) || !p[1])))
741 {
742 do
743 {
744 p++;
745 }
746 while (isdigit(*p));
747 type = TOK_PREPROC_ID;
748 }
749 else if (*p == '{')
750 {
751 p++;
752 while (*p && *p != '}')
753 {
754 p[-1] = *p;
755 p++;
756 }
757 p[-1] = '\0';
758 if (*p)
759 p++;
760 type = TOK_PREPROC_ID;
761 }
762 else if (isidchar(*p) ||
763 ((*p == '!' || *p == '%' || *p == '$') &&
764 isidchar(p[1])))
765 {
766 do
767 {
768 p++;
769 }
770 while (isidchar(*p));
771 type = TOK_PREPROC_ID;
772 }
773 else
774 {
775 type = TOK_OTHER;
776 if (*p == '%')
777 p++;
778 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000779 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000780 else if (isidstart(*p) || (*p == '$' && isidstart(p[1])))
H. Peter Anvineba20a72002-04-30 20:53:55 +0000781 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000782 type = TOK_ID;
783 p++;
784 while (*p && isidchar(*p))
785 p++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000786 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000787 else if (*p == '\'' || *p == '"')
788 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000789 /*
790 * A string token.
791 */
792 char c = *p;
793 p++;
794 type = TOK_STRING;
795 while (*p && *p != c)
796 p++;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000797 if (*p)
798 {
799 p++;
800 }
801 else
802 {
803 error(ERR_WARNING, "unterminated string");
804 }
805 }
806 else if (isnumstart(*p))
807 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000808 /*
809 * A number token.
810 */
811 type = TOK_NUMBER;
812 p++;
813 while (*p && isnumchar(*p))
814 p++;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000815 }
816 else if (isspace(*p))
817 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000818 type = TOK_WHITESPACE;
819 p++;
820 while (*p && isspace(*p))
821 p++;
822 /*
823 * Whitespace just before end-of-line is discarded by
824 * pretending it's a comment; whitespace just before a
825 * comment gets lumped into the comment.
826 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000827 if (!*p || *p == ';')
828 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000829 type = TOK_COMMENT;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000830 while (*p)
831 p++;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000832 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000833 }
834 else if (*p == ';')
835 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000836 type = TOK_COMMENT;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000837 while (*p)
838 p++;
839 }
840 else
841 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000842 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000843 * Anything else is an operator of some kind. We check
844 * for all the double-character operators (>>, <<, //,
845 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
846 * else is a single-character operator.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000847 */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000848 type = TOK_OTHER;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000849 if ((p[0] == '>' && p[1] == '>') ||
H. Peter Anvin734b1882002-04-30 21:01:08 +0000850 (p[0] == '<' && p[1] == '<') ||
851 (p[0] == '/' && p[1] == '/') ||
852 (p[0] == '<' && p[1] == '=') ||
853 (p[0] == '>' && p[1] == '=') ||
854 (p[0] == '=' && p[1] == '=') ||
855 (p[0] == '!' && p[1] == '=') ||
856 (p[0] == '<' && p[1] == '>') ||
857 (p[0] == '&' && p[1] == '&') ||
858 (p[0] == '|' && p[1] == '|') ||
859 (p[0] == '^' && p[1] == '^'))
H. Peter Anvineba20a72002-04-30 20:53:55 +0000860 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000861 p++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000862 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000863 p++;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000864 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000865 if (type != TOK_COMMENT)
866 {
867 *tail = t = new_Token(NULL, type, line, p - line);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000868 tail = &t->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000869 }
870 line = p;
871 }
872
873 return list;
874}
875
H. Peter Anvin734b1882002-04-30 21:01:08 +0000876
877/*
878 * this function creates a new Token and passes a pointer to it
879 * back to the caller. It sets the type and text elements, and
880 * also the mac and next elements to NULL.
881 */
882static Token *
883new_Token(Token * next, int type, char *text, int txtlen)
884{
885 Token *t;
886 int i;
887
888 if (freeTokens == NULL)
889 {
890 freeTokens = nasm_malloc(TOKEN_BLOCKSIZE * sizeof(Token));
891 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
892 freeTokens[i].next = &freeTokens[i + 1];
893 freeTokens[i].next = NULL;
894 }
895 t = freeTokens;
896 freeTokens = t->next;
897 t->next = next;
898 t->mac = NULL;
899 t->type = type;
900 if (type == TOK_WHITESPACE || text == NULL)
901 {
902 t->text = NULL;
903 }
904 else
905 {
906 if (txtlen == 0)
907 txtlen = strlen(text);
908 t->text = nasm_malloc(1 + txtlen);
909 strncpy(t->text, text, txtlen);
910 t->text[txtlen] = '\0';
911 }
912 return t;
913}
914
915static Token *
916delete_Token(Token * t)
917{
918 Token *next = t->next;
919 nasm_free(t->text);
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000920/* t->next = freeTokens ? freeTokens->next : NULL; */
921 t->next = freeTokens;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000922 freeTokens = t;
923 return next;
924}
925
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000926/*
927 * Convert a line of tokens back into text.
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000928 * If expand_locals is not zero, identifiers of the form "%$*xxx"
929 * will be transformed into ..@ctxnum.xxx
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000930 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000931static char *
932detoken(Token * tlist, int expand_locals)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000933{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000934 Token *t;
935 int len;
936 char *line, *p;
937
938 len = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000939 for (t = tlist; t; t = t->next)
940 {
941 if (t->type == TOK_PREPROC_ID && t->text[1] == '!')
942 {
943 char *p = getenv(t->text + 2);
944 nasm_free(t->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000945 if (p)
946 t->text = nasm_strdup(p);
947 else
948 t->text = NULL;
949 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000950 /* Expand local macros here and not during preprocessing */
951 if (expand_locals &&
H. Peter Anvin734b1882002-04-30 21:01:08 +0000952 t->type == TOK_PREPROC_ID && t->text &&
953 t->text[0] == '%' && t->text[1] == '$')
954 {
955 Context *ctx = get_ctx(t->text, FALSE);
956 if (ctx)
957 {
958 char buffer[40];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000959 char *p, *q = t->text + 2;
960
H. Peter Anvin734b1882002-04-30 21:01:08 +0000961 q += strspn(q, "$");
962 sprintf(buffer, "..@%lu.", ctx->number);
963 p = nasm_strcat(buffer, q);
964 nasm_free(t->text);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000965 t->text = p;
966 }
967 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000968 if (t->type == TOK_WHITESPACE)
969 {
970 len++;
971 }
972 else if (t->text)
973 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000974 len += strlen(t->text);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000975 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000976 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000977 p = line = nasm_malloc(len + 1);
978 for (t = tlist; t; t = t->next)
979 {
980 if (t->type == TOK_WHITESPACE)
981 {
982 *p = ' ';
983 p++;
984 *p = '\0';
985 }
986 else if (t->text)
987 {
988 strcpy(p, t->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000989 p += strlen(p);
990 }
991 }
992 *p = '\0';
993 return line;
994}
995
996/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000997 * A scanner, suitable for use by the expression evaluator, which
998 * operates on a line of Tokens. Expects a pointer to a pointer to
999 * the first token in the line to be passed in as its private_data
1000 * field.
1001 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001002static int
1003ppscan(void *private_data, struct tokenval *tokval)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001004{
H. Peter Anvin76690a12002-04-30 20:52:49 +00001005 Token **tlineptr = private_data;
1006 Token *tline;
1007
H. Peter Anvin734b1882002-04-30 21:01:08 +00001008 do
1009 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00001010 tline = *tlineptr;
1011 *tlineptr = tline ? tline->next : NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001012 }
1013 while (tline && (tline->type == TOK_WHITESPACE ||
1014 tline->type == TOK_COMMENT));
H. Peter Anvin76690a12002-04-30 20:52:49 +00001015
1016 if (!tline)
1017 return tokval->t_type = TOKEN_EOS;
1018
1019 if (tline->text[0] == '$' && !tline->text[1])
1020 return tokval->t_type = TOKEN_HERE;
1021 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[1])
1022 return tokval->t_type = TOKEN_BASE;
1023
H. Peter Anvin734b1882002-04-30 21:01:08 +00001024 if (tline->type == TOK_ID)
1025 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00001026 tokval->t_charptr = tline->text;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001027 if (tline->text[0] == '$')
1028 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00001029 tokval->t_charptr++;
1030 return tokval->t_type = TOKEN_ID;
1031 }
1032
1033 /*
1034 * This is the only special case we actually need to worry
1035 * about in this restricted context.
1036 */
1037 if (!nasm_stricmp(tline->text, "seg"))
1038 return tokval->t_type = TOKEN_SEG;
1039
1040 return tokval->t_type = TOKEN_ID;
1041 }
1042
H. Peter Anvin734b1882002-04-30 21:01:08 +00001043 if (tline->type == TOK_NUMBER)
1044 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00001045 int rn_error;
1046
1047 tokval->t_integer = readnum(tline->text, &rn_error);
1048 if (rn_error)
1049 return tokval->t_type = TOKEN_ERRNUM;
1050 tokval->t_charptr = NULL;
1051 return tokval->t_type = TOKEN_NUM;
1052 }
1053
H. Peter Anvin734b1882002-04-30 21:01:08 +00001054 if (tline->type == TOK_STRING)
1055 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00001056 int rn_warn;
1057 char q, *r;
1058 int l;
1059
1060 r = tline->text;
1061 q = *r++;
1062 l = strlen(r);
1063
H. Peter Anvin734b1882002-04-30 21:01:08 +00001064 if (l == 0 || r[l - 1] != q)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001065 return tokval->t_type = TOKEN_ERRNUM;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001066 tokval->t_integer = readstrnum(r, l - 1, &rn_warn);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001067 if (rn_warn)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001068 error(ERR_WARNING | ERR_PASS1, "character constant too long");
H. Peter Anvineba20a72002-04-30 20:53:55 +00001069 tokval->t_charptr = NULL;
1070 return tokval->t_type = TOKEN_NUM;
1071 }
1072
H. Peter Anvin734b1882002-04-30 21:01:08 +00001073 if (tline->type == TOK_OTHER)
1074 {
1075 if (!strcmp(tline->text, "<<"))
1076 return tokval->t_type = TOKEN_SHL;
1077 if (!strcmp(tline->text, ">>"))
1078 return tokval->t_type = TOKEN_SHR;
1079 if (!strcmp(tline->text, "//"))
1080 return tokval->t_type = TOKEN_SDIV;
1081 if (!strcmp(tline->text, "%%"))
1082 return tokval->t_type = TOKEN_SMOD;
1083 if (!strcmp(tline->text, "=="))
1084 return tokval->t_type = TOKEN_EQ;
1085 if (!strcmp(tline->text, "<>"))
1086 return tokval->t_type = TOKEN_NE;
1087 if (!strcmp(tline->text, "!="))
1088 return tokval->t_type = TOKEN_NE;
1089 if (!strcmp(tline->text, "<="))
1090 return tokval->t_type = TOKEN_LE;
1091 if (!strcmp(tline->text, ">="))
1092 return tokval->t_type = TOKEN_GE;
1093 if (!strcmp(tline->text, "&&"))
1094 return tokval->t_type = TOKEN_DBL_AND;
1095 if (!strcmp(tline->text, "^^"))
1096 return tokval->t_type = TOKEN_DBL_XOR;
1097 if (!strcmp(tline->text, "||"))
1098 return tokval->t_type = TOKEN_DBL_OR;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001099 }
1100
1101 /*
1102 * We have no other options: just return the first character of
1103 * the token text.
1104 */
1105 return tokval->t_type = tline->text[0];
1106}
1107
1108/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001109 * Compare a string to the name of an existing macro; this is a
1110 * simple wrapper which calls either strcmp or nasm_stricmp
1111 * depending on the value of the `casesense' parameter.
1112 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001113static int
1114mstrcmp(char *p, char *q, int casesense)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001115{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001116 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001117}
1118
1119/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001120 * Return the Context structure associated with a %$ token. Return
1121 * NULL, having _already_ reported an error condition, if the
1122 * context stack isn't deep enough for the supplied number of $
1123 * signs.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001124 * If all_contexts == TRUE, contexts that enclose current are
1125 * also scanned for such smacro, until it is found; if not -
1126 * only the context that directly results from the number of $'s
1127 * in variable's name.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001128 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001129static Context *
1130get_ctx(char *name, int all_contexts)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001131{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001132 Context *ctx;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001133 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001134 int i;
1135
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001136 if (!name || name[0] != '%' || name[1] != '$')
1137 return NULL;
1138
H. Peter Anvin734b1882002-04-30 21:01:08 +00001139 if (!cstk)
1140 {
1141 error(ERR_NONFATAL, "`%s': context stack is empty", name);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001142 return NULL;
1143 }
1144
H. Peter Anvin734b1882002-04-30 21:01:08 +00001145 for (i = strspn(name + 2, "$"), ctx = cstk; (i > 0) && ctx; i--)
1146 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001147 ctx = ctx->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001148 i--;
1149 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001150 if (!ctx)
1151 {
1152 error(ERR_NONFATAL, "`%s': context stack is only"
1153 " %d level%s deep", name, i - 1, (i == 2 ? "" : "s"));
1154 return NULL;
1155 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001156 if (!all_contexts)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001157 return ctx;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001158
H. Peter Anvin734b1882002-04-30 21:01:08 +00001159 do
1160 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001161 /* Search for this smacro in found context */
1162 m = ctx->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001163 while (m)
1164 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001165 if (!mstrcmp(m->name, name, m->casesense))
1166 return ctx;
1167 m = m->next;
1168 }
1169 ctx = ctx->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001170 }
1171 while (ctx);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001172 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001173}
1174
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001175/* Add a slash to the end of a path if it is missing. We use the
1176 * forward slash to make it compatible with Unix systems.
1177 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001178static void
1179backslash(char *s)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001180{
1181 int pos = strlen(s);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001182 if (s[pos - 1] != '\\' && s[pos - 1] != '/')
1183 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001184 s[pos] = '/';
H. Peter Anvin734b1882002-04-30 21:01:08 +00001185 s[pos + 1] = '\0';
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001186 }
1187}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001188
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001189/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001190 * Open an include file. This routine must always return a valid
1191 * file pointer if it returns - it's responsible for throwing an
1192 * ERR_FATAL and bombing out completely if not. It should also try
1193 * the include path one by one until it finds the file or reaches
1194 * the end of the path.
1195 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001196static FILE *
1197inc_fopen(char *file)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001198{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001199 FILE *fp;
1200 char *prefix = "", *combine;
1201 IncPath *ip = ipath;
H. Peter Anvin620515a2002-04-30 20:57:38 +00001202 static int namelen = 0;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001203 int len = strlen(file);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001204
H. Peter Anvin734b1882002-04-30 21:01:08 +00001205 while (1)
1206 {
1207 combine = nasm_malloc(strlen(prefix) + 1 + len + 1);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001208 strcpy(combine, prefix);
1209 if (prefix[0] != 0)
1210 backslash(combine);
1211 strcat(combine, file);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001212 fp = fopen(combine, "r");
H. Peter Anvin620515a2002-04-30 20:57:38 +00001213 if (pass == 0 && fp)
1214 {
H. Peter Anvin734b1882002-04-30 21:01:08 +00001215 namelen += strlen(combine) + 1;
1216 if (namelen > 62)
1217 {
1218 printf(" \\\n ");
1219 namelen = 2;
1220 }
1221 printf(" %s", combine);
H. Peter Anvin620515a2002-04-30 20:57:38 +00001222 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001223 nasm_free(combine);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001224 if (fp)
1225 return fp;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001226 if (!ip)
1227 break;
1228 prefix = ip->path;
1229 ip = ip->next;
1230 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001231
H. Peter Anvin734b1882002-04-30 21:01:08 +00001232 error(ERR_FATAL, "unable to open include file `%s'", file);
1233 return NULL; /* never reached - placate compilers */
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001234}
1235
1236/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001237 * Determine if we should warn on defining a single-line macro of
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001238 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001239 * return TRUE if _any_ single-line macro of that name is defined.
1240 * Otherwise, will return TRUE if a single-line macro with either
1241 * `nparam' or no parameters is defined.
1242 *
1243 * If a macro with precisely the right number of parameters is
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001244 * defined, or nparam is -1, the address of the definition structure
1245 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001246 * is NULL, no action will be taken regarding its contents, and no
1247 * error will occur.
1248 *
1249 * Note that this is also called with nparam zero to resolve
1250 * `ifdef'.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001251 *
1252 * If you already know which context macro belongs to, you can pass
1253 * the context pointer as first parameter; if you won't but name begins
1254 * with %$ the context will be automatically computed. If all_contexts
1255 * is true, macro will be searched in outer contexts as well.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001256 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001257static int
1258smacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn,
1259 int nocase)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001260{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001261 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001262
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001263 if (ctx)
1264 m = ctx->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001265 else if (name[0] == '%' && name[1] == '$')
1266 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001267 if (cstk)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001268 ctx = get_ctx(name, FALSE);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001269 if (!ctx)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001270 return FALSE; /* got to return _something_ */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001271 m = ctx->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001272 }
1273 else
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001274 m = smacros[hash(name)];
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001275
H. Peter Anvin734b1882002-04-30 21:01:08 +00001276 while (m)
1277 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001278 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
H. Peter Anvin734b1882002-04-30 21:01:08 +00001279 (nparam <= 0 || m->nparam == 0 || nparam == m->nparam))
1280 {
1281 if (defn)
1282 {
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001283 if (nparam == m->nparam || nparam == -1)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001284 *defn = m;
1285 else
1286 *defn = NULL;
1287 }
1288 return TRUE;
1289 }
1290 m = m->next;
1291 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001292
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001293 return FALSE;
1294}
1295
1296/*
1297 * Count and mark off the parameters in a multi-line macro call.
1298 * This is called both from within the multi-line macro expansion
1299 * code, and also to mark off the default parameters when provided
1300 * in a %macro definition line.
1301 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001302static void
1303count_mmac_params(Token * t, int *nparam, Token *** params)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001304{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001305 int paramsize, brace;
1306
1307 *nparam = paramsize = 0;
1308 *params = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001309 while (t)
1310 {
1311 if (*nparam >= paramsize)
1312 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001313 paramsize += PARAM_DELTA;
1314 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1315 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001316 skip_white_(t);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001317 brace = FALSE;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001318 if (tok_is_(t, "{"))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001319 brace = TRUE;
1320 (*params)[(*nparam)++] = t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001321 while (tok_isnt_(t, brace ? "}" : ","))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001322 t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001323 if (t)
1324 { /* got a comma/brace */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001325 t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001326 if (brace)
1327 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001328 /*
1329 * Now we've found the closing brace, look further
1330 * for the comma.
1331 */
H. Peter Anvineba20a72002-04-30 20:53:55 +00001332 skip_white_(t);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001333 if (tok_isnt_(t, ","))
1334 {
1335 error(ERR_NONFATAL,
1336 "braces do not enclose all of macro parameter");
H. Peter Anvineba20a72002-04-30 20:53:55 +00001337 while (tok_isnt_(t, ","))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001338 t = t->next;
1339 }
1340 if (t)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001341 t = t->next; /* eat the comma */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001342 }
1343 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001344 }
1345}
1346
1347/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001348 * Determine whether one of the various `if' conditions is true or
1349 * not.
1350 *
1351 * We must free the tline we get passed.
1352 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001353static int
1354if_condition(Token * tline, int i)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001355{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001356 int j, casesense;
1357 Token *t, *tt, **tptr, *origline;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001358 struct tokenval tokval;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001359 expr *evalresult;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001360
1361 origline = tline;
1362
H. Peter Anvin734b1882002-04-30 21:01:08 +00001363 switch (i)
1364 {
1365 case PP_IFCTX:
1366 case PP_ELIFCTX:
1367 case PP_IFNCTX:
1368 case PP_ELIFNCTX:
1369 j = FALSE; /* have we matched yet? */
1370 while (cstk && tline)
1371 {
1372 skip_white_(tline);
1373 if (!tline || tline->type != TOK_ID)
1374 {
1375 error(ERR_NONFATAL,
1376 "`%s' expects context identifiers",
1377 directives[i]);
1378 free_tlist(origline);
1379 return -1;
1380 }
1381 if (!nasm_stricmp(tline->text, cstk->name))
1382 j = TRUE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001383 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001384 }
1385 if (i == PP_IFNCTX || i == PP_ELIFNCTX)
1386 j = !j;
1387 free_tlist(origline);
1388 return j;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001389
H. Peter Anvin734b1882002-04-30 21:01:08 +00001390 case PP_IFDEF:
1391 case PP_ELIFDEF:
1392 case PP_IFNDEF:
1393 case PP_ELIFNDEF:
1394 j = FALSE; /* have we matched yet? */
1395 while (tline)
1396 {
1397 skip_white_(tline);
1398 if (!tline || (tline->type != TOK_ID &&
1399 (tline->type != TOK_PREPROC_ID ||
1400 tline->text[1] != '$')))
1401 {
1402 error(ERR_NONFATAL,
1403 "`%%if%sdef' expects macro identifiers",
1404 (i == PP_ELIFNDEF ? "n" : ""));
1405 free_tlist(origline);
1406 return -1;
1407 }
1408 if (smacro_defined(NULL, tline->text, 0, NULL, 1))
1409 j = TRUE;
1410 tline = tline->next;
1411 }
1412 if (i == PP_IFNDEF || i == PP_ELIFNDEF)
1413 j = !j;
1414 free_tlist(origline);
1415 return j;
1416
1417 case PP_IFIDN:
1418 case PP_ELIFIDN:
1419 case PP_IFNIDN:
1420 case PP_ELIFNIDN:
1421 case PP_IFIDNI:
1422 case PP_ELIFIDNI:
1423 case PP_IFNIDNI:
1424 case PP_ELIFNIDNI:
1425 tline = expand_smacro(tline);
1426 t = tt = tline;
1427 while (tok_isnt_(tt, ","))
1428 tt = tt->next;
1429 if (!tt)
1430 {
1431 error(ERR_NONFATAL,
1432 "`%s' expects two comma-separated arguments",
1433 directives[i]);
1434 free_tlist(tline);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001435 return -1;
1436 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001437 tt = tt->next;
1438 casesense = (i == PP_IFIDN || i == PP_ELIFIDN ||
1439 i == PP_IFNIDN || i == PP_ELIFNIDN);
1440 j = TRUE; /* assume equality unless proved not */
1441 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt)
1442 {
1443 if (tt->type == TOK_OTHER && !strcmp(tt->text, ","))
1444 {
1445 error(ERR_NONFATAL, "`%s': more than one comma on line",
1446 directives[i]);
1447 free_tlist(tline);
1448 return -1;
1449 }
1450 if (t->type == TOK_WHITESPACE)
1451 {
1452 t = t->next;
1453 continue;
1454 }
1455 else if (tt->type == TOK_WHITESPACE)
1456 {
1457 tt = tt->next;
1458 continue;
1459 }
1460 else if (tt->type != t->type ||
1461 mstrcmp(tt->text, t->text, casesense))
1462 {
1463 j = FALSE; /* found mismatching tokens */
1464 break;
1465 }
1466 else
1467 {
1468 t = t->next;
1469 tt = tt->next;
1470 continue;
1471 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001472 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001473 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
1474 j = FALSE; /* trailing gunk on one end or other */
1475 if (i == PP_IFNIDN || i == PP_ELIFNIDN ||
1476 i == PP_IFNIDNI || i == PP_ELIFNIDNI)
1477 j = !j;
1478 free_tlist(tline);
1479 return j;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001480
H. Peter Anvin734b1882002-04-30 21:01:08 +00001481 case PP_IFID:
1482 case PP_ELIFID:
1483 case PP_IFNID:
1484 case PP_ELIFNID:
1485 case PP_IFNUM:
1486 case PP_ELIFNUM:
1487 case PP_IFNNUM:
1488 case PP_ELIFNNUM:
1489 case PP_IFSTR:
1490 case PP_ELIFSTR:
1491 case PP_IFNSTR:
1492 case PP_ELIFNSTR:
1493 tline = expand_smacro(tline);
1494 t = tline;
1495 while (tok_type_(t, TOK_WHITESPACE))
1496 t = t->next;
1497 j = FALSE; /* placate optimiser */
1498 if (t)
1499 switch (i)
1500 {
1501 case PP_IFID:
1502 case PP_ELIFID:
1503 case PP_IFNID:
1504 case PP_ELIFNID:
1505 j = (t->type == TOK_ID);
1506 break;
1507 case PP_IFNUM:
1508 case PP_ELIFNUM:
1509 case PP_IFNNUM:
1510 case PP_ELIFNNUM:
1511 j = (t->type == TOK_NUMBER);
1512 break;
1513 case PP_IFSTR:
1514 case PP_ELIFSTR:
1515 case PP_IFNSTR:
1516 case PP_ELIFNSTR:
1517 j = (t->type == TOK_STRING);
1518 break;
1519 }
1520 if (i == PP_IFNID || i == PP_ELIFNID ||
1521 i == PP_IFNNUM || i == PP_ELIFNNUM ||
1522 i == PP_IFNSTR || i == PP_ELIFNSTR)
1523 j = !j;
1524 free_tlist(tline);
1525 return j;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001526
H. Peter Anvin734b1882002-04-30 21:01:08 +00001527 case PP_IF:
1528 case PP_ELIF:
1529 t = tline = expand_smacro(tline);
1530 tptr = &t;
1531 tokval.t_type = TOKEN_INVALID;
1532 evalresult = evaluate(ppscan, tptr, &tokval,
1533 NULL, pass | CRITICAL, error, NULL);
1534 free_tlist(tline);
1535 if (!evalresult)
1536 return -1;
1537 if (tokval.t_type)
1538 error(ERR_WARNING,
1539 "trailing garbage after expression ignored");
1540 if (!is_simple(evalresult))
1541 {
1542 error(ERR_NONFATAL,
1543 "non-constant value given to `%s'", directives[i]);
1544 return -1;
1545 }
1546 return reloc_value(evalresult) != 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001547
H. Peter Anvin734b1882002-04-30 21:01:08 +00001548 default:
1549 error(ERR_FATAL,
1550 "preprocessor directive `%s' not yet implemented",
1551 directives[i]);
1552 free_tlist(origline);
1553 return -1; /* yeah, right */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001554 }
1555}
1556
1557/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001558 * Expand macros in a string. Used in %error and %include directives.
1559 * First tokenise the string, apply "expand_smacro" and then de-tokenise back.
1560 * The returned variable should ALWAYS be freed after usage.
1561 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001562void
1563expand_macros_in_string(char **p)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001564{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001565 Token *line = tokenise(*p);
1566 line = expand_smacro(line);
1567 *p = detoken(line, FALSE);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001568}
1569
1570/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001571 * Find out if a line contains a preprocessor directive, and deal
1572 * with it if so.
1573 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00001574 * If a directive _is_ found, we are expected to free_tlist() the
1575 * line.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001576 *
1577 * Return values go like this:
1578 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00001579 * bit 0 is set if a directive was found (so the line gets freed)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001580 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001581static int
1582do_directive(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001583{
H. Peter Anvin76690a12002-04-30 20:52:49 +00001584 int i, j, k, m, nparam, nolist;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001585 int offset;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001586 char *p, *mname;
1587 Include *inc;
1588 Context *ctx;
1589 Cond *cond;
1590 SMacro *smac, **smhead;
1591 MMacro *mmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001592 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
1593 Line *l;
1594 struct tokenval tokval;
1595 expr *evalresult;
H. Peter Anvinb64535f2002-04-30 20:55:37 +00001596 MMacro *tmp_defining; /* Used when manipulating rep_nest */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001597
1598 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001599
H. Peter Anvineba20a72002-04-30 20:53:55 +00001600 skip_white_(tline);
1601 if (!tok_type_(tline, TOK_PREPROC_ID) ||
H. Peter Anvin734b1882002-04-30 21:01:08 +00001602 (tline->text[1] == '%' || tline->text[1] == '$'
1603 || tline->text[1] == '!'))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001604 return 0;
1605
1606 i = -1;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001607 j = sizeof(directives) / sizeof(*directives);
1608 while (j - i > 1)
1609 {
1610 k = (j + i) / 2;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001611 m = nasm_stricmp(tline->text, directives[k]);
1612 if (m == 0) {
H. Peter Anvin734b1882002-04-30 21:01:08 +00001613 if (tasm_compatible_mode) {
1614 i = k;
1615 j = -2;
1616 } else if (k != PP_ARG && k != PP_LOCAL && k != PP_STACKSIZE) {
1617 i = k;
1618 j = -2;
1619 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001620 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001621 }
1622 else if (m < 0) {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001623 j = k;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001624 }
1625 else
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001626 i = k;
1627 }
1628
1629 /*
1630 * If we're in a non-emitting branch of a condition construct,
H. Peter Anvin76690a12002-04-30 20:52:49 +00001631 * or walking to the end of an already terminated %rep block,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001632 * we should ignore all directives except for condition
1633 * directives.
1634 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001635 if (((istk->conds && !emitting(istk->conds->state)) ||
H. Peter Anvin734b1882002-04-30 21:01:08 +00001636 (istk->mstk && !istk->mstk->in_progress)) &&
1637 i != PP_IF && i != PP_ELIF &&
1638 i != PP_IFCTX && i != PP_ELIFCTX &&
1639 i != PP_IFDEF && i != PP_ELIFDEF &&
1640 i != PP_IFID && i != PP_ELIFID &&
1641 i != PP_IFIDN && i != PP_ELIFIDN &&
1642 i != PP_IFIDNI && i != PP_ELIFIDNI &&
1643 i != PP_IFNCTX && i != PP_ELIFNCTX &&
1644 i != PP_IFNDEF && i != PP_ELIFNDEF &&
1645 i != PP_IFNID && i != PP_ELIFNID &&
1646 i != PP_IFNIDN && i != PP_ELIFNIDN &&
1647 i != PP_IFNIDNI && i != PP_ELIFNIDNI &&
1648 i != PP_IFNNUM && i != PP_ELIFNNUM &&
1649 i != PP_IFNSTR && i != PP_ELIFNSTR &&
1650 i != PP_IFNUM && i != PP_ELIFNUM &&
1651 i != PP_IFSTR && i != PP_ELIFSTR && i != PP_ELSE && i != PP_ENDIF)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001652 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001653 return 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001654 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001655
1656 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001657 * If we're defining a macro or reading a %rep block, we should
1658 * ignore all directives except for %macro/%imacro (which
1659 * generate an error), %endm/%endmacro, and (only if we're in a
H. Peter Anvineba20a72002-04-30 20:53:55 +00001660 * %rep block) %endrep. If we're in a %rep block, another %rep
1661 * causes an error, so should be let through.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001662 */
1663 if (defining && i != PP_MACRO && i != PP_IMACRO &&
H. Peter Anvin734b1882002-04-30 21:01:08 +00001664 i != PP_ENDMACRO && i != PP_ENDM &&
1665 (defining->name || (i != PP_ENDREP && i != PP_REP)))
H. Peter Anvineba20a72002-04-30 20:53:55 +00001666 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001667 return 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001668 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001669
H. Peter Anvin734b1882002-04-30 21:01:08 +00001670 if (j != -2)
1671 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00001672 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
H. Peter Anvin734b1882002-04-30 21:01:08 +00001673 tline->text);
1674 return 0; /* didn't get it */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001675 }
1676
H. Peter Anvin734b1882002-04-30 21:01:08 +00001677 switch (i)
1678 {
1679 case PP_STACKSIZE:
1680 /* Directive to tell NASM what the default stack size is. The
1681 * default is for a 16-bit stack, and this can be overriden with
1682 * %stacksize large.
1683 * the following form:
1684 *
1685 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001686 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001687 tline = tline->next;
1688 if (tline && tline->type == TOK_WHITESPACE)
1689 tline = tline->next;
1690 if (!tline || tline->type != TOK_ID)
1691 {
1692 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
1693 free_tlist(origline);
1694 return 3;
1695 }
1696 if (nasm_stricmp(tline->text, "flat") == 0)
1697 {
1698 /* All subsequent ARG directives are for a 32-bit stack */
1699 StackSize = 4;
1700 StackPointer = "ebp";
1701 ArgOffset = 8;
1702 LocalOffset = 4;
1703 }
1704 else if (nasm_stricmp(tline->text, "large") == 0)
1705 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001706 /* All subsequent ARG directives are for a 16-bit stack,
H. Peter Anvin734b1882002-04-30 21:01:08 +00001707 * far function call.
1708 */
1709 StackSize = 2;
1710 StackPointer = "bp";
1711 ArgOffset = 4;
1712 LocalOffset = 2;
1713 }
1714 else if (nasm_stricmp(tline->text, "small") == 0)
1715 {
1716 /* All subsequent ARG directives are for a 16-bit stack,
1717 * far function call. We don't support near functions.
1718 */
1719 StackSize = 2;
1720 StackPointer = "bp";
1721 ArgOffset = 6;
1722 LocalOffset = 2;
1723 }
1724 else
1725 {
1726 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
1727 free_tlist(origline);
1728 return 3;
1729 }
1730 free_tlist(origline);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001731 return 3;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001732
H. Peter Anvin734b1882002-04-30 21:01:08 +00001733 case PP_ARG:
1734 /* TASM like ARG directive to define arguments to functions, in
1735 * the following form:
1736 *
1737 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1738 */
1739 offset = ArgOffset;
1740 do
1741 {
1742 char *arg, directive[256];
1743 int size = StackSize;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001744
H. Peter Anvin734b1882002-04-30 21:01:08 +00001745 /* Find the argument name */
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001746 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001747 if (tline && tline->type == TOK_WHITESPACE)
1748 tline = tline->next;
1749 if (!tline || tline->type != TOK_ID)
1750 {
1751 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
1752 free_tlist(origline);
1753 return 3;
1754 }
1755 arg = tline->text;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001756
H. Peter Anvin734b1882002-04-30 21:01:08 +00001757 /* Find the argument size type */
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001758 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001759 if (!tline || tline->type != TOK_OTHER
1760 || tline->text[0] != ':')
1761 {
1762 error(ERR_NONFATAL,
1763 "Syntax error processing `%%arg' directive");
1764 free_tlist(origline);
1765 return 3;
1766 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001767 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001768 if (!tline || tline->type != TOK_ID)
1769 {
1770 error(ERR_NONFATAL,
1771 "`%%arg' missing size type parameter");
1772 free_tlist(origline);
1773 return 3;
1774 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001775
H. Peter Anvin734b1882002-04-30 21:01:08 +00001776 /* Allow macro expansion of type parameter */
1777 tt = tokenise(tline->text);
1778 tt = expand_smacro(tt);
1779 if (nasm_stricmp(tt->text, "byte") == 0)
1780 {
1781 size = MAX(StackSize, 1);
1782 }
1783 else if (nasm_stricmp(tt->text, "word") == 0)
1784 {
1785 size = MAX(StackSize, 2);
1786 }
1787 else if (nasm_stricmp(tt->text, "dword") == 0)
1788 {
1789 size = MAX(StackSize, 4);
1790 }
1791 else if (nasm_stricmp(tt->text, "qword") == 0)
1792 {
1793 size = MAX(StackSize, 8);
1794 }
1795 else if (nasm_stricmp(tt->text, "tword") == 0)
1796 {
1797 size = MAX(StackSize, 10);
1798 }
1799 else
1800 {
1801 error(ERR_NONFATAL,
1802 "Invalid size type for `%%arg' missing directive");
1803 free_tlist(tt);
1804 free_tlist(origline);
1805 return 3;
1806 }
1807 free_tlist(tt);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001808
H. Peter Anvin734b1882002-04-30 21:01:08 +00001809 /* Now define the macro for the argument */
1810 sprintf(directive, "%%define %s (%s+%d)", arg, StackPointer,
1811 offset);
1812 do_directive(tokenise(directive));
1813 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001814
H. Peter Anvin734b1882002-04-30 21:01:08 +00001815 /* Move to the next argument in the list */
1816 tline = tline->next;
1817 if (tline && tline->type == TOK_WHITESPACE)
1818 tline = tline->next;
1819 }
1820 while (tline && tline->type == TOK_OTHER
1821 && tline->text[0] == ',');
1822 free_tlist(origline);
1823 return 3;
1824
1825 case PP_LOCAL:
1826 /* TASM like LOCAL directive to define local variables for a
1827 * function, in the following form:
1828 *
1829 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
1830 *
1831 * The '= LocalSize' at the end is ignored by NASM, but is
1832 * required by TASM to define the local parameter size (and used
1833 * by the TASM macro package).
1834 */
1835 offset = LocalOffset;
1836 do
1837 {
1838 char *local, directive[256];
1839 int size = StackSize;
1840
1841 /* Find the argument name */
1842 tline = tline->next;
1843 if (tline && tline->type == TOK_WHITESPACE)
1844 tline = tline->next;
1845 if (!tline || tline->type != TOK_ID)
1846 {
1847 error(ERR_NONFATAL,
1848 "`%%local' missing argument parameter");
1849 free_tlist(origline);
1850 return 3;
1851 }
1852 local = tline->text;
1853
1854 /* Find the argument size type */
1855 tline = tline->next;
1856 if (!tline || tline->type != TOK_OTHER
1857 || tline->text[0] != ':')
1858 {
1859 error(ERR_NONFATAL,
1860 "Syntax error processing `%%local' directive");
1861 free_tlist(origline);
1862 return 3;
1863 }
1864 tline = tline->next;
1865 if (!tline || tline->type != TOK_ID)
1866 {
1867 error(ERR_NONFATAL,
1868 "`%%local' missing size type parameter");
1869 free_tlist(origline);
1870 return 3;
1871 }
1872
1873 /* Allow macro expansion of type parameter */
1874 tt = tokenise(tline->text);
1875 tt = expand_smacro(tt);
1876 if (nasm_stricmp(tt->text, "byte") == 0)
1877 {
1878 size = MAX(StackSize, 1);
1879 }
1880 else if (nasm_stricmp(tt->text, "word") == 0)
1881 {
1882 size = MAX(StackSize, 2);
1883 }
1884 else if (nasm_stricmp(tt->text, "dword") == 0)
1885 {
1886 size = MAX(StackSize, 4);
1887 }
1888 else if (nasm_stricmp(tt->text, "qword") == 0)
1889 {
1890 size = MAX(StackSize, 8);
1891 }
1892 else if (nasm_stricmp(tt->text, "tword") == 0)
1893 {
1894 size = MAX(StackSize, 10);
1895 }
1896 else
1897 {
1898 error(ERR_NONFATAL,
1899 "Invalid size type for `%%local' missing directive");
1900 free_tlist(tt);
1901 free_tlist(origline);
1902 return 3;
1903 }
1904 free_tlist(tt);
1905
1906 /* Now define the macro for the argument */
1907 sprintf(directive, "%%define %s (%s-%d)", local, StackPointer,
1908 offset);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001909 do_directive(tokenise(directive));
1910 offset += size;
1911
1912 /* Now define the assign to setup the enter_c macro correctly */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001913 sprintf(directive, "%%assign %%$localsize %%$localsize+%d",
1914 size);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001915 do_directive(tokenise(directive));
1916
H. Peter Anvin734b1882002-04-30 21:01:08 +00001917 /* Move to the next argument in the list */
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001918 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001919 if (tline && tline->type == TOK_WHITESPACE)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001920 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001921 }
1922 while (tline && tline->type == TOK_OTHER
1923 && tline->text[0] == ',');
1924 free_tlist(origline);
1925 return 3;
1926
1927 case PP_CLEAR:
1928 if (tline->next)
1929 error(ERR_WARNING,
1930 "trailing garbage after `%%clear' ignored");
1931 for (j = 0; j < NHASH; j++)
1932 {
1933 while (mmacros[j])
1934 {
1935 MMacro *m = mmacros[j];
1936 mmacros[j] = m->next;
1937 free_mmacro(m);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001938 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001939 while (smacros[j])
1940 {
1941 SMacro *s = smacros[j];
1942 smacros[j] = smacros[j]->next;
1943 nasm_free(s->name);
1944 free_tlist(s->expansion);
1945 nasm_free(s);
1946 }
1947 }
1948 free_tlist(origline);
1949 return 3;
1950
1951 case PP_INCLUDE:
1952 tline = tline->next;
1953 skip_white_(tline);
1954 if (!tline || (tline->type != TOK_STRING &&
1955 tline->type != TOK_INTERNAL_STRING))
1956 {
1957 error(ERR_NONFATAL, "`%%include' expects a file name");
1958 free_tlist(origline);
1959 return 3; /* but we did _something_ */
1960 }
1961 if (tline->next)
1962 error(ERR_WARNING,
1963 "trailing garbage after `%%include' ignored");
1964 if (tline->type != TOK_INTERNAL_STRING)
1965 {
1966 p = tline->text + 1; /* point past the quote to the name */
1967 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
1968 }
1969 else
1970 p = tline->text; /* internal_string is easier */
1971 expand_macros_in_string(&p);
1972 inc = nasm_malloc(sizeof(Include));
1973 inc->next = istk;
1974 inc->conds = NULL;
1975 inc->fp = inc_fopen(p);
1976 inc->fname = src_set_fname(p);
1977 inc->lineno = src_set_linnum(0);
1978 inc->lineinc = 1;
1979 inc->expansion = NULL;
1980 inc->mstk = NULL;
1981 istk = inc;
1982 list->uplevel(LIST_INCLUDE);
1983 free_tlist(origline);
1984 return 5;
1985
1986 case PP_PUSH:
1987 tline = tline->next;
1988 skip_white_(tline);
1989 tline = expand_id(tline);
1990 if (!tok_type_(tline, TOK_ID))
1991 {
1992 error(ERR_NONFATAL, "`%%push' expects a context identifier");
1993 free_tlist(origline);
1994 return 3; /* but we did _something_ */
1995 }
1996 if (tline->next)
1997 error(ERR_WARNING, "trailing garbage after `%%push' ignored");
1998 ctx = nasm_malloc(sizeof(Context));
1999 ctx->next = cstk;
2000 ctx->localmac = NULL;
2001 ctx->name = nasm_strdup(tline->text);
2002 ctx->number = unique++;
2003 cstk = ctx;
2004 free_tlist(origline);
2005 break;
2006
2007 case PP_REPL:
2008 tline = tline->next;
2009 skip_white_(tline);
2010 tline = expand_id(tline);
2011 if (!tok_type_(tline, TOK_ID))
2012 {
2013 error(ERR_NONFATAL, "`%%repl' expects a context identifier");
2014 free_tlist(origline);
2015 return 3; /* but we did _something_ */
2016 }
2017 if (tline->next)
2018 error(ERR_WARNING, "trailing garbage after `%%repl' ignored");
2019 if (!cstk)
2020 error(ERR_NONFATAL, "`%%repl': context stack is empty");
2021 else
2022 {
2023 nasm_free(cstk->name);
2024 cstk->name = nasm_strdup(tline->text);
2025 }
2026 free_tlist(origline);
2027 break;
2028
2029 case PP_POP:
2030 if (tline->next)
2031 error(ERR_WARNING, "trailing garbage after `%%pop' ignored");
2032 if (!cstk)
2033 error(ERR_NONFATAL,
2034 "`%%pop': context stack is already empty");
2035 else
2036 ctx_pop();
2037 free_tlist(origline);
2038 break;
2039
2040 case PP_ERROR:
2041 tline->next = expand_smacro(tline->next);
2042 tline = tline->next;
2043 skip_white_(tline);
2044 if (tok_type_(tline, TOK_STRING))
2045 {
2046 p = tline->text + 1; /* point past the quote to the name */
2047 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
2048 expand_macros_in_string(&p);
2049 error(ERR_NONFATAL, "%s", p);
2050 nasm_free(p);
2051 }
2052 else
2053 {
2054 p = detoken(tline, FALSE);
2055 error(ERR_WARNING, "%s", p);
2056 nasm_free(p);
2057 }
2058 free_tlist(origline);
2059 break;
2060
2061 case PP_IF:
2062 case PP_IFCTX:
2063 case PP_IFDEF:
2064 case PP_IFID:
2065 case PP_IFIDN:
2066 case PP_IFIDNI:
2067 case PP_IFNCTX:
2068 case PP_IFNDEF:
2069 case PP_IFNID:
2070 case PP_IFNIDN:
2071 case PP_IFNIDNI:
2072 case PP_IFNNUM:
2073 case PP_IFNSTR:
2074 case PP_IFNUM:
2075 case PP_IFSTR:
2076 if (istk->conds && !emitting(istk->conds->state))
2077 j = COND_NEVER;
2078 else
2079 {
2080 j = if_condition(tline->next, i);
2081 tline->next = NULL; /* it got freed */
2082 free_tlist(origline);
2083 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2084 }
2085 cond = nasm_malloc(sizeof(Cond));
2086 cond->next = istk->conds;
2087 cond->state = j;
2088 istk->conds = cond;
2089 return (j == COND_IF_TRUE ? 3 : 1);
2090
2091 case PP_ELIF:
2092 case PP_ELIFCTX:
2093 case PP_ELIFDEF:
2094 case PP_ELIFID:
2095 case PP_ELIFIDN:
2096 case PP_ELIFIDNI:
2097 case PP_ELIFNCTX:
2098 case PP_ELIFNDEF:
2099 case PP_ELIFNID:
2100 case PP_ELIFNIDN:
2101 case PP_ELIFNIDNI:
2102 case PP_ELIFNNUM:
2103 case PP_ELIFNSTR:
2104 case PP_ELIFNUM:
2105 case PP_ELIFSTR:
2106 if (!istk->conds)
2107 error(ERR_FATAL, "`%s': no matching `%%if'", directives[i]);
2108 if (emitting(istk->conds->state)
2109 || istk->conds->state == COND_NEVER)
2110 istk->conds->state = COND_NEVER;
2111 else
2112 {
2113 j = if_condition(expand_mmac_params(tline->next), i);
2114 tline->next = NULL; /* it got freed */
2115 free_tlist(origline);
2116 istk->conds->state =
2117 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2118 }
2119 return (istk->conds->state == COND_IF_TRUE ? 5 : 1);
2120
2121 case PP_ELSE:
2122 if (tline->next)
2123 error(ERR_WARNING, "trailing garbage after `%%else' ignored");
2124 if (!istk->conds)
2125 error(ERR_FATAL, "`%%else': no matching `%%if'");
2126 if (emitting(istk->conds->state)
2127 || istk->conds->state == COND_NEVER)
2128 istk->conds->state = COND_ELSE_FALSE;
2129 else
2130 istk->conds->state = COND_ELSE_TRUE;
2131 free_tlist(origline);
2132 return 5;
2133
2134 case PP_ENDIF:
2135 if (tline->next)
2136 error(ERR_WARNING,
2137 "trailing garbage after `%%endif' ignored");
2138 if (!istk->conds)
2139 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2140 cond = istk->conds;
2141 istk->conds = cond->next;
2142 nasm_free(cond);
2143 free_tlist(origline);
2144 return 5;
2145
2146 case PP_MACRO:
2147 case PP_IMACRO:
2148 if (defining)
2149 error(ERR_FATAL,
2150 "`%%%smacro': already defining a macro",
2151 (i == PP_IMACRO ? "i" : ""));
2152 tline = tline->next;
2153 skip_white_(tline);
2154 tline = expand_id(tline);
2155 if (!tok_type_(tline, TOK_ID))
2156 {
2157 error(ERR_NONFATAL,
2158 "`%%%smacro' expects a macro name",
2159 (i == PP_IMACRO ? "i" : ""));
2160 return 3;
2161 }
2162 defining = nasm_malloc(sizeof(MMacro));
2163 defining->name = nasm_strdup(tline->text);
2164 defining->casesense = (i == PP_MACRO);
2165 defining->plus = FALSE;
2166 defining->nolist = FALSE;
2167 defining->in_progress = FALSE;
2168 defining->rep_nest = NULL;
2169 tline = expand_smacro(tline->next);
2170 skip_white_(tline);
2171 if (!tok_type_(tline, TOK_NUMBER))
2172 {
2173 error(ERR_NONFATAL,
2174 "`%%%smacro' expects a parameter count",
2175 (i == PP_IMACRO ? "i" : ""));
2176 defining->nparam_min = defining->nparam_max = 0;
2177 }
2178 else
2179 {
2180 defining->nparam_min = defining->nparam_max =
2181 readnum(tline->text, &j);
2182 if (j)
2183 error(ERR_NONFATAL,
2184 "unable to parse parameter count `%s'",
2185 tline->text);
2186 }
2187 if (tline && tok_is_(tline->next, "-"))
2188 {
2189 tline = tline->next->next;
2190 if (tok_is_(tline, "*"))
2191 defining->nparam_max = INT_MAX;
2192 else if (!tok_type_(tline, TOK_NUMBER))
2193 error(ERR_NONFATAL,
2194 "`%%%smacro' expects a parameter count after `-'",
2195 (i == PP_IMACRO ? "i" : ""));
2196 else
2197 {
2198 defining->nparam_max = readnum(tline->text, &j);
2199 if (j)
2200 error(ERR_NONFATAL,
2201 "unable to parse parameter count `%s'",
2202 tline->text);
2203 if (defining->nparam_min > defining->nparam_max)
2204 error(ERR_NONFATAL,
2205 "minimum parameter count exceeds maximum");
2206 }
2207 }
2208 if (tline && tok_is_(tline->next, "+"))
2209 {
2210 tline = tline->next;
2211 defining->plus = TRUE;
2212 }
2213 if (tline && tok_type_(tline->next, TOK_ID) &&
2214 !nasm_stricmp(tline->next->text, ".nolist"))
2215 {
2216 tline = tline->next;
2217 defining->nolist = TRUE;
2218 }
2219 mmac = mmacros[hash(defining->name)];
2220 while (mmac)
2221 {
2222 if (!strcmp(mmac->name, defining->name) &&
2223 (mmac->nparam_min <= defining->nparam_max
2224 || defining->plus)
2225 && (defining->nparam_min <= mmac->nparam_max
2226 || mmac->plus))
2227 {
2228 error(ERR_WARNING,
2229 "redefining multi-line macro `%s'",
2230 defining->name);
2231 break;
2232 }
2233 mmac = mmac->next;
2234 }
2235 /*
2236 * Handle default parameters.
2237 */
2238 if (tline && tline->next)
2239 {
2240 defining->dlist = tline->next;
2241 tline->next = NULL;
2242 count_mmac_params(defining->dlist, &defining->ndefs,
2243 &defining->defaults);
2244 }
2245 else
2246 {
2247 defining->dlist = NULL;
2248 defining->defaults = NULL;
2249 }
2250 defining->expansion = NULL;
2251 free_tlist(origline);
2252 return 1;
2253
2254 case PP_ENDM:
2255 case PP_ENDMACRO:
2256 if (!defining)
2257 {
2258 error(ERR_NONFATAL, "`%s': not defining a macro",
2259 tline->text);
2260 return 3;
2261 }
2262 k = hash(defining->name);
2263 defining->next = mmacros[k];
2264 mmacros[k] = defining;
2265 defining = NULL;
2266 free_tlist(origline);
2267 return 5;
2268
2269 case PP_ROTATE:
2270 if (tline->next && tline->next->type == TOK_WHITESPACE)
2271 tline = tline->next;
2272 t = expand_smacro(tline->next);
2273 tline->next = NULL;
2274 free_tlist(origline);
2275 tline = t;
2276 tptr = &t;
2277 tokval.t_type = TOKEN_INVALID;
2278 evalresult =
2279 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2280 free_tlist(tline);
2281 if (!evalresult)
2282 return 3;
2283 if (tokval.t_type)
2284 error(ERR_WARNING,
2285 "trailing garbage after expression ignored");
2286 if (!is_simple(evalresult))
2287 {
2288 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2289 return 3;
2290 }
2291 mmac = istk->mstk;
2292 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2293 mmac = mmac->next_active;
2294 if (!mmac)
2295 error(ERR_NONFATAL,
2296 "`%%rotate' invoked outside a macro call");
2297 mmac->rotate = mmac->rotate + reloc_value(evalresult);
2298 if (mmac->rotate < 0)
2299 mmac->rotate = mmac->nparam - (-mmac->rotate) % mmac->nparam;
2300 mmac->rotate %= mmac->nparam;
2301 return 1;
2302
2303 case PP_REP:
2304 nolist = FALSE;
2305 tline = tline->next;
2306 if (tline->next && tline->next->type == TOK_WHITESPACE)
2307 tline = tline->next;
2308 if (tline->next && tline->next->type == TOK_ID &&
2309 !nasm_stricmp(tline->next->text, ".nolist"))
2310 {
2311 tline = tline->next;
2312 nolist = TRUE;
2313 }
2314 t = expand_smacro(tline->next);
2315 tline->next = NULL;
2316 free_tlist(origline);
2317 tline = t;
2318 tptr = &t;
2319 tokval.t_type = TOKEN_INVALID;
2320 evalresult =
2321 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2322 free_tlist(tline);
2323 if (!evalresult)
2324 return 3;
2325 if (tokval.t_type)
2326 error(ERR_WARNING,
2327 "trailing garbage after expression ignored");
2328 if (!is_simple(evalresult))
2329 {
2330 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2331 return 3;
2332 }
2333 tmp_defining = defining;
2334 defining = nasm_malloc(sizeof(MMacro));
2335 defining->name = NULL; /* flags this macro as a %rep block */
2336 defining->casesense = 0;
2337 defining->plus = FALSE;
2338 defining->nolist = nolist;
2339 defining->in_progress = reloc_value(evalresult) + 1;
2340 defining->nparam_min = defining->nparam_max = 0;
2341 defining->defaults = NULL;
2342 defining->dlist = NULL;
2343 defining->expansion = NULL;
2344 defining->next_active = istk->mstk;
2345 defining->rep_nest = tmp_defining;
2346 return 1;
2347
2348 case PP_ENDREP:
2349 if (!defining || defining->name)
2350 {
2351 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2352 return 3;
2353 }
2354
2355 /*
2356 * Now we have a "macro" defined - although it has no name
2357 * and we won't be entering it in the hash tables - we must
2358 * push a macro-end marker for it on to istk->expansion.
2359 * After that, it will take care of propagating itself (a
2360 * macro-end marker line for a macro which is really a %rep
2361 * block will cause the macro to be re-expanded, complete
2362 * with another macro-end marker to ensure the process
2363 * continues) until the whole expansion is forcibly removed
2364 * from istk->expansion by a %exitrep.
2365 */
2366 l = nasm_malloc(sizeof(Line));
2367 l->next = istk->expansion;
2368 l->finishes = defining;
2369 l->first = NULL;
2370 istk->expansion = l;
2371
2372 istk->mstk = defining;
2373
2374 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2375 tmp_defining = defining;
2376 defining = defining->rep_nest;
2377 free_tlist(origline);
2378 return 1;
2379
2380 case PP_EXITREP:
2381 /*
2382 * We must search along istk->expansion until we hit a
2383 * macro-end marker for a macro with no name. Then we set
2384 * its `in_progress' flag to 0.
2385 */
2386 for (l = istk->expansion; l; l = l->next)
2387 if (l->finishes && !l->finishes->name)
2388 break;
2389
2390 if (l)
2391 l->finishes->in_progress = 0;
2392 else
2393 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2394 free_tlist(origline);
2395 return 1;
2396
2397 case PP_XDEFINE:
2398 case PP_IXDEFINE:
2399 case PP_DEFINE:
2400 case PP_IDEFINE:
2401 tline = tline->next;
2402 skip_white_(tline);
2403 tline = expand_id(tline);
2404 if (!tline || (tline->type != TOK_ID &&
2405 (tline->type != TOK_PREPROC_ID ||
2406 tline->text[1] != '$')))
2407 {
2408 error(ERR_NONFATAL,
2409 "`%%%s%sdefine' expects a macro identifier",
2410 ((i == PP_IDEFINE || i == PP_IXDEFINE) ? "i" : ""),
2411 ((i == PP_XDEFINE || i == PP_IXDEFINE) ? "x" : ""));
2412 free_tlist(origline);
2413 return 3;
2414 }
2415
2416 ctx = get_ctx(tline->text, FALSE);
2417 if (!ctx)
2418 smhead = &smacros[hash(tline->text)];
2419 else
2420 smhead = &ctx->localmac;
2421 mname = tline->text;
2422 last = tline;
2423 param_start = tline = tline->next;
2424 nparam = 0;
2425
2426 /* Expand the macro definition now for %xdefine and %ixdefine */
2427 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2428 tline = expand_smacro(tline);
2429
2430 if (tok_is_(tline, "("))
2431 {
2432 /*
2433 * This macro has parameters.
2434 */
2435
2436 tline = tline->next;
2437 while (1)
2438 {
2439 skip_white_(tline);
2440 if (!tline)
2441 {
2442 error(ERR_NONFATAL, "parameter identifier expected");
2443 free_tlist(origline);
2444 return 3;
2445 }
2446 if (tline->type != TOK_ID)
2447 {
2448 error(ERR_NONFATAL,
2449 "`%s': parameter identifier expected",
2450 tline->text);
2451 free_tlist(origline);
2452 return 3;
2453 }
2454 tline->type = TOK_SMAC_PARAM + nparam++;
2455 tline = tline->next;
2456 skip_white_(tline);
2457 if (tok_is_(tline, ","))
2458 {
2459 tline = tline->next;
2460 continue;
2461 }
2462 if (!tok_is_(tline, ")"))
2463 {
2464 error(ERR_NONFATAL,
2465 "`)' expected to terminate macro template");
2466 free_tlist(origline);
2467 return 3;
2468 }
2469 break;
2470 }
2471 last = tline;
2472 tline = tline->next;
2473 }
2474 if (tok_type_(tline, TOK_WHITESPACE))
2475 last = tline, tline = tline->next;
2476 macro_start = NULL;
2477 last->next = NULL;
2478 t = tline;
2479 while (t)
2480 {
2481 if (t->type == TOK_ID)
2482 {
2483 for (tt = param_start; tt; tt = tt->next)
2484 if (tt->type >= TOK_SMAC_PARAM &&
2485 !strcmp(tt->text, t->text))
2486 t->type = tt->type;
2487 }
2488 tt = t->next;
2489 t->next = macro_start;
2490 macro_start = t;
2491 t = tt;
2492 }
2493 /*
2494 * Good. We now have a macro name, a parameter count, and a
2495 * token list (in reverse order) for an expansion. We ought
2496 * to be OK just to create an SMacro, store it, and let
2497 * free_tlist have the rest of the line (which we have
2498 * carefully re-terminated after chopping off the expansion
2499 * from the end).
2500 */
2501 if (smacro_defined(ctx, mname, nparam, &smac, i == PP_DEFINE))
2502 {
2503 if (!smac)
2504 {
2505 error(ERR_WARNING,
2506 "single-line macro `%s' defined both with and"
2507 " without parameters", mname);
2508 free_tlist(origline);
2509 free_tlist(macro_start);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002510 return 3;
2511 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002512 else
2513 {
2514 /*
2515 * We're redefining, so we have to take over an
2516 * existing SMacro structure. This means freeing
2517 * what was already in it.
2518 */
2519 nasm_free(smac->name);
2520 free_tlist(smac->expansion);
2521 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002522 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002523 else
2524 {
2525 smac = nasm_malloc(sizeof(SMacro));
2526 smac->next = *smhead;
2527 *smhead = smac;
2528 }
2529 smac->name = nasm_strdup(mname);
2530 smac->casesense = ((i == PP_DEFINE) || (i == PP_XDEFINE));
2531 smac->nparam = nparam;
2532 smac->expansion = macro_start;
2533 smac->in_progress = FALSE;
2534 free_tlist(origline);
2535 return 3;
2536
2537 case PP_UNDEF:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002538 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002539 skip_white_(tline);
2540 tline = expand_id(tline);
2541 if (!tline || (tline->type != TOK_ID &&
2542 (tline->type != TOK_PREPROC_ID ||
2543 tline->text[1] != '$')))
2544 {
2545 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
2546 free_tlist(origline);
H. Peter Anvineba20a72002-04-30 20:53:55 +00002547 return 3;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002548 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002549 if (tline->next)
2550 {
2551 error(ERR_WARNING,
2552 "trailing garbage after macro name ignored");
2553 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002554
H. Peter Anvin734b1882002-04-30 21:01:08 +00002555 /* Find the context that symbol belongs to */
2556 ctx = get_ctx(tline->text, FALSE);
2557 if (!ctx)
2558 smhead = &smacros[hash(tline->text)];
2559 else
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002560 smhead = &ctx->localmac;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002561
H. Peter Anvin734b1882002-04-30 21:01:08 +00002562 mname = tline->text;
2563 last = tline;
2564 last->next = NULL;
2565
2566 /*
2567 * We now have a macro name... go hunt for it.
2568 */
2569 while (smacro_defined(ctx, mname, -1, &smac, 1))
2570 {
2571 /* Defined, so we need to find its predecessor and nuke it */
2572 SMacro **s;
2573 for (s = smhead; *s && *s != smac; s = &(*s)->next);
2574 if (*s)
2575 {
2576 *s = smac->next;
2577 nasm_free(smac->name);
2578 free_tlist(smac->expansion);
2579 nasm_free(smac);
2580 }
2581 }
2582 free_tlist(origline);
2583 return 3;
2584
2585 case PP_STRLEN:
2586 tline = tline->next;
2587 skip_white_(tline);
2588 tline = expand_id(tline);
2589 if (!tline || (tline->type != TOK_ID &&
2590 (tline->type != TOK_PREPROC_ID ||
2591 tline->text[1] != '$')))
2592 {
2593 error(ERR_NONFATAL,
2594 "`%%strlen' expects a macro identifier as first parameter");
2595 free_tlist(origline);
2596 return 3;
2597 }
2598 ctx = get_ctx(tline->text, FALSE);
2599 if (!ctx)
2600 smhead = &smacros[hash(tline->text)];
2601 else
2602 smhead = &ctx->localmac;
2603 mname = tline->text;
2604 last = tline;
2605 tline = expand_smacro(tline->next);
2606 last->next = NULL;
2607
2608 t = tline;
2609 while (tok_type_(t, TOK_WHITESPACE))
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002610 t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002611 /* t should now point to the string */
2612 if (t->type != TOK_STRING)
2613 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002614 error(ERR_NONFATAL,
2615 "`%%strlen` requires string as second parameter");
2616 free_tlist(tline);
2617 free_tlist(origline);
2618 return 3;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002619 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002620
H. Peter Anvin734b1882002-04-30 21:01:08 +00002621 macro_start = nasm_malloc(sizeof(*macro_start));
2622 macro_start->next = NULL;
2623 make_tok_num(macro_start, strlen(t->text) - 2);
2624 macro_start->mac = NULL;
2625
2626 /*
2627 * We now have a macro name, an implicit parameter count of
2628 * zero, and a numeric token to use as an expansion. Create
2629 * and store an SMacro.
2630 */
2631 if (smacro_defined(ctx, mname, 0, &smac, i == PP_STRLEN))
2632 {
2633 if (!smac)
2634 error(ERR_WARNING,
2635 "single-line macro `%s' defined both with and"
2636 " without parameters", mname);
2637 else
2638 {
2639 /*
2640 * We're redefining, so we have to take over an
2641 * existing SMacro structure. This means freeing
2642 * what was already in it.
2643 */
2644 nasm_free(smac->name);
2645 free_tlist(smac->expansion);
2646 }
2647 }
2648 else
2649 {
2650 smac = nasm_malloc(sizeof(SMacro));
2651 smac->next = *smhead;
2652 *smhead = smac;
2653 }
2654 smac->name = nasm_strdup(mname);
2655 smac->casesense = (i == PP_STRLEN);
2656 smac->nparam = 0;
2657 smac->expansion = macro_start;
2658 smac->in_progress = FALSE;
2659 free_tlist(tline);
2660 free_tlist(origline);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002661 return 3;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002662
H. Peter Anvin734b1882002-04-30 21:01:08 +00002663 case PP_SUBSTR:
2664 tline = tline->next;
2665 skip_white_(tline);
2666 tline = expand_id(tline);
2667 if (!tline || (tline->type != TOK_ID &&
2668 (tline->type != TOK_PREPROC_ID ||
2669 tline->text[1] != '$')))
2670 {
2671 error(ERR_NONFATAL,
2672 "`%%substr' expects a macro identifier as first parameter");
2673 free_tlist(origline);
2674 return 3;
2675 }
2676 ctx = get_ctx(tline->text, FALSE);
2677 if (!ctx)
2678 smhead = &smacros[hash(tline->text)];
2679 else
2680 smhead = &ctx->localmac;
2681 mname = tline->text;
2682 last = tline;
2683 tline = expand_smacro(tline->next);
2684 last->next = NULL;
2685
2686 t = tline->next;
2687 while (tok_type_(t, TOK_WHITESPACE))
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002688 t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002689
2690 /* t should now point to the string */
2691 if (t->type != TOK_STRING)
2692 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002693 error(ERR_NONFATAL,
2694 "`%%substr` requires string as second parameter");
2695 free_tlist(tline);
2696 free_tlist(origline);
2697 return 3;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002698 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002699
H. Peter Anvin734b1882002-04-30 21:01:08 +00002700 tt = t->next;
2701 tptr = &tt;
2702 tokval.t_type = TOKEN_INVALID;
2703 evalresult =
2704 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2705 if (!evalresult)
2706 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002707 free_tlist(tline);
2708 free_tlist(origline);
2709 return 3;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002710 }
2711 if (!is_simple(evalresult))
2712 {
2713 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002714 free_tlist(tline);
2715 free_tlist(origline);
2716 return 3;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002717 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002718
H. Peter Anvin734b1882002-04-30 21:01:08 +00002719 macro_start = nasm_malloc(sizeof(*macro_start));
2720 macro_start->next = NULL;
2721 macro_start->text = nasm_strdup("'''");
2722 if (evalresult->value > 0
2723 && evalresult->value < strlen(t->text) - 1)
2724 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002725 macro_start->text[1] = t->text[evalresult->value];
H. Peter Anvin734b1882002-04-30 21:01:08 +00002726 }
2727 else
2728 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002729 macro_start->text[2] = '\0';
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002730 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002731 macro_start->type = TOK_STRING;
2732 macro_start->mac = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002733
H. Peter Anvin734b1882002-04-30 21:01:08 +00002734 /*
2735 * We now have a macro name, an implicit parameter count of
2736 * zero, and a numeric token to use as an expansion. Create
2737 * and store an SMacro.
2738 */
2739 if (smacro_defined(ctx, mname, 0, &smac, i == PP_SUBSTR))
2740 {
2741 if (!smac)
2742 error(ERR_WARNING,
2743 "single-line macro `%s' defined both with and"
2744 " without parameters", mname);
2745 else
2746 {
2747 /*
2748 * We're redefining, so we have to take over an
2749 * existing SMacro structure. This means freeing
2750 * what was already in it.
2751 */
2752 nasm_free(smac->name);
2753 free_tlist(smac->expansion);
2754 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002755 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002756 else
2757 {
2758 smac = nasm_malloc(sizeof(SMacro));
2759 smac->next = *smhead;
2760 *smhead = smac;
2761 }
2762 smac->name = nasm_strdup(mname);
2763 smac->casesense = (i == PP_SUBSTR);
2764 smac->nparam = 0;
2765 smac->expansion = macro_start;
2766 smac->in_progress = FALSE;
2767 free_tlist(tline);
2768 free_tlist(origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002769 return 3;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002770
2771
2772 case PP_ASSIGN:
2773 case PP_IASSIGN:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002774 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002775 skip_white_(tline);
2776 tline = expand_id(tline);
2777 if (!tline || (tline->type != TOK_ID &&
2778 (tline->type != TOK_PREPROC_ID ||
2779 tline->text[1] != '$')))
2780 {
2781 error(ERR_NONFATAL,
2782 "`%%%sassign' expects a macro identifier",
2783 (i == PP_IASSIGN ? "i" : ""));
2784 free_tlist(origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002785 return 3;
2786 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002787 ctx = get_ctx(tline->text, FALSE);
2788 if (!ctx)
2789 smhead = &smacros[hash(tline->text)];
2790 else
2791 smhead = &ctx->localmac;
2792 mname = tline->text;
2793 last = tline;
2794 tline = expand_smacro(tline->next);
2795 last->next = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002796
H. Peter Anvin734b1882002-04-30 21:01:08 +00002797 t = tline;
2798 tptr = &t;
2799 tokval.t_type = TOKEN_INVALID;
2800 evalresult =
2801 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2802 free_tlist(tline);
2803 if (!evalresult)
2804 {
2805 free_tlist(origline);
2806 return 3;
2807 }
2808
2809 if (tokval.t_type)
2810 error(ERR_WARNING,
2811 "trailing garbage after expression ignored");
2812
2813 if (!is_simple(evalresult))
2814 {
2815 error(ERR_NONFATAL,
2816 "non-constant value given to `%%%sassign'",
2817 (i == PP_IASSIGN ? "i" : ""));
2818 free_tlist(origline);
2819 return 3;
2820 }
2821
2822 macro_start = nasm_malloc(sizeof(*macro_start));
2823 macro_start->next = NULL;
2824 make_tok_num(macro_start, reloc_value(evalresult));
2825 macro_start->mac = NULL;
2826
2827 /*
2828 * We now have a macro name, an implicit parameter count of
2829 * zero, and a numeric token to use as an expansion. Create
2830 * and store an SMacro.
2831 */
2832 if (smacro_defined(ctx, mname, 0, &smac, i == PP_ASSIGN))
2833 {
2834 if (!smac)
2835 error(ERR_WARNING,
2836 "single-line macro `%s' defined both with and"
2837 " without parameters", mname);
2838 else
2839 {
2840 /*
2841 * We're redefining, so we have to take over an
2842 * existing SMacro structure. This means freeing
2843 * what was already in it.
2844 */
2845 nasm_free(smac->name);
2846 free_tlist(smac->expansion);
2847 }
2848 }
2849 else
2850 {
2851 smac = nasm_malloc(sizeof(SMacro));
2852 smac->next = *smhead;
2853 *smhead = smac;
2854 }
2855 smac->name = nasm_strdup(mname);
2856 smac->casesense = (i == PP_ASSIGN);
2857 smac->nparam = 0;
2858 smac->expansion = macro_start;
2859 smac->in_progress = FALSE;
2860 free_tlist(origline);
2861 return 3;
2862
2863 case PP_LINE:
2864 /*
2865 * Syntax is `%line nnn[+mmm] [filename]'
2866 */
2867 tline = tline->next;
2868 skip_white_(tline);
2869 if (!tok_type_(tline, TOK_NUMBER))
2870 {
2871 error(ERR_NONFATAL, "`%%line' expects line number");
2872 free_tlist(origline);
2873 return 3;
2874 }
2875 k = readnum(tline->text, &j);
2876 m = 1;
2877 tline = tline->next;
2878 if (tok_is_(tline, "+"))
2879 {
2880 tline = tline->next;
2881 if (!tok_type_(tline, TOK_NUMBER))
2882 {
2883 error(ERR_NONFATAL, "`%%line' expects line increment");
2884 free_tlist(origline);
2885 return 3;
2886 }
2887 m = readnum(tline->text, &j);
2888 tline = tline->next;
2889 }
2890 skip_white_(tline);
2891 src_set_linnum(k);
2892 istk->lineinc = m;
2893 if (tline)
2894 {
2895 nasm_free(src_set_fname(detoken(tline, FALSE)));
2896 }
2897 free_tlist(origline);
2898 return 5;
2899
2900 default:
2901 error(ERR_FATAL,
2902 "preprocessor directive `%s' not yet implemented",
2903 directives[i]);
2904 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002905 }
2906 return 3;
2907}
2908
2909/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002910 * Ensure that a macro parameter contains a condition code and
2911 * nothing else. Return the condition code index if so, or -1
2912 * otherwise.
2913 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002914static int
2915find_cc(Token * t)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002916{
H. Peter Anvin76690a12002-04-30 20:52:49 +00002917 Token *tt;
2918 int i, j, k, m;
2919
H. Peter Anvineba20a72002-04-30 20:53:55 +00002920 skip_white_(t);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002921 if (t->type != TOK_ID)
2922 return -1;
2923 tt = t->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002924 skip_white_(tt);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002925 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
2926 return -1;
2927
2928 i = -1;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002929 j = sizeof(conditions) / sizeof(*conditions);
2930 while (j - i > 1)
2931 {
2932 k = (j + i) / 2;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002933 m = nasm_stricmp(t->text, conditions[k]);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002934 if (m == 0)
2935 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00002936 i = k;
2937 j = -2;
2938 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002939 }
2940 else if (m < 0)
2941 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00002942 j = k;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002943 }
2944 else
H. Peter Anvin76690a12002-04-30 20:52:49 +00002945 i = k;
2946 }
2947 if (j != -2)
2948 return -1;
2949 return i;
2950}
2951
2952/*
2953 * Expand MMacro-local things: parameter references (%0, %n, %+n,
2954 * %-n) and MMacro-local identifiers (%%foo).
2955 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002956static Token *
2957expand_mmac_params(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002958{
H. Peter Anvin734b1882002-04-30 21:01:08 +00002959 Token *t, *tt, **tail, *thead;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002960
2961 tail = &thead;
2962 thead = NULL;
2963
H. Peter Anvin734b1882002-04-30 21:01:08 +00002964 while (tline)
2965 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00002966 if (tline->type == TOK_PREPROC_ID &&
H. Peter Anvin734b1882002-04-30 21:01:08 +00002967 (((tline->text[1] == '+' || tline->text[1] == '-')
2968 && tline->text[2]) || tline->text[1] == '%'
2969 || (tline->text[1] >= '0' && tline->text[1] <= '9')))
2970 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00002971 char *text = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002972 int type = 0, cc; /* type = 0 to placate optimisers */
H. Peter Anvin76690a12002-04-30 20:52:49 +00002973 char tmpbuf[30];
2974 int n, i;
2975 MMacro *mac;
2976
2977 t = tline;
2978 tline = tline->next;
2979
2980 mac = istk->mstk;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002981 while (mac && !mac->name) /* avoid mistaking %reps for macros */
H. Peter Anvin76690a12002-04-30 20:52:49 +00002982 mac = mac->next_active;
2983 if (!mac)
2984 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002985 else
2986 switch (t->text[1])
2987 {
2988 /*
2989 * We have to make a substitution of one of the
2990 * forms %1, %-1, %+1, %%foo, %0.
2991 */
2992 case '0':
2993 type = TOK_NUMBER;
2994 sprintf(tmpbuf, "%d", mac->nparam);
2995 text = nasm_strdup(tmpbuf);
2996 break;
2997 case '%':
2998 type = TOK_ID;
2999 sprintf(tmpbuf, "..@%lu.", mac->unique);
3000 text = nasm_strcat(tmpbuf, t->text + 2);
3001 break;
3002 case '-':
3003 n = atoi(t->text + 2) - 1;
3004 if (n >= mac->nparam)
3005 tt = NULL;
3006 else
3007 {
3008 if (mac->nparam > 1)
3009 n = (n + mac->rotate) % mac->nparam;
3010 tt = mac->params[n];
3011 }
3012 cc = find_cc(tt);
3013 if (cc == -1)
3014 {
3015 error(ERR_NONFATAL,
3016 "macro parameter %d is not a condition code",
3017 n + 1);
3018 text = NULL;
3019 }
3020 else
3021 {
3022 type = TOK_ID;
3023 if (inverse_ccs[cc] == -1)
3024 {
3025 error(ERR_NONFATAL,
3026 "condition code `%s' is not invertible",
3027 conditions[cc]);
3028 text = NULL;
3029 }
3030 else
3031 text =
3032 nasm_strdup(conditions[inverse_ccs
3033 [cc]]);
3034 }
3035 break;
3036 case '+':
3037 n = atoi(t->text + 2) - 1;
3038 if (n >= mac->nparam)
3039 tt = NULL;
3040 else
3041 {
3042 if (mac->nparam > 1)
3043 n = (n + mac->rotate) % mac->nparam;
3044 tt = mac->params[n];
3045 }
3046 cc = find_cc(tt);
3047 if (cc == -1)
3048 {
3049 error(ERR_NONFATAL,
3050 "macro parameter %d is not a condition code",
3051 n + 1);
3052 text = NULL;
3053 }
3054 else
3055 {
3056 type = TOK_ID;
3057 text = nasm_strdup(conditions[cc]);
3058 }
3059 break;
3060 default:
3061 n = atoi(t->text + 1) - 1;
3062 if (n >= mac->nparam)
3063 tt = NULL;
3064 else
3065 {
3066 if (mac->nparam > 1)
3067 n = (n + mac->rotate) % mac->nparam;
3068 tt = mac->params[n];
3069 }
3070 if (tt)
3071 {
3072 for (i = 0; i < mac->paramlen[n]; i++)
3073 {
3074 *tail =
3075 new_Token(NULL, tt->type, tt->text,
3076 0);
3077 tail = &(*tail)->next;
3078 tt = tt->next;
3079 }
3080 }
3081 text = NULL; /* we've done it here */
3082 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003083 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003084 if (!text)
3085 {
3086 delete_Token(t);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003087 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003088 else
3089 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003090 *tail = t;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003091 tail = &t->next;
3092 t->type = type;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003093 nasm_free(t->text);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003094 t->text = text;
3095 t->mac = NULL;
3096 }
3097 continue;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003098 }
3099 else
3100 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00003101 t = *tail = tline;
3102 tline = tline->next;
3103 t->mac = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003104 tail = &t->next;
3105 }
3106 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00003107 *tail = NULL;
3108 t = thead;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003109 for (; t && (tt = t->next) != NULL; t = t->next)
3110 switch (t->type)
3111 {
3112 case TOK_WHITESPACE:
3113 if (tt->type == TOK_WHITESPACE)
3114 {
3115 t->next = delete_Token(tt);
3116 }
3117 break;
3118 case TOK_ID:
3119 if (tt->type == TOK_ID || tt->type == TOK_NUMBER)
3120 {
3121 char *tmp = nasm_strcat(t->text, tt->text);
3122 nasm_free(t->text);
3123 t->text = tmp;
3124 t->next = delete_Token(tt);
3125 }
3126 break;
3127 case TOK_NUMBER:
3128 if (tt->type == TOK_NUMBER)
3129 {
3130 char *tmp = nasm_strcat(t->text, tt->text);
3131 nasm_free(t->text);
3132 t->text = tmp;
3133 t->next = delete_Token(tt);
3134 }
3135 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003136 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003137
H. Peter Anvin76690a12002-04-30 20:52:49 +00003138 return thead;
3139}
3140
3141/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003142 * Expand all single-line macro calls made in the given line.
3143 * Return the expanded version of the line. The original is deemed
3144 * to be destroyed in the process. (In reality we'll just move
3145 * Tokens from input to output a lot of the time, rather than
3146 * actually bothering to destroy and replicate.)
3147 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003148static Token *
3149expand_smacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003150{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003151 Token *t, *tt, *mstart, **tail, *thead;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003152 SMacro *head = NULL, *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003153 Token **params;
3154 int *paramsize;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003155 int nparam, sparam, brackets, rescan;
3156 Token *org_tline = tline;
3157 Context *ctx;
3158 char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003159
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003160 /*
3161 * Trick: we should avoid changing the start token pointer since it can
3162 * be contained in "next" field of other token. Because of this
3163 * we allocate a copy of first token and work with it; at the end of
3164 * routine we copy it back
3165 */
3166 if (org_tline)
3167 {
H. Peter Anvin734b1882002-04-30 21:01:08 +00003168 tline =
3169 new_Token(org_tline->next, org_tline->type, org_tline->text,
3170 0);
3171 tline->mac = org_tline->mac;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003172 }
3173
H. Peter Anvin734b1882002-04-30 21:01:08 +00003174 again:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003175 tail = &thead;
3176 thead = NULL;
3177
H. Peter Anvin734b1882002-04-30 21:01:08 +00003178 while (tline)
3179 { /* main token loop */
3180 if ((mname = tline->text))
3181 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003182 /* if this token is a local macro, look in local context */
3183 if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
H. Peter Anvin734b1882002-04-30 21:01:08 +00003184 ctx = get_ctx(mname, TRUE);
3185 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003186 ctx = NULL;
3187 if (!ctx)
3188 head = smacros[hash(mname)];
3189 else
H. Peter Anvineba20a72002-04-30 20:53:55 +00003190 head = ctx->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003191 /*
3192 * We've hit an identifier. As in is_mmacro below, we first
3193 * check whether the identifier is a single-line macro at
3194 * all, then think about checking for parameters if
3195 * necessary.
3196 */
H. Peter Anvineba20a72002-04-30 20:53:55 +00003197 for (m = head; m; m = m->next)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003198 if (!mstrcmp(m->name, mname, m->casesense))
H. Peter Anvineba20a72002-04-30 20:53:55 +00003199 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003200 if (m)
3201 {
3202 mstart = tline;
3203 params = NULL;
3204 paramsize = NULL;
3205 if (m->nparam == 0)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003206 {
H. Peter Anvin734b1882002-04-30 21:01:08 +00003207 /*
3208 * Simple case: the macro is parameterless. Discard the
3209 * one token that the macro call took, and push the
3210 * expansion back on the to-do stack.
3211 */
3212 if (!m->expansion)
3213 {
3214 if (!strcmp("__FILE__", m->name))
3215 {
3216 long num = 0;
3217 src_get(&num, &(tline->text));
3218 nasm_quote(&(tline->text));
3219 tline->type = TOK_STRING;
3220 continue;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003221 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003222 if (!strcmp("__LINE__", m->name))
3223 {
3224 nasm_free(tline->text);
3225 make_tok_num(tline, src_get_linnum());
3226 continue;
3227 }
3228 tline = delete_Token(tline);
3229 continue;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003230 }
3231 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003232 else
3233 {
3234 /*
3235 * Complicated case: at least one macro with this name
3236 * exists and takes parameters. We must find the
3237 * parameters in the call, count them, find the SMacro
3238 * that corresponds to that form of the macro call, and
3239 * substitute for the parameters when we expand. What a
3240 * pain.
3241 */
3242 tline = tline->next;
3243 skip_white_(tline);
3244 if (!tok_is_(tline, "("))
3245 {
3246 /*
3247 * This macro wasn't called with parameters: ignore
3248 * the call. (Behaviour borrowed from gnu cpp.)
3249 */
3250 tline = mstart;
3251 m = NULL;
3252 }
3253 else
3254 {
3255 int paren = 0;
3256 int white = 0;
3257 brackets = 0;
3258 nparam = 0;
3259 tline = tline->next;
3260 sparam = PARAM_DELTA;
3261 params = nasm_malloc(sparam * sizeof(Token *));
3262 params[0] = tline;
3263 paramsize = nasm_malloc(sparam * sizeof(int));
3264 paramsize[0] = 0;
3265 for (;; tline = tline->next)
3266 { /* parameter loop */
3267 if (!tline)
3268 {
3269 error(ERR_NONFATAL,
3270 "macro call expects terminating `)'");
3271 break;
3272 }
3273 if (tline->type == TOK_WHITESPACE
3274 && brackets <= 0)
3275 {
3276 if (paramsize[nparam])
3277 white++;
3278 else
3279 params[nparam] = tline->next;
3280 continue; /* parameter loop */
3281 }
3282 if (tline->type == TOK_OTHER
3283 && tline->text[1] == 0)
3284 {
3285 char ch = tline->text[0];
3286 if (ch == ',' && !paren && brackets <= 0)
3287 {
3288 if (++nparam >= sparam)
3289 {
3290 sparam += PARAM_DELTA;
3291 params = nasm_realloc(params,
3292 sparam * sizeof(Token *));
3293 paramsize = nasm_realloc(paramsize,
3294 sparam * sizeof(int));
3295 }
3296 params[nparam] = tline->next;
3297 paramsize[nparam] = 0;
3298 white = 0;
3299 continue; /* parameter loop */
3300 }
3301 if (ch == '{' &&
3302 (brackets > 0 || (brackets == 0 &&
3303 !paramsize[nparam])))
3304 {
3305 if (!(brackets++))
3306 {
3307 params[nparam] = tline->next;
3308 continue; /* parameter loop */
3309 }
3310 }
3311 if (ch == '}' && brackets > 0)
3312 if (--brackets == 0)
3313 {
3314 brackets = -1;
3315 continue; /* parameter loop */
3316 }
3317 if (ch == '(' && !brackets)
3318 paren++;
3319 if (ch == ')' && brackets <= 0)
3320 if (--paren < 0)
3321 break;
3322 }
3323 if (brackets < 0)
3324 {
3325 brackets = 0;
3326 error(ERR_NONFATAL, "braces do not "
3327 "enclose all of macro parameter");
3328 }
3329 paramsize[nparam] += white + 1;
3330 white = 0;
3331 } /* parameter loop */
3332 nparam++;
3333 while (m && (m->nparam != nparam ||
3334 mstrcmp(m->name, mname,
3335 m->casesense)))
3336 m = m->next;
3337 if (!m)
3338 error(ERR_WARNING | ERR_WARN_MNP,
3339 "macro `%s' exists, "
3340 "but not taking %d parameters",
3341 mstart->text, nparam);
3342 }
3343 }
3344 if (m && m->in_progress)
3345 m = NULL;
3346 if (!m) /* in progess or didn't find '(' or wrong nparam */
3347 {
3348 /*
3349 * Design question: should we handle !tline, which
3350 * indicates missing ')' here, or expand those
3351 * macros anyway, which requires the (t) test a few
3352 * lines down?
3353 */
3354 nasm_free(params);
3355 nasm_free(paramsize);
3356 tline = mstart;
3357 }
3358 else
3359 {
3360 /*
3361 * Expand the macro: we are placed on the last token of the
3362 * call, so that we can easily split the call from the
3363 * following tokens. We also start by pushing an SMAC_END
3364 * token for the cycle removal.
3365 */
3366 t = tline;
3367 if (t)
3368 {
3369 tline = t->next;
3370 t->next = NULL;
3371 }
3372 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
3373 tt->mac = m;
3374 m->in_progress = TRUE;
3375 tline = tt;
3376 for (t = m->expansion; t; t = t->next)
3377 {
3378 if (t->type >= TOK_SMAC_PARAM)
3379 {
3380 Token *pcopy = tline, **ptail = &pcopy;
3381 Token *ttt, *pt;
3382 int i;
3383
3384 ttt = params[t->type - TOK_SMAC_PARAM];
3385 for (i = paramsize[t->type - TOK_SMAC_PARAM];
3386 --i >= 0;)
3387 {
3388 pt = *ptail =
3389 new_Token(tline, ttt->type, ttt->text,
3390 0);
3391 ptail = &pt->next;
3392 ttt = ttt->next;
3393 }
3394 tline = pcopy;
3395 }
3396 else
3397 {
3398 tt = new_Token(tline, t->type, t->text, 0);
3399 tline = tt;
3400 }
3401 }
3402
3403 /*
3404 * Having done that, get rid of the macro call, and clean
3405 * up the parameters.
3406 */
3407 nasm_free(params);
3408 nasm_free(paramsize);
3409 free_tlist(mstart);
3410 continue; /* main token loop */
3411 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003412 }
3413 }
3414
H. Peter Anvin734b1882002-04-30 21:01:08 +00003415 if (tline->type == TOK_SMAC_END)
3416 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003417 tline->mac->in_progress = FALSE;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003418 tline = delete_Token(tline);
3419 }
3420 else
3421 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003422 t = *tail = tline;
3423 tline = tline->next;
3424 t->mac = NULL;
3425 t->next = NULL;
3426 tail = &t->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003427 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003428 }
3429
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003430 /*
3431 * Now scan the entire line and look for successive TOK_IDs that resulted
3432 * after expansion (they can't be produced by tokenise()). The successive
3433 * TOK_IDs should be concatenated.
3434 * Also we look for %+ tokens and concatenate the tokens before and after
3435 * them (without white spaces in between).
3436 */
3437 t = thead;
3438 rescan = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003439 while (t)
3440 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003441 while (t && t->type != TOK_ID && t->type != TOK_PREPROC_ID)
3442 t = t->next;
3443 if (!t || !t->next)
3444 break;
3445 if (t->next->type == TOK_ID ||
H. Peter Anvin734b1882002-04-30 21:01:08 +00003446 t->next->type == TOK_PREPROC_ID ||
3447 t->next->type == TOK_NUMBER)
3448 {
3449 char *p = nasm_strcat(t->text, t->next->text);
3450 nasm_free(t->text);
3451 t->next = delete_Token(t->next);
3452 t->text = p;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003453 rescan = 1;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003454 }
3455 else if (t->next->type == TOK_WHITESPACE && t->next->next &&
3456 t->next->next->type == TOK_PREPROC_ID &&
3457 strcmp(t->next->next->text, "%+") == 0)
3458 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003459 /* free the next whitespace, the %+ token and next whitespace */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003460 int i;
3461 for (i = 1; i <= 3; i++)
3462 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003463 if (!t->next || (i != 2 && t->next->type != TOK_WHITESPACE))
3464 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003465 t->next = delete_Token(t->next);
3466 } /* endfor */
3467 }
3468 else
3469 t = t->next;
3470 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003471 /* If we concatenaded something, re-scan the line for macros */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003472 if (rescan)
3473 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003474 tline = thead;
3475 goto again;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003476 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003477
3478 if (org_tline)
3479 {
H. Peter Anvin734b1882002-04-30 21:01:08 +00003480 if (thead)
3481 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003482 *org_tline = *thead;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003483 /* since we just gave text to org_line, don't free it */
3484 thead->text = NULL;
3485 delete_Token(thead);
3486 }
3487 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003488 {
3489 /* the expression expanded to empty line;
3490 we can't return NULL for some reasons
3491 we just set the line to a single WHITESPACE token. */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003492 memset(org_tline, 0, sizeof(*org_tline));
3493 org_tline->text = NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003494 org_tline->type = TOK_WHITESPACE;
3495 }
3496 thead = org_tline;
3497 }
3498
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003499 return thead;
3500}
3501
3502/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003503 * Similar to expand_smacro but used exclusively with macro identifiers
3504 * right before they are fetched in. The reason is that there can be
3505 * identifiers consisting of several subparts. We consider that if there
3506 * are more than one element forming the name, user wants a expansion,
3507 * otherwise it will be left as-is. Example:
3508 *
3509 * %define %$abc cde
3510 *
3511 * the identifier %$abc will be left as-is so that the handler for %define
3512 * will suck it and define the corresponding value. Other case:
3513 *
3514 * %define _%$abc cde
3515 *
3516 * In this case user wants name to be expanded *before* %define starts
3517 * working, so we'll expand %$abc into something (if it has a value;
3518 * otherwise it will be left as-is) then concatenate all successive
3519 * PP_IDs into one.
3520 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003521static Token *
3522expand_id(Token * tline)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003523{
3524 Token *cur, *oldnext = NULL;
3525
H. Peter Anvin734b1882002-04-30 21:01:08 +00003526 if (!tline || !tline->next)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003527 return tline;
3528
3529 cur = tline;
3530 while (cur->next &&
H. Peter Anvin734b1882002-04-30 21:01:08 +00003531 (cur->next->type == TOK_ID ||
3532 cur->next->type == TOK_PREPROC_ID || cur->next->type == TOK_NUMBER))
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003533 cur = cur->next;
3534
3535 /* If identifier consists of just one token, don't expand */
3536 if (cur == tline)
3537 return tline;
3538
H. Peter Anvin734b1882002-04-30 21:01:08 +00003539 if (cur)
3540 {
3541 oldnext = cur->next; /* Detach the tail past identifier */
3542 cur->next = NULL; /* so that expand_smacro stops here */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003543 }
3544
H. Peter Anvin734b1882002-04-30 21:01:08 +00003545 tline = expand_smacro(tline);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003546
H. Peter Anvin734b1882002-04-30 21:01:08 +00003547 if (cur)
3548 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003549 /* expand_smacro possibly changhed tline; re-scan for EOL */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003550 cur = tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003551 while (cur && cur->next)
3552 cur = cur->next;
3553 if (cur)
3554 cur->next = oldnext;
3555 }
3556
3557 return tline;
3558}
3559
3560/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003561 * Determine whether the given line constitutes a multi-line macro
3562 * call, and return the MMacro structure called if so. Doesn't have
3563 * to check for an initial label - that's taken care of in
3564 * expand_mmacro - but must check numbers of parameters. Guaranteed
3565 * to be called with tline->type == TOK_ID, so the putative macro
3566 * name is easy to find.
3567 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003568static MMacro *
3569is_mmacro(Token * tline, Token *** params_array)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003570{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003571 MMacro *head, *m;
3572 Token **params;
3573 int nparam;
3574
3575 head = mmacros[hash(tline->text)];
3576
3577 /*
3578 * Efficiency: first we see if any macro exists with the given
3579 * name. If not, we can return NULL immediately. _Then_ we
3580 * count the parameters, and then we look further along the
3581 * list if necessary to find the proper MMacro.
3582 */
3583 for (m = head; m; m = m->next)
3584 if (!mstrcmp(m->name, tline->text, m->casesense))
3585 break;
3586 if (!m)
3587 return NULL;
3588
3589 /*
3590 * OK, we have a potential macro. Count and demarcate the
3591 * parameters.
3592 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003593 count_mmac_params(tline->next, &nparam, &params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003594
3595 /*
3596 * So we know how many parameters we've got. Find the MMacro
3597 * structure that handles this number.
3598 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003599 while (m)
3600 {
3601 if (m->nparam_min <= nparam && (m->plus || nparam <= m->nparam_max))
3602 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003603 /*
3604 * This one is right. Just check if cycle removal
3605 * prohibits us using it before we actually celebrate...
3606 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003607 if (m->in_progress)
3608 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003609#if 0
H. Peter Anvin734b1882002-04-30 21:01:08 +00003610 error(ERR_NONFATAL,
3611 "self-reference in multi-line macro `%s'", m->name);
H. Peter Anvineba20a72002-04-30 20:53:55 +00003612#endif
H. Peter Anvin734b1882002-04-30 21:01:08 +00003613 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003614 return NULL;
3615 }
3616 /*
3617 * It's right, and we can use it. Add its default
3618 * parameters to the end of our list if necessary.
3619 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003620 if (m->defaults && nparam < m->nparam_min + m->ndefs)
3621 {
3622 params =
3623 nasm_realloc(params,
3624 ((m->nparam_min + m->ndefs + 1) * sizeof(*params)));
3625 while (nparam < m->nparam_min + m->ndefs)
3626 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003627 params[nparam] = m->defaults[nparam - m->nparam_min];
3628 nparam++;
3629 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003630 }
3631 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00003632 * If we've gone over the maximum parameter count (and
3633 * we're in Plus mode), ignore parameters beyond
3634 * nparam_max.
3635 */
3636 if (m->plus && nparam > m->nparam_max)
3637 nparam = m->nparam_max;
3638 /*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003639 * Then terminate the parameter list, and leave.
3640 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003641 if (!params)
3642 { /* need this special case */
H. Peter Anvin76690a12002-04-30 20:52:49 +00003643 params = nasm_malloc(sizeof(*params));
3644 nparam = 0;
3645 }
3646 params[nparam] = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003647 *params_array = params;
3648 return m;
3649 }
3650 /*
3651 * This one wasn't right: look for the next one with the
3652 * same name.
3653 */
3654 for (m = m->next; m; m = m->next)
3655 if (!mstrcmp(m->name, tline->text, m->casesense))
3656 break;
3657 }
3658
3659 /*
3660 * After all that, we didn't find one with the right number of
3661 * parameters. Issue a warning, and fail to expand the macro.
3662 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003663 error(ERR_WARNING | ERR_WARN_MNP,
3664 "macro `%s' exists, but not taking %d parameters",
3665 tline->text, nparam);
3666 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003667 return NULL;
3668}
3669
3670/*
3671 * Expand the multi-line macro call made by the given line, if
3672 * there is one to be expanded. If there is, push the expansion on
H. Peter Anvineba20a72002-04-30 20:53:55 +00003673 * istk->expansion and return 1. Otherwise return 0.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003674 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003675static int
3676expand_mmacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003677{
3678 Token *startline = tline;
3679 Token *label = NULL;
3680 int dont_prepend = 0;
3681 Token **params, *t, *tt;
3682 MMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003683 Line *l, *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003684 int i, nparam, *paramlen;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003685
3686 t = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003687 skip_white_(t);
3688 if (!tok_type_(t, TOK_ID))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003689 return 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003690 m = is_mmacro(t, &params);
3691 if (!m)
3692 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003693 Token *last;
3694 /*
3695 * We have an id which isn't a macro call. We'll assume
3696 * it might be a label; we'll also check to see if a
3697 * colon follows it. Then, if there's another id after
3698 * that lot, we'll check it again for macro-hood.
3699 */
3700 label = last = t;
3701 t = t->next;
3702 if (tok_type_(t, TOK_WHITESPACE))
3703 last = t, t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003704 if (tok_is_(t, ":"))
3705 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003706 dont_prepend = 1;
3707 last = t, t = t->next;
3708 if (tok_type_(t, TOK_WHITESPACE))
3709 last = t, t = t->next;
3710 }
3711 if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
3712 return 0;
3713 last->next = NULL;
3714 tline = t;
3715 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003716
3717 /*
3718 * Fix up the parameters: this involves stripping leading and
3719 * trailing whitespace, then stripping braces if they are
3720 * present.
3721 */
H. Peter Anvineba20a72002-04-30 20:53:55 +00003722 for (nparam = 0; params[nparam]; nparam++)
3723 ;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003724 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003725
H. Peter Anvin734b1882002-04-30 21:01:08 +00003726 for (i = 0; params[i]; i++)
3727 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003728 int brace = FALSE;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003729 int comma = (!m->plus || i < nparam - 1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003730
3731 t = params[i];
H. Peter Anvineba20a72002-04-30 20:53:55 +00003732 skip_white_(t);
3733 if (tok_is_(t, "{"))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003734 t = t->next, brace = TRUE, comma = FALSE;
3735 params[i] = t;
3736 paramlen[i] = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003737 while (t)
3738 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003739 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
H. Peter Anvin734b1882002-04-30 21:01:08 +00003740 break; /* ... because we have hit a comma */
H. Peter Anvineba20a72002-04-30 20:53:55 +00003741 if (comma && t->type == TOK_WHITESPACE && tok_is_(t->next, ","))
H. Peter Anvin734b1882002-04-30 21:01:08 +00003742 break; /* ... or a space then a comma */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003743 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
H. Peter Anvin734b1882002-04-30 21:01:08 +00003744 break; /* ... or a brace */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003745 t = t->next;
3746 paramlen[i]++;
3747 }
3748 }
3749
3750 /*
3751 * OK, we have a MMacro structure together with a set of
3752 * parameters. We must now go through the expansion and push
H. Peter Anvin76690a12002-04-30 20:52:49 +00003753 * copies of each Line on to istk->expansion. Substitution of
3754 * parameter tokens and macro-local tokens doesn't get done
3755 * until the single-line macro substitution process; this is
3756 * because delaying them allows us to change the semantics
3757 * later through %rotate.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003758 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00003759 * First, push an end marker on to istk->expansion, mark this
3760 * macro as in progress, and set up its invocation-specific
3761 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003762 */
3763 ll = nasm_malloc(sizeof(Line));
3764 ll->next = istk->expansion;
3765 ll->finishes = m;
3766 ll->first = NULL;
3767 istk->expansion = ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003768
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003769 m->in_progress = TRUE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003770 m->params = params;
3771 m->iline = tline;
3772 m->nparam = nparam;
3773 m->rotate = 0;
3774 m->paramlen = paramlen;
3775 m->unique = unique++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003776 m->lineno = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003777
3778 m->next_active = istk->mstk;
3779 istk->mstk = m;
3780
H. Peter Anvin734b1882002-04-30 21:01:08 +00003781 for (l = m->expansion; l; l = l->next)
3782 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003783 Token **tail;
3784
3785 ll = nasm_malloc(sizeof(Line));
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003786 ll->finishes = NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003787 ll->next = istk->expansion;
3788 istk->expansion = ll;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003789 tail = &ll->first;
3790
H. Peter Anvin734b1882002-04-30 21:01:08 +00003791 for (t = l->first; t; t = t->next)
3792 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003793 Token *x = t;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003794 if (t->type == TOK_PREPROC_ID &&
3795 t->text[1] == '0' && t->text[2] == '0')
H. Peter Anvineba20a72002-04-30 20:53:55 +00003796 {
3797 dont_prepend = -1;
3798 x = label;
3799 if (!x)
3800 continue;
3801 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003802 tt = *tail = new_Token(NULL, x->type, x->text, 0);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003803 tail = &tt->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003804 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00003805 *tail = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003806 }
3807
3808 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +00003809 * If we had a label, push it on as the first line of
3810 * the macro expansion.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003811 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003812 if (label)
3813 {
3814 if (dont_prepend < 0)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003815 free_tlist(startline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003816 else
3817 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003818 ll = nasm_malloc(sizeof(Line));
3819 ll->finishes = NULL;
3820 ll->next = istk->expansion;
3821 istk->expansion = ll;
3822 ll->first = startline;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003823 if (!dont_prepend)
3824 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003825 while (label->next)
3826 label = label->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003827 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
H. Peter Anvineba20a72002-04-30 20:53:55 +00003828 }
H. Peter Anvin87bc6192002-04-30 20:53:16 +00003829 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003830 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003831
H. Peter Anvin734b1882002-04-30 21:01:08 +00003832 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003833
H. Peter Anvineba20a72002-04-30 20:53:55 +00003834 return 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003835}
3836
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003837/*
3838 * Since preprocessor always operate only on the line that didn't
3839 * arrived yet, we should always use ERR_OFFBY1. Also since user
3840 * won't want to see same error twice (preprocessing is done once
3841 * per pass) we will want to show errors only during pass one.
3842 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003843static void
3844error(int severity, char *fmt, ...)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003845{
3846 va_list arg;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003847 char buff[1024];
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003848
3849 /* If we're in a dead branch of IF or something like it, ignore the error */
3850 if (istk->conds && !emitting(istk->conds->state))
3851 return;
3852
H. Peter Anvin734b1882002-04-30 21:01:08 +00003853 va_start(arg, fmt);
3854 vsprintf(buff, fmt, arg);
3855 va_end(arg);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003856
3857 if (istk->mstk && istk->mstk->name)
H. Peter Anvin734b1882002-04-30 21:01:08 +00003858 __error(severity | ERR_PASS1, "(%s:%d) %s", istk->mstk->name,
3859 istk->mstk->lineno, buff);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003860 else
H. Peter Anvin734b1882002-04-30 21:01:08 +00003861 __error(severity | ERR_PASS1, "%s", buff);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003862}
3863
H. Peter Anvin734b1882002-04-30 21:01:08 +00003864static void
3865pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
3866 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003867{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003868 int h;
3869
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003870 __error = errfunc;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003871 cstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003872 istk = nasm_malloc(sizeof(Include));
3873 istk->next = NULL;
3874 istk->conds = NULL;
3875 istk->expansion = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003876 istk->mstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003877 istk->fp = fopen(file, "r");
H. Peter Anvineba20a72002-04-30 20:53:55 +00003878 istk->fname = NULL;
3879 src_set_fname(nasm_strdup(file));
3880 src_set_linnum(0);
3881 istk->lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003882 if (!istk->fp)
H. Peter Anvin734b1882002-04-30 21:01:08 +00003883 error(ERR_FATAL | ERR_NOFILE, "unable to open input file `%s'", file);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003884 defining = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003885 for (h = 0; h < NHASH; h++)
3886 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003887 mmacros[h] = NULL;
3888 smacros[h] = NULL;
3889 }
3890 unique = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003891 if (tasm_compatible_mode) {
3892 stdmacpos = stdmac;
3893 } else {
3894 stdmacpos = &stdmac[TASM_MACRO_COUNT];
3895 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003896 any_extrastdmac = (extrastdmac != NULL);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003897 list = listgen;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003898 evaluate = eval;
3899 pass = apass;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003900}
3901
H. Peter Anvin734b1882002-04-30 21:01:08 +00003902static char *
3903pp_getline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003904{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003905 char *line;
3906 Token *tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003907
H. Peter Anvin734b1882002-04-30 21:01:08 +00003908 while (1)
3909 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003910 /*
3911 * Fetch a tokenised line, either from the macro-expansion
3912 * buffer or from the input file.
3913 */
3914 tline = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003915 while (istk->expansion && istk->expansion->finishes)
3916 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003917 Line *l = istk->expansion;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003918 if (!l->finishes->name && l->finishes->in_progress > 1)
3919 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00003920 Line *ll;
3921
3922 /*
3923 * This is a macro-end marker for a macro with no
3924 * name, which means it's not really a macro at all
3925 * but a %rep block, and the `in_progress' field is
3926 * more than 1, meaning that we still need to
3927 * repeat. (1 means the natural last repetition; 0
3928 * means termination by %exitrep.) We have
3929 * therefore expanded up to the %endrep, and must
3930 * push the whole block on to the expansion buffer
3931 * again. We don't bother to remove the macro-end
3932 * marker: we'd only have to generate another one
3933 * if we did.
3934 */
3935 l->finishes->in_progress--;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003936 for (l = l->finishes->expansion; l; l = l->next)
3937 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00003938 Token *t, *tt, **tail;
3939
3940 ll = nasm_malloc(sizeof(Line));
3941 ll->next = istk->expansion;
3942 ll->finishes = NULL;
3943 ll->first = NULL;
3944 tail = &ll->first;
3945
H. Peter Anvin734b1882002-04-30 21:01:08 +00003946 for (t = l->first; t; t = t->next)
3947 {
3948 if (t->text || t->type == TOK_WHITESPACE)
3949 {
3950 tt = *tail = new_Token(NULL, t->type, t->text, 0);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003951 tail = &tt->next;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003952 }
3953 }
3954
3955 istk->expansion = ll;
3956 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003957 }
3958 else
3959 {
H. Peter Anvin87bc6192002-04-30 20:53:16 +00003960 /*
3961 * Check whether a `%rep' was started and not ended
3962 * within this macro expansion. This can happen and
3963 * should be detected. It's a fatal error because
3964 * I'm too confused to work out how to recover
3965 * sensibly from it.
3966 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003967 if (defining)
3968 {
H. Peter Anvin87bc6192002-04-30 20:53:16 +00003969 if (defining->name)
H. Peter Anvin734b1882002-04-30 21:01:08 +00003970 error(ERR_PANIC, "defining with name in expansion");
H. Peter Anvinb64535f2002-04-30 20:55:37 +00003971 else if (istk->mstk->name)
H. Peter Anvin734b1882002-04-30 21:01:08 +00003972 error(ERR_FATAL, "`%%rep' without `%%endrep' within"
3973 " expansion of macro `%s'", istk->mstk->name);
H. Peter Anvin87bc6192002-04-30 20:53:16 +00003974 }
3975
H. Peter Anvin734b1882002-04-30 21:01:08 +00003976 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +00003977 * FIXME: investigate the relationship at this point between
3978 * istk->mstk and l->finishes
3979 */
3980 {
3981 MMacro *m = istk->mstk;
3982 istk->mstk = m->next_active;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003983 if (m->name)
3984 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003985 /*
3986 * This was a real macro call, not a %rep, and
3987 * therefore the parameter information needs to
3988 * be freed.
3989 */
3990 nasm_free(m->params);
3991 free_tlist(m->iline);
3992 nasm_free(m->paramlen);
3993 l->finishes->in_progress = FALSE;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003994 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00003995 else
3996 free_mmacro(m);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003997 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003998 istk->expansion = l->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003999 nasm_free(l);
4000 list->downlevel(LIST_MACRO);
H. Peter Anvin76690a12002-04-30 20:52:49 +00004001 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004002 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004003 while (1)
4004 { /* until we get a line we can use */
H. Peter Anvineba20a72002-04-30 20:53:55 +00004005
H. Peter Anvin734b1882002-04-30 21:01:08 +00004006 if (istk->expansion)
4007 { /* from a macro expansion */
H. Peter Anvineba20a72002-04-30 20:53:55 +00004008 char *p;
4009 Line *l = istk->expansion;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004010 if (istk->mstk)
4011 istk->mstk->lineno++;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004012 tline = l->first;
4013 istk->expansion = l->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004014 nasm_free(l);
4015 p = detoken(tline, FALSE);
4016 list->line(LIST_MACRO, p);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004017 nasm_free(p);
4018 break;
4019 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004020 line = read_line();
H. Peter Anvin734b1882002-04-30 21:01:08 +00004021 if (line)
4022 { /* from the current input file */
H. Peter Anvineba20a72002-04-30 20:53:55 +00004023 line = prepreproc(line);
4024 tline = tokenise(line);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004025 nasm_free(line);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004026 break;
4027 }
4028 /*
4029 * The current file has ended; work down the istk
4030 */
4031 {
4032 Include *i = istk;
4033 fclose(i->fp);
4034 if (i->conds)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004035 error(ERR_FATAL, "expected `%%endif' before end of file");
H. Peter Anvineba20a72002-04-30 20:53:55 +00004036 istk = i->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004037 list->downlevel(LIST_INCLUDE);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004038 src_set_linnum(i->lineno);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004039 nasm_free(src_set_fname(i->fname));
4040 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004041 if (!istk)
4042 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004043 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004044 }
4045
4046 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00004047 * We must expand MMacro parameters and MMacro-local labels
4048 * _before_ we plunge into directive processing, to cope
4049 * with things like `%define something %1' such as STRUC
4050 * uses. Unless we're _defining_ a MMacro, in which case
4051 * those tokens should be left alone to go into the
H. Peter Anvineba20a72002-04-30 20:53:55 +00004052 * definition; and unless we're in a non-emitting
4053 * condition, in which case we don't want to meddle with
4054 * anything.
H. Peter Anvin76690a12002-04-30 20:52:49 +00004055 */
H. Peter Anvineba20a72002-04-30 20:53:55 +00004056 if (!defining && !(istk->conds && !emitting(istk->conds->state)))
H. Peter Anvin76690a12002-04-30 20:52:49 +00004057 tline = expand_mmac_params(tline);
4058
4059 /*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004060 * Check the line to see if it's a preprocessor directive.
4061 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00004062 if (do_directive(tline) & 1)
4063 {
4064 continue;
4065 }
4066 else if (defining)
4067 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004068 /*
4069 * We're defining a multi-line macro. We emit nothing
H. Peter Anvineba20a72002-04-30 20:53:55 +00004070 * at all, and just
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004071 * shove the tokenised line on to the macro definition.
4072 */
4073 Line *l = nasm_malloc(sizeof(Line));
4074 l->next = defining->expansion;
4075 l->first = tline;
4076 l->finishes = FALSE;
4077 defining->expansion = l;
4078 continue;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004079 }
4080 else if (istk->conds && !emitting(istk->conds->state))
4081 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004082 /*
4083 * We're in a non-emitting branch of a condition block.
4084 * Emit nothing at all, not even a blank line: when we
4085 * emerge from the condition we'll give a line-number
4086 * directive so we keep our place correctly.
4087 */
4088 free_tlist(tline);
4089 continue;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004090 }
4091 else if (istk->mstk && !istk->mstk->in_progress)
4092 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00004093 /*
4094 * We're in a %rep block which has been terminated, so
4095 * we're walking through to the %endrep without
4096 * emitting anything. Emit nothing at all, not even a
4097 * blank line: when we emerge from the %rep block we'll
4098 * give a line-number directive so we keep our place
4099 * correctly.
4100 */
4101 free_tlist(tline);
4102 continue;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004103 }
4104 else
4105 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004106 tline = expand_smacro(tline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004107 if (!expand_mmacro(tline))
4108 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004109 /*
4110 * De-tokenise the line again, and emit it.
4111 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004112 line = detoken(tline, TRUE);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004113 free_tlist(tline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004114 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004115 }
4116 else
4117 {
4118 continue; /* expand_mmacro calls free_tlist */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004119 }
4120 }
4121 }
4122
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004123 return line;
4124}
4125
H. Peter Anvin734b1882002-04-30 21:01:08 +00004126static void
4127pp_cleanup(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004128{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004129 int h;
4130
H. Peter Anvin734b1882002-04-30 21:01:08 +00004131 if (defining)
4132 {
4133 error(ERR_NONFATAL, "end of file while still defining macro `%s'",
4134 defining->name);
4135 free_mmacro(defining);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004136 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004137 while (cstk)
4138 ctx_pop();
H. Peter Anvin734b1882002-04-30 21:01:08 +00004139 for (h = 0; h < NHASH; h++)
4140 {
4141 while (mmacros[h])
4142 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004143 MMacro *m = mmacros[h];
4144 mmacros[h] = mmacros[h]->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004145 free_mmacro(m);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004146 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004147 while (smacros[h])
4148 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004149 SMacro *s = smacros[h];
4150 smacros[h] = smacros[h]->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004151 nasm_free(s->name);
4152 free_tlist(s->expansion);
4153 nasm_free(s);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004154 }
4155 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004156 while (istk)
4157 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004158 Include *i = istk;
4159 istk = istk->next;
4160 fclose(i->fp);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004161 nasm_free(i->fname);
4162 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004163 }
4164 while (cstk)
4165 ctx_pop();
4166}
4167
H. Peter Anvin734b1882002-04-30 21:01:08 +00004168void
4169pp_include_path(char *path)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004170{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004171 IncPath *i;
4172
4173 i = nasm_malloc(sizeof(IncPath));
4174 i->path = nasm_strdup(path);
4175 i->next = ipath;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004176 ipath = i;
4177}
4178
H. Peter Anvin734b1882002-04-30 21:01:08 +00004179void
4180pp_pre_include(char *fname)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004181{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004182 Token *inc, *space, *name;
4183 Line *l;
4184
H. Peter Anvin734b1882002-04-30 21:01:08 +00004185 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
4186 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
4187 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004188
4189 l = nasm_malloc(sizeof(Line));
4190 l->next = predef;
4191 l->first = inc;
4192 l->finishes = FALSE;
4193 predef = l;
4194}
4195
H. Peter Anvin734b1882002-04-30 21:01:08 +00004196void
4197pp_pre_define(char *definition)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004198{
4199 Token *def, *space;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004200 Line *l;
4201 char *equals;
4202
4203 equals = strchr(definition, '=');
H. Peter Anvin734b1882002-04-30 21:01:08 +00004204 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4205 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004206 if (equals)
4207 *equals = ' ';
H. Peter Anvineba20a72002-04-30 20:53:55 +00004208 space->next = tokenise(definition);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004209 if (equals)
4210 *equals = '=';
4211
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004212 l = nasm_malloc(sizeof(Line));
4213 l->next = predef;
4214 l->first = def;
4215 l->finishes = FALSE;
4216 predef = l;
4217}
4218
H. Peter Anvin734b1882002-04-30 21:01:08 +00004219void
4220pp_pre_undefine(char *definition)
H. Peter Anvin620515a2002-04-30 20:57:38 +00004221{
4222 Token *def, *space;
4223 Line *l;
4224
H. Peter Anvin734b1882002-04-30 21:01:08 +00004225 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4226 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
H. Peter Anvin620515a2002-04-30 20:57:38 +00004227
4228 l = nasm_malloc(sizeof(Line));
4229 l->next = predef;
4230 l->first = def;
4231 l->finishes = FALSE;
4232 predef = l;
4233}
4234
H. Peter Anvin734b1882002-04-30 21:01:08 +00004235void
4236pp_extra_stdmac(char **macros)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004237{
H. Peter Anvin76690a12002-04-30 20:52:49 +00004238 extrastdmac = macros;
4239}
4240
H. Peter Anvin734b1882002-04-30 21:01:08 +00004241static void
4242make_tok_num(Token * tok, long val)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004243{
4244 char numbuf[20];
4245 sprintf(numbuf, "%ld", val);
4246 tok->text = nasm_strdup(numbuf);
4247 tok->type = TOK_NUMBER;
4248}
4249
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004250Preproc nasmpp = {
4251 pp_reset,
4252 pp_getline,
4253 pp_cleanup
4254};