blob: 488517b640c53f39a36d5ef30faa54d84417a2d7 [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);
920 t->next = freeTokens ? freeTokens->next : NULL;
921 freeTokens = t;
922 return next;
923}
924
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000925/*
926 * Convert a line of tokens back into text.
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000927 * If expand_locals is not zero, identifiers of the form "%$*xxx"
928 * will be transformed into ..@ctxnum.xxx
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000929 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000930static char *
931detoken(Token * tlist, int expand_locals)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000932{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000933 Token *t;
934 int len;
935 char *line, *p;
936
937 len = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000938 for (t = tlist; t; t = t->next)
939 {
940 if (t->type == TOK_PREPROC_ID && t->text[1] == '!')
941 {
942 char *p = getenv(t->text + 2);
943 nasm_free(t->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000944 if (p)
945 t->text = nasm_strdup(p);
946 else
947 t->text = NULL;
948 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000949 /* Expand local macros here and not during preprocessing */
950 if (expand_locals &&
H. Peter Anvin734b1882002-04-30 21:01:08 +0000951 t->type == TOK_PREPROC_ID && t->text &&
952 t->text[0] == '%' && t->text[1] == '$')
953 {
954 Context *ctx = get_ctx(t->text, FALSE);
955 if (ctx)
956 {
957 char buffer[40];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000958 char *p, *q = t->text + 2;
959
H. Peter Anvin734b1882002-04-30 21:01:08 +0000960 q += strspn(q, "$");
961 sprintf(buffer, "..@%lu.", ctx->number);
962 p = nasm_strcat(buffer, q);
963 nasm_free(t->text);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000964 t->text = p;
965 }
966 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000967 if (t->type == TOK_WHITESPACE)
968 {
969 len++;
970 }
971 else if (t->text)
972 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000973 len += strlen(t->text);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000974 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000975 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000976 p = line = nasm_malloc(len + 1);
977 for (t = tlist; t; t = t->next)
978 {
979 if (t->type == TOK_WHITESPACE)
980 {
981 *p = ' ';
982 p++;
983 *p = '\0';
984 }
985 else if (t->text)
986 {
987 strcpy(p, t->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000988 p += strlen(p);
989 }
990 }
991 *p = '\0';
992 return line;
993}
994
995/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000996 * A scanner, suitable for use by the expression evaluator, which
997 * operates on a line of Tokens. Expects a pointer to a pointer to
998 * the first token in the line to be passed in as its private_data
999 * field.
1000 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001001static int
1002ppscan(void *private_data, struct tokenval *tokval)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001003{
H. Peter Anvin76690a12002-04-30 20:52:49 +00001004 Token **tlineptr = private_data;
1005 Token *tline;
1006
H. Peter Anvin734b1882002-04-30 21:01:08 +00001007 do
1008 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00001009 tline = *tlineptr;
1010 *tlineptr = tline ? tline->next : NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001011 }
1012 while (tline && (tline->type == TOK_WHITESPACE ||
1013 tline->type == TOK_COMMENT));
H. Peter Anvin76690a12002-04-30 20:52:49 +00001014
1015 if (!tline)
1016 return tokval->t_type = TOKEN_EOS;
1017
1018 if (tline->text[0] == '$' && !tline->text[1])
1019 return tokval->t_type = TOKEN_HERE;
1020 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[1])
1021 return tokval->t_type = TOKEN_BASE;
1022
H. Peter Anvin734b1882002-04-30 21:01:08 +00001023 if (tline->type == TOK_ID)
1024 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00001025 tokval->t_charptr = tline->text;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001026 if (tline->text[0] == '$')
1027 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00001028 tokval->t_charptr++;
1029 return tokval->t_type = TOKEN_ID;
1030 }
1031
1032 /*
1033 * This is the only special case we actually need to worry
1034 * about in this restricted context.
1035 */
1036 if (!nasm_stricmp(tline->text, "seg"))
1037 return tokval->t_type = TOKEN_SEG;
1038
1039 return tokval->t_type = TOKEN_ID;
1040 }
1041
H. Peter Anvin734b1882002-04-30 21:01:08 +00001042 if (tline->type == TOK_NUMBER)
1043 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00001044 int rn_error;
1045
1046 tokval->t_integer = readnum(tline->text, &rn_error);
1047 if (rn_error)
1048 return tokval->t_type = TOKEN_ERRNUM;
1049 tokval->t_charptr = NULL;
1050 return tokval->t_type = TOKEN_NUM;
1051 }
1052
H. Peter Anvin734b1882002-04-30 21:01:08 +00001053 if (tline->type == TOK_STRING)
1054 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00001055 int rn_warn;
1056 char q, *r;
1057 int l;
1058
1059 r = tline->text;
1060 q = *r++;
1061 l = strlen(r);
1062
H. Peter Anvin734b1882002-04-30 21:01:08 +00001063 if (l == 0 || r[l - 1] != q)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001064 return tokval->t_type = TOKEN_ERRNUM;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001065 tokval->t_integer = readstrnum(r, l - 1, &rn_warn);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001066 if (rn_warn)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001067 error(ERR_WARNING | ERR_PASS1, "character constant too long");
H. Peter Anvineba20a72002-04-30 20:53:55 +00001068 tokval->t_charptr = NULL;
1069 return tokval->t_type = TOKEN_NUM;
1070 }
1071
H. Peter Anvin734b1882002-04-30 21:01:08 +00001072 if (tline->type == TOK_OTHER)
1073 {
1074 if (!strcmp(tline->text, "<<"))
1075 return tokval->t_type = TOKEN_SHL;
1076 if (!strcmp(tline->text, ">>"))
1077 return tokval->t_type = TOKEN_SHR;
1078 if (!strcmp(tline->text, "//"))
1079 return tokval->t_type = TOKEN_SDIV;
1080 if (!strcmp(tline->text, "%%"))
1081 return tokval->t_type = TOKEN_SMOD;
1082 if (!strcmp(tline->text, "=="))
1083 return tokval->t_type = TOKEN_EQ;
1084 if (!strcmp(tline->text, "<>"))
1085 return tokval->t_type = TOKEN_NE;
1086 if (!strcmp(tline->text, "!="))
1087 return tokval->t_type = TOKEN_NE;
1088 if (!strcmp(tline->text, "<="))
1089 return tokval->t_type = TOKEN_LE;
1090 if (!strcmp(tline->text, ">="))
1091 return tokval->t_type = TOKEN_GE;
1092 if (!strcmp(tline->text, "&&"))
1093 return tokval->t_type = TOKEN_DBL_AND;
1094 if (!strcmp(tline->text, "^^"))
1095 return tokval->t_type = TOKEN_DBL_XOR;
1096 if (!strcmp(tline->text, "||"))
1097 return tokval->t_type = TOKEN_DBL_OR;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001098 }
1099
1100 /*
1101 * We have no other options: just return the first character of
1102 * the token text.
1103 */
1104 return tokval->t_type = tline->text[0];
1105}
1106
1107/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001108 * Compare a string to the name of an existing macro; this is a
1109 * simple wrapper which calls either strcmp or nasm_stricmp
1110 * depending on the value of the `casesense' parameter.
1111 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001112static int
1113mstrcmp(char *p, char *q, int casesense)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001114{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001115 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001116}
1117
1118/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001119 * Return the Context structure associated with a %$ token. Return
1120 * NULL, having _already_ reported an error condition, if the
1121 * context stack isn't deep enough for the supplied number of $
1122 * signs.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001123 * If all_contexts == TRUE, contexts that enclose current are
1124 * also scanned for such smacro, until it is found; if not -
1125 * only the context that directly results from the number of $'s
1126 * in variable's name.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001127 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001128static Context *
1129get_ctx(char *name, int all_contexts)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001130{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001131 Context *ctx;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001132 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001133 int i;
1134
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001135 if (!name || name[0] != '%' || name[1] != '$')
1136 return NULL;
1137
H. Peter Anvin734b1882002-04-30 21:01:08 +00001138 if (!cstk)
1139 {
1140 error(ERR_NONFATAL, "`%s': context stack is empty", name);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001141 return NULL;
1142 }
1143
H. Peter Anvin734b1882002-04-30 21:01:08 +00001144 for (i = strspn(name + 2, "$"), ctx = cstk; (i > 0) && ctx; i--)
1145 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001146 ctx = ctx->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001147 i--;
1148 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001149 if (!ctx)
1150 {
1151 error(ERR_NONFATAL, "`%s': context stack is only"
1152 " %d level%s deep", name, i - 1, (i == 2 ? "" : "s"));
1153 return NULL;
1154 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001155 if (!all_contexts)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001156 return ctx;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001157
H. Peter Anvin734b1882002-04-30 21:01:08 +00001158 do
1159 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001160 /* Search for this smacro in found context */
1161 m = ctx->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001162 while (m)
1163 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001164 if (!mstrcmp(m->name, name, m->casesense))
1165 return ctx;
1166 m = m->next;
1167 }
1168 ctx = ctx->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001169 }
1170 while (ctx);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001171 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001172}
1173
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001174/* Add a slash to the end of a path if it is missing. We use the
1175 * forward slash to make it compatible with Unix systems.
1176 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001177static void
1178backslash(char *s)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001179{
1180 int pos = strlen(s);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001181 if (s[pos - 1] != '\\' && s[pos - 1] != '/')
1182 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001183 s[pos] = '/';
H. Peter Anvin734b1882002-04-30 21:01:08 +00001184 s[pos + 1] = '\0';
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001185 }
1186}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001187
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001188/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001189 * Open an include file. This routine must always return a valid
1190 * file pointer if it returns - it's responsible for throwing an
1191 * ERR_FATAL and bombing out completely if not. It should also try
1192 * the include path one by one until it finds the file or reaches
1193 * the end of the path.
1194 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001195static FILE *
1196inc_fopen(char *file)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001197{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001198 FILE *fp;
1199 char *prefix = "", *combine;
1200 IncPath *ip = ipath;
H. Peter Anvin620515a2002-04-30 20:57:38 +00001201 static int namelen = 0;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001202 int len = strlen(file);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001203
H. Peter Anvin734b1882002-04-30 21:01:08 +00001204 while (1)
1205 {
1206 combine = nasm_malloc(strlen(prefix) + 1 + len + 1);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001207 strcpy(combine, prefix);
1208 if (prefix[0] != 0)
1209 backslash(combine);
1210 strcat(combine, file);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001211 fp = fopen(combine, "r");
H. Peter Anvin620515a2002-04-30 20:57:38 +00001212 if (pass == 0 && fp)
1213 {
H. Peter Anvin734b1882002-04-30 21:01:08 +00001214 namelen += strlen(combine) + 1;
1215 if (namelen > 62)
1216 {
1217 printf(" \\\n ");
1218 namelen = 2;
1219 }
1220 printf(" %s", combine);
H. Peter Anvin620515a2002-04-30 20:57:38 +00001221 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001222 nasm_free(combine);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001223 if (fp)
1224 return fp;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001225 if (!ip)
1226 break;
1227 prefix = ip->path;
1228 ip = ip->next;
1229 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001230
H. Peter Anvin734b1882002-04-30 21:01:08 +00001231 error(ERR_FATAL, "unable to open include file `%s'", file);
1232 return NULL; /* never reached - placate compilers */
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001233}
1234
1235/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001236 * Determine if we should warn on defining a single-line macro of
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001237 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001238 * return TRUE if _any_ single-line macro of that name is defined.
1239 * Otherwise, will return TRUE if a single-line macro with either
1240 * `nparam' or no parameters is defined.
1241 *
1242 * If a macro with precisely the right number of parameters is
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001243 * defined, or nparam is -1, the address of the definition structure
1244 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001245 * is NULL, no action will be taken regarding its contents, and no
1246 * error will occur.
1247 *
1248 * Note that this is also called with nparam zero to resolve
1249 * `ifdef'.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001250 *
1251 * If you already know which context macro belongs to, you can pass
1252 * the context pointer as first parameter; if you won't but name begins
1253 * with %$ the context will be automatically computed. If all_contexts
1254 * is true, macro will be searched in outer contexts as well.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001255 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001256static int
1257smacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn,
1258 int nocase)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001259{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001260 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001261
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001262 if (ctx)
1263 m = ctx->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001264 else if (name[0] == '%' && name[1] == '$')
1265 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001266 if (cstk)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001267 ctx = get_ctx(name, FALSE);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001268 if (!ctx)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001269 return FALSE; /* got to return _something_ */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001270 m = ctx->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001271 }
1272 else
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001273 m = smacros[hash(name)];
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001274
H. Peter Anvin734b1882002-04-30 21:01:08 +00001275 while (m)
1276 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001277 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
H. Peter Anvin734b1882002-04-30 21:01:08 +00001278 (nparam <= 0 || m->nparam == 0 || nparam == m->nparam))
1279 {
1280 if (defn)
1281 {
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001282 if (nparam == m->nparam || nparam == -1)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001283 *defn = m;
1284 else
1285 *defn = NULL;
1286 }
1287 return TRUE;
1288 }
1289 m = m->next;
1290 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001291
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001292 return FALSE;
1293}
1294
1295/*
1296 * Count and mark off the parameters in a multi-line macro call.
1297 * This is called both from within the multi-line macro expansion
1298 * code, and also to mark off the default parameters when provided
1299 * in a %macro definition line.
1300 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001301static void
1302count_mmac_params(Token * t, int *nparam, Token *** params)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001303{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001304 int paramsize, brace;
1305
1306 *nparam = paramsize = 0;
1307 *params = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001308 while (t)
1309 {
1310 if (*nparam >= paramsize)
1311 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001312 paramsize += PARAM_DELTA;
1313 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1314 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001315 skip_white_(t);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001316 brace = FALSE;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001317 if (tok_is_(t, "{"))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001318 brace = TRUE;
1319 (*params)[(*nparam)++] = t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001320 while (tok_isnt_(t, brace ? "}" : ","))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001321 t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001322 if (t)
1323 { /* got a comma/brace */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001324 t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001325 if (brace)
1326 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001327 /*
1328 * Now we've found the closing brace, look further
1329 * for the comma.
1330 */
H. Peter Anvineba20a72002-04-30 20:53:55 +00001331 skip_white_(t);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001332 if (tok_isnt_(t, ","))
1333 {
1334 error(ERR_NONFATAL,
1335 "braces do not enclose all of macro parameter");
H. Peter Anvineba20a72002-04-30 20:53:55 +00001336 while (tok_isnt_(t, ","))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001337 t = t->next;
1338 }
1339 if (t)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001340 t = t->next; /* eat the comma */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001341 }
1342 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001343 }
1344}
1345
1346/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001347 * Determine whether one of the various `if' conditions is true or
1348 * not.
1349 *
1350 * We must free the tline we get passed.
1351 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001352static int
1353if_condition(Token * tline, int i)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001354{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001355 int j, casesense;
1356 Token *t, *tt, **tptr, *origline;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001357 struct tokenval tokval;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001358 expr *evalresult;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001359
1360 origline = tline;
1361
H. Peter Anvin734b1882002-04-30 21:01:08 +00001362 switch (i)
1363 {
1364 case PP_IFCTX:
1365 case PP_ELIFCTX:
1366 case PP_IFNCTX:
1367 case PP_ELIFNCTX:
1368 j = FALSE; /* have we matched yet? */
1369 while (cstk && tline)
1370 {
1371 skip_white_(tline);
1372 if (!tline || tline->type != TOK_ID)
1373 {
1374 error(ERR_NONFATAL,
1375 "`%s' expects context identifiers",
1376 directives[i]);
1377 free_tlist(origline);
1378 return -1;
1379 }
1380 if (!nasm_stricmp(tline->text, cstk->name))
1381 j = TRUE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001382 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001383 }
1384 if (i == PP_IFNCTX || i == PP_ELIFNCTX)
1385 j = !j;
1386 free_tlist(origline);
1387 return j;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001388
H. Peter Anvin734b1882002-04-30 21:01:08 +00001389 case PP_IFDEF:
1390 case PP_ELIFDEF:
1391 case PP_IFNDEF:
1392 case PP_ELIFNDEF:
1393 j = FALSE; /* have we matched yet? */
1394 while (tline)
1395 {
1396 skip_white_(tline);
1397 if (!tline || (tline->type != TOK_ID &&
1398 (tline->type != TOK_PREPROC_ID ||
1399 tline->text[1] != '$')))
1400 {
1401 error(ERR_NONFATAL,
1402 "`%%if%sdef' expects macro identifiers",
1403 (i == PP_ELIFNDEF ? "n" : ""));
1404 free_tlist(origline);
1405 return -1;
1406 }
1407 if (smacro_defined(NULL, tline->text, 0, NULL, 1))
1408 j = TRUE;
1409 tline = tline->next;
1410 }
1411 if (i == PP_IFNDEF || i == PP_ELIFNDEF)
1412 j = !j;
1413 free_tlist(origline);
1414 return j;
1415
1416 case PP_IFIDN:
1417 case PP_ELIFIDN:
1418 case PP_IFNIDN:
1419 case PP_ELIFNIDN:
1420 case PP_IFIDNI:
1421 case PP_ELIFIDNI:
1422 case PP_IFNIDNI:
1423 case PP_ELIFNIDNI:
1424 tline = expand_smacro(tline);
1425 t = tt = tline;
1426 while (tok_isnt_(tt, ","))
1427 tt = tt->next;
1428 if (!tt)
1429 {
1430 error(ERR_NONFATAL,
1431 "`%s' expects two comma-separated arguments",
1432 directives[i]);
1433 free_tlist(tline);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001434 return -1;
1435 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001436 tt = tt->next;
1437 casesense = (i == PP_IFIDN || i == PP_ELIFIDN ||
1438 i == PP_IFNIDN || i == PP_ELIFNIDN);
1439 j = TRUE; /* assume equality unless proved not */
1440 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt)
1441 {
1442 if (tt->type == TOK_OTHER && !strcmp(tt->text, ","))
1443 {
1444 error(ERR_NONFATAL, "`%s': more than one comma on line",
1445 directives[i]);
1446 free_tlist(tline);
1447 return -1;
1448 }
1449 if (t->type == TOK_WHITESPACE)
1450 {
1451 t = t->next;
1452 continue;
1453 }
1454 else if (tt->type == TOK_WHITESPACE)
1455 {
1456 tt = tt->next;
1457 continue;
1458 }
1459 else if (tt->type != t->type ||
1460 mstrcmp(tt->text, t->text, casesense))
1461 {
1462 j = FALSE; /* found mismatching tokens */
1463 break;
1464 }
1465 else
1466 {
1467 t = t->next;
1468 tt = tt->next;
1469 continue;
1470 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001471 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001472 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
1473 j = FALSE; /* trailing gunk on one end or other */
1474 if (i == PP_IFNIDN || i == PP_ELIFNIDN ||
1475 i == PP_IFNIDNI || i == PP_ELIFNIDNI)
1476 j = !j;
1477 free_tlist(tline);
1478 return j;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001479
H. Peter Anvin734b1882002-04-30 21:01:08 +00001480 case PP_IFID:
1481 case PP_ELIFID:
1482 case PP_IFNID:
1483 case PP_ELIFNID:
1484 case PP_IFNUM:
1485 case PP_ELIFNUM:
1486 case PP_IFNNUM:
1487 case PP_ELIFNNUM:
1488 case PP_IFSTR:
1489 case PP_ELIFSTR:
1490 case PP_IFNSTR:
1491 case PP_ELIFNSTR:
1492 tline = expand_smacro(tline);
1493 t = tline;
1494 while (tok_type_(t, TOK_WHITESPACE))
1495 t = t->next;
1496 j = FALSE; /* placate optimiser */
1497 if (t)
1498 switch (i)
1499 {
1500 case PP_IFID:
1501 case PP_ELIFID:
1502 case PP_IFNID:
1503 case PP_ELIFNID:
1504 j = (t->type == TOK_ID);
1505 break;
1506 case PP_IFNUM:
1507 case PP_ELIFNUM:
1508 case PP_IFNNUM:
1509 case PP_ELIFNNUM:
1510 j = (t->type == TOK_NUMBER);
1511 break;
1512 case PP_IFSTR:
1513 case PP_ELIFSTR:
1514 case PP_IFNSTR:
1515 case PP_ELIFNSTR:
1516 j = (t->type == TOK_STRING);
1517 break;
1518 }
1519 if (i == PP_IFNID || i == PP_ELIFNID ||
1520 i == PP_IFNNUM || i == PP_ELIFNNUM ||
1521 i == PP_IFNSTR || i == PP_ELIFNSTR)
1522 j = !j;
1523 free_tlist(tline);
1524 return j;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001525
H. Peter Anvin734b1882002-04-30 21:01:08 +00001526 case PP_IF:
1527 case PP_ELIF:
1528 t = tline = expand_smacro(tline);
1529 tptr = &t;
1530 tokval.t_type = TOKEN_INVALID;
1531 evalresult = evaluate(ppscan, tptr, &tokval,
1532 NULL, pass | CRITICAL, error, NULL);
1533 free_tlist(tline);
1534 if (!evalresult)
1535 return -1;
1536 if (tokval.t_type)
1537 error(ERR_WARNING,
1538 "trailing garbage after expression ignored");
1539 if (!is_simple(evalresult))
1540 {
1541 error(ERR_NONFATAL,
1542 "non-constant value given to `%s'", directives[i]);
1543 return -1;
1544 }
1545 return reloc_value(evalresult) != 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001546
H. Peter Anvin734b1882002-04-30 21:01:08 +00001547 default:
1548 error(ERR_FATAL,
1549 "preprocessor directive `%s' not yet implemented",
1550 directives[i]);
1551 free_tlist(origline);
1552 return -1; /* yeah, right */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001553 }
1554}
1555
1556/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001557 * Expand macros in a string. Used in %error and %include directives.
1558 * First tokenise the string, apply "expand_smacro" and then de-tokenise back.
1559 * The returned variable should ALWAYS be freed after usage.
1560 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001561void
1562expand_macros_in_string(char **p)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001563{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001564 Token *line = tokenise(*p);
1565 line = expand_smacro(line);
1566 *p = detoken(line, FALSE);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001567}
1568
1569/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001570 * Find out if a line contains a preprocessor directive, and deal
1571 * with it if so.
1572 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00001573 * If a directive _is_ found, we are expected to free_tlist() the
1574 * line.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001575 *
1576 * Return values go like this:
1577 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00001578 * bit 0 is set if a directive was found (so the line gets freed)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001579 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001580static int
1581do_directive(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001582{
H. Peter Anvin76690a12002-04-30 20:52:49 +00001583 int i, j, k, m, nparam, nolist;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001584 int offset;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001585 char *p, *mname;
1586 Include *inc;
1587 Context *ctx;
1588 Cond *cond;
1589 SMacro *smac, **smhead;
1590 MMacro *mmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001591 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
1592 Line *l;
1593 struct tokenval tokval;
1594 expr *evalresult;
H. Peter Anvinb64535f2002-04-30 20:55:37 +00001595 MMacro *tmp_defining; /* Used when manipulating rep_nest */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001596
1597 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001598
H. Peter Anvineba20a72002-04-30 20:53:55 +00001599 skip_white_(tline);
1600 if (!tok_type_(tline, TOK_PREPROC_ID) ||
H. Peter Anvin734b1882002-04-30 21:01:08 +00001601 (tline->text[1] == '%' || tline->text[1] == '$'
1602 || tline->text[1] == '!'))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001603 return 0;
1604
1605 i = -1;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001606 j = sizeof(directives) / sizeof(*directives);
1607 while (j - i > 1)
1608 {
1609 k = (j + i) / 2;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001610 m = nasm_stricmp(tline->text, directives[k]);
1611 if (m == 0) {
H. Peter Anvin734b1882002-04-30 21:01:08 +00001612 if (tasm_compatible_mode) {
1613 i = k;
1614 j = -2;
1615 } else if (k != PP_ARG && k != PP_LOCAL && k != PP_STACKSIZE) {
1616 i = k;
1617 j = -2;
1618 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001619 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001620 }
1621 else if (m < 0) {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001622 j = k;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001623 }
1624 else
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001625 i = k;
1626 }
1627
1628 /*
1629 * If we're in a non-emitting branch of a condition construct,
H. Peter Anvin76690a12002-04-30 20:52:49 +00001630 * or walking to the end of an already terminated %rep block,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001631 * we should ignore all directives except for condition
1632 * directives.
1633 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001634 if (((istk->conds && !emitting(istk->conds->state)) ||
H. Peter Anvin734b1882002-04-30 21:01:08 +00001635 (istk->mstk && !istk->mstk->in_progress)) &&
1636 i != PP_IF && i != PP_ELIF &&
1637 i != PP_IFCTX && i != PP_ELIFCTX &&
1638 i != PP_IFDEF && i != PP_ELIFDEF &&
1639 i != PP_IFID && i != PP_ELIFID &&
1640 i != PP_IFIDN && i != PP_ELIFIDN &&
1641 i != PP_IFIDNI && i != PP_ELIFIDNI &&
1642 i != PP_IFNCTX && i != PP_ELIFNCTX &&
1643 i != PP_IFNDEF && i != PP_ELIFNDEF &&
1644 i != PP_IFNID && i != PP_ELIFNID &&
1645 i != PP_IFNIDN && i != PP_ELIFNIDN &&
1646 i != PP_IFNIDNI && i != PP_ELIFNIDNI &&
1647 i != PP_IFNNUM && i != PP_ELIFNNUM &&
1648 i != PP_IFNSTR && i != PP_ELIFNSTR &&
1649 i != PP_IFNUM && i != PP_ELIFNUM &&
1650 i != PP_IFSTR && i != PP_ELIFSTR && i != PP_ELSE && i != PP_ENDIF)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001651 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001652 return 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001653 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001654
1655 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001656 * If we're defining a macro or reading a %rep block, we should
1657 * ignore all directives except for %macro/%imacro (which
1658 * generate an error), %endm/%endmacro, and (only if we're in a
H. Peter Anvineba20a72002-04-30 20:53:55 +00001659 * %rep block) %endrep. If we're in a %rep block, another %rep
1660 * causes an error, so should be let through.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001661 */
1662 if (defining && i != PP_MACRO && i != PP_IMACRO &&
H. Peter Anvin734b1882002-04-30 21:01:08 +00001663 i != PP_ENDMACRO && i != PP_ENDM &&
1664 (defining->name || (i != PP_ENDREP && i != PP_REP)))
H. Peter Anvineba20a72002-04-30 20:53:55 +00001665 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001666 return 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001667 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001668
H. Peter Anvin734b1882002-04-30 21:01:08 +00001669 if (j != -2)
1670 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00001671 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
H. Peter Anvin734b1882002-04-30 21:01:08 +00001672 tline->text);
1673 return 0; /* didn't get it */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001674 }
1675
H. Peter Anvin734b1882002-04-30 21:01:08 +00001676 switch (i)
1677 {
1678 case PP_STACKSIZE:
1679 /* Directive to tell NASM what the default stack size is. The
1680 * default is for a 16-bit stack, and this can be overriden with
1681 * %stacksize large.
1682 * the following form:
1683 *
1684 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001685 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001686 tline = tline->next;
1687 if (tline && tline->type == TOK_WHITESPACE)
1688 tline = tline->next;
1689 if (!tline || tline->type != TOK_ID)
1690 {
1691 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
1692 free_tlist(origline);
1693 return 3;
1694 }
1695 if (nasm_stricmp(tline->text, "flat") == 0)
1696 {
1697 /* All subsequent ARG directives are for a 32-bit stack */
1698 StackSize = 4;
1699 StackPointer = "ebp";
1700 ArgOffset = 8;
1701 LocalOffset = 4;
1702 }
1703 else if (nasm_stricmp(tline->text, "large") == 0)
1704 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001705 /* All subsequent ARG directives are for a 16-bit stack,
H. Peter Anvin734b1882002-04-30 21:01:08 +00001706 * far function call.
1707 */
1708 StackSize = 2;
1709 StackPointer = "bp";
1710 ArgOffset = 4;
1711 LocalOffset = 2;
1712 }
1713 else if (nasm_stricmp(tline->text, "small") == 0)
1714 {
1715 /* All subsequent ARG directives are for a 16-bit stack,
1716 * far function call. We don't support near functions.
1717 */
1718 StackSize = 2;
1719 StackPointer = "bp";
1720 ArgOffset = 6;
1721 LocalOffset = 2;
1722 }
1723 else
1724 {
1725 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
1726 free_tlist(origline);
1727 return 3;
1728 }
1729 free_tlist(origline);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001730 return 3;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001731
H. Peter Anvin734b1882002-04-30 21:01:08 +00001732 case PP_ARG:
1733 /* TASM like ARG directive to define arguments to functions, in
1734 * the following form:
1735 *
1736 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1737 */
1738 offset = ArgOffset;
1739 do
1740 {
1741 char *arg, directive[256];
1742 int size = StackSize;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001743
H. Peter Anvin734b1882002-04-30 21:01:08 +00001744 /* Find the argument name */
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001745 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001746 if (tline && tline->type == TOK_WHITESPACE)
1747 tline = tline->next;
1748 if (!tline || tline->type != TOK_ID)
1749 {
1750 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
1751 free_tlist(origline);
1752 return 3;
1753 }
1754 arg = tline->text;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001755
H. Peter Anvin734b1882002-04-30 21:01:08 +00001756 /* Find the argument size type */
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001757 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001758 if (!tline || tline->type != TOK_OTHER
1759 || tline->text[0] != ':')
1760 {
1761 error(ERR_NONFATAL,
1762 "Syntax error processing `%%arg' directive");
1763 free_tlist(origline);
1764 return 3;
1765 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001766 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001767 if (!tline || tline->type != TOK_ID)
1768 {
1769 error(ERR_NONFATAL,
1770 "`%%arg' missing size type parameter");
1771 free_tlist(origline);
1772 return 3;
1773 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001774
H. Peter Anvin734b1882002-04-30 21:01:08 +00001775 /* Allow macro expansion of type parameter */
1776 tt = tokenise(tline->text);
1777 tt = expand_smacro(tt);
1778 if (nasm_stricmp(tt->text, "byte") == 0)
1779 {
1780 size = MAX(StackSize, 1);
1781 }
1782 else if (nasm_stricmp(tt->text, "word") == 0)
1783 {
1784 size = MAX(StackSize, 2);
1785 }
1786 else if (nasm_stricmp(tt->text, "dword") == 0)
1787 {
1788 size = MAX(StackSize, 4);
1789 }
1790 else if (nasm_stricmp(tt->text, "qword") == 0)
1791 {
1792 size = MAX(StackSize, 8);
1793 }
1794 else if (nasm_stricmp(tt->text, "tword") == 0)
1795 {
1796 size = MAX(StackSize, 10);
1797 }
1798 else
1799 {
1800 error(ERR_NONFATAL,
1801 "Invalid size type for `%%arg' missing directive");
1802 free_tlist(tt);
1803 free_tlist(origline);
1804 return 3;
1805 }
1806 free_tlist(tt);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001807
H. Peter Anvin734b1882002-04-30 21:01:08 +00001808 /* Now define the macro for the argument */
1809 sprintf(directive, "%%define %s (%s+%d)", arg, StackPointer,
1810 offset);
1811 do_directive(tokenise(directive));
1812 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001813
H. Peter Anvin734b1882002-04-30 21:01:08 +00001814 /* Move to the next argument in the list */
1815 tline = tline->next;
1816 if (tline && tline->type == TOK_WHITESPACE)
1817 tline = tline->next;
1818 }
1819 while (tline && tline->type == TOK_OTHER
1820 && tline->text[0] == ',');
1821 free_tlist(origline);
1822 return 3;
1823
1824 case PP_LOCAL:
1825 /* TASM like LOCAL directive to define local variables for a
1826 * function, in the following form:
1827 *
1828 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
1829 *
1830 * The '= LocalSize' at the end is ignored by NASM, but is
1831 * required by TASM to define the local parameter size (and used
1832 * by the TASM macro package).
1833 */
1834 offset = LocalOffset;
1835 do
1836 {
1837 char *local, directive[256];
1838 int size = StackSize;
1839
1840 /* Find the argument name */
1841 tline = tline->next;
1842 if (tline && tline->type == TOK_WHITESPACE)
1843 tline = tline->next;
1844 if (!tline || tline->type != TOK_ID)
1845 {
1846 error(ERR_NONFATAL,
1847 "`%%local' missing argument parameter");
1848 free_tlist(origline);
1849 return 3;
1850 }
1851 local = tline->text;
1852
1853 /* Find the argument size type */
1854 tline = tline->next;
1855 if (!tline || tline->type != TOK_OTHER
1856 || tline->text[0] != ':')
1857 {
1858 error(ERR_NONFATAL,
1859 "Syntax error processing `%%local' directive");
1860 free_tlist(origline);
1861 return 3;
1862 }
1863 tline = tline->next;
1864 if (!tline || tline->type != TOK_ID)
1865 {
1866 error(ERR_NONFATAL,
1867 "`%%local' missing size type parameter");
1868 free_tlist(origline);
1869 return 3;
1870 }
1871
1872 /* Allow macro expansion of type parameter */
1873 tt = tokenise(tline->text);
1874 tt = expand_smacro(tt);
1875 if (nasm_stricmp(tt->text, "byte") == 0)
1876 {
1877 size = MAX(StackSize, 1);
1878 }
1879 else if (nasm_stricmp(tt->text, "word") == 0)
1880 {
1881 size = MAX(StackSize, 2);
1882 }
1883 else if (nasm_stricmp(tt->text, "dword") == 0)
1884 {
1885 size = MAX(StackSize, 4);
1886 }
1887 else if (nasm_stricmp(tt->text, "qword") == 0)
1888 {
1889 size = MAX(StackSize, 8);
1890 }
1891 else if (nasm_stricmp(tt->text, "tword") == 0)
1892 {
1893 size = MAX(StackSize, 10);
1894 }
1895 else
1896 {
1897 error(ERR_NONFATAL,
1898 "Invalid size type for `%%local' missing directive");
1899 free_tlist(tt);
1900 free_tlist(origline);
1901 return 3;
1902 }
1903 free_tlist(tt);
1904
1905 /* Now define the macro for the argument */
1906 sprintf(directive, "%%define %s (%s-%d)", local, StackPointer,
1907 offset);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001908 do_directive(tokenise(directive));
1909 offset += size;
1910
1911 /* Now define the assign to setup the enter_c macro correctly */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001912 sprintf(directive, "%%assign %%$localsize %%$localsize+%d",
1913 size);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001914 do_directive(tokenise(directive));
1915
H. Peter Anvin734b1882002-04-30 21:01:08 +00001916 /* Move to the next argument in the list */
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001917 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001918 if (tline && tline->type == TOK_WHITESPACE)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001919 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001920 }
1921 while (tline && tline->type == TOK_OTHER
1922 && tline->text[0] == ',');
1923 free_tlist(origline);
1924 return 3;
1925
1926 case PP_CLEAR:
1927 if (tline->next)
1928 error(ERR_WARNING,
1929 "trailing garbage after `%%clear' ignored");
1930 for (j = 0; j < NHASH; j++)
1931 {
1932 while (mmacros[j])
1933 {
1934 MMacro *m = mmacros[j];
1935 mmacros[j] = m->next;
1936 free_mmacro(m);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001937 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001938 while (smacros[j])
1939 {
1940 SMacro *s = smacros[j];
1941 smacros[j] = smacros[j]->next;
1942 nasm_free(s->name);
1943 free_tlist(s->expansion);
1944 nasm_free(s);
1945 }
1946 }
1947 free_tlist(origline);
1948 return 3;
1949
1950 case PP_INCLUDE:
1951 tline = tline->next;
1952 skip_white_(tline);
1953 if (!tline || (tline->type != TOK_STRING &&
1954 tline->type != TOK_INTERNAL_STRING))
1955 {
1956 error(ERR_NONFATAL, "`%%include' expects a file name");
1957 free_tlist(origline);
1958 return 3; /* but we did _something_ */
1959 }
1960 if (tline->next)
1961 error(ERR_WARNING,
1962 "trailing garbage after `%%include' ignored");
1963 if (tline->type != TOK_INTERNAL_STRING)
1964 {
1965 p = tline->text + 1; /* point past the quote to the name */
1966 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
1967 }
1968 else
1969 p = tline->text; /* internal_string is easier */
1970 expand_macros_in_string(&p);
1971 inc = nasm_malloc(sizeof(Include));
1972 inc->next = istk;
1973 inc->conds = NULL;
1974 inc->fp = inc_fopen(p);
1975 inc->fname = src_set_fname(p);
1976 inc->lineno = src_set_linnum(0);
1977 inc->lineinc = 1;
1978 inc->expansion = NULL;
1979 inc->mstk = NULL;
1980 istk = inc;
1981 list->uplevel(LIST_INCLUDE);
1982 free_tlist(origline);
1983 return 5;
1984
1985 case PP_PUSH:
1986 tline = tline->next;
1987 skip_white_(tline);
1988 tline = expand_id(tline);
1989 if (!tok_type_(tline, TOK_ID))
1990 {
1991 error(ERR_NONFATAL, "`%%push' expects a context identifier");
1992 free_tlist(origline);
1993 return 3; /* but we did _something_ */
1994 }
1995 if (tline->next)
1996 error(ERR_WARNING, "trailing garbage after `%%push' ignored");
1997 ctx = nasm_malloc(sizeof(Context));
1998 ctx->next = cstk;
1999 ctx->localmac = NULL;
2000 ctx->name = nasm_strdup(tline->text);
2001 ctx->number = unique++;
2002 cstk = ctx;
2003 free_tlist(origline);
2004 break;
2005
2006 case PP_REPL:
2007 tline = tline->next;
2008 skip_white_(tline);
2009 tline = expand_id(tline);
2010 if (!tok_type_(tline, TOK_ID))
2011 {
2012 error(ERR_NONFATAL, "`%%repl' expects a context identifier");
2013 free_tlist(origline);
2014 return 3; /* but we did _something_ */
2015 }
2016 if (tline->next)
2017 error(ERR_WARNING, "trailing garbage after `%%repl' ignored");
2018 if (!cstk)
2019 error(ERR_NONFATAL, "`%%repl': context stack is empty");
2020 else
2021 {
2022 nasm_free(cstk->name);
2023 cstk->name = nasm_strdup(tline->text);
2024 }
2025 free_tlist(origline);
2026 break;
2027
2028 case PP_POP:
2029 if (tline->next)
2030 error(ERR_WARNING, "trailing garbage after `%%pop' ignored");
2031 if (!cstk)
2032 error(ERR_NONFATAL,
2033 "`%%pop': context stack is already empty");
2034 else
2035 ctx_pop();
2036 free_tlist(origline);
2037 break;
2038
2039 case PP_ERROR:
2040 tline->next = expand_smacro(tline->next);
2041 tline = tline->next;
2042 skip_white_(tline);
2043 if (tok_type_(tline, TOK_STRING))
2044 {
2045 p = tline->text + 1; /* point past the quote to the name */
2046 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
2047 expand_macros_in_string(&p);
2048 error(ERR_NONFATAL, "%s", p);
2049 nasm_free(p);
2050 }
2051 else
2052 {
2053 p = detoken(tline, FALSE);
2054 error(ERR_WARNING, "%s", p);
2055 nasm_free(p);
2056 }
2057 free_tlist(origline);
2058 break;
2059
2060 case PP_IF:
2061 case PP_IFCTX:
2062 case PP_IFDEF:
2063 case PP_IFID:
2064 case PP_IFIDN:
2065 case PP_IFIDNI:
2066 case PP_IFNCTX:
2067 case PP_IFNDEF:
2068 case PP_IFNID:
2069 case PP_IFNIDN:
2070 case PP_IFNIDNI:
2071 case PP_IFNNUM:
2072 case PP_IFNSTR:
2073 case PP_IFNUM:
2074 case PP_IFSTR:
2075 if (istk->conds && !emitting(istk->conds->state))
2076 j = COND_NEVER;
2077 else
2078 {
2079 j = if_condition(tline->next, i);
2080 tline->next = NULL; /* it got freed */
2081 free_tlist(origline);
2082 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2083 }
2084 cond = nasm_malloc(sizeof(Cond));
2085 cond->next = istk->conds;
2086 cond->state = j;
2087 istk->conds = cond;
2088 return (j == COND_IF_TRUE ? 3 : 1);
2089
2090 case PP_ELIF:
2091 case PP_ELIFCTX:
2092 case PP_ELIFDEF:
2093 case PP_ELIFID:
2094 case PP_ELIFIDN:
2095 case PP_ELIFIDNI:
2096 case PP_ELIFNCTX:
2097 case PP_ELIFNDEF:
2098 case PP_ELIFNID:
2099 case PP_ELIFNIDN:
2100 case PP_ELIFNIDNI:
2101 case PP_ELIFNNUM:
2102 case PP_ELIFNSTR:
2103 case PP_ELIFNUM:
2104 case PP_ELIFSTR:
2105 if (!istk->conds)
2106 error(ERR_FATAL, "`%s': no matching `%%if'", directives[i]);
2107 if (emitting(istk->conds->state)
2108 || istk->conds->state == COND_NEVER)
2109 istk->conds->state = COND_NEVER;
2110 else
2111 {
2112 j = if_condition(expand_mmac_params(tline->next), i);
2113 tline->next = NULL; /* it got freed */
2114 free_tlist(origline);
2115 istk->conds->state =
2116 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2117 }
2118 return (istk->conds->state == COND_IF_TRUE ? 5 : 1);
2119
2120 case PP_ELSE:
2121 if (tline->next)
2122 error(ERR_WARNING, "trailing garbage after `%%else' ignored");
2123 if (!istk->conds)
2124 error(ERR_FATAL, "`%%else': no matching `%%if'");
2125 if (emitting(istk->conds->state)
2126 || istk->conds->state == COND_NEVER)
2127 istk->conds->state = COND_ELSE_FALSE;
2128 else
2129 istk->conds->state = COND_ELSE_TRUE;
2130 free_tlist(origline);
2131 return 5;
2132
2133 case PP_ENDIF:
2134 if (tline->next)
2135 error(ERR_WARNING,
2136 "trailing garbage after `%%endif' ignored");
2137 if (!istk->conds)
2138 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2139 cond = istk->conds;
2140 istk->conds = cond->next;
2141 nasm_free(cond);
2142 free_tlist(origline);
2143 return 5;
2144
2145 case PP_MACRO:
2146 case PP_IMACRO:
2147 if (defining)
2148 error(ERR_FATAL,
2149 "`%%%smacro': already defining a macro",
2150 (i == PP_IMACRO ? "i" : ""));
2151 tline = tline->next;
2152 skip_white_(tline);
2153 tline = expand_id(tline);
2154 if (!tok_type_(tline, TOK_ID))
2155 {
2156 error(ERR_NONFATAL,
2157 "`%%%smacro' expects a macro name",
2158 (i == PP_IMACRO ? "i" : ""));
2159 return 3;
2160 }
2161 defining = nasm_malloc(sizeof(MMacro));
2162 defining->name = nasm_strdup(tline->text);
2163 defining->casesense = (i == PP_MACRO);
2164 defining->plus = FALSE;
2165 defining->nolist = FALSE;
2166 defining->in_progress = FALSE;
2167 defining->rep_nest = NULL;
2168 tline = expand_smacro(tline->next);
2169 skip_white_(tline);
2170 if (!tok_type_(tline, TOK_NUMBER))
2171 {
2172 error(ERR_NONFATAL,
2173 "`%%%smacro' expects a parameter count",
2174 (i == PP_IMACRO ? "i" : ""));
2175 defining->nparam_min = defining->nparam_max = 0;
2176 }
2177 else
2178 {
2179 defining->nparam_min = defining->nparam_max =
2180 readnum(tline->text, &j);
2181 if (j)
2182 error(ERR_NONFATAL,
2183 "unable to parse parameter count `%s'",
2184 tline->text);
2185 }
2186 if (tline && tok_is_(tline->next, "-"))
2187 {
2188 tline = tline->next->next;
2189 if (tok_is_(tline, "*"))
2190 defining->nparam_max = INT_MAX;
2191 else if (!tok_type_(tline, TOK_NUMBER))
2192 error(ERR_NONFATAL,
2193 "`%%%smacro' expects a parameter count after `-'",
2194 (i == PP_IMACRO ? "i" : ""));
2195 else
2196 {
2197 defining->nparam_max = readnum(tline->text, &j);
2198 if (j)
2199 error(ERR_NONFATAL,
2200 "unable to parse parameter count `%s'",
2201 tline->text);
2202 if (defining->nparam_min > defining->nparam_max)
2203 error(ERR_NONFATAL,
2204 "minimum parameter count exceeds maximum");
2205 }
2206 }
2207 if (tline && tok_is_(tline->next, "+"))
2208 {
2209 tline = tline->next;
2210 defining->plus = TRUE;
2211 }
2212 if (tline && tok_type_(tline->next, TOK_ID) &&
2213 !nasm_stricmp(tline->next->text, ".nolist"))
2214 {
2215 tline = tline->next;
2216 defining->nolist = TRUE;
2217 }
2218 mmac = mmacros[hash(defining->name)];
2219 while (mmac)
2220 {
2221 if (!strcmp(mmac->name, defining->name) &&
2222 (mmac->nparam_min <= defining->nparam_max
2223 || defining->plus)
2224 && (defining->nparam_min <= mmac->nparam_max
2225 || mmac->plus))
2226 {
2227 error(ERR_WARNING,
2228 "redefining multi-line macro `%s'",
2229 defining->name);
2230 break;
2231 }
2232 mmac = mmac->next;
2233 }
2234 /*
2235 * Handle default parameters.
2236 */
2237 if (tline && tline->next)
2238 {
2239 defining->dlist = tline->next;
2240 tline->next = NULL;
2241 count_mmac_params(defining->dlist, &defining->ndefs,
2242 &defining->defaults);
2243 }
2244 else
2245 {
2246 defining->dlist = NULL;
2247 defining->defaults = NULL;
2248 }
2249 defining->expansion = NULL;
2250 free_tlist(origline);
2251 return 1;
2252
2253 case PP_ENDM:
2254 case PP_ENDMACRO:
2255 if (!defining)
2256 {
2257 error(ERR_NONFATAL, "`%s': not defining a macro",
2258 tline->text);
2259 return 3;
2260 }
2261 k = hash(defining->name);
2262 defining->next = mmacros[k];
2263 mmacros[k] = defining;
2264 defining = NULL;
2265 free_tlist(origline);
2266 return 5;
2267
2268 case PP_ROTATE:
2269 if (tline->next && tline->next->type == TOK_WHITESPACE)
2270 tline = tline->next;
2271 t = expand_smacro(tline->next);
2272 tline->next = NULL;
2273 free_tlist(origline);
2274 tline = t;
2275 tptr = &t;
2276 tokval.t_type = TOKEN_INVALID;
2277 evalresult =
2278 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2279 free_tlist(tline);
2280 if (!evalresult)
2281 return 3;
2282 if (tokval.t_type)
2283 error(ERR_WARNING,
2284 "trailing garbage after expression ignored");
2285 if (!is_simple(evalresult))
2286 {
2287 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2288 return 3;
2289 }
2290 mmac = istk->mstk;
2291 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2292 mmac = mmac->next_active;
2293 if (!mmac)
2294 error(ERR_NONFATAL,
2295 "`%%rotate' invoked outside a macro call");
2296 mmac->rotate = mmac->rotate + reloc_value(evalresult);
2297 if (mmac->rotate < 0)
2298 mmac->rotate = mmac->nparam - (-mmac->rotate) % mmac->nparam;
2299 mmac->rotate %= mmac->nparam;
2300 return 1;
2301
2302 case PP_REP:
2303 nolist = FALSE;
2304 tline = tline->next;
2305 if (tline->next && tline->next->type == TOK_WHITESPACE)
2306 tline = tline->next;
2307 if (tline->next && tline->next->type == TOK_ID &&
2308 !nasm_stricmp(tline->next->text, ".nolist"))
2309 {
2310 tline = tline->next;
2311 nolist = TRUE;
2312 }
2313 t = expand_smacro(tline->next);
2314 tline->next = NULL;
2315 free_tlist(origline);
2316 tline = t;
2317 tptr = &t;
2318 tokval.t_type = TOKEN_INVALID;
2319 evalresult =
2320 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2321 free_tlist(tline);
2322 if (!evalresult)
2323 return 3;
2324 if (tokval.t_type)
2325 error(ERR_WARNING,
2326 "trailing garbage after expression ignored");
2327 if (!is_simple(evalresult))
2328 {
2329 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2330 return 3;
2331 }
2332 tmp_defining = defining;
2333 defining = nasm_malloc(sizeof(MMacro));
2334 defining->name = NULL; /* flags this macro as a %rep block */
2335 defining->casesense = 0;
2336 defining->plus = FALSE;
2337 defining->nolist = nolist;
2338 defining->in_progress = reloc_value(evalresult) + 1;
2339 defining->nparam_min = defining->nparam_max = 0;
2340 defining->defaults = NULL;
2341 defining->dlist = NULL;
2342 defining->expansion = NULL;
2343 defining->next_active = istk->mstk;
2344 defining->rep_nest = tmp_defining;
2345 return 1;
2346
2347 case PP_ENDREP:
2348 if (!defining || defining->name)
2349 {
2350 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2351 return 3;
2352 }
2353
2354 /*
2355 * Now we have a "macro" defined - although it has no name
2356 * and we won't be entering it in the hash tables - we must
2357 * push a macro-end marker for it on to istk->expansion.
2358 * After that, it will take care of propagating itself (a
2359 * macro-end marker line for a macro which is really a %rep
2360 * block will cause the macro to be re-expanded, complete
2361 * with another macro-end marker to ensure the process
2362 * continues) until the whole expansion is forcibly removed
2363 * from istk->expansion by a %exitrep.
2364 */
2365 l = nasm_malloc(sizeof(Line));
2366 l->next = istk->expansion;
2367 l->finishes = defining;
2368 l->first = NULL;
2369 istk->expansion = l;
2370
2371 istk->mstk = defining;
2372
2373 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2374 tmp_defining = defining;
2375 defining = defining->rep_nest;
2376 free_tlist(origline);
2377 return 1;
2378
2379 case PP_EXITREP:
2380 /*
2381 * We must search along istk->expansion until we hit a
2382 * macro-end marker for a macro with no name. Then we set
2383 * its `in_progress' flag to 0.
2384 */
2385 for (l = istk->expansion; l; l = l->next)
2386 if (l->finishes && !l->finishes->name)
2387 break;
2388
2389 if (l)
2390 l->finishes->in_progress = 0;
2391 else
2392 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2393 free_tlist(origline);
2394 return 1;
2395
2396 case PP_XDEFINE:
2397 case PP_IXDEFINE:
2398 case PP_DEFINE:
2399 case PP_IDEFINE:
2400 tline = tline->next;
2401 skip_white_(tline);
2402 tline = expand_id(tline);
2403 if (!tline || (tline->type != TOK_ID &&
2404 (tline->type != TOK_PREPROC_ID ||
2405 tline->text[1] != '$')))
2406 {
2407 error(ERR_NONFATAL,
2408 "`%%%s%sdefine' expects a macro identifier",
2409 ((i == PP_IDEFINE || i == PP_IXDEFINE) ? "i" : ""),
2410 ((i == PP_XDEFINE || i == PP_IXDEFINE) ? "x" : ""));
2411 free_tlist(origline);
2412 return 3;
2413 }
2414
2415 ctx = get_ctx(tline->text, FALSE);
2416 if (!ctx)
2417 smhead = &smacros[hash(tline->text)];
2418 else
2419 smhead = &ctx->localmac;
2420 mname = tline->text;
2421 last = tline;
2422 param_start = tline = tline->next;
2423 nparam = 0;
2424
2425 /* Expand the macro definition now for %xdefine and %ixdefine */
2426 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2427 tline = expand_smacro(tline);
2428
2429 if (tok_is_(tline, "("))
2430 {
2431 /*
2432 * This macro has parameters.
2433 */
2434
2435 tline = tline->next;
2436 while (1)
2437 {
2438 skip_white_(tline);
2439 if (!tline)
2440 {
2441 error(ERR_NONFATAL, "parameter identifier expected");
2442 free_tlist(origline);
2443 return 3;
2444 }
2445 if (tline->type != TOK_ID)
2446 {
2447 error(ERR_NONFATAL,
2448 "`%s': parameter identifier expected",
2449 tline->text);
2450 free_tlist(origline);
2451 return 3;
2452 }
2453 tline->type = TOK_SMAC_PARAM + nparam++;
2454 tline = tline->next;
2455 skip_white_(tline);
2456 if (tok_is_(tline, ","))
2457 {
2458 tline = tline->next;
2459 continue;
2460 }
2461 if (!tok_is_(tline, ")"))
2462 {
2463 error(ERR_NONFATAL,
2464 "`)' expected to terminate macro template");
2465 free_tlist(origline);
2466 return 3;
2467 }
2468 break;
2469 }
2470 last = tline;
2471 tline = tline->next;
2472 }
2473 if (tok_type_(tline, TOK_WHITESPACE))
2474 last = tline, tline = tline->next;
2475 macro_start = NULL;
2476 last->next = NULL;
2477 t = tline;
2478 while (t)
2479 {
2480 if (t->type == TOK_ID)
2481 {
2482 for (tt = param_start; tt; tt = tt->next)
2483 if (tt->type >= TOK_SMAC_PARAM &&
2484 !strcmp(tt->text, t->text))
2485 t->type = tt->type;
2486 }
2487 tt = t->next;
2488 t->next = macro_start;
2489 macro_start = t;
2490 t = tt;
2491 }
2492 /*
2493 * Good. We now have a macro name, a parameter count, and a
2494 * token list (in reverse order) for an expansion. We ought
2495 * to be OK just to create an SMacro, store it, and let
2496 * free_tlist have the rest of the line (which we have
2497 * carefully re-terminated after chopping off the expansion
2498 * from the end).
2499 */
2500 if (smacro_defined(ctx, mname, nparam, &smac, i == PP_DEFINE))
2501 {
2502 if (!smac)
2503 {
2504 error(ERR_WARNING,
2505 "single-line macro `%s' defined both with and"
2506 " without parameters", mname);
2507 free_tlist(origline);
2508 free_tlist(macro_start);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002509 return 3;
2510 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002511 else
2512 {
2513 /*
2514 * We're redefining, so we have to take over an
2515 * existing SMacro structure. This means freeing
2516 * what was already in it.
2517 */
2518 nasm_free(smac->name);
2519 free_tlist(smac->expansion);
2520 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002521 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002522 else
2523 {
2524 smac = nasm_malloc(sizeof(SMacro));
2525 smac->next = *smhead;
2526 *smhead = smac;
2527 }
2528 smac->name = nasm_strdup(mname);
2529 smac->casesense = ((i == PP_DEFINE) || (i == PP_XDEFINE));
2530 smac->nparam = nparam;
2531 smac->expansion = macro_start;
2532 smac->in_progress = FALSE;
2533 free_tlist(origline);
2534 return 3;
2535
2536 case PP_UNDEF:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002537 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002538 skip_white_(tline);
2539 tline = expand_id(tline);
2540 if (!tline || (tline->type != TOK_ID &&
2541 (tline->type != TOK_PREPROC_ID ||
2542 tline->text[1] != '$')))
2543 {
2544 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
2545 free_tlist(origline);
H. Peter Anvineba20a72002-04-30 20:53:55 +00002546 return 3;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002547 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002548 if (tline->next)
2549 {
2550 error(ERR_WARNING,
2551 "trailing garbage after macro name ignored");
2552 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002553
H. Peter Anvin734b1882002-04-30 21:01:08 +00002554 /* Find the context that symbol belongs to */
2555 ctx = get_ctx(tline->text, FALSE);
2556 if (!ctx)
2557 smhead = &smacros[hash(tline->text)];
2558 else
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002559 smhead = &ctx->localmac;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002560
H. Peter Anvin734b1882002-04-30 21:01:08 +00002561 mname = tline->text;
2562 last = tline;
2563 last->next = NULL;
2564
2565 /*
2566 * We now have a macro name... go hunt for it.
2567 */
2568 while (smacro_defined(ctx, mname, -1, &smac, 1))
2569 {
2570 /* Defined, so we need to find its predecessor and nuke it */
2571 SMacro **s;
2572 for (s = smhead; *s && *s != smac; s = &(*s)->next);
2573 if (*s)
2574 {
2575 *s = smac->next;
2576 nasm_free(smac->name);
2577 free_tlist(smac->expansion);
2578 nasm_free(smac);
2579 }
2580 }
2581 free_tlist(origline);
2582 return 3;
2583
2584 case PP_STRLEN:
2585 tline = tline->next;
2586 skip_white_(tline);
2587 tline = expand_id(tline);
2588 if (!tline || (tline->type != TOK_ID &&
2589 (tline->type != TOK_PREPROC_ID ||
2590 tline->text[1] != '$')))
2591 {
2592 error(ERR_NONFATAL,
2593 "`%%strlen' expects a macro identifier as first parameter");
2594 free_tlist(origline);
2595 return 3;
2596 }
2597 ctx = get_ctx(tline->text, FALSE);
2598 if (!ctx)
2599 smhead = &smacros[hash(tline->text)];
2600 else
2601 smhead = &ctx->localmac;
2602 mname = tline->text;
2603 last = tline;
2604 tline = expand_smacro(tline->next);
2605 last->next = NULL;
2606
2607 t = tline;
2608 while (tok_type_(t, TOK_WHITESPACE))
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002609 t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002610 /* t should now point to the string */
2611 if (t->type != TOK_STRING)
2612 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002613 error(ERR_NONFATAL,
2614 "`%%strlen` requires string as second parameter");
2615 free_tlist(tline);
2616 free_tlist(origline);
2617 return 3;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002618 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002619
H. Peter Anvin734b1882002-04-30 21:01:08 +00002620 macro_start = nasm_malloc(sizeof(*macro_start));
2621 macro_start->next = NULL;
2622 make_tok_num(macro_start, strlen(t->text) - 2);
2623 macro_start->mac = NULL;
2624
2625 /*
2626 * We now have a macro name, an implicit parameter count of
2627 * zero, and a numeric token to use as an expansion. Create
2628 * and store an SMacro.
2629 */
2630 if (smacro_defined(ctx, mname, 0, &smac, i == PP_STRLEN))
2631 {
2632 if (!smac)
2633 error(ERR_WARNING,
2634 "single-line macro `%s' defined both with and"
2635 " without parameters", mname);
2636 else
2637 {
2638 /*
2639 * We're redefining, so we have to take over an
2640 * existing SMacro structure. This means freeing
2641 * what was already in it.
2642 */
2643 nasm_free(smac->name);
2644 free_tlist(smac->expansion);
2645 }
2646 }
2647 else
2648 {
2649 smac = nasm_malloc(sizeof(SMacro));
2650 smac->next = *smhead;
2651 *smhead = smac;
2652 }
2653 smac->name = nasm_strdup(mname);
2654 smac->casesense = (i == PP_STRLEN);
2655 smac->nparam = 0;
2656 smac->expansion = macro_start;
2657 smac->in_progress = FALSE;
2658 free_tlist(tline);
2659 free_tlist(origline);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002660 return 3;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002661
H. Peter Anvin734b1882002-04-30 21:01:08 +00002662 case PP_SUBSTR:
2663 tline = tline->next;
2664 skip_white_(tline);
2665 tline = expand_id(tline);
2666 if (!tline || (tline->type != TOK_ID &&
2667 (tline->type != TOK_PREPROC_ID ||
2668 tline->text[1] != '$')))
2669 {
2670 error(ERR_NONFATAL,
2671 "`%%substr' expects a macro identifier as first parameter");
2672 free_tlist(origline);
2673 return 3;
2674 }
2675 ctx = get_ctx(tline->text, FALSE);
2676 if (!ctx)
2677 smhead = &smacros[hash(tline->text)];
2678 else
2679 smhead = &ctx->localmac;
2680 mname = tline->text;
2681 last = tline;
2682 tline = expand_smacro(tline->next);
2683 last->next = NULL;
2684
2685 t = tline->next;
2686 while (tok_type_(t, TOK_WHITESPACE))
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002687 t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002688
2689 /* t should now point to the string */
2690 if (t->type != TOK_STRING)
2691 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002692 error(ERR_NONFATAL,
2693 "`%%substr` requires string as second parameter");
2694 free_tlist(tline);
2695 free_tlist(origline);
2696 return 3;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002697 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002698
H. Peter Anvin734b1882002-04-30 21:01:08 +00002699 tt = t->next;
2700 tptr = &tt;
2701 tokval.t_type = TOKEN_INVALID;
2702 evalresult =
2703 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2704 if (!evalresult)
2705 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002706 free_tlist(tline);
2707 free_tlist(origline);
2708 return 3;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002709 }
2710 if (!is_simple(evalresult))
2711 {
2712 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002713 free_tlist(tline);
2714 free_tlist(origline);
2715 return 3;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002716 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002717
H. Peter Anvin734b1882002-04-30 21:01:08 +00002718 macro_start = nasm_malloc(sizeof(*macro_start));
2719 macro_start->next = NULL;
2720 macro_start->text = nasm_strdup("'''");
2721 if (evalresult->value > 0
2722 && evalresult->value < strlen(t->text) - 1)
2723 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002724 macro_start->text[1] = t->text[evalresult->value];
H. Peter Anvin734b1882002-04-30 21:01:08 +00002725 }
2726 else
2727 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002728 macro_start->text[2] = '\0';
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002729 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002730 macro_start->type = TOK_STRING;
2731 macro_start->mac = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002732
H. Peter Anvin734b1882002-04-30 21:01:08 +00002733 /*
2734 * We now have a macro name, an implicit parameter count of
2735 * zero, and a numeric token to use as an expansion. Create
2736 * and store an SMacro.
2737 */
2738 if (smacro_defined(ctx, mname, 0, &smac, i == PP_SUBSTR))
2739 {
2740 if (!smac)
2741 error(ERR_WARNING,
2742 "single-line macro `%s' defined both with and"
2743 " without parameters", mname);
2744 else
2745 {
2746 /*
2747 * We're redefining, so we have to take over an
2748 * existing SMacro structure. This means freeing
2749 * what was already in it.
2750 */
2751 nasm_free(smac->name);
2752 free_tlist(smac->expansion);
2753 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002754 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002755 else
2756 {
2757 smac = nasm_malloc(sizeof(SMacro));
2758 smac->next = *smhead;
2759 *smhead = smac;
2760 }
2761 smac->name = nasm_strdup(mname);
2762 smac->casesense = (i == PP_SUBSTR);
2763 smac->nparam = 0;
2764 smac->expansion = macro_start;
2765 smac->in_progress = FALSE;
2766 free_tlist(tline);
2767 free_tlist(origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002768 return 3;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002769
2770
2771 case PP_ASSIGN:
2772 case PP_IASSIGN:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002773 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002774 skip_white_(tline);
2775 tline = expand_id(tline);
2776 if (!tline || (tline->type != TOK_ID &&
2777 (tline->type != TOK_PREPROC_ID ||
2778 tline->text[1] != '$')))
2779 {
2780 error(ERR_NONFATAL,
2781 "`%%%sassign' expects a macro identifier",
2782 (i == PP_IASSIGN ? "i" : ""));
2783 free_tlist(origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002784 return 3;
2785 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002786 ctx = get_ctx(tline->text, FALSE);
2787 if (!ctx)
2788 smhead = &smacros[hash(tline->text)];
2789 else
2790 smhead = &ctx->localmac;
2791 mname = tline->text;
2792 last = tline;
2793 tline = expand_smacro(tline->next);
2794 last->next = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002795
H. Peter Anvin734b1882002-04-30 21:01:08 +00002796 t = tline;
2797 tptr = &t;
2798 tokval.t_type = TOKEN_INVALID;
2799 evalresult =
2800 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2801 free_tlist(tline);
2802 if (!evalresult)
2803 {
2804 free_tlist(origline);
2805 return 3;
2806 }
2807
2808 if (tokval.t_type)
2809 error(ERR_WARNING,
2810 "trailing garbage after expression ignored");
2811
2812 if (!is_simple(evalresult))
2813 {
2814 error(ERR_NONFATAL,
2815 "non-constant value given to `%%%sassign'",
2816 (i == PP_IASSIGN ? "i" : ""));
2817 free_tlist(origline);
2818 return 3;
2819 }
2820
2821 macro_start = nasm_malloc(sizeof(*macro_start));
2822 macro_start->next = NULL;
2823 make_tok_num(macro_start, reloc_value(evalresult));
2824 macro_start->mac = NULL;
2825
2826 /*
2827 * We now have a macro name, an implicit parameter count of
2828 * zero, and a numeric token to use as an expansion. Create
2829 * and store an SMacro.
2830 */
2831 if (smacro_defined(ctx, mname, 0, &smac, i == PP_ASSIGN))
2832 {
2833 if (!smac)
2834 error(ERR_WARNING,
2835 "single-line macro `%s' defined both with and"
2836 " without parameters", mname);
2837 else
2838 {
2839 /*
2840 * We're redefining, so we have to take over an
2841 * existing SMacro structure. This means freeing
2842 * what was already in it.
2843 */
2844 nasm_free(smac->name);
2845 free_tlist(smac->expansion);
2846 }
2847 }
2848 else
2849 {
2850 smac = nasm_malloc(sizeof(SMacro));
2851 smac->next = *smhead;
2852 *smhead = smac;
2853 }
2854 smac->name = nasm_strdup(mname);
2855 smac->casesense = (i == PP_ASSIGN);
2856 smac->nparam = 0;
2857 smac->expansion = macro_start;
2858 smac->in_progress = FALSE;
2859 free_tlist(origline);
2860 return 3;
2861
2862 case PP_LINE:
2863 /*
2864 * Syntax is `%line nnn[+mmm] [filename]'
2865 */
2866 tline = tline->next;
2867 skip_white_(tline);
2868 if (!tok_type_(tline, TOK_NUMBER))
2869 {
2870 error(ERR_NONFATAL, "`%%line' expects line number");
2871 free_tlist(origline);
2872 return 3;
2873 }
2874 k = readnum(tline->text, &j);
2875 m = 1;
2876 tline = tline->next;
2877 if (tok_is_(tline, "+"))
2878 {
2879 tline = tline->next;
2880 if (!tok_type_(tline, TOK_NUMBER))
2881 {
2882 error(ERR_NONFATAL, "`%%line' expects line increment");
2883 free_tlist(origline);
2884 return 3;
2885 }
2886 m = readnum(tline->text, &j);
2887 tline = tline->next;
2888 }
2889 skip_white_(tline);
2890 src_set_linnum(k);
2891 istk->lineinc = m;
2892 if (tline)
2893 {
2894 nasm_free(src_set_fname(detoken(tline, FALSE)));
2895 }
2896 free_tlist(origline);
2897 return 5;
2898
2899 default:
2900 error(ERR_FATAL,
2901 "preprocessor directive `%s' not yet implemented",
2902 directives[i]);
2903 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002904 }
2905 return 3;
2906}
2907
2908/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002909 * Ensure that a macro parameter contains a condition code and
2910 * nothing else. Return the condition code index if so, or -1
2911 * otherwise.
2912 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002913static int
2914find_cc(Token * t)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002915{
H. Peter Anvin76690a12002-04-30 20:52:49 +00002916 Token *tt;
2917 int i, j, k, m;
2918
H. Peter Anvineba20a72002-04-30 20:53:55 +00002919 skip_white_(t);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002920 if (t->type != TOK_ID)
2921 return -1;
2922 tt = t->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002923 skip_white_(tt);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002924 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
2925 return -1;
2926
2927 i = -1;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002928 j = sizeof(conditions) / sizeof(*conditions);
2929 while (j - i > 1)
2930 {
2931 k = (j + i) / 2;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002932 m = nasm_stricmp(t->text, conditions[k]);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002933 if (m == 0)
2934 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00002935 i = k;
2936 j = -2;
2937 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002938 }
2939 else if (m < 0)
2940 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00002941 j = k;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002942 }
2943 else
H. Peter Anvin76690a12002-04-30 20:52:49 +00002944 i = k;
2945 }
2946 if (j != -2)
2947 return -1;
2948 return i;
2949}
2950
2951/*
2952 * Expand MMacro-local things: parameter references (%0, %n, %+n,
2953 * %-n) and MMacro-local identifiers (%%foo).
2954 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002955static Token *
2956expand_mmac_params(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002957{
H. Peter Anvin734b1882002-04-30 21:01:08 +00002958 Token *t, *tt, **tail, *thead;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002959
2960 tail = &thead;
2961 thead = NULL;
2962
H. Peter Anvin734b1882002-04-30 21:01:08 +00002963 while (tline)
2964 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00002965 if (tline->type == TOK_PREPROC_ID &&
H. Peter Anvin734b1882002-04-30 21:01:08 +00002966 (((tline->text[1] == '+' || tline->text[1] == '-')
2967 && tline->text[2]) || tline->text[1] == '%'
2968 || (tline->text[1] >= '0' && tline->text[1] <= '9')))
2969 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00002970 char *text = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002971 int type = 0, cc; /* type = 0 to placate optimisers */
H. Peter Anvin76690a12002-04-30 20:52:49 +00002972 char tmpbuf[30];
2973 int n, i;
2974 MMacro *mac;
2975
2976 t = tline;
2977 tline = tline->next;
2978
2979 mac = istk->mstk;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002980 while (mac && !mac->name) /* avoid mistaking %reps for macros */
H. Peter Anvin76690a12002-04-30 20:52:49 +00002981 mac = mac->next_active;
2982 if (!mac)
2983 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002984 else
2985 switch (t->text[1])
2986 {
2987 /*
2988 * We have to make a substitution of one of the
2989 * forms %1, %-1, %+1, %%foo, %0.
2990 */
2991 case '0':
2992 type = TOK_NUMBER;
2993 sprintf(tmpbuf, "%d", mac->nparam);
2994 text = nasm_strdup(tmpbuf);
2995 break;
2996 case '%':
2997 type = TOK_ID;
2998 sprintf(tmpbuf, "..@%lu.", mac->unique);
2999 text = nasm_strcat(tmpbuf, t->text + 2);
3000 break;
3001 case '-':
3002 n = atoi(t->text + 2) - 1;
3003 if (n >= mac->nparam)
3004 tt = NULL;
3005 else
3006 {
3007 if (mac->nparam > 1)
3008 n = (n + mac->rotate) % mac->nparam;
3009 tt = mac->params[n];
3010 }
3011 cc = find_cc(tt);
3012 if (cc == -1)
3013 {
3014 error(ERR_NONFATAL,
3015 "macro parameter %d is not a condition code",
3016 n + 1);
3017 text = NULL;
3018 }
3019 else
3020 {
3021 type = TOK_ID;
3022 if (inverse_ccs[cc] == -1)
3023 {
3024 error(ERR_NONFATAL,
3025 "condition code `%s' is not invertible",
3026 conditions[cc]);
3027 text = NULL;
3028 }
3029 else
3030 text =
3031 nasm_strdup(conditions[inverse_ccs
3032 [cc]]);
3033 }
3034 break;
3035 case '+':
3036 n = atoi(t->text + 2) - 1;
3037 if (n >= mac->nparam)
3038 tt = NULL;
3039 else
3040 {
3041 if (mac->nparam > 1)
3042 n = (n + mac->rotate) % mac->nparam;
3043 tt = mac->params[n];
3044 }
3045 cc = find_cc(tt);
3046 if (cc == -1)
3047 {
3048 error(ERR_NONFATAL,
3049 "macro parameter %d is not a condition code",
3050 n + 1);
3051 text = NULL;
3052 }
3053 else
3054 {
3055 type = TOK_ID;
3056 text = nasm_strdup(conditions[cc]);
3057 }
3058 break;
3059 default:
3060 n = atoi(t->text + 1) - 1;
3061 if (n >= mac->nparam)
3062 tt = NULL;
3063 else
3064 {
3065 if (mac->nparam > 1)
3066 n = (n + mac->rotate) % mac->nparam;
3067 tt = mac->params[n];
3068 }
3069 if (tt)
3070 {
3071 for (i = 0; i < mac->paramlen[n]; i++)
3072 {
3073 *tail =
3074 new_Token(NULL, tt->type, tt->text,
3075 0);
3076 tail = &(*tail)->next;
3077 tt = tt->next;
3078 }
3079 }
3080 text = NULL; /* we've done it here */
3081 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003082 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003083 if (!text)
3084 {
3085 delete_Token(t);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003086 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003087 else
3088 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003089 *tail = t;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003090 tail = &t->next;
3091 t->type = type;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003092 nasm_free(t->text);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003093 t->text = text;
3094 t->mac = NULL;
3095 }
3096 continue;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003097 }
3098 else
3099 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00003100 t = *tail = tline;
3101 tline = tline->next;
3102 t->mac = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003103 tail = &t->next;
3104 }
3105 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00003106 *tail = NULL;
3107 t = thead;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003108 for (; t && (tt = t->next) != NULL; t = t->next)
3109 switch (t->type)
3110 {
3111 case TOK_WHITESPACE:
3112 if (tt->type == TOK_WHITESPACE)
3113 {
3114 t->next = delete_Token(tt);
3115 }
3116 break;
3117 case TOK_ID:
3118 if (tt->type == TOK_ID || tt->type == TOK_NUMBER)
3119 {
3120 char *tmp = nasm_strcat(t->text, tt->text);
3121 nasm_free(t->text);
3122 t->text = tmp;
3123 t->next = delete_Token(tt);
3124 }
3125 break;
3126 case TOK_NUMBER:
3127 if (tt->type == TOK_NUMBER)
3128 {
3129 char *tmp = nasm_strcat(t->text, tt->text);
3130 nasm_free(t->text);
3131 t->text = tmp;
3132 t->next = delete_Token(tt);
3133 }
3134 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003135 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003136
H. Peter Anvin76690a12002-04-30 20:52:49 +00003137 return thead;
3138}
3139
3140/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003141 * Expand all single-line macro calls made in the given line.
3142 * Return the expanded version of the line. The original is deemed
3143 * to be destroyed in the process. (In reality we'll just move
3144 * Tokens from input to output a lot of the time, rather than
3145 * actually bothering to destroy and replicate.)
3146 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003147static Token *
3148expand_smacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003149{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003150 Token *t, *tt, *mstart, **tail, *thead;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003151 SMacro *head = NULL, *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003152 Token **params;
3153 int *paramsize;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003154 int nparam, sparam, brackets, rescan;
3155 Token *org_tline = tline;
3156 Context *ctx;
3157 char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003158
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003159 /*
3160 * Trick: we should avoid changing the start token pointer since it can
3161 * be contained in "next" field of other token. Because of this
3162 * we allocate a copy of first token and work with it; at the end of
3163 * routine we copy it back
3164 */
3165 if (org_tline)
3166 {
H. Peter Anvin734b1882002-04-30 21:01:08 +00003167 tline =
3168 new_Token(org_tline->next, org_tline->type, org_tline->text,
3169 0);
3170 tline->mac = org_tline->mac;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003171 }
3172
H. Peter Anvin734b1882002-04-30 21:01:08 +00003173 again:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003174 tail = &thead;
3175 thead = NULL;
3176
H. Peter Anvin734b1882002-04-30 21:01:08 +00003177 while (tline)
3178 { /* main token loop */
3179 if ((mname = tline->text))
3180 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003181 /* if this token is a local macro, look in local context */
3182 if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
H. Peter Anvin734b1882002-04-30 21:01:08 +00003183 ctx = get_ctx(mname, TRUE);
3184 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003185 ctx = NULL;
3186 if (!ctx)
3187 head = smacros[hash(mname)];
3188 else
H. Peter Anvineba20a72002-04-30 20:53:55 +00003189 head = ctx->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003190 /*
3191 * We've hit an identifier. As in is_mmacro below, we first
3192 * check whether the identifier is a single-line macro at
3193 * all, then think about checking for parameters if
3194 * necessary.
3195 */
H. Peter Anvineba20a72002-04-30 20:53:55 +00003196 for (m = head; m; m = m->next)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003197 if (!mstrcmp(m->name, mname, m->casesense))
H. Peter Anvineba20a72002-04-30 20:53:55 +00003198 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003199 if (m)
3200 {
3201 mstart = tline;
3202 params = NULL;
3203 paramsize = NULL;
3204 if (m->nparam == 0)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003205 {
H. Peter Anvin734b1882002-04-30 21:01:08 +00003206 /*
3207 * Simple case: the macro is parameterless. Discard the
3208 * one token that the macro call took, and push the
3209 * expansion back on the to-do stack.
3210 */
3211 if (!m->expansion)
3212 {
3213 if (!strcmp("__FILE__", m->name))
3214 {
3215 long num = 0;
3216 src_get(&num, &(tline->text));
3217 nasm_quote(&(tline->text));
3218 tline->type = TOK_STRING;
3219 continue;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003220 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003221 if (!strcmp("__LINE__", m->name))
3222 {
3223 nasm_free(tline->text);
3224 make_tok_num(tline, src_get_linnum());
3225 continue;
3226 }
3227 tline = delete_Token(tline);
3228 continue;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003229 }
3230 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003231 else
3232 {
3233 /*
3234 * Complicated case: at least one macro with this name
3235 * exists and takes parameters. We must find the
3236 * parameters in the call, count them, find the SMacro
3237 * that corresponds to that form of the macro call, and
3238 * substitute for the parameters when we expand. What a
3239 * pain.
3240 */
3241 tline = tline->next;
3242 skip_white_(tline);
3243 if (!tok_is_(tline, "("))
3244 {
3245 /*
3246 * This macro wasn't called with parameters: ignore
3247 * the call. (Behaviour borrowed from gnu cpp.)
3248 */
3249 tline = mstart;
3250 m = NULL;
3251 }
3252 else
3253 {
3254 int paren = 0;
3255 int white = 0;
3256 brackets = 0;
3257 nparam = 0;
3258 tline = tline->next;
3259 sparam = PARAM_DELTA;
3260 params = nasm_malloc(sparam * sizeof(Token *));
3261 params[0] = tline;
3262 paramsize = nasm_malloc(sparam * sizeof(int));
3263 paramsize[0] = 0;
3264 for (;; tline = tline->next)
3265 { /* parameter loop */
3266 if (!tline)
3267 {
3268 error(ERR_NONFATAL,
3269 "macro call expects terminating `)'");
3270 break;
3271 }
3272 if (tline->type == TOK_WHITESPACE
3273 && brackets <= 0)
3274 {
3275 if (paramsize[nparam])
3276 white++;
3277 else
3278 params[nparam] = tline->next;
3279 continue; /* parameter loop */
3280 }
3281 if (tline->type == TOK_OTHER
3282 && tline->text[1] == 0)
3283 {
3284 char ch = tline->text[0];
3285 if (ch == ',' && !paren && brackets <= 0)
3286 {
3287 if (++nparam >= sparam)
3288 {
3289 sparam += PARAM_DELTA;
3290 params = nasm_realloc(params,
3291 sparam * sizeof(Token *));
3292 paramsize = nasm_realloc(paramsize,
3293 sparam * sizeof(int));
3294 }
3295 params[nparam] = tline->next;
3296 paramsize[nparam] = 0;
3297 white = 0;
3298 continue; /* parameter loop */
3299 }
3300 if (ch == '{' &&
3301 (brackets > 0 || (brackets == 0 &&
3302 !paramsize[nparam])))
3303 {
3304 if (!(brackets++))
3305 {
3306 params[nparam] = tline->next;
3307 continue; /* parameter loop */
3308 }
3309 }
3310 if (ch == '}' && brackets > 0)
3311 if (--brackets == 0)
3312 {
3313 brackets = -1;
3314 continue; /* parameter loop */
3315 }
3316 if (ch == '(' && !brackets)
3317 paren++;
3318 if (ch == ')' && brackets <= 0)
3319 if (--paren < 0)
3320 break;
3321 }
3322 if (brackets < 0)
3323 {
3324 brackets = 0;
3325 error(ERR_NONFATAL, "braces do not "
3326 "enclose all of macro parameter");
3327 }
3328 paramsize[nparam] += white + 1;
3329 white = 0;
3330 } /* parameter loop */
3331 nparam++;
3332 while (m && (m->nparam != nparam ||
3333 mstrcmp(m->name, mname,
3334 m->casesense)))
3335 m = m->next;
3336 if (!m)
3337 error(ERR_WARNING | ERR_WARN_MNP,
3338 "macro `%s' exists, "
3339 "but not taking %d parameters",
3340 mstart->text, nparam);
3341 }
3342 }
3343 if (m && m->in_progress)
3344 m = NULL;
3345 if (!m) /* in progess or didn't find '(' or wrong nparam */
3346 {
3347 /*
3348 * Design question: should we handle !tline, which
3349 * indicates missing ')' here, or expand those
3350 * macros anyway, which requires the (t) test a few
3351 * lines down?
3352 */
3353 nasm_free(params);
3354 nasm_free(paramsize);
3355 tline = mstart;
3356 }
3357 else
3358 {
3359 /*
3360 * Expand the macro: we are placed on the last token of the
3361 * call, so that we can easily split the call from the
3362 * following tokens. We also start by pushing an SMAC_END
3363 * token for the cycle removal.
3364 */
3365 t = tline;
3366 if (t)
3367 {
3368 tline = t->next;
3369 t->next = NULL;
3370 }
3371 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
3372 tt->mac = m;
3373 m->in_progress = TRUE;
3374 tline = tt;
3375 for (t = m->expansion; t; t = t->next)
3376 {
3377 if (t->type >= TOK_SMAC_PARAM)
3378 {
3379 Token *pcopy = tline, **ptail = &pcopy;
3380 Token *ttt, *pt;
3381 int i;
3382
3383 ttt = params[t->type - TOK_SMAC_PARAM];
3384 for (i = paramsize[t->type - TOK_SMAC_PARAM];
3385 --i >= 0;)
3386 {
3387 pt = *ptail =
3388 new_Token(tline, ttt->type, ttt->text,
3389 0);
3390 ptail = &pt->next;
3391 ttt = ttt->next;
3392 }
3393 tline = pcopy;
3394 }
3395 else
3396 {
3397 tt = new_Token(tline, t->type, t->text, 0);
3398 tline = tt;
3399 }
3400 }
3401
3402 /*
3403 * Having done that, get rid of the macro call, and clean
3404 * up the parameters.
3405 */
3406 nasm_free(params);
3407 nasm_free(paramsize);
3408 free_tlist(mstart);
3409 continue; /* main token loop */
3410 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003411 }
3412 }
3413
H. Peter Anvin734b1882002-04-30 21:01:08 +00003414 if (tline->type == TOK_SMAC_END)
3415 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003416 tline->mac->in_progress = FALSE;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003417 tline = delete_Token(tline);
3418 }
3419 else
3420 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003421 t = *tail = tline;
3422 tline = tline->next;
3423 t->mac = NULL;
3424 t->next = NULL;
3425 tail = &t->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003426 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003427 }
3428
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003429 /*
3430 * Now scan the entire line and look for successive TOK_IDs that resulted
3431 * after expansion (they can't be produced by tokenise()). The successive
3432 * TOK_IDs should be concatenated.
3433 * Also we look for %+ tokens and concatenate the tokens before and after
3434 * them (without white spaces in between).
3435 */
3436 t = thead;
3437 rescan = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003438 while (t)
3439 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003440 while (t && t->type != TOK_ID && t->type != TOK_PREPROC_ID)
3441 t = t->next;
3442 if (!t || !t->next)
3443 break;
3444 if (t->next->type == TOK_ID ||
H. Peter Anvin734b1882002-04-30 21:01:08 +00003445 t->next->type == TOK_PREPROC_ID ||
3446 t->next->type == TOK_NUMBER)
3447 {
3448 char *p = nasm_strcat(t->text, t->next->text);
3449 nasm_free(t->text);
3450 t->next = delete_Token(t->next);
3451 t->text = p;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003452 rescan = 1;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003453 }
3454 else if (t->next->type == TOK_WHITESPACE && t->next->next &&
3455 t->next->next->type == TOK_PREPROC_ID &&
3456 strcmp(t->next->next->text, "%+") == 0)
3457 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003458 /* free the next whitespace, the %+ token and next whitespace */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003459 int i;
3460 for (i = 1; i <= 3; i++)
3461 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003462 if (!t->next || (i != 2 && t->next->type != TOK_WHITESPACE))
3463 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003464 t->next = delete_Token(t->next);
3465 } /* endfor */
3466 }
3467 else
3468 t = t->next;
3469 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003470 /* If we concatenaded something, re-scan the line for macros */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003471 if (rescan)
3472 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003473 tline = thead;
3474 goto again;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003475 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003476
3477 if (org_tline)
3478 {
H. Peter Anvin734b1882002-04-30 21:01:08 +00003479 if (thead)
3480 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003481 *org_tline = *thead;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003482 /* since we just gave text to org_line, don't free it */
3483 thead->text = NULL;
3484 delete_Token(thead);
3485 }
3486 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003487 {
3488 /* the expression expanded to empty line;
3489 we can't return NULL for some reasons
3490 we just set the line to a single WHITESPACE token. */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003491 memset(org_tline, 0, sizeof(*org_tline));
3492 org_tline->text = NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003493 org_tline->type = TOK_WHITESPACE;
3494 }
3495 thead = org_tline;
3496 }
3497
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003498 return thead;
3499}
3500
3501/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003502 * Similar to expand_smacro but used exclusively with macro identifiers
3503 * right before they are fetched in. The reason is that there can be
3504 * identifiers consisting of several subparts. We consider that if there
3505 * are more than one element forming the name, user wants a expansion,
3506 * otherwise it will be left as-is. Example:
3507 *
3508 * %define %$abc cde
3509 *
3510 * the identifier %$abc will be left as-is so that the handler for %define
3511 * will suck it and define the corresponding value. Other case:
3512 *
3513 * %define _%$abc cde
3514 *
3515 * In this case user wants name to be expanded *before* %define starts
3516 * working, so we'll expand %$abc into something (if it has a value;
3517 * otherwise it will be left as-is) then concatenate all successive
3518 * PP_IDs into one.
3519 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003520static Token *
3521expand_id(Token * tline)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003522{
3523 Token *cur, *oldnext = NULL;
3524
H. Peter Anvin734b1882002-04-30 21:01:08 +00003525 if (!tline || !tline->next)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003526 return tline;
3527
3528 cur = tline;
3529 while (cur->next &&
H. Peter Anvin734b1882002-04-30 21:01:08 +00003530 (cur->next->type == TOK_ID ||
3531 cur->next->type == TOK_PREPROC_ID || cur->next->type == TOK_NUMBER))
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003532 cur = cur->next;
3533
3534 /* If identifier consists of just one token, don't expand */
3535 if (cur == tline)
3536 return tline;
3537
H. Peter Anvin734b1882002-04-30 21:01:08 +00003538 if (cur)
3539 {
3540 oldnext = cur->next; /* Detach the tail past identifier */
3541 cur->next = NULL; /* so that expand_smacro stops here */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003542 }
3543
H. Peter Anvin734b1882002-04-30 21:01:08 +00003544 tline = expand_smacro(tline);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003545
H. Peter Anvin734b1882002-04-30 21:01:08 +00003546 if (cur)
3547 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003548 /* expand_smacro possibly changhed tline; re-scan for EOL */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003549 cur = tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003550 while (cur && cur->next)
3551 cur = cur->next;
3552 if (cur)
3553 cur->next = oldnext;
3554 }
3555
3556 return tline;
3557}
3558
3559/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003560 * Determine whether the given line constitutes a multi-line macro
3561 * call, and return the MMacro structure called if so. Doesn't have
3562 * to check for an initial label - that's taken care of in
3563 * expand_mmacro - but must check numbers of parameters. Guaranteed
3564 * to be called with tline->type == TOK_ID, so the putative macro
3565 * name is easy to find.
3566 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003567static MMacro *
3568is_mmacro(Token * tline, Token *** params_array)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003569{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003570 MMacro *head, *m;
3571 Token **params;
3572 int nparam;
3573
3574 head = mmacros[hash(tline->text)];
3575
3576 /*
3577 * Efficiency: first we see if any macro exists with the given
3578 * name. If not, we can return NULL immediately. _Then_ we
3579 * count the parameters, and then we look further along the
3580 * list if necessary to find the proper MMacro.
3581 */
3582 for (m = head; m; m = m->next)
3583 if (!mstrcmp(m->name, tline->text, m->casesense))
3584 break;
3585 if (!m)
3586 return NULL;
3587
3588 /*
3589 * OK, we have a potential macro. Count and demarcate the
3590 * parameters.
3591 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003592 count_mmac_params(tline->next, &nparam, &params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003593
3594 /*
3595 * So we know how many parameters we've got. Find the MMacro
3596 * structure that handles this number.
3597 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003598 while (m)
3599 {
3600 if (m->nparam_min <= nparam && (m->plus || nparam <= m->nparam_max))
3601 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003602 /*
3603 * This one is right. Just check if cycle removal
3604 * prohibits us using it before we actually celebrate...
3605 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003606 if (m->in_progress)
3607 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003608#if 0
H. Peter Anvin734b1882002-04-30 21:01:08 +00003609 error(ERR_NONFATAL,
3610 "self-reference in multi-line macro `%s'", m->name);
H. Peter Anvineba20a72002-04-30 20:53:55 +00003611#endif
H. Peter Anvin734b1882002-04-30 21:01:08 +00003612 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003613 return NULL;
3614 }
3615 /*
3616 * It's right, and we can use it. Add its default
3617 * parameters to the end of our list if necessary.
3618 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003619 if (m->defaults && nparam < m->nparam_min + m->ndefs)
3620 {
3621 params =
3622 nasm_realloc(params,
3623 ((m->nparam_min + m->ndefs + 1) * sizeof(*params)));
3624 while (nparam < m->nparam_min + m->ndefs)
3625 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003626 params[nparam] = m->defaults[nparam - m->nparam_min];
3627 nparam++;
3628 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003629 }
3630 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00003631 * If we've gone over the maximum parameter count (and
3632 * we're in Plus mode), ignore parameters beyond
3633 * nparam_max.
3634 */
3635 if (m->plus && nparam > m->nparam_max)
3636 nparam = m->nparam_max;
3637 /*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003638 * Then terminate the parameter list, and leave.
3639 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003640 if (!params)
3641 { /* need this special case */
H. Peter Anvin76690a12002-04-30 20:52:49 +00003642 params = nasm_malloc(sizeof(*params));
3643 nparam = 0;
3644 }
3645 params[nparam] = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003646 *params_array = params;
3647 return m;
3648 }
3649 /*
3650 * This one wasn't right: look for the next one with the
3651 * same name.
3652 */
3653 for (m = m->next; m; m = m->next)
3654 if (!mstrcmp(m->name, tline->text, m->casesense))
3655 break;
3656 }
3657
3658 /*
3659 * After all that, we didn't find one with the right number of
3660 * parameters. Issue a warning, and fail to expand the macro.
3661 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003662 error(ERR_WARNING | ERR_WARN_MNP,
3663 "macro `%s' exists, but not taking %d parameters",
3664 tline->text, nparam);
3665 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003666 return NULL;
3667}
3668
3669/*
3670 * Expand the multi-line macro call made by the given line, if
3671 * there is one to be expanded. If there is, push the expansion on
H. Peter Anvineba20a72002-04-30 20:53:55 +00003672 * istk->expansion and return 1. Otherwise return 0.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003673 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003674static int
3675expand_mmacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003676{
3677 Token *startline = tline;
3678 Token *label = NULL;
3679 int dont_prepend = 0;
3680 Token **params, *t, *tt;
3681 MMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003682 Line *l, *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003683 int i, nparam, *paramlen;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003684
3685 t = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003686 skip_white_(t);
3687 if (!tok_type_(t, TOK_ID))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003688 return 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003689 m = is_mmacro(t, &params);
3690 if (!m)
3691 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003692 Token *last;
3693 /*
3694 * We have an id which isn't a macro call. We'll assume
3695 * it might be a label; we'll also check to see if a
3696 * colon follows it. Then, if there's another id after
3697 * that lot, we'll check it again for macro-hood.
3698 */
3699 label = last = t;
3700 t = t->next;
3701 if (tok_type_(t, TOK_WHITESPACE))
3702 last = t, t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003703 if (tok_is_(t, ":"))
3704 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003705 dont_prepend = 1;
3706 last = t, t = t->next;
3707 if (tok_type_(t, TOK_WHITESPACE))
3708 last = t, t = t->next;
3709 }
3710 if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
3711 return 0;
3712 last->next = NULL;
3713 tline = t;
3714 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003715
3716 /*
3717 * Fix up the parameters: this involves stripping leading and
3718 * trailing whitespace, then stripping braces if they are
3719 * present.
3720 */
H. Peter Anvineba20a72002-04-30 20:53:55 +00003721 for (nparam = 0; params[nparam]; nparam++)
3722 ;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003723 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003724
H. Peter Anvin734b1882002-04-30 21:01:08 +00003725 for (i = 0; params[i]; i++)
3726 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003727 int brace = FALSE;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003728 int comma = (!m->plus || i < nparam - 1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003729
3730 t = params[i];
H. Peter Anvineba20a72002-04-30 20:53:55 +00003731 skip_white_(t);
3732 if (tok_is_(t, "{"))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003733 t = t->next, brace = TRUE, comma = FALSE;
3734 params[i] = t;
3735 paramlen[i] = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003736 while (t)
3737 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003738 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
H. Peter Anvin734b1882002-04-30 21:01:08 +00003739 break; /* ... because we have hit a comma */
H. Peter Anvineba20a72002-04-30 20:53:55 +00003740 if (comma && t->type == TOK_WHITESPACE && tok_is_(t->next, ","))
H. Peter Anvin734b1882002-04-30 21:01:08 +00003741 break; /* ... or a space then a comma */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003742 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
H. Peter Anvin734b1882002-04-30 21:01:08 +00003743 break; /* ... or a brace */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003744 t = t->next;
3745 paramlen[i]++;
3746 }
3747 }
3748
3749 /*
3750 * OK, we have a MMacro structure together with a set of
3751 * parameters. We must now go through the expansion and push
H. Peter Anvin76690a12002-04-30 20:52:49 +00003752 * copies of each Line on to istk->expansion. Substitution of
3753 * parameter tokens and macro-local tokens doesn't get done
3754 * until the single-line macro substitution process; this is
3755 * because delaying them allows us to change the semantics
3756 * later through %rotate.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003757 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00003758 * First, push an end marker on to istk->expansion, mark this
3759 * macro as in progress, and set up its invocation-specific
3760 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003761 */
3762 ll = nasm_malloc(sizeof(Line));
3763 ll->next = istk->expansion;
3764 ll->finishes = m;
3765 ll->first = NULL;
3766 istk->expansion = ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003767
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003768 m->in_progress = TRUE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003769 m->params = params;
3770 m->iline = tline;
3771 m->nparam = nparam;
3772 m->rotate = 0;
3773 m->paramlen = paramlen;
3774 m->unique = unique++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003775 m->lineno = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003776
3777 m->next_active = istk->mstk;
3778 istk->mstk = m;
3779
H. Peter Anvin734b1882002-04-30 21:01:08 +00003780 for (l = m->expansion; l; l = l->next)
3781 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003782 Token **tail;
3783
3784 ll = nasm_malloc(sizeof(Line));
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003785 ll->finishes = NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003786 ll->next = istk->expansion;
3787 istk->expansion = ll;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003788 tail = &ll->first;
3789
H. Peter Anvin734b1882002-04-30 21:01:08 +00003790 for (t = l->first; t; t = t->next)
3791 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003792 Token *x = t;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003793 if (t->type == TOK_PREPROC_ID &&
3794 t->text[1] == '0' && t->text[2] == '0')
H. Peter Anvineba20a72002-04-30 20:53:55 +00003795 {
3796 dont_prepend = -1;
3797 x = label;
3798 if (!x)
3799 continue;
3800 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003801 tt = *tail = new_Token(NULL, x->type, x->text, 0);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003802 tail = &tt->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003803 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00003804 *tail = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003805 }
3806
3807 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +00003808 * If we had a label, push it on as the first line of
3809 * the macro expansion.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003810 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003811 if (label)
3812 {
3813 if (dont_prepend < 0)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003814 free_tlist(startline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003815 else
3816 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003817 ll = nasm_malloc(sizeof(Line));
3818 ll->finishes = NULL;
3819 ll->next = istk->expansion;
3820 istk->expansion = ll;
3821 ll->first = startline;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003822 if (!dont_prepend)
3823 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003824 while (label->next)
3825 label = label->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003826 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
H. Peter Anvineba20a72002-04-30 20:53:55 +00003827 }
H. Peter Anvin87bc6192002-04-30 20:53:16 +00003828 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003829 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003830
H. Peter Anvin734b1882002-04-30 21:01:08 +00003831 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003832
H. Peter Anvineba20a72002-04-30 20:53:55 +00003833 return 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003834}
3835
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003836/*
3837 * Since preprocessor always operate only on the line that didn't
3838 * arrived yet, we should always use ERR_OFFBY1. Also since user
3839 * won't want to see same error twice (preprocessing is done once
3840 * per pass) we will want to show errors only during pass one.
3841 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003842static void
3843error(int severity, char *fmt, ...)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003844{
3845 va_list arg;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003846 char buff[1024];
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003847
3848 /* If we're in a dead branch of IF or something like it, ignore the error */
3849 if (istk->conds && !emitting(istk->conds->state))
3850 return;
3851
H. Peter Anvin734b1882002-04-30 21:01:08 +00003852 va_start(arg, fmt);
3853 vsprintf(buff, fmt, arg);
3854 va_end(arg);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003855
3856 if (istk->mstk && istk->mstk->name)
H. Peter Anvin734b1882002-04-30 21:01:08 +00003857 __error(severity | ERR_PASS1, "(%s:%d) %s", istk->mstk->name,
3858 istk->mstk->lineno, buff);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003859 else
H. Peter Anvin734b1882002-04-30 21:01:08 +00003860 __error(severity | ERR_PASS1, "%s", buff);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003861}
3862
H. Peter Anvin734b1882002-04-30 21:01:08 +00003863static void
3864pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
3865 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003866{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003867 int h;
3868
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003869 __error = errfunc;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003870 cstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003871 istk = nasm_malloc(sizeof(Include));
3872 istk->next = NULL;
3873 istk->conds = NULL;
3874 istk->expansion = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003875 istk->mstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003876 istk->fp = fopen(file, "r");
H. Peter Anvineba20a72002-04-30 20:53:55 +00003877 istk->fname = NULL;
3878 src_set_fname(nasm_strdup(file));
3879 src_set_linnum(0);
3880 istk->lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003881 if (!istk->fp)
H. Peter Anvin734b1882002-04-30 21:01:08 +00003882 error(ERR_FATAL | ERR_NOFILE, "unable to open input file `%s'", file);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003883 defining = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003884 for (h = 0; h < NHASH; h++)
3885 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003886 mmacros[h] = NULL;
3887 smacros[h] = NULL;
3888 }
3889 unique = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003890 if (tasm_compatible_mode) {
3891 stdmacpos = stdmac;
3892 } else {
3893 stdmacpos = &stdmac[TASM_MACRO_COUNT];
3894 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003895 any_extrastdmac = (extrastdmac != NULL);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003896 list = listgen;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003897 evaluate = eval;
3898 pass = apass;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003899}
3900
H. Peter Anvin734b1882002-04-30 21:01:08 +00003901static char *
3902pp_getline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003903{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003904 char *line;
3905 Token *tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003906
H. Peter Anvin734b1882002-04-30 21:01:08 +00003907 while (1)
3908 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003909 /*
3910 * Fetch a tokenised line, either from the macro-expansion
3911 * buffer or from the input file.
3912 */
3913 tline = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003914 while (istk->expansion && istk->expansion->finishes)
3915 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003916 Line *l = istk->expansion;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003917 if (!l->finishes->name && l->finishes->in_progress > 1)
3918 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00003919 Line *ll;
3920
3921 /*
3922 * This is a macro-end marker for a macro with no
3923 * name, which means it's not really a macro at all
3924 * but a %rep block, and the `in_progress' field is
3925 * more than 1, meaning that we still need to
3926 * repeat. (1 means the natural last repetition; 0
3927 * means termination by %exitrep.) We have
3928 * therefore expanded up to the %endrep, and must
3929 * push the whole block on to the expansion buffer
3930 * again. We don't bother to remove the macro-end
3931 * marker: we'd only have to generate another one
3932 * if we did.
3933 */
3934 l->finishes->in_progress--;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003935 for (l = l->finishes->expansion; l; l = l->next)
3936 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00003937 Token *t, *tt, **tail;
3938
3939 ll = nasm_malloc(sizeof(Line));
3940 ll->next = istk->expansion;
3941 ll->finishes = NULL;
3942 ll->first = NULL;
3943 tail = &ll->first;
3944
H. Peter Anvin734b1882002-04-30 21:01:08 +00003945 for (t = l->first; t; t = t->next)
3946 {
3947 if (t->text || t->type == TOK_WHITESPACE)
3948 {
3949 tt = *tail = new_Token(NULL, t->type, t->text, 0);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003950 tail = &tt->next;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003951 }
3952 }
3953
3954 istk->expansion = ll;
3955 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003956 }
3957 else
3958 {
H. Peter Anvin87bc6192002-04-30 20:53:16 +00003959 /*
3960 * Check whether a `%rep' was started and not ended
3961 * within this macro expansion. This can happen and
3962 * should be detected. It's a fatal error because
3963 * I'm too confused to work out how to recover
3964 * sensibly from it.
3965 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003966 if (defining)
3967 {
H. Peter Anvin87bc6192002-04-30 20:53:16 +00003968 if (defining->name)
H. Peter Anvin734b1882002-04-30 21:01:08 +00003969 error(ERR_PANIC, "defining with name in expansion");
H. Peter Anvinb64535f2002-04-30 20:55:37 +00003970 else if (istk->mstk->name)
H. Peter Anvin734b1882002-04-30 21:01:08 +00003971 error(ERR_FATAL, "`%%rep' without `%%endrep' within"
3972 " expansion of macro `%s'", istk->mstk->name);
H. Peter Anvin87bc6192002-04-30 20:53:16 +00003973 }
3974
H. Peter Anvin734b1882002-04-30 21:01:08 +00003975 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +00003976 * FIXME: investigate the relationship at this point between
3977 * istk->mstk and l->finishes
3978 */
3979 {
3980 MMacro *m = istk->mstk;
3981 istk->mstk = m->next_active;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003982 if (m->name)
3983 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003984 /*
3985 * This was a real macro call, not a %rep, and
3986 * therefore the parameter information needs to
3987 * be freed.
3988 */
3989 nasm_free(m->params);
3990 free_tlist(m->iline);
3991 nasm_free(m->paramlen);
3992 l->finishes->in_progress = FALSE;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003993 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00003994 else
3995 free_mmacro(m);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003996 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003997 istk->expansion = l->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003998 nasm_free(l);
3999 list->downlevel(LIST_MACRO);
H. Peter Anvin76690a12002-04-30 20:52:49 +00004000 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004001 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004002 while (1)
4003 { /* until we get a line we can use */
H. Peter Anvineba20a72002-04-30 20:53:55 +00004004
H. Peter Anvin734b1882002-04-30 21:01:08 +00004005 if (istk->expansion)
4006 { /* from a macro expansion */
H. Peter Anvineba20a72002-04-30 20:53:55 +00004007 char *p;
4008 Line *l = istk->expansion;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004009 if (istk->mstk)
4010 istk->mstk->lineno++;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004011 tline = l->first;
4012 istk->expansion = l->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004013 nasm_free(l);
4014 p = detoken(tline, FALSE);
4015 list->line(LIST_MACRO, p);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004016 nasm_free(p);
4017 break;
4018 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004019 line = read_line();
H. Peter Anvin734b1882002-04-30 21:01:08 +00004020 if (line)
4021 { /* from the current input file */
H. Peter Anvineba20a72002-04-30 20:53:55 +00004022 line = prepreproc(line);
4023 tline = tokenise(line);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004024 nasm_free(line);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004025 break;
4026 }
4027 /*
4028 * The current file has ended; work down the istk
4029 */
4030 {
4031 Include *i = istk;
4032 fclose(i->fp);
4033 if (i->conds)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004034 error(ERR_FATAL, "expected `%%endif' before end of file");
H. Peter Anvineba20a72002-04-30 20:53:55 +00004035 istk = i->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004036 list->downlevel(LIST_INCLUDE);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004037 src_set_linnum(i->lineno);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004038 nasm_free(src_set_fname(i->fname));
4039 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004040 if (!istk)
4041 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004042 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004043 }
4044
4045 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00004046 * We must expand MMacro parameters and MMacro-local labels
4047 * _before_ we plunge into directive processing, to cope
4048 * with things like `%define something %1' such as STRUC
4049 * uses. Unless we're _defining_ a MMacro, in which case
4050 * those tokens should be left alone to go into the
H. Peter Anvineba20a72002-04-30 20:53:55 +00004051 * definition; and unless we're in a non-emitting
4052 * condition, in which case we don't want to meddle with
4053 * anything.
H. Peter Anvin76690a12002-04-30 20:52:49 +00004054 */
H. Peter Anvineba20a72002-04-30 20:53:55 +00004055 if (!defining && !(istk->conds && !emitting(istk->conds->state)))
H. Peter Anvin76690a12002-04-30 20:52:49 +00004056 tline = expand_mmac_params(tline);
4057
4058 /*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004059 * Check the line to see if it's a preprocessor directive.
4060 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00004061 if (do_directive(tline) & 1)
4062 {
4063 continue;
4064 }
4065 else if (defining)
4066 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004067 /*
4068 * We're defining a multi-line macro. We emit nothing
H. Peter Anvineba20a72002-04-30 20:53:55 +00004069 * at all, and just
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004070 * shove the tokenised line on to the macro definition.
4071 */
4072 Line *l = nasm_malloc(sizeof(Line));
4073 l->next = defining->expansion;
4074 l->first = tline;
4075 l->finishes = FALSE;
4076 defining->expansion = l;
4077 continue;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004078 }
4079 else if (istk->conds && !emitting(istk->conds->state))
4080 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004081 /*
4082 * We're in a non-emitting branch of a condition block.
4083 * Emit nothing at all, not even a blank line: when we
4084 * emerge from the condition we'll give a line-number
4085 * directive so we keep our place correctly.
4086 */
4087 free_tlist(tline);
4088 continue;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004089 }
4090 else if (istk->mstk && !istk->mstk->in_progress)
4091 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00004092 /*
4093 * We're in a %rep block which has been terminated, so
4094 * we're walking through to the %endrep without
4095 * emitting anything. Emit nothing at all, not even a
4096 * blank line: when we emerge from the %rep block we'll
4097 * give a line-number directive so we keep our place
4098 * correctly.
4099 */
4100 free_tlist(tline);
4101 continue;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004102 }
4103 else
4104 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004105 tline = expand_smacro(tline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004106 if (!expand_mmacro(tline))
4107 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004108 /*
4109 * De-tokenise the line again, and emit it.
4110 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004111 line = detoken(tline, TRUE);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004112 free_tlist(tline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004113 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004114 }
4115 else
4116 {
4117 continue; /* expand_mmacro calls free_tlist */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004118 }
4119 }
4120 }
4121
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004122 return line;
4123}
4124
H. Peter Anvin734b1882002-04-30 21:01:08 +00004125static void
4126pp_cleanup(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004127{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004128 int h;
4129
H. Peter Anvin734b1882002-04-30 21:01:08 +00004130 if (defining)
4131 {
4132 error(ERR_NONFATAL, "end of file while still defining macro `%s'",
4133 defining->name);
4134 free_mmacro(defining);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004135 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004136 while (cstk)
4137 ctx_pop();
H. Peter Anvin734b1882002-04-30 21:01:08 +00004138 for (h = 0; h < NHASH; h++)
4139 {
4140 while (mmacros[h])
4141 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004142 MMacro *m = mmacros[h];
4143 mmacros[h] = mmacros[h]->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004144 free_mmacro(m);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004145 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004146 while (smacros[h])
4147 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004148 SMacro *s = smacros[h];
4149 smacros[h] = smacros[h]->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004150 nasm_free(s->name);
4151 free_tlist(s->expansion);
4152 nasm_free(s);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004153 }
4154 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004155 while (istk)
4156 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004157 Include *i = istk;
4158 istk = istk->next;
4159 fclose(i->fp);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004160 nasm_free(i->fname);
4161 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004162 }
4163 while (cstk)
4164 ctx_pop();
4165}
4166
H. Peter Anvin734b1882002-04-30 21:01:08 +00004167void
4168pp_include_path(char *path)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004169{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004170 IncPath *i;
4171
4172 i = nasm_malloc(sizeof(IncPath));
4173 i->path = nasm_strdup(path);
4174 i->next = ipath;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004175 ipath = i;
4176}
4177
H. Peter Anvin734b1882002-04-30 21:01:08 +00004178void
4179pp_pre_include(char *fname)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004180{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004181 Token *inc, *space, *name;
4182 Line *l;
4183
H. Peter Anvin734b1882002-04-30 21:01:08 +00004184 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
4185 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
4186 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004187
4188 l = nasm_malloc(sizeof(Line));
4189 l->next = predef;
4190 l->first = inc;
4191 l->finishes = FALSE;
4192 predef = l;
4193}
4194
H. Peter Anvin734b1882002-04-30 21:01:08 +00004195void
4196pp_pre_define(char *definition)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004197{
4198 Token *def, *space;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004199 Line *l;
4200 char *equals;
4201
4202 equals = strchr(definition, '=');
H. Peter Anvin734b1882002-04-30 21:01:08 +00004203 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4204 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004205 if (equals)
4206 *equals = ' ';
H. Peter Anvineba20a72002-04-30 20:53:55 +00004207 space->next = tokenise(definition);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004208 if (equals)
4209 *equals = '=';
4210
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004211 l = nasm_malloc(sizeof(Line));
4212 l->next = predef;
4213 l->first = def;
4214 l->finishes = FALSE;
4215 predef = l;
4216}
4217
H. Peter Anvin734b1882002-04-30 21:01:08 +00004218void
4219pp_pre_undefine(char *definition)
H. Peter Anvin620515a2002-04-30 20:57:38 +00004220{
4221 Token *def, *space;
4222 Line *l;
4223
H. Peter Anvin734b1882002-04-30 21:01:08 +00004224 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4225 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
H. Peter Anvin620515a2002-04-30 20:57:38 +00004226
4227 l = nasm_malloc(sizeof(Line));
4228 l->next = predef;
4229 l->first = def;
4230 l->finishes = FALSE;
4231 predef = l;
4232}
4233
H. Peter Anvin734b1882002-04-30 21:01:08 +00004234void
4235pp_extra_stdmac(char **macros)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004236{
H. Peter Anvin76690a12002-04-30 20:52:49 +00004237 extrastdmac = macros;
4238}
4239
H. Peter Anvin734b1882002-04-30 21:01:08 +00004240static void
4241make_tok_num(Token * tok, long val)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004242{
4243 char numbuf[20];
4244 sprintf(numbuf, "%ld", val);
4245 tok->text = nasm_strdup(numbuf);
4246 tok->type = TOK_NUMBER;
4247}
4248
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004249Preproc nasmpp = {
4250 pp_reset,
4251 pp_getline,
4252 pp_cleanup
4253};