blob: e2fcb70e4177cb56efb56a03dc481c9043ae2ae0 [file] [log] [blame]
H. Peter Anvin65747262002-05-07 00:10:05 +00001/* -*- mode: c; c-file-style: "bsd" -*- */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002/* preproc.c macro preprocessor for the Netwide Assembler
3 *
4 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
5 * Julian Hall. All rights reserved. The software is
6 * redistributable under the licence given in the file "Licence"
7 * distributed in the NASM archive.
8 *
9 * initial version 18/iii/97 by Simon Tatham
10 */
11
H. Peter Anvin4836e332002-04-30 20:56:43 +000012/* Typical flow of text through preproc
13 *
14 * pp_getline gets tokenised lines, either
15 *
16 * from a macro expansion
17 *
18 * or
19 * {
20 * read_line gets raw text from stdmacpos, or predef, or current input file
21 * tokenise converts to tokens
22 * }
23 *
24 * expand_mmac_params is used to expand %1 etc., unless a macro is being
25 * defined or a false conditional is being processed
26 * (%0, %1, %+1, %-1, %%foo
27 *
28 * do_directive checks for directives
29 *
30 * expand_smacro is used to expand single line macros
31 *
32 * expand_mmacro is used to expand multi-line macros
33 *
34 * detoken is used to convert the line back to text
35 */
H. Peter Anvineba20a72002-04-30 20:53:55 +000036
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000037#include <stdio.h>
H. Peter Anvinaf535c12002-04-30 20:59:21 +000038#include <stdarg.h>
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000039#include <stdlib.h>
40#include <stddef.h>
41#include <string.h>
42#include <ctype.h>
H. Peter Anvin76690a12002-04-30 20:52:49 +000043#include <limits.h>
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000044
45#include "nasm.h"
46#include "nasmlib.h"
47
48typedef struct SMacro SMacro;
49typedef struct MMacro MMacro;
50typedef struct Context Context;
51typedef struct Token Token;
H. Peter Anvince616072002-04-30 21:02:23 +000052typedef struct Blocks Blocks;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000053typedef struct Line Line;
54typedef struct Include Include;
55typedef struct Cond Cond;
H. Peter Anvin6768eb72002-04-30 20:52:26 +000056typedef struct IncPath IncPath;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000057
58/*
59 * Store the definition of a single-line macro.
60 */
H. Peter Anvin734b1882002-04-30 21:01:08 +000061struct SMacro
62{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000063 SMacro *next;
64 char *name;
65 int casesense;
66 int nparam;
67 int in_progress;
68 Token *expansion;
69};
70
71/*
H. Peter Anvin76690a12002-04-30 20:52:49 +000072 * Store the definition of a multi-line macro. This is also used to
73 * store the interiors of `%rep...%endrep' blocks, which are
74 * effectively self-re-invoking multi-line macros which simply
75 * don't have a name or bother to appear in the hash tables. %rep
76 * blocks are signified by having a NULL `name' field.
77 *
78 * In a MMacro describing a `%rep' block, the `in_progress' field
79 * isn't merely boolean, but gives the number of repeats left to
80 * run.
81 *
82 * The `next' field is used for storing MMacros in hash tables; the
83 * `next_active' field is for stacking them on istk entries.
84 *
85 * When a MMacro is being expanded, `params', `iline', `nparam',
86 * `paramlen', `rotate' and `unique' are local to the invocation.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000087 */
H. Peter Anvin734b1882002-04-30 21:01:08 +000088struct MMacro
89{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000090 MMacro *next;
91 char *name;
92 int casesense;
93 int nparam_min, nparam_max;
H. Peter Anvin734b1882002-04-30 21:01:08 +000094 int plus; /* is the last parameter greedy? */
95 int nolist; /* is this macro listing-inhibited? */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000096 int in_progress;
H. Peter Anvin734b1882002-04-30 21:01:08 +000097 Token *dlist; /* All defaults as one list */
98 Token **defaults; /* Parameter default pointers */
99 int ndefs; /* number of default parameters */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000100 Line *expansion;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000101
102 MMacro *next_active;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000103 MMacro *rep_nest; /* used for nesting %rep */
104 Token **params; /* actual parameters */
105 Token *iline; /* invocation line */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000106 int nparam, rotate, *paramlen;
107 unsigned long unique;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000108 int lineno; /* Current line number on expansion */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000109};
110
111/*
112 * The context stack is composed of a linked list of these.
113 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000114struct Context
115{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000116 Context *next;
117 SMacro *localmac;
118 char *name;
119 unsigned long number;
120};
121
122/*
123 * This is the internal form which we break input lines up into.
124 * Typically stored in linked lists.
125 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000126 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
127 * necessarily used as-is, but is intended to denote the number of
128 * the substituted parameter. So in the definition
129 *
130 * %define a(x,y) ( (x) & ~(y) )
131 *
132 * the token representing `x' will have its type changed to
133 * TOK_SMAC_PARAM, but the one representing `y' will be
134 * TOK_SMAC_PARAM+1.
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000135 *
136 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
137 * which doesn't need quotes around it. Used in the pre-include
138 * mechanism as an alternative to trying to find a sensible type of
139 * quote to use on the filename we were passed.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000140 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000141struct Token
142{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000143 Token *next;
144 char *text;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000145 SMacro *mac; /* associated macro for TOK_SMAC_END */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000146 int type;
147};
H. Peter Anvin734b1882002-04-30 21:01:08 +0000148enum
149{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000150 TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000151 TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_SMAC_PARAM,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000152 TOK_INTERNAL_STRING
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000153};
154
155/*
156 * Multi-line macro definitions are stored as a linked list of
157 * these, which is essentially a container to allow several linked
158 * lists of Tokens.
159 *
160 * Note that in this module, linked lists are treated as stacks
161 * wherever possible. For this reason, Lines are _pushed_ on to the
162 * `expansion' field in MMacro structures, so that the linked list,
163 * if walked, would give the macro lines in reverse order; this
164 * means that we can walk the list when expanding a macro, and thus
165 * push the lines on to the `expansion' field in _istk_ in reverse
166 * order (so that when popped back off they are in the right
167 * order). It may seem cockeyed, and it relies on my design having
168 * an even number of steps in, but it works...
169 *
170 * Some of these structures, rather than being actual lines, are
171 * markers delimiting the end of the expansion of a given macro.
H. Peter Anvin76690a12002-04-30 20:52:49 +0000172 * This is for use in the cycle-tracking and %rep-handling code.
173 * Such structures have `finishes' non-NULL, and `first' NULL. All
174 * others have `finishes' NULL, but `first' may still be NULL if
175 * the line is blank.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000176 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000177struct Line
178{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000179 Line *next;
180 MMacro *finishes;
181 Token *first;
182};
183
184/*
185 * To handle an arbitrary level of file inclusion, we maintain a
186 * stack (ie linked list) of these things.
187 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000188struct Include
189{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000190 Include *next;
191 FILE *fp;
192 Cond *conds;
193 Line *expansion;
194 char *fname;
195 int lineno, lineinc;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000196 MMacro *mstk; /* stack of active macros/reps */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000197};
198
199/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000200 * Include search path. This is simply a list of strings which get
201 * prepended, in turn, to the name of an include file, in an
202 * attempt to find the file if it's not in the current directory.
203 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000204struct IncPath
205{
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000206 IncPath *next;
207 char *path;
208};
209
210/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000211 * Conditional assembly: we maintain a separate stack of these for
212 * each level of file inclusion. (The only reason we keep the
213 * stacks separate is to ensure that a stray `%endif' in a file
214 * included from within the true branch of a `%if' won't terminate
215 * it and cause confusion: instead, rightly, it'll cause an error.)
216 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000217struct Cond
218{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000219 Cond *next;
220 int state;
221};
H. Peter Anvin734b1882002-04-30 21:01:08 +0000222enum
223{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000224 /*
225 * These states are for use just after %if or %elif: IF_TRUE
226 * means the condition has evaluated to truth so we are
227 * currently emitting, whereas IF_FALSE means we are not
228 * currently emitting but will start doing so if a %else comes
229 * up. In these states, all directives are admissible: %elif,
230 * %else and %endif. (And of course %if.)
231 */
232 COND_IF_TRUE, COND_IF_FALSE,
233 /*
234 * These states come up after a %else: ELSE_TRUE means we're
235 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
236 * any %elif or %else will cause an error.
237 */
238 COND_ELSE_TRUE, COND_ELSE_FALSE,
239 /*
240 * This state means that we're not emitting now, and also that
241 * nothing until %endif will be emitted at all. It's for use in
242 * two circumstances: (i) when we've had our moment of emission
243 * and have now started seeing %elifs, and (ii) when the
244 * condition construct in question is contained within a
245 * non-emitting branch of a larger condition construct.
246 */
247 COND_NEVER
248};
249#define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
250
Ed Beroset3ab3f412002-06-11 03:31:49 +0000251/*
252 * These defines are used as the possible return values for do_directive
253 */
254#define NO_DIRECTIVE_FOUND 0
255#define DIRECTIVE_FOUND 1
256
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000257/*
258 * Condition codes. Note that we use c_ prefix not C_ because C_ is
259 * used in nasm.h for the "real" condition codes. At _this_ level,
260 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
261 * ones, so we need a different enum...
262 */
H. Peter Anvin0a7a3b42002-05-14 23:54:46 +0000263static const char *conditions[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000264 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
265 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
266 "np", "ns", "nz", "o", "p", "pe", "po", "s", "z"
267};
H. Peter Anvin734b1882002-04-30 21:01:08 +0000268enum
269{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000270 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
271 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
272 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_S, c_Z
273};
274static int inverse_ccs[] = {
275 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
276 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,
277 c_Z, c_NO, c_NP, c_PO, c_PE, c_NS, c_NZ
278};
279
H. Peter Anvin76690a12002-04-30 20:52:49 +0000280/*
281 * Directive names.
282 */
H. Peter Anvin0a7a3b42002-05-14 23:54:46 +0000283static const char *directives[] = {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000284 "%arg",
H. Peter Anvin76690a12002-04-30 20:52:49 +0000285 "%assign", "%clear", "%define", "%elif", "%elifctx", "%elifdef",
H. Peter Anvin65747262002-05-07 00:10:05 +0000286 "%elifid", "%elifidn", "%elifidni", "%elifmacro", "%elifnctx", "%elifndef",
287 "%elifnid", "%elifnidn", "%elifnidni", "%elifnmacro", "%elifnnum", "%elifnstr",
H. Peter Anvin76690a12002-04-30 20:52:49 +0000288 "%elifnum", "%elifstr", "%else", "%endif", "%endm", "%endmacro",
289 "%endrep", "%error", "%exitrep", "%iassign", "%idefine", "%if",
H. Peter Anvin65747262002-05-07 00:10:05 +0000290 "%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifmacro", "%ifnctx",
291 "%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnmacro", "%ifnnum",
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000292 "%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include",
293 "%ixdefine", "%line",
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000294 "%local",
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000295 "%macro", "%pop", "%push", "%rep", "%repl", "%rotate",
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000296 "%stacksize",
H. Peter Anvin734b1882002-04-30 21:01:08 +0000297 "%strlen", "%substr", "%undef", "%xdefine"
H. Peter Anvin76690a12002-04-30 20:52:49 +0000298};
H. Peter Anvin734b1882002-04-30 21:01:08 +0000299enum
300{
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000301 PP_ARG,
H. Peter Anvin76690a12002-04-30 20:52:49 +0000302 PP_ASSIGN, PP_CLEAR, PP_DEFINE, PP_ELIF, PP_ELIFCTX, PP_ELIFDEF,
H. Peter Anvin65747262002-05-07 00:10:05 +0000303 PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFMACRO, PP_ELIFNCTX, PP_ELIFNDEF,
304 PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNMACRO, PP_ELIFNNUM, PP_ELIFNSTR,
H. Peter Anvin76690a12002-04-30 20:52:49 +0000305 PP_ELIFNUM, PP_ELIFSTR, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO,
306 PP_ENDREP, PP_ERROR, PP_EXITREP, PP_IASSIGN, PP_IDEFINE, PP_IF,
H. Peter Anvin65747262002-05-07 00:10:05 +0000307 PP_IFCTX, PP_IFDEF, PP_IFID, PP_IFIDN, PP_IFIDNI, PP_IFMACRO, PP_IFNCTX,
308 PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNMACRO, PP_IFNNUM,
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000309 PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE,
310 PP_IXDEFINE, PP_LINE,
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000311 PP_LOCAL,
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000312 PP_MACRO, PP_POP, PP_PUSH, PP_REP, PP_REPL, PP_ROTATE,
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000313 PP_STACKSIZE,
H. Peter Anvin734b1882002-04-30 21:01:08 +0000314 PP_STRLEN, PP_SUBSTR, PP_UNDEF, PP_XDEFINE
H. Peter Anvin76690a12002-04-30 20:52:49 +0000315};
316
H. Peter Anvin65747262002-05-07 00:10:05 +0000317/* If this is a an IF, ELIF, ELSE or ENDIF keyword */
318static int is_condition(int arg)
319{
320 return ((arg >= PP_ELIF) && (arg <= PP_ENDIF)) ||
321 ((arg >= PP_IF) && (arg <= PP_IFSTR));
322}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000323
324/* For TASM compatibility we need to be able to recognise TASM compatible
325 * conditional compilation directives. Using the NASM pre-processor does
326 * not work, so we look for them specifically from the following list and
327 * then jam in the equivalent NASM directive into the input stream.
328 */
329
330#ifndef MAX
331# define MAX(a,b) ( ((a) > (b)) ? (a) : (b))
332#endif
333
H. Peter Anvin734b1882002-04-30 21:01:08 +0000334enum
335{
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000336 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
337 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
338};
339
H. Peter Anvin0a7a3b42002-05-14 23:54:46 +0000340static const char *tasm_directives[] = {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000341 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
342 "ifndef", "include", "local"
343};
344
345static int StackSize = 4;
346static char *StackPointer = "ebp";
347static int ArgOffset = 8;
348static int LocalOffset = 4;
349
H. Peter Anvin76690a12002-04-30 20:52:49 +0000350
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000351static Context *cstk;
352static Include *istk;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000353static IncPath *ipath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000354
H. Peter Anvin99941bf2002-05-14 17:44:03 +0000355static efunc _error; /* Pointer to client-provided error reporting function */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000356static evalfunc evaluate;
357
H. Peter Anvin620515a2002-04-30 20:57:38 +0000358static int pass; /* HACK: pass 0 = generate dependencies only */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000359
H. Peter Anvin734b1882002-04-30 21:01:08 +0000360static unsigned long unique; /* unique identifier numbers */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000361
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000362static Line *predef = NULL;
363
364static ListGen *list;
365
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000366/*
367 * The number of hash values we use for the macro lookup tables.
H. Peter Anvineba20a72002-04-30 20:53:55 +0000368 * FIXME: We should *really* be able to configure this at run time,
369 * or even have the hash table automatically expanding when necessary.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000370 */
371#define NHASH 31
372
373/*
374 * The current set of multi-line macros we have defined.
375 */
376static MMacro *mmacros[NHASH];
377
378/*
379 * The current set of single-line macros we have defined.
380 */
381static SMacro *smacros[NHASH];
382
383/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000384 * The multi-line macro we are currently defining, or the %rep
385 * block we are currently reading, if any.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000386 */
387static MMacro *defining;
388
389/*
390 * The number of macro parameters to allocate space for at a time.
391 */
392#define PARAM_DELTA 16
393
394/*
395 * The standard macro set: defined as `static char *stdmac[]'. Also
396 * gives our position in the macro set, when we're processing it.
397 */
398#include "macros.c"
Ed Beroset168c9c02002-05-17 03:10:13 +0000399static const char **stdmacpos;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000400
401/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000402 * The extra standard macros that come from the object format, if
403 * any.
404 */
H. Peter Anvinbfebdb02002-09-12 02:23:54 +0000405static const char **extrastdmac = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000406int any_extrastdmac;
407
408/*
H. Peter Anvin734b1882002-04-30 21:01:08 +0000409 * Tokens are allocated in blocks to improve speed
410 */
411#define TOKEN_BLOCKSIZE 4096
412static Token *freeTokens = NULL;
H. Peter Anvince616072002-04-30 21:02:23 +0000413struct Blocks {
414 Blocks *next;
415 void *chunk;
416};
417
418static Blocks blocks = { NULL, NULL };
H. Peter Anvin734b1882002-04-30 21:01:08 +0000419
420/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000421 * Forward declarations.
422 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000423static Token *expand_mmac_params(Token * tline);
424static Token *expand_smacro(Token * tline);
425static Token *expand_id(Token * tline);
426static Context *get_ctx(char *name, int all_contexts);
427static void make_tok_num(Token * tok, long val);
Ed Beroset168c9c02002-05-17 03:10:13 +0000428static void error(int severity, const char *fmt, ...);
H. Peter Anvince616072002-04-30 21:02:23 +0000429static void *new_Block(size_t size);
430static void delete_Blocks(void);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000431static Token *new_Token(Token * next, int type, char *text, int txtlen);
432static Token *delete_Token(Token * t);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000433
434/*
435 * Macros for safe checking of token pointers, avoid *(NULL)
436 */
437#define tok_type_(x,t) ((x) && (x)->type == (t))
438#define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
439#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
440#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
H. Peter Anvin76690a12002-04-30 20:52:49 +0000441
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000442/* Handle TASM specific directives, which do not contain a % in
443 * front of them. We do it here because I could not find any other
444 * place to do it for the moment, and it is a hack (ideally it would
445 * be nice to be able to use the NASM pre-processor to do it).
446 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000447static char *
448check_tasm_directive(char *line)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000449{
450 int i, j, k, m, len;
451 char *p = line, *oldline, oldchar;
452
453 /* Skip whitespace */
454 while (isspace(*p) && *p != 0)
455 p++;
456
457 /* Binary search for the directive name */
458 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +0000459 j = elements(tasm_directives);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000460 len = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000461 while (!isspace(p[len]) && p[len] != 0)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000462 len++;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000463 if (len)
464 {
465 oldchar = p[len];
466 p[len] = 0;
467 while (j - i > 1)
468 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000469 k = (j + i) / 2;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000470 m = nasm_stricmp(p, tasm_directives[k]);
471 if (m == 0)
472 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000473 /* We have found a directive, so jam a % in front of it
474 * so that NASM will then recognise it as one if it's own.
475 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000476 p[len] = oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000477 len = strlen(p);
478 oldline = line;
479 line = nasm_malloc(len + 2);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000480 line[0] = '%';
481 if (k == TM_IFDIFI)
482 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000483 /* NASM does not recognise IFDIFI, so we convert it to
484 * %ifdef BOGUS. This is not used in NASM comaptible
485 * code, but does need to parse for the TASM macro
486 * package.
487 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000488 strcpy(line + 1, "ifdef BOGUS");
489 }
490 else
491 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000492 memcpy(line + 1, p, len + 1);
493 }
494 nasm_free(oldline);
495 return line;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000496 }
497 else if (m < 0)
498 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000499 j = k;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000500 }
501 else
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000502 i = k;
503 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000504 p[len] = oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000505 }
506 return line;
507}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000508
H. Peter Anvin76690a12002-04-30 20:52:49 +0000509/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000510 * The pre-preprocessing stage... This function translates line
511 * number indications as they emerge from GNU cpp (`# lineno "file"
512 * flags') into NASM preprocessor line number indications (`%line
513 * lineno file').
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000514 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000515static char *
516prepreproc(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000517{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000518 int lineno, fnlen;
519 char *fname, *oldline;
520
H. Peter Anvin734b1882002-04-30 21:01:08 +0000521 if (line[0] == '#' && line[1] == ' ')
522 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000523 oldline = line;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000524 fname = oldline + 2;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000525 lineno = atoi(fname);
526 fname += strspn(fname, "0123456789 ");
527 if (*fname == '"')
528 fname++;
529 fnlen = strcspn(fname, "\"");
H. Peter Anvin734b1882002-04-30 21:01:08 +0000530 line = nasm_malloc(20 + fnlen);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000531 sprintf(line, "%%line %d %.*s", lineno, fnlen, fname);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000532 nasm_free(oldline);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000533 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000534 if (tasm_compatible_mode)
535 return check_tasm_directive(line);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000536 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000537}
538
539/*
540 * The hash function for macro lookups. Note that due to some
541 * macros having case-insensitive names, the hash function must be
542 * invariant under case changes. We implement this by applying a
543 * perfectly normal hash function to the uppercase of the string.
544 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000545static int
546hash(char *s)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000547{
548 unsigned int h = 0;
549 int i = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000550 /*
551 * Powers of three, mod 31.
552 */
553 static const int multipliers[] = {
554 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10,
555 30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21
556 };
H. Peter Anvineba20a72002-04-30 20:53:55 +0000557
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000558
H. Peter Anvin734b1882002-04-30 21:01:08 +0000559 while (*s)
560 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000561 h += multipliers[i] * (unsigned char) (toupper(*s));
562 s++;
Ed Beroset3ab3f412002-06-11 03:31:49 +0000563 if (++i >= elements(multipliers))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000564 i = 0;
565 }
566 h %= NHASH;
567 return h;
568}
569
570/*
571 * Free a linked list of tokens.
572 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000573static void
574free_tlist(Token * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000575{
H. Peter Anvin734b1882002-04-30 21:01:08 +0000576 while (list)
577 {
578 list = delete_Token(list);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000579 }
580}
581
582/*
583 * Free a linked list of lines.
584 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000585static void
586free_llist(Line * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000587{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000588 Line *l;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000589 while (list)
590 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000591 l = list;
592 list = list->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000593 free_tlist(l->first);
594 nasm_free(l);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000595 }
596}
597
598/*
H. Peter Anvineba20a72002-04-30 20:53:55 +0000599 * Free an MMacro
600 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000601static void
602free_mmacro(MMacro * m)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000603{
H. Peter Anvin734b1882002-04-30 21:01:08 +0000604 nasm_free(m->name);
605 free_tlist(m->dlist);
606 nasm_free(m->defaults);
607 free_llist(m->expansion);
608 nasm_free(m);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000609}
610
611/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000612 * Pop the context stack.
613 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000614static void
615ctx_pop(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000616{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000617 Context *c = cstk;
618 SMacro *smac, *s;
619
620 cstk = cstk->next;
621 smac = c->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000622 while (smac)
623 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000624 s = smac;
625 smac = smac->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000626 nasm_free(s->name);
627 free_tlist(s->expansion);
628 nasm_free(s);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000629 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000630 nasm_free(c->name);
631 nasm_free(c);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000632}
633
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000634#define BUF_DELTA 512
635/*
636 * Read a line from the top file in istk, handling multiple CR/LFs
637 * at the end of the line read, and handling spurious ^Zs. Will
638 * return lines from the standard macro set if this has not already
639 * been done.
640 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000641static char *
642read_line(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000643{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000644 char *buffer, *p, *q;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000645 int bufsize, continued_count;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000646
H. Peter Anvin734b1882002-04-30 21:01:08 +0000647 if (stdmacpos)
648 {
649 if (*stdmacpos)
650 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000651 char *ret = nasm_strdup(*stdmacpos++);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000652 if (!*stdmacpos && any_extrastdmac)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000653 {
H. Peter Anvin76690a12002-04-30 20:52:49 +0000654 stdmacpos = extrastdmac;
655 any_extrastdmac = FALSE;
656 return ret;
657 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000658 /*
659 * Nasty hack: here we push the contents of `predef' on
660 * to the top-level expansion stack, since this is the
661 * most convenient way to implement the pre-include and
662 * pre-define features.
663 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000664 if (!*stdmacpos)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000665 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000666 Line *pd, *l;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000667 Token *head, **tail, *t;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000668
H. Peter Anvin734b1882002-04-30 21:01:08 +0000669 for (pd = predef; pd; pd = pd->next)
670 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000671 head = NULL;
672 tail = &head;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000673 for (t = pd->first; t; t = t->next)
674 {
675 *tail = new_Token(NULL, t->type, t->text, 0);
676 tail = &(*tail)->next;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000677 }
678 l = nasm_malloc(sizeof(Line));
679 l->next = istk->expansion;
680 l->first = head;
681 l->finishes = FALSE;
682 istk->expansion = l;
683 }
684 }
685 return ret;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000686 }
687 else
688 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000689 stdmacpos = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000690 }
691 }
692
693 bufsize = BUF_DELTA;
694 buffer = nasm_malloc(BUF_DELTA);
695 p = buffer;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000696 continued_count = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000697 while (1)
698 {
699 q = fgets(p, bufsize - (p - buffer), istk->fp);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000700 if (!q)
701 break;
702 p += strlen(p);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000703 if (p > buffer && p[-1] == '\n')
704 {
H. Peter Anvin9f394642002-04-30 21:07:51 +0000705 /* Convert backslash-CRLF line continuation sequences into
706 nothing at all (for DOS and Windows) */
707 if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
708 p -= 3;
709 *p = 0;
710 continued_count++;
711 }
712 /* Also convert backslash-LF line continuation sequences into
713 nothing at all (for Unix) */
714 else if (((p - 1) > buffer) && (p[-2] == '\\')) {
715 p -= 2;
716 *p = 0;
717 continued_count++;
718 }
719 else {
720 break;
721 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000722 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000723 if (p - buffer > bufsize - 10)
724 {
725 long offset = p - buffer;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000726 bufsize += BUF_DELTA;
727 buffer = nasm_realloc(buffer, bufsize);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000728 p = buffer + offset; /* prevent stale-pointer problems */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000729 }
730 }
731
H. Peter Anvin734b1882002-04-30 21:01:08 +0000732 if (!q && p == buffer)
733 {
734 nasm_free(buffer);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000735 return NULL;
736 }
737
H. Peter Anvin9a633fa2002-04-30 21:08:11 +0000738 src_set_linnum(src_get_linnum() + istk->lineinc + (continued_count * istk->lineinc));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000739
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000740 /*
741 * Play safe: remove CRs as well as LFs, if any of either are
742 * present at the end of the line.
743 */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000744 while (--p >= buffer && (*p == '\n' || *p == '\r'))
745 *p = '\0';
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000746
747 /*
748 * Handle spurious ^Z, which may be inserted into source files
749 * by some file transfer utilities.
750 */
751 buffer[strcspn(buffer, "\032")] = '\0';
752
H. Peter Anvin734b1882002-04-30 21:01:08 +0000753 list->line(LIST_READ, buffer);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000754
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000755 return buffer;
756}
757
758/*
759 * Tokenise a line of text. This is a very simple process since we
760 * don't need to parse the value out of e.g. numeric tokens: we
761 * simply split one string into many.
762 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000763static Token *
764tokenise(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000765{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000766 char *p = line;
767 int type;
768 Token *list = NULL;
769 Token *t, **tail = &list;
770
H. Peter Anvin734b1882002-04-30 21:01:08 +0000771 while (*line)
772 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000773 p = line;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000774 if (*p == '%')
H. Peter Anvineba20a72002-04-30 20:53:55 +0000775 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000776 p++;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000777 if ( isdigit(*p) ||
778 ((*p == '-' || *p == '+') && isdigit(p[1])) ||
779 ((*p == '+') && (isspace(p[1]) || !p[1])))
780 {
781 do
782 {
783 p++;
784 }
785 while (isdigit(*p));
786 type = TOK_PREPROC_ID;
787 }
788 else if (*p == '{')
789 {
790 p++;
791 while (*p && *p != '}')
792 {
793 p[-1] = *p;
794 p++;
795 }
796 p[-1] = '\0';
797 if (*p)
798 p++;
799 type = TOK_PREPROC_ID;
800 }
801 else if (isidchar(*p) ||
802 ((*p == '!' || *p == '%' || *p == '$') &&
803 isidchar(p[1])))
804 {
805 do
806 {
807 p++;
808 }
809 while (isidchar(*p));
810 type = TOK_PREPROC_ID;
811 }
812 else
813 {
814 type = TOK_OTHER;
815 if (*p == '%')
816 p++;
817 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000818 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000819 else if (isidstart(*p) || (*p == '$' && isidstart(p[1])))
H. Peter Anvineba20a72002-04-30 20:53:55 +0000820 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000821 type = TOK_ID;
822 p++;
823 while (*p && isidchar(*p))
824 p++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000825 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000826 else if (*p == '\'' || *p == '"')
827 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000828 /*
829 * A string token.
830 */
831 char c = *p;
832 p++;
833 type = TOK_STRING;
834 while (*p && *p != c)
835 p++;
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +0000836
H. Peter Anvin734b1882002-04-30 21:01:08 +0000837 if (*p)
838 {
839 p++;
840 }
841 else
842 {
843 error(ERR_WARNING, "unterminated string");
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +0000844 type = -1;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000845 }
846 }
847 else if (isnumstart(*p))
848 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000849 /*
850 * A number token.
851 */
852 type = TOK_NUMBER;
853 p++;
854 while (*p && isnumchar(*p))
855 p++;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000856 }
857 else if (isspace(*p))
858 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000859 type = TOK_WHITESPACE;
860 p++;
861 while (*p && isspace(*p))
862 p++;
863 /*
864 * Whitespace just before end-of-line is discarded by
865 * pretending it's a comment; whitespace just before a
866 * comment gets lumped into the comment.
867 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000868 if (!*p || *p == ';')
869 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000870 type = TOK_COMMENT;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000871 while (*p)
872 p++;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000873 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000874 }
875 else if (*p == ';')
876 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000877 type = TOK_COMMENT;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000878 while (*p)
879 p++;
880 }
881 else
882 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000883 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000884 * Anything else is an operator of some kind. We check
885 * for all the double-character operators (>>, <<, //,
886 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
887 * else is a single-character operator.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000888 */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000889 type = TOK_OTHER;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000890 if ((p[0] == '>' && p[1] == '>') ||
H. Peter Anvin734b1882002-04-30 21:01:08 +0000891 (p[0] == '<' && p[1] == '<') ||
892 (p[0] == '/' && p[1] == '/') ||
893 (p[0] == '<' && p[1] == '=') ||
894 (p[0] == '>' && p[1] == '=') ||
895 (p[0] == '=' && p[1] == '=') ||
896 (p[0] == '!' && p[1] == '=') ||
897 (p[0] == '<' && p[1] == '>') ||
898 (p[0] == '&' && p[1] == '&') ||
899 (p[0] == '|' && p[1] == '|') ||
900 (p[0] == '^' && p[1] == '^'))
H. Peter Anvineba20a72002-04-30 20:53:55 +0000901 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000902 p++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000903 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000904 p++;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000905 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +0000906
907 /* Handle unterminated string */
908 if (type == -1)
909 {
910 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
911 t->text[p-line] = *line;
912 tail = &t->next;
913 }
914 else if (type != TOK_COMMENT)
H. Peter Anvin734b1882002-04-30 21:01:08 +0000915 {
916 *tail = t = new_Token(NULL, type, line, p - line);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000917 tail = &t->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000918 }
919 line = p;
920 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000921 return list;
922}
923
H. Peter Anvince616072002-04-30 21:02:23 +0000924/*
925 * this function allocates a new managed block of memory and
926 * returns a pointer to the block. The managed blocks are
927 * deleted only all at once by the delete_Blocks function.
928 */
929static void *
930new_Block(size_t size)
931{
932 Blocks *b = &blocks;
933
934 /* first, get to the end of the linked list */
935 while (b->next)
936 b = b->next;
937 /* now allocate the requested chunk */
938 b->chunk = nasm_malloc(size);
939
940 /* now allocate a new block for the next request */
941 b->next = nasm_malloc(sizeof(Blocks));
942 /* and initialize the contents of the new block */
943 b->next->next = NULL;
944 b->next->chunk = NULL;
945 return b->chunk;
946}
947
948/*
949 * this function deletes all managed blocks of memory
950 */
951static void
952delete_Blocks(void)
953{
954 Blocks *a,*b = &blocks;
955
956 /*
957 * keep in mind that the first block, pointed to by blocks
958 * is a static and not dynamically allocated, so we don't
959 * free it.
960 */
961 while (b)
962 {
963 if (b->chunk)
964 nasm_free(b->chunk);
965 a = b;
966 b = b->next;
H. Peter Anvin9eb185b2002-04-30 21:02:47 +0000967 if (a != &blocks)
H. Peter Anvince616072002-04-30 21:02:23 +0000968 nasm_free(a);
969 }
970}
H. Peter Anvin734b1882002-04-30 21:01:08 +0000971
972/*
973 * this function creates a new Token and passes a pointer to it
974 * back to the caller. It sets the type and text elements, and
975 * also the mac and next elements to NULL.
976 */
977static Token *
978new_Token(Token * next, int type, char *text, int txtlen)
979{
980 Token *t;
981 int i;
982
983 if (freeTokens == NULL)
984 {
H. Peter Anvince616072002-04-30 21:02:23 +0000985 freeTokens = (Token *)new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
H. Peter Anvin734b1882002-04-30 21:01:08 +0000986 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
987 freeTokens[i].next = &freeTokens[i + 1];
988 freeTokens[i].next = NULL;
989 }
990 t = freeTokens;
991 freeTokens = t->next;
992 t->next = next;
993 t->mac = NULL;
994 t->type = type;
995 if (type == TOK_WHITESPACE || text == NULL)
996 {
997 t->text = NULL;
998 }
999 else
1000 {
1001 if (txtlen == 0)
1002 txtlen = strlen(text);
1003 t->text = nasm_malloc(1 + txtlen);
1004 strncpy(t->text, text, txtlen);
1005 t->text[txtlen] = '\0';
1006 }
1007 return t;
1008}
1009
1010static Token *
1011delete_Token(Token * t)
1012{
1013 Token *next = t->next;
1014 nasm_free(t->text);
H. Peter Anvin788e6c12002-04-30 21:02:01 +00001015 t->next = freeTokens;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001016 freeTokens = t;
1017 return next;
1018}
1019
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001020/*
1021 * Convert a line of tokens back into text.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001022 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1023 * will be transformed into ..@ctxnum.xxx
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001024 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001025static char *
1026detoken(Token * tlist, int expand_locals)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001027{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001028 Token *t;
1029 int len;
1030 char *line, *p;
1031
1032 len = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001033 for (t = tlist; t; t = t->next)
1034 {
1035 if (t->type == TOK_PREPROC_ID && t->text[1] == '!')
1036 {
1037 char *p = getenv(t->text + 2);
1038 nasm_free(t->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001039 if (p)
1040 t->text = nasm_strdup(p);
1041 else
1042 t->text = NULL;
1043 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001044 /* Expand local macros here and not during preprocessing */
1045 if (expand_locals &&
H. Peter Anvin734b1882002-04-30 21:01:08 +00001046 t->type == TOK_PREPROC_ID && t->text &&
1047 t->text[0] == '%' && t->text[1] == '$')
1048 {
1049 Context *ctx = get_ctx(t->text, FALSE);
1050 if (ctx)
1051 {
1052 char buffer[40];
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001053 char *p, *q = t->text + 2;
1054
H. Peter Anvin734b1882002-04-30 21:01:08 +00001055 q += strspn(q, "$");
1056 sprintf(buffer, "..@%lu.", ctx->number);
1057 p = nasm_strcat(buffer, q);
1058 nasm_free(t->text);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001059 t->text = p;
1060 }
1061 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001062 if (t->type == TOK_WHITESPACE)
1063 {
1064 len++;
1065 }
1066 else if (t->text)
1067 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001068 len += strlen(t->text);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001069 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001070 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001071 p = line = nasm_malloc(len + 1);
1072 for (t = tlist; t; t = t->next)
1073 {
1074 if (t->type == TOK_WHITESPACE)
1075 {
1076 *p = ' ';
1077 p++;
1078 *p = '\0';
1079 }
1080 else if (t->text)
1081 {
1082 strcpy(p, t->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001083 p += strlen(p);
1084 }
1085 }
1086 *p = '\0';
1087 return line;
1088}
1089
1090/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001091 * A scanner, suitable for use by the expression evaluator, which
1092 * operates on a line of Tokens. Expects a pointer to a pointer to
1093 * the first token in the line to be passed in as its private_data
1094 * field.
1095 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001096static int
1097ppscan(void *private_data, struct tokenval *tokval)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001098{
H. Peter Anvin76690a12002-04-30 20:52:49 +00001099 Token **tlineptr = private_data;
1100 Token *tline;
1101
H. Peter Anvin734b1882002-04-30 21:01:08 +00001102 do
1103 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00001104 tline = *tlineptr;
1105 *tlineptr = tline ? tline->next : NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001106 }
1107 while (tline && (tline->type == TOK_WHITESPACE ||
1108 tline->type == TOK_COMMENT));
H. Peter Anvin76690a12002-04-30 20:52:49 +00001109
1110 if (!tline)
1111 return tokval->t_type = TOKEN_EOS;
1112
1113 if (tline->text[0] == '$' && !tline->text[1])
1114 return tokval->t_type = TOKEN_HERE;
H. Peter Anvin7cf897e2002-05-30 21:30:33 +00001115 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
H. Peter Anvin76690a12002-04-30 20:52:49 +00001116 return tokval->t_type = TOKEN_BASE;
1117
H. Peter Anvin734b1882002-04-30 21:01:08 +00001118 if (tline->type == TOK_ID)
1119 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00001120 tokval->t_charptr = tline->text;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001121 if (tline->text[0] == '$')
1122 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00001123 tokval->t_charptr++;
1124 return tokval->t_type = TOKEN_ID;
1125 }
1126
1127 /*
1128 * This is the only special case we actually need to worry
1129 * about in this restricted context.
1130 */
1131 if (!nasm_stricmp(tline->text, "seg"))
1132 return tokval->t_type = TOKEN_SEG;
1133
1134 return tokval->t_type = TOKEN_ID;
1135 }
1136
H. Peter Anvin734b1882002-04-30 21:01:08 +00001137 if (tline->type == TOK_NUMBER)
1138 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00001139 int rn_error;
1140
1141 tokval->t_integer = readnum(tline->text, &rn_error);
1142 if (rn_error)
1143 return tokval->t_type = TOKEN_ERRNUM;
1144 tokval->t_charptr = NULL;
1145 return tokval->t_type = TOKEN_NUM;
1146 }
1147
H. Peter Anvin734b1882002-04-30 21:01:08 +00001148 if (tline->type == TOK_STRING)
1149 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00001150 int rn_warn;
1151 char q, *r;
1152 int l;
1153
1154 r = tline->text;
1155 q = *r++;
1156 l = strlen(r);
1157
H. Peter Anvin734b1882002-04-30 21:01:08 +00001158 if (l == 0 || r[l - 1] != q)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001159 return tokval->t_type = TOKEN_ERRNUM;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001160 tokval->t_integer = readstrnum(r, l - 1, &rn_warn);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001161 if (rn_warn)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001162 error(ERR_WARNING | ERR_PASS1, "character constant too long");
H. Peter Anvineba20a72002-04-30 20:53:55 +00001163 tokval->t_charptr = NULL;
1164 return tokval->t_type = TOKEN_NUM;
1165 }
1166
H. Peter Anvin734b1882002-04-30 21:01:08 +00001167 if (tline->type == TOK_OTHER)
1168 {
1169 if (!strcmp(tline->text, "<<"))
1170 return tokval->t_type = TOKEN_SHL;
1171 if (!strcmp(tline->text, ">>"))
1172 return tokval->t_type = TOKEN_SHR;
1173 if (!strcmp(tline->text, "//"))
1174 return tokval->t_type = TOKEN_SDIV;
1175 if (!strcmp(tline->text, "%%"))
1176 return tokval->t_type = TOKEN_SMOD;
1177 if (!strcmp(tline->text, "=="))
1178 return tokval->t_type = TOKEN_EQ;
1179 if (!strcmp(tline->text, "<>"))
1180 return tokval->t_type = TOKEN_NE;
1181 if (!strcmp(tline->text, "!="))
1182 return tokval->t_type = TOKEN_NE;
1183 if (!strcmp(tline->text, "<="))
1184 return tokval->t_type = TOKEN_LE;
1185 if (!strcmp(tline->text, ">="))
1186 return tokval->t_type = TOKEN_GE;
1187 if (!strcmp(tline->text, "&&"))
1188 return tokval->t_type = TOKEN_DBL_AND;
1189 if (!strcmp(tline->text, "^^"))
1190 return tokval->t_type = TOKEN_DBL_XOR;
1191 if (!strcmp(tline->text, "||"))
1192 return tokval->t_type = TOKEN_DBL_OR;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001193 }
1194
1195 /*
1196 * We have no other options: just return the first character of
1197 * the token text.
1198 */
1199 return tokval->t_type = tline->text[0];
1200}
1201
1202/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001203 * Compare a string to the name of an existing macro; this is a
1204 * simple wrapper which calls either strcmp or nasm_stricmp
1205 * depending on the value of the `casesense' parameter.
1206 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001207static int
1208mstrcmp(char *p, char *q, int casesense)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001209{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001210 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001211}
1212
1213/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001214 * Return the Context structure associated with a %$ token. Return
1215 * NULL, having _already_ reported an error condition, if the
1216 * context stack isn't deep enough for the supplied number of $
1217 * signs.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001218 * If all_contexts == TRUE, contexts that enclose current are
1219 * also scanned for such smacro, until it is found; if not -
1220 * only the context that directly results from the number of $'s
1221 * in variable's name.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001222 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001223static Context *
1224get_ctx(char *name, int all_contexts)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001225{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001226 Context *ctx;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001227 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001228 int i;
1229
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001230 if (!name || name[0] != '%' || name[1] != '$')
1231 return NULL;
1232
H. Peter Anvin734b1882002-04-30 21:01:08 +00001233 if (!cstk)
1234 {
1235 error(ERR_NONFATAL, "`%s': context stack is empty", name);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001236 return NULL;
1237 }
1238
H. Peter Anvin734b1882002-04-30 21:01:08 +00001239 for (i = strspn(name + 2, "$"), ctx = cstk; (i > 0) && ctx; i--)
1240 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001241 ctx = ctx->next;
H. Peter Anvindce1e2f2002-04-30 21:06:37 +00001242/* i--; Lino - 02/25/02 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001243 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001244 if (!ctx)
1245 {
1246 error(ERR_NONFATAL, "`%s': context stack is only"
1247 " %d level%s deep", name, i - 1, (i == 2 ? "" : "s"));
1248 return NULL;
1249 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001250 if (!all_contexts)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001251 return ctx;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001252
H. Peter Anvin734b1882002-04-30 21:01:08 +00001253 do
1254 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001255 /* Search for this smacro in found context */
1256 m = ctx->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001257 while (m)
1258 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001259 if (!mstrcmp(m->name, name, m->casesense))
1260 return ctx;
1261 m = m->next;
1262 }
1263 ctx = ctx->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001264 }
1265 while (ctx);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001266 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001267}
1268
1269/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001270 * Open an include file. This routine must always return a valid
1271 * file pointer if it returns - it's responsible for throwing an
1272 * ERR_FATAL and bombing out completely if not. It should also try
1273 * the include path one by one until it finds the file or reaches
1274 * the end of the path.
1275 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001276static FILE *
1277inc_fopen(char *file)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001278{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001279 FILE *fp;
1280 char *prefix = "", *combine;
1281 IncPath *ip = ipath;
H. Peter Anvin620515a2002-04-30 20:57:38 +00001282 static int namelen = 0;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001283 int len = strlen(file);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001284
H. Peter Anvin734b1882002-04-30 21:01:08 +00001285 while (1)
1286 {
Frank Kotler7fd4f002003-08-06 07:10:16 +00001287 combine = nasm_malloc(strlen(prefix) + len + 1);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001288 strcpy(combine, prefix);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001289 strcat(combine, file);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001290 fp = fopen(combine, "r");
H. Peter Anvin620515a2002-04-30 20:57:38 +00001291 if (pass == 0 && fp)
1292 {
H. Peter Anvin734b1882002-04-30 21:01:08 +00001293 namelen += strlen(combine) + 1;
1294 if (namelen > 62)
1295 {
1296 printf(" \\\n ");
1297 namelen = 2;
1298 }
1299 printf(" %s", combine);
H. Peter Anvin620515a2002-04-30 20:57:38 +00001300 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001301 nasm_free(combine);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001302 if (fp)
1303 return fp;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001304 if (!ip)
1305 break;
1306 prefix = ip->path;
1307 ip = ip->next;
1308 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001309
H. Peter Anvin734b1882002-04-30 21:01:08 +00001310 error(ERR_FATAL, "unable to open include file `%s'", file);
1311 return NULL; /* never reached - placate compilers */
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001312}
1313
1314/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001315 * Determine if we should warn on defining a single-line macro of
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001316 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001317 * return TRUE if _any_ single-line macro of that name is defined.
1318 * Otherwise, will return TRUE if a single-line macro with either
1319 * `nparam' or no parameters is defined.
1320 *
1321 * If a macro with precisely the right number of parameters is
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001322 * defined, or nparam is -1, the address of the definition structure
1323 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001324 * is NULL, no action will be taken regarding its contents, and no
1325 * error will occur.
1326 *
1327 * Note that this is also called with nparam zero to resolve
1328 * `ifdef'.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001329 *
1330 * If you already know which context macro belongs to, you can pass
1331 * the context pointer as first parameter; if you won't but name begins
1332 * with %$ the context will be automatically computed. If all_contexts
1333 * is true, macro will be searched in outer contexts as well.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001334 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001335static int
1336smacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn,
1337 int nocase)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001338{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001339 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001340
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001341 if (ctx)
1342 m = ctx->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001343 else if (name[0] == '%' && name[1] == '$')
1344 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001345 if (cstk)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001346 ctx = get_ctx(name, FALSE);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001347 if (!ctx)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001348 return FALSE; /* got to return _something_ */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001349 m = ctx->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001350 }
1351 else
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001352 m = smacros[hash(name)];
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001353
H. Peter Anvin734b1882002-04-30 21:01:08 +00001354 while (m)
1355 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001356 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
H. Peter Anvin734b1882002-04-30 21:01:08 +00001357 (nparam <= 0 || m->nparam == 0 || nparam == m->nparam))
1358 {
1359 if (defn)
1360 {
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001361 if (nparam == m->nparam || nparam == -1)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001362 *defn = m;
1363 else
1364 *defn = NULL;
1365 }
1366 return TRUE;
1367 }
1368 m = m->next;
1369 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001370
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001371 return FALSE;
1372}
1373
1374/*
1375 * Count and mark off the parameters in a multi-line macro call.
1376 * This is called both from within the multi-line macro expansion
1377 * code, and also to mark off the default parameters when provided
1378 * in a %macro definition line.
1379 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001380static void
1381count_mmac_params(Token * t, int *nparam, Token *** params)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001382{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001383 int paramsize, brace;
1384
1385 *nparam = paramsize = 0;
1386 *params = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001387 while (t)
1388 {
1389 if (*nparam >= paramsize)
1390 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001391 paramsize += PARAM_DELTA;
1392 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1393 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001394 skip_white_(t);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001395 brace = FALSE;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001396 if (tok_is_(t, "{"))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001397 brace = TRUE;
1398 (*params)[(*nparam)++] = t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001399 while (tok_isnt_(t, brace ? "}" : ","))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001400 t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001401 if (t)
1402 { /* got a comma/brace */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001403 t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001404 if (brace)
1405 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001406 /*
1407 * Now we've found the closing brace, look further
1408 * for the comma.
1409 */
H. Peter Anvineba20a72002-04-30 20:53:55 +00001410 skip_white_(t);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001411 if (tok_isnt_(t, ","))
1412 {
1413 error(ERR_NONFATAL,
1414 "braces do not enclose all of macro parameter");
H. Peter Anvineba20a72002-04-30 20:53:55 +00001415 while (tok_isnt_(t, ","))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001416 t = t->next;
1417 }
1418 if (t)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001419 t = t->next; /* eat the comma */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001420 }
1421 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001422 }
1423}
1424
1425/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001426 * Determine whether one of the various `if' conditions is true or
1427 * not.
1428 *
1429 * We must free the tline we get passed.
1430 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001431static int
1432if_condition(Token * tline, int i)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001433{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001434 int j, casesense;
1435 Token *t, *tt, **tptr, *origline;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001436 struct tokenval tokval;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001437 expr *evalresult;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001438
1439 origline = tline;
1440
H. Peter Anvin734b1882002-04-30 21:01:08 +00001441 switch (i)
1442 {
1443 case PP_IFCTX:
1444 case PP_ELIFCTX:
1445 case PP_IFNCTX:
1446 case PP_ELIFNCTX:
1447 j = FALSE; /* have we matched yet? */
1448 while (cstk && tline)
1449 {
1450 skip_white_(tline);
1451 if (!tline || tline->type != TOK_ID)
1452 {
1453 error(ERR_NONFATAL,
1454 "`%s' expects context identifiers",
1455 directives[i]);
1456 free_tlist(origline);
1457 return -1;
1458 }
1459 if (!nasm_stricmp(tline->text, cstk->name))
1460 j = TRUE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001461 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001462 }
1463 if (i == PP_IFNCTX || i == PP_ELIFNCTX)
1464 j = !j;
1465 free_tlist(origline);
1466 return j;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001467
H. Peter Anvin734b1882002-04-30 21:01:08 +00001468 case PP_IFDEF:
1469 case PP_ELIFDEF:
1470 case PP_IFNDEF:
1471 case PP_ELIFNDEF:
1472 j = FALSE; /* have we matched yet? */
1473 while (tline)
1474 {
1475 skip_white_(tline);
1476 if (!tline || (tline->type != TOK_ID &&
1477 (tline->type != TOK_PREPROC_ID ||
1478 tline->text[1] != '$')))
1479 {
1480 error(ERR_NONFATAL,
H. Peter Anvin65747262002-05-07 00:10:05 +00001481 "`%s' expects macro identifiers",
1482 directives[i]);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001483 free_tlist(origline);
1484 return -1;
1485 }
1486 if (smacro_defined(NULL, tline->text, 0, NULL, 1))
1487 j = TRUE;
1488 tline = tline->next;
1489 }
1490 if (i == PP_IFNDEF || i == PP_ELIFNDEF)
1491 j = !j;
1492 free_tlist(origline);
1493 return j;
1494
1495 case PP_IFIDN:
1496 case PP_ELIFIDN:
1497 case PP_IFNIDN:
1498 case PP_ELIFNIDN:
1499 case PP_IFIDNI:
1500 case PP_ELIFIDNI:
1501 case PP_IFNIDNI:
1502 case PP_ELIFNIDNI:
1503 tline = expand_smacro(tline);
1504 t = tt = tline;
1505 while (tok_isnt_(tt, ","))
1506 tt = tt->next;
1507 if (!tt)
1508 {
1509 error(ERR_NONFATAL,
1510 "`%s' expects two comma-separated arguments",
1511 directives[i]);
1512 free_tlist(tline);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001513 return -1;
1514 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001515 tt = tt->next;
1516 casesense = (i == PP_IFIDN || i == PP_ELIFIDN ||
1517 i == PP_IFNIDN || i == PP_ELIFNIDN);
1518 j = TRUE; /* assume equality unless proved not */
1519 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt)
1520 {
1521 if (tt->type == TOK_OTHER && !strcmp(tt->text, ","))
1522 {
1523 error(ERR_NONFATAL, "`%s': more than one comma on line",
1524 directives[i]);
1525 free_tlist(tline);
1526 return -1;
1527 }
1528 if (t->type == TOK_WHITESPACE)
1529 {
1530 t = t->next;
1531 continue;
1532 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001533 if (tt->type == TOK_WHITESPACE)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001534 {
1535 tt = tt->next;
1536 continue;
1537 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001538 if (tt->type != t->type)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001539 {
1540 j = FALSE; /* found mismatching tokens */
1541 break;
1542 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001543 /* Unify surrounding quotes for strings */
1544 if (t->type == TOK_STRING)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001545 {
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001546 tt->text[0] = t->text[0];
1547 tt->text[strlen(tt->text) - 1] = t->text[0];
H. Peter Anvin734b1882002-04-30 21:01:08 +00001548 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001549 if (mstrcmp(tt->text, t->text, casesense) != 0)
1550 {
1551 j = FALSE; /* found mismatching tokens */
1552 break;
1553 }
1554
1555 t = t->next;
1556 tt = tt->next;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001557 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001558 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
1559 j = FALSE; /* trailing gunk on one end or other */
1560 if (i == PP_IFNIDN || i == PP_ELIFNIDN ||
1561 i == PP_IFNIDNI || i == PP_ELIFNIDNI)
1562 j = !j;
1563 free_tlist(tline);
1564 return j;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001565
H. Peter Anvin65747262002-05-07 00:10:05 +00001566 case PP_IFMACRO:
1567 case PP_ELIFMACRO:
1568 case PP_IFNMACRO:
1569 case PP_ELIFNMACRO:
1570 {
1571 int found = 0;
1572 MMacro searching, *mmac;
1573
1574 tline = tline->next;
1575 skip_white_(tline);
1576 tline = expand_id(tline);
1577 if (!tok_type_(tline, TOK_ID))
1578 {
1579 error(ERR_NONFATAL,
1580 "`%s' expects a macro name",
1581 directives[i]);
1582 return -1;
1583 }
1584 searching.name = nasm_strdup(tline->text);
1585 searching.casesense = (i == PP_MACRO);
1586 searching.plus = FALSE;
1587 searching.nolist = FALSE;
1588 searching.in_progress = FALSE;
1589 searching.rep_nest = NULL;
1590 searching.nparam_min = 0;
1591 searching.nparam_max = INT_MAX;
1592 tline = expand_smacro(tline->next);
1593 skip_white_(tline);
1594 if (!tline)
1595 {
1596 } else if (!tok_type_(tline, TOK_NUMBER))
1597 {
1598 error(ERR_NONFATAL,
1599 "`%s' expects a parameter count or nothing",
1600 directives[i]);
1601 }
1602 else
1603 {
1604 searching.nparam_min = searching.nparam_max =
1605 readnum(tline->text, &j);
1606 if (j)
1607 error(ERR_NONFATAL,
1608 "unable to parse parameter count `%s'",
1609 tline->text);
1610 }
1611 if (tline && tok_is_(tline->next, "-"))
1612 {
1613 tline = tline->next->next;
1614 if (tok_is_(tline, "*"))
1615 searching.nparam_max = INT_MAX;
1616 else if (!tok_type_(tline, TOK_NUMBER))
1617 error(ERR_NONFATAL,
1618 "`%s' expects a parameter count after `-'",
1619 directives[i]);
1620 else
1621 {
1622 searching.nparam_max = readnum(tline->text, &j);
1623 if (j)
1624 error(ERR_NONFATAL,
1625 "unable to parse parameter count `%s'",
1626 tline->text);
1627 if (searching.nparam_min > searching.nparam_max)
1628 error(ERR_NONFATAL,
1629 "minimum parameter count exceeds maximum");
1630 }
1631 }
1632 if (tline && tok_is_(tline->next, "+"))
1633 {
1634 tline = tline->next;
1635 searching.plus = TRUE;
1636 }
1637 mmac = mmacros[hash(searching.name)];
1638 while (mmac)
1639 {
1640 if (!strcmp(mmac->name, searching.name) &&
1641 (mmac->nparam_min <= searching.nparam_max
1642 || searching.plus)
1643 && (searching.nparam_min <= mmac->nparam_max
1644 || mmac->plus))
1645 {
1646 found = TRUE;
1647 break;
1648 }
1649 mmac = mmac->next;
1650 }
1651 nasm_free(searching.name);
1652 free_tlist(origline);
1653 if (i == PP_IFNMACRO || i == PP_ELIFNMACRO)
1654 found = !found;
1655 return found;
1656 }
1657
H. Peter Anvin734b1882002-04-30 21:01:08 +00001658 case PP_IFID:
1659 case PP_ELIFID:
1660 case PP_IFNID:
1661 case PP_ELIFNID:
1662 case PP_IFNUM:
1663 case PP_ELIFNUM:
1664 case PP_IFNNUM:
1665 case PP_ELIFNNUM:
1666 case PP_IFSTR:
1667 case PP_ELIFSTR:
1668 case PP_IFNSTR:
1669 case PP_ELIFNSTR:
1670 tline = expand_smacro(tline);
1671 t = tline;
1672 while (tok_type_(t, TOK_WHITESPACE))
1673 t = t->next;
1674 j = FALSE; /* placate optimiser */
1675 if (t)
1676 switch (i)
1677 {
1678 case PP_IFID:
1679 case PP_ELIFID:
1680 case PP_IFNID:
1681 case PP_ELIFNID:
1682 j = (t->type == TOK_ID);
1683 break;
1684 case PP_IFNUM:
1685 case PP_ELIFNUM:
1686 case PP_IFNNUM:
1687 case PP_ELIFNNUM:
1688 j = (t->type == TOK_NUMBER);
1689 break;
1690 case PP_IFSTR:
1691 case PP_ELIFSTR:
1692 case PP_IFNSTR:
1693 case PP_ELIFNSTR:
1694 j = (t->type == TOK_STRING);
1695 break;
1696 }
1697 if (i == PP_IFNID || i == PP_ELIFNID ||
1698 i == PP_IFNNUM || i == PP_ELIFNNUM ||
1699 i == PP_IFNSTR || i == PP_ELIFNSTR)
1700 j = !j;
1701 free_tlist(tline);
1702 return j;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001703
H. Peter Anvin734b1882002-04-30 21:01:08 +00001704 case PP_IF:
1705 case PP_ELIF:
1706 t = tline = expand_smacro(tline);
1707 tptr = &t;
1708 tokval.t_type = TOKEN_INVALID;
1709 evalresult = evaluate(ppscan, tptr, &tokval,
1710 NULL, pass | CRITICAL, error, NULL);
1711 free_tlist(tline);
1712 if (!evalresult)
1713 return -1;
1714 if (tokval.t_type)
1715 error(ERR_WARNING,
1716 "trailing garbage after expression ignored");
1717 if (!is_simple(evalresult))
1718 {
1719 error(ERR_NONFATAL,
1720 "non-constant value given to `%s'", directives[i]);
1721 return -1;
1722 }
1723 return reloc_value(evalresult) != 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001724
H. Peter Anvin734b1882002-04-30 21:01:08 +00001725 default:
1726 error(ERR_FATAL,
1727 "preprocessor directive `%s' not yet implemented",
1728 directives[i]);
1729 free_tlist(origline);
1730 return -1; /* yeah, right */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001731 }
1732}
1733
1734/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001735 * Expand macros in a string. Used in %error and %include directives.
1736 * First tokenise the string, apply "expand_smacro" and then de-tokenise back.
1737 * The returned variable should ALWAYS be freed after usage.
1738 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001739void
1740expand_macros_in_string(char **p)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001741{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001742 Token *line = tokenise(*p);
1743 line = expand_smacro(line);
1744 *p = detoken(line, FALSE);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001745}
1746
Ed Beroset3ab3f412002-06-11 03:31:49 +00001747/**
1748 * find and process preprocessor directive in passed line
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001749 * Find out if a line contains a preprocessor directive, and deal
1750 * with it if so.
1751 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00001752 * If a directive _is_ found, it is the responsibility of this routine
1753 * (and not the caller) to free_tlist() the line.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001754 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00001755 * @param tline a pointer to the current tokeninzed line linked list
1756 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001757 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001758 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001759static int
1760do_directive(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001761{
H. Peter Anvin76690a12002-04-30 20:52:49 +00001762 int i, j, k, m, nparam, nolist;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001763 int offset;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001764 char *p, *mname;
1765 Include *inc;
1766 Context *ctx;
1767 Cond *cond;
1768 SMacro *smac, **smhead;
1769 MMacro *mmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001770 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
1771 Line *l;
1772 struct tokenval tokval;
1773 expr *evalresult;
H. Peter Anvinb64535f2002-04-30 20:55:37 +00001774 MMacro *tmp_defining; /* Used when manipulating rep_nest */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001775
1776 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001777
H. Peter Anvineba20a72002-04-30 20:53:55 +00001778 skip_white_(tline);
1779 if (!tok_type_(tline, TOK_PREPROC_ID) ||
H. Peter Anvin734b1882002-04-30 21:01:08 +00001780 (tline->text[1] == '%' || tline->text[1] == '$'
1781 || tline->text[1] == '!'))
Ed Beroset3ab3f412002-06-11 03:31:49 +00001782 return NO_DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001783
1784 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +00001785 j = elements(directives);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001786 while (j - i > 1)
1787 {
1788 k = (j + i) / 2;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001789 m = nasm_stricmp(tline->text, directives[k]);
1790 if (m == 0) {
H. Peter Anvin734b1882002-04-30 21:01:08 +00001791 if (tasm_compatible_mode) {
1792 i = k;
1793 j = -2;
1794 } else if (k != PP_ARG && k != PP_LOCAL && k != PP_STACKSIZE) {
1795 i = k;
1796 j = -2;
1797 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001798 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001799 }
1800 else if (m < 0) {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001801 j = k;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001802 }
1803 else
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001804 i = k;
1805 }
1806
1807 /*
1808 * If we're in a non-emitting branch of a condition construct,
H. Peter Anvin76690a12002-04-30 20:52:49 +00001809 * or walking to the end of an already terminated %rep block,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001810 * we should ignore all directives except for condition
1811 * directives.
1812 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001813 if (((istk->conds && !emitting(istk->conds->state)) ||
H. Peter Anvin65747262002-05-07 00:10:05 +00001814 (istk->mstk && !istk->mstk->in_progress)) &&
1815 !is_condition(i))
H. Peter Anvineba20a72002-04-30 20:53:55 +00001816 {
Ed Beroset3ab3f412002-06-11 03:31:49 +00001817 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001818 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001819
1820 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001821 * If we're defining a macro or reading a %rep block, we should
1822 * ignore all directives except for %macro/%imacro (which
1823 * generate an error), %endm/%endmacro, and (only if we're in a
H. Peter Anvineba20a72002-04-30 20:53:55 +00001824 * %rep block) %endrep. If we're in a %rep block, another %rep
1825 * causes an error, so should be let through.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001826 */
1827 if (defining && i != PP_MACRO && i != PP_IMACRO &&
H. Peter Anvin734b1882002-04-30 21:01:08 +00001828 i != PP_ENDMACRO && i != PP_ENDM &&
1829 (defining->name || (i != PP_ENDREP && i != PP_REP)))
H. Peter Anvineba20a72002-04-30 20:53:55 +00001830 {
Ed Beroset3ab3f412002-06-11 03:31:49 +00001831 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001832 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001833
H. Peter Anvin734b1882002-04-30 21:01:08 +00001834 if (j != -2)
1835 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00001836 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
H. Peter Anvin734b1882002-04-30 21:01:08 +00001837 tline->text);
Ed Beroset3ab3f412002-06-11 03:31:49 +00001838 return NO_DIRECTIVE_FOUND; /* didn't get it */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001839 }
1840
H. Peter Anvin734b1882002-04-30 21:01:08 +00001841 switch (i)
1842 {
1843 case PP_STACKSIZE:
1844 /* Directive to tell NASM what the default stack size is. The
1845 * default is for a 16-bit stack, and this can be overriden with
1846 * %stacksize large.
1847 * the following form:
1848 *
1849 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001850 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001851 tline = tline->next;
1852 if (tline && tline->type == TOK_WHITESPACE)
1853 tline = tline->next;
1854 if (!tline || tline->type != TOK_ID)
1855 {
1856 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
1857 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00001858 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001859 }
1860 if (nasm_stricmp(tline->text, "flat") == 0)
1861 {
1862 /* All subsequent ARG directives are for a 32-bit stack */
1863 StackSize = 4;
1864 StackPointer = "ebp";
1865 ArgOffset = 8;
1866 LocalOffset = 4;
1867 }
1868 else if (nasm_stricmp(tline->text, "large") == 0)
1869 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001870 /* All subsequent ARG directives are for a 16-bit stack,
H. Peter Anvin734b1882002-04-30 21:01:08 +00001871 * far function call.
1872 */
1873 StackSize = 2;
1874 StackPointer = "bp";
1875 ArgOffset = 4;
1876 LocalOffset = 2;
1877 }
1878 else if (nasm_stricmp(tline->text, "small") == 0)
1879 {
1880 /* All subsequent ARG directives are for a 16-bit stack,
1881 * far function call. We don't support near functions.
1882 */
1883 StackSize = 2;
1884 StackPointer = "bp";
1885 ArgOffset = 6;
1886 LocalOffset = 2;
1887 }
1888 else
1889 {
1890 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
1891 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00001892 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001893 }
1894 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00001895 return DIRECTIVE_FOUND;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001896
H. Peter Anvin734b1882002-04-30 21:01:08 +00001897 case PP_ARG:
1898 /* TASM like ARG directive to define arguments to functions, in
1899 * the following form:
1900 *
1901 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1902 */
1903 offset = ArgOffset;
1904 do
1905 {
1906 char *arg, directive[256];
1907 int size = StackSize;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001908
H. Peter Anvin734b1882002-04-30 21:01:08 +00001909 /* Find the argument name */
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001910 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001911 if (tline && tline->type == TOK_WHITESPACE)
1912 tline = tline->next;
1913 if (!tline || tline->type != TOK_ID)
1914 {
1915 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
1916 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00001917 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001918 }
1919 arg = tline->text;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001920
H. Peter Anvin734b1882002-04-30 21:01:08 +00001921 /* Find the argument size type */
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001922 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001923 if (!tline || tline->type != TOK_OTHER
1924 || tline->text[0] != ':')
1925 {
1926 error(ERR_NONFATAL,
1927 "Syntax error processing `%%arg' directive");
1928 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00001929 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001930 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001931 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001932 if (!tline || tline->type != TOK_ID)
1933 {
1934 error(ERR_NONFATAL,
1935 "`%%arg' missing size type parameter");
1936 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00001937 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001938 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001939
H. Peter Anvin734b1882002-04-30 21:01:08 +00001940 /* Allow macro expansion of type parameter */
1941 tt = tokenise(tline->text);
1942 tt = expand_smacro(tt);
1943 if (nasm_stricmp(tt->text, "byte") == 0)
1944 {
1945 size = MAX(StackSize, 1);
1946 }
1947 else if (nasm_stricmp(tt->text, "word") == 0)
1948 {
1949 size = MAX(StackSize, 2);
1950 }
1951 else if (nasm_stricmp(tt->text, "dword") == 0)
1952 {
1953 size = MAX(StackSize, 4);
1954 }
1955 else if (nasm_stricmp(tt->text, "qword") == 0)
1956 {
1957 size = MAX(StackSize, 8);
1958 }
1959 else if (nasm_stricmp(tt->text, "tword") == 0)
1960 {
1961 size = MAX(StackSize, 10);
1962 }
1963 else
1964 {
1965 error(ERR_NONFATAL,
1966 "Invalid size type for `%%arg' missing directive");
1967 free_tlist(tt);
1968 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00001969 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001970 }
1971 free_tlist(tt);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001972
H. Peter Anvin734b1882002-04-30 21:01:08 +00001973 /* Now define the macro for the argument */
1974 sprintf(directive, "%%define %s (%s+%d)", arg, StackPointer,
1975 offset);
1976 do_directive(tokenise(directive));
1977 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001978
H. Peter Anvin734b1882002-04-30 21:01:08 +00001979 /* Move to the next argument in the list */
1980 tline = tline->next;
1981 if (tline && tline->type == TOK_WHITESPACE)
1982 tline = tline->next;
1983 }
1984 while (tline && tline->type == TOK_OTHER
1985 && tline->text[0] == ',');
1986 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00001987 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001988
1989 case PP_LOCAL:
1990 /* TASM like LOCAL directive to define local variables for a
1991 * function, in the following form:
1992 *
1993 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
1994 *
1995 * The '= LocalSize' at the end is ignored by NASM, but is
1996 * required by TASM to define the local parameter size (and used
1997 * by the TASM macro package).
1998 */
1999 offset = LocalOffset;
2000 do
2001 {
2002 char *local, directive[256];
2003 int size = StackSize;
2004
2005 /* Find the argument name */
2006 tline = tline->next;
2007 if (tline && tline->type == TOK_WHITESPACE)
2008 tline = tline->next;
2009 if (!tline || tline->type != TOK_ID)
2010 {
2011 error(ERR_NONFATAL,
2012 "`%%local' missing argument parameter");
2013 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002014 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002015 }
2016 local = tline->text;
2017
2018 /* Find the argument size type */
2019 tline = tline->next;
2020 if (!tline || tline->type != TOK_OTHER
2021 || tline->text[0] != ':')
2022 {
2023 error(ERR_NONFATAL,
2024 "Syntax error processing `%%local' directive");
2025 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002026 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002027 }
2028 tline = tline->next;
2029 if (!tline || tline->type != TOK_ID)
2030 {
2031 error(ERR_NONFATAL,
2032 "`%%local' missing size type parameter");
2033 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002034 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002035 }
2036
2037 /* Allow macro expansion of type parameter */
2038 tt = tokenise(tline->text);
2039 tt = expand_smacro(tt);
2040 if (nasm_stricmp(tt->text, "byte") == 0)
2041 {
2042 size = MAX(StackSize, 1);
2043 }
2044 else if (nasm_stricmp(tt->text, "word") == 0)
2045 {
2046 size = MAX(StackSize, 2);
2047 }
2048 else if (nasm_stricmp(tt->text, "dword") == 0)
2049 {
2050 size = MAX(StackSize, 4);
2051 }
2052 else if (nasm_stricmp(tt->text, "qword") == 0)
2053 {
2054 size = MAX(StackSize, 8);
2055 }
2056 else if (nasm_stricmp(tt->text, "tword") == 0)
2057 {
2058 size = MAX(StackSize, 10);
2059 }
2060 else
2061 {
2062 error(ERR_NONFATAL,
2063 "Invalid size type for `%%local' missing directive");
2064 free_tlist(tt);
2065 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002066 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002067 }
2068 free_tlist(tt);
2069
2070 /* Now define the macro for the argument */
2071 sprintf(directive, "%%define %s (%s-%d)", local, StackPointer,
2072 offset);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002073 do_directive(tokenise(directive));
2074 offset += size;
2075
2076 /* Now define the assign to setup the enter_c macro correctly */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002077 sprintf(directive, "%%assign %%$localsize %%$localsize+%d",
2078 size);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002079 do_directive(tokenise(directive));
2080
H. Peter Anvin734b1882002-04-30 21:01:08 +00002081 /* Move to the next argument in the list */
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002082 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002083 if (tline && tline->type == TOK_WHITESPACE)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002084 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002085 }
2086 while (tline && tline->type == TOK_OTHER
2087 && tline->text[0] == ',');
2088 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002089 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002090
2091 case PP_CLEAR:
2092 if (tline->next)
2093 error(ERR_WARNING,
2094 "trailing garbage after `%%clear' ignored");
2095 for (j = 0; j < NHASH; j++)
2096 {
2097 while (mmacros[j])
2098 {
2099 MMacro *m = mmacros[j];
2100 mmacros[j] = m->next;
2101 free_mmacro(m);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002102 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002103 while (smacros[j])
2104 {
2105 SMacro *s = smacros[j];
2106 smacros[j] = smacros[j]->next;
2107 nasm_free(s->name);
2108 free_tlist(s->expansion);
2109 nasm_free(s);
2110 }
2111 }
2112 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002113 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002114
2115 case PP_INCLUDE:
2116 tline = tline->next;
2117 skip_white_(tline);
2118 if (!tline || (tline->type != TOK_STRING &&
2119 tline->type != TOK_INTERNAL_STRING))
2120 {
2121 error(ERR_NONFATAL, "`%%include' expects a file name");
2122 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002123 return DIRECTIVE_FOUND; /* but we did _something_ */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002124 }
2125 if (tline->next)
2126 error(ERR_WARNING,
2127 "trailing garbage after `%%include' ignored");
2128 if (tline->type != TOK_INTERNAL_STRING)
2129 {
2130 p = tline->text + 1; /* point past the quote to the name */
2131 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
2132 }
2133 else
2134 p = tline->text; /* internal_string is easier */
2135 expand_macros_in_string(&p);
2136 inc = nasm_malloc(sizeof(Include));
2137 inc->next = istk;
2138 inc->conds = NULL;
2139 inc->fp = inc_fopen(p);
2140 inc->fname = src_set_fname(p);
2141 inc->lineno = src_set_linnum(0);
2142 inc->lineinc = 1;
2143 inc->expansion = NULL;
2144 inc->mstk = NULL;
2145 istk = inc;
2146 list->uplevel(LIST_INCLUDE);
2147 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002148 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002149
2150 case PP_PUSH:
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, "`%%push' expects a context identifier");
2157 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002158 return DIRECTIVE_FOUND; /* but we did _something_ */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002159 }
2160 if (tline->next)
2161 error(ERR_WARNING, "trailing garbage after `%%push' ignored");
2162 ctx = nasm_malloc(sizeof(Context));
2163 ctx->next = cstk;
2164 ctx->localmac = NULL;
2165 ctx->name = nasm_strdup(tline->text);
2166 ctx->number = unique++;
2167 cstk = ctx;
2168 free_tlist(origline);
2169 break;
2170
2171 case PP_REPL:
2172 tline = tline->next;
2173 skip_white_(tline);
2174 tline = expand_id(tline);
2175 if (!tok_type_(tline, TOK_ID))
2176 {
2177 error(ERR_NONFATAL, "`%%repl' expects a context identifier");
2178 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002179 return DIRECTIVE_FOUND; /* but we did _something_ */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002180 }
2181 if (tline->next)
2182 error(ERR_WARNING, "trailing garbage after `%%repl' ignored");
2183 if (!cstk)
2184 error(ERR_NONFATAL, "`%%repl': context stack is empty");
2185 else
2186 {
2187 nasm_free(cstk->name);
2188 cstk->name = nasm_strdup(tline->text);
2189 }
2190 free_tlist(origline);
2191 break;
2192
2193 case PP_POP:
2194 if (tline->next)
2195 error(ERR_WARNING, "trailing garbage after `%%pop' ignored");
2196 if (!cstk)
2197 error(ERR_NONFATAL,
2198 "`%%pop': context stack is already empty");
2199 else
2200 ctx_pop();
2201 free_tlist(origline);
2202 break;
2203
2204 case PP_ERROR:
2205 tline->next = expand_smacro(tline->next);
2206 tline = tline->next;
2207 skip_white_(tline);
2208 if (tok_type_(tline, TOK_STRING))
2209 {
2210 p = tline->text + 1; /* point past the quote to the name */
2211 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
2212 expand_macros_in_string(&p);
2213 error(ERR_NONFATAL, "%s", p);
2214 nasm_free(p);
2215 }
2216 else
2217 {
2218 p = detoken(tline, FALSE);
2219 error(ERR_WARNING, "%s", p);
2220 nasm_free(p);
2221 }
2222 free_tlist(origline);
2223 break;
2224
2225 case PP_IF:
2226 case PP_IFCTX:
2227 case PP_IFDEF:
2228 case PP_IFID:
2229 case PP_IFIDN:
2230 case PP_IFIDNI:
H. Peter Anvin65747262002-05-07 00:10:05 +00002231 case PP_IFMACRO:
H. Peter Anvin734b1882002-04-30 21:01:08 +00002232 case PP_IFNCTX:
2233 case PP_IFNDEF:
2234 case PP_IFNID:
2235 case PP_IFNIDN:
2236 case PP_IFNIDNI:
H. Peter Anvin65747262002-05-07 00:10:05 +00002237 case PP_IFNMACRO:
H. Peter Anvin734b1882002-04-30 21:01:08 +00002238 case PP_IFNNUM:
2239 case PP_IFNSTR:
2240 case PP_IFNUM:
2241 case PP_IFSTR:
2242 if (istk->conds && !emitting(istk->conds->state))
2243 j = COND_NEVER;
2244 else
2245 {
2246 j = if_condition(tline->next, i);
2247 tline->next = NULL; /* it got freed */
2248 free_tlist(origline);
2249 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2250 }
2251 cond = nasm_malloc(sizeof(Cond));
2252 cond->next = istk->conds;
2253 cond->state = j;
2254 istk->conds = cond;
Ed Beroset3ab3f412002-06-11 03:31:49 +00002255 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002256
2257 case PP_ELIF:
2258 case PP_ELIFCTX:
2259 case PP_ELIFDEF:
2260 case PP_ELIFID:
2261 case PP_ELIFIDN:
2262 case PP_ELIFIDNI:
H. Peter Anvin65747262002-05-07 00:10:05 +00002263 case PP_ELIFMACRO:
H. Peter Anvin734b1882002-04-30 21:01:08 +00002264 case PP_ELIFNCTX:
2265 case PP_ELIFNDEF:
2266 case PP_ELIFNID:
2267 case PP_ELIFNIDN:
2268 case PP_ELIFNIDNI:
H. Peter Anvin65747262002-05-07 00:10:05 +00002269 case PP_ELIFNMACRO:
H. Peter Anvin734b1882002-04-30 21:01:08 +00002270 case PP_ELIFNNUM:
2271 case PP_ELIFNSTR:
2272 case PP_ELIFNUM:
2273 case PP_ELIFSTR:
2274 if (!istk->conds)
2275 error(ERR_FATAL, "`%s': no matching `%%if'", directives[i]);
2276 if (emitting(istk->conds->state)
2277 || istk->conds->state == COND_NEVER)
2278 istk->conds->state = COND_NEVER;
2279 else
2280 {
H. Peter Anvin0c608152002-05-22 22:59:40 +00002281 /*
2282 * IMPORTANT: In the case of %if, we will already have
2283 * called expand_mmac_params(); however, if we're
2284 * processing an %elif we must have been in a
2285 * non-emitting mode, which would have inhibited
2286 * the normal invocation of expand_mmac_params(). Therefore,
2287 * we have to do it explicitly here.
2288 */
2289 j = if_condition(expand_mmac_params(tline->next), i);
2290 tline->next = NULL; /* it got freed */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002291 free_tlist(origline);
2292 istk->conds->state =
2293 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2294 }
Ed Beroset3ab3f412002-06-11 03:31:49 +00002295 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002296
2297 case PP_ELSE:
2298 if (tline->next)
2299 error(ERR_WARNING, "trailing garbage after `%%else' ignored");
2300 if (!istk->conds)
2301 error(ERR_FATAL, "`%%else': no matching `%%if'");
2302 if (emitting(istk->conds->state)
2303 || istk->conds->state == COND_NEVER)
2304 istk->conds->state = COND_ELSE_FALSE;
2305 else
2306 istk->conds->state = COND_ELSE_TRUE;
2307 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002308 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002309
2310 case PP_ENDIF:
2311 if (tline->next)
2312 error(ERR_WARNING,
2313 "trailing garbage after `%%endif' ignored");
2314 if (!istk->conds)
2315 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2316 cond = istk->conds;
2317 istk->conds = cond->next;
2318 nasm_free(cond);
2319 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002320 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002321
2322 case PP_MACRO:
2323 case PP_IMACRO:
2324 if (defining)
2325 error(ERR_FATAL,
2326 "`%%%smacro': already defining a macro",
2327 (i == PP_IMACRO ? "i" : ""));
2328 tline = tline->next;
2329 skip_white_(tline);
2330 tline = expand_id(tline);
2331 if (!tok_type_(tline, TOK_ID))
2332 {
2333 error(ERR_NONFATAL,
2334 "`%%%smacro' expects a macro name",
2335 (i == PP_IMACRO ? "i" : ""));
Ed Beroset3ab3f412002-06-11 03:31:49 +00002336 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002337 }
2338 defining = nasm_malloc(sizeof(MMacro));
2339 defining->name = nasm_strdup(tline->text);
2340 defining->casesense = (i == PP_MACRO);
2341 defining->plus = FALSE;
2342 defining->nolist = FALSE;
2343 defining->in_progress = FALSE;
2344 defining->rep_nest = NULL;
2345 tline = expand_smacro(tline->next);
2346 skip_white_(tline);
2347 if (!tok_type_(tline, TOK_NUMBER))
2348 {
2349 error(ERR_NONFATAL,
2350 "`%%%smacro' expects a parameter count",
2351 (i == PP_IMACRO ? "i" : ""));
2352 defining->nparam_min = defining->nparam_max = 0;
2353 }
2354 else
2355 {
2356 defining->nparam_min = defining->nparam_max =
2357 readnum(tline->text, &j);
2358 if (j)
2359 error(ERR_NONFATAL,
2360 "unable to parse parameter count `%s'",
2361 tline->text);
2362 }
2363 if (tline && tok_is_(tline->next, "-"))
2364 {
2365 tline = tline->next->next;
2366 if (tok_is_(tline, "*"))
2367 defining->nparam_max = INT_MAX;
2368 else if (!tok_type_(tline, TOK_NUMBER))
2369 error(ERR_NONFATAL,
2370 "`%%%smacro' expects a parameter count after `-'",
2371 (i == PP_IMACRO ? "i" : ""));
2372 else
2373 {
2374 defining->nparam_max = readnum(tline->text, &j);
2375 if (j)
2376 error(ERR_NONFATAL,
2377 "unable to parse parameter count `%s'",
2378 tline->text);
2379 if (defining->nparam_min > defining->nparam_max)
2380 error(ERR_NONFATAL,
2381 "minimum parameter count exceeds maximum");
2382 }
2383 }
2384 if (tline && tok_is_(tline->next, "+"))
2385 {
2386 tline = tline->next;
2387 defining->plus = TRUE;
2388 }
2389 if (tline && tok_type_(tline->next, TOK_ID) &&
2390 !nasm_stricmp(tline->next->text, ".nolist"))
2391 {
2392 tline = tline->next;
2393 defining->nolist = TRUE;
2394 }
2395 mmac = mmacros[hash(defining->name)];
2396 while (mmac)
2397 {
2398 if (!strcmp(mmac->name, defining->name) &&
2399 (mmac->nparam_min <= defining->nparam_max
2400 || defining->plus)
2401 && (defining->nparam_min <= mmac->nparam_max
2402 || mmac->plus))
2403 {
2404 error(ERR_WARNING,
2405 "redefining multi-line macro `%s'",
2406 defining->name);
2407 break;
2408 }
2409 mmac = mmac->next;
2410 }
2411 /*
2412 * Handle default parameters.
2413 */
2414 if (tline && tline->next)
2415 {
2416 defining->dlist = tline->next;
2417 tline->next = NULL;
2418 count_mmac_params(defining->dlist, &defining->ndefs,
2419 &defining->defaults);
2420 }
2421 else
2422 {
2423 defining->dlist = NULL;
2424 defining->defaults = NULL;
2425 }
2426 defining->expansion = NULL;
2427 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002428 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002429
2430 case PP_ENDM:
2431 case PP_ENDMACRO:
2432 if (!defining)
2433 {
2434 error(ERR_NONFATAL, "`%s': not defining a macro",
2435 tline->text);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002436 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002437 }
2438 k = hash(defining->name);
2439 defining->next = mmacros[k];
2440 mmacros[k] = defining;
2441 defining = NULL;
2442 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002443 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002444
2445 case PP_ROTATE:
2446 if (tline->next && tline->next->type == TOK_WHITESPACE)
2447 tline = tline->next;
Ed Beroset3ab3f412002-06-11 03:31:49 +00002448 if (tline->next == NULL)
2449 {
2450 free_tlist(origline);
2451 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
2452 return DIRECTIVE_FOUND;
2453 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002454 t = expand_smacro(tline->next);
2455 tline->next = NULL;
2456 free_tlist(origline);
2457 tline = t;
2458 tptr = &t;
2459 tokval.t_type = TOKEN_INVALID;
2460 evalresult =
2461 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2462 free_tlist(tline);
2463 if (!evalresult)
Ed Beroset3ab3f412002-06-11 03:31:49 +00002464 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002465 if (tokval.t_type)
2466 error(ERR_WARNING,
2467 "trailing garbage after expression ignored");
2468 if (!is_simple(evalresult))
2469 {
2470 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
Ed Beroset3ab3f412002-06-11 03:31:49 +00002471 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002472 }
2473 mmac = istk->mstk;
2474 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2475 mmac = mmac->next_active;
2476 if (!mmac)
Ed Beroset3ab3f412002-06-11 03:31:49 +00002477 {
H. Peter Anvin734b1882002-04-30 21:01:08 +00002478 error(ERR_NONFATAL,
2479 "`%%rotate' invoked outside a macro call");
Ed Beroset3ab3f412002-06-11 03:31:49 +00002480 }
2481 else if (mmac->nparam == 0)
2482 {
2483 error(ERR_NONFATAL,
2484 "`%%rotate' invoked within macro without parameters");
2485 }
2486 else
2487 {
2488 mmac->rotate = mmac->rotate + reloc_value(evalresult);
2489
2490 if (mmac->rotate < 0)
2491 mmac->rotate =
2492 mmac->nparam - (-mmac->rotate) % mmac->nparam;
2493 mmac->rotate %= mmac->nparam;
2494 }
2495 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002496
2497 case PP_REP:
2498 nolist = FALSE;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002499 do {
H. Peter Anvin734b1882002-04-30 21:01:08 +00002500 tline = tline->next;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002501 } while (tok_type_(tline, TOK_WHITESPACE));
2502
2503 if (tok_type_(tline, TOK_ID) &&
2504 nasm_stricmp(tline->text, ".nolist") == 0)
H. Peter Anvin734b1882002-04-30 21:01:08 +00002505 {
H. Peter Anvin734b1882002-04-30 21:01:08 +00002506 nolist = TRUE;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002507 do {
2508 tline = tline->next;
2509 } while (tok_type_(tline, TOK_WHITESPACE));
H. Peter Anvin734b1882002-04-30 21:01:08 +00002510 }
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002511
2512 if (tline)
H. Peter Anvin734b1882002-04-30 21:01:08 +00002513 {
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002514 t = expand_smacro(tline);
2515 tptr = &t;
2516 tokval.t_type = TOKEN_INVALID;
2517 evalresult =
2518 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2519 if (!evalresult)
2520 {
2521 free_tlist(origline);
2522 return DIRECTIVE_FOUND;
2523 }
2524 if (tokval.t_type)
2525 error(ERR_WARNING,
2526 "trailing garbage after expression ignored");
2527 if (!is_simple(evalresult))
2528 {
2529 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2530 return DIRECTIVE_FOUND;
2531 }
2532 i = (int)reloc_value(evalresult) + 1;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002533 }
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002534 else
2535 {
2536 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
2537 i = 0;
2538 }
2539 free_tlist(origline);
2540
H. Peter Anvin734b1882002-04-30 21:01:08 +00002541 tmp_defining = defining;
2542 defining = nasm_malloc(sizeof(MMacro));
2543 defining->name = NULL; /* flags this macro as a %rep block */
2544 defining->casesense = 0;
2545 defining->plus = FALSE;
2546 defining->nolist = nolist;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002547 defining->in_progress = i;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002548 defining->nparam_min = defining->nparam_max = 0;
2549 defining->defaults = NULL;
2550 defining->dlist = NULL;
2551 defining->expansion = NULL;
2552 defining->next_active = istk->mstk;
2553 defining->rep_nest = tmp_defining;
Ed Beroset3ab3f412002-06-11 03:31:49 +00002554 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002555
2556 case PP_ENDREP:
2557 if (!defining || defining->name)
2558 {
2559 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
Ed Beroset3ab3f412002-06-11 03:31:49 +00002560 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002561 }
2562
2563 /*
2564 * Now we have a "macro" defined - although it has no name
2565 * and we won't be entering it in the hash tables - we must
2566 * push a macro-end marker for it on to istk->expansion.
2567 * After that, it will take care of propagating itself (a
2568 * macro-end marker line for a macro which is really a %rep
2569 * block will cause the macro to be re-expanded, complete
2570 * with another macro-end marker to ensure the process
2571 * continues) until the whole expansion is forcibly removed
2572 * from istk->expansion by a %exitrep.
2573 */
2574 l = nasm_malloc(sizeof(Line));
2575 l->next = istk->expansion;
2576 l->finishes = defining;
2577 l->first = NULL;
2578 istk->expansion = l;
2579
2580 istk->mstk = defining;
2581
2582 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2583 tmp_defining = defining;
2584 defining = defining->rep_nest;
2585 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002586 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002587
2588 case PP_EXITREP:
2589 /*
2590 * We must search along istk->expansion until we hit a
2591 * macro-end marker for a macro with no name. Then we set
2592 * its `in_progress' flag to 0.
2593 */
2594 for (l = istk->expansion; l; l = l->next)
2595 if (l->finishes && !l->finishes->name)
2596 break;
2597
2598 if (l)
2599 l->finishes->in_progress = 0;
2600 else
2601 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2602 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002603 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002604
2605 case PP_XDEFINE:
2606 case PP_IXDEFINE:
2607 case PP_DEFINE:
2608 case PP_IDEFINE:
2609 tline = tline->next;
2610 skip_white_(tline);
2611 tline = expand_id(tline);
2612 if (!tline || (tline->type != TOK_ID &&
2613 (tline->type != TOK_PREPROC_ID ||
2614 tline->text[1] != '$')))
2615 {
2616 error(ERR_NONFATAL,
2617 "`%%%s%sdefine' expects a macro identifier",
2618 ((i == PP_IDEFINE || i == PP_IXDEFINE) ? "i" : ""),
2619 ((i == PP_XDEFINE || i == PP_IXDEFINE) ? "x" : ""));
2620 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002621 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002622 }
2623
2624 ctx = get_ctx(tline->text, FALSE);
2625 if (!ctx)
2626 smhead = &smacros[hash(tline->text)];
2627 else
2628 smhead = &ctx->localmac;
2629 mname = tline->text;
2630 last = tline;
2631 param_start = tline = tline->next;
2632 nparam = 0;
2633
2634 /* Expand the macro definition now for %xdefine and %ixdefine */
2635 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2636 tline = expand_smacro(tline);
2637
2638 if (tok_is_(tline, "("))
2639 {
2640 /*
2641 * This macro has parameters.
2642 */
2643
2644 tline = tline->next;
2645 while (1)
2646 {
2647 skip_white_(tline);
2648 if (!tline)
2649 {
2650 error(ERR_NONFATAL, "parameter identifier expected");
2651 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002652 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002653 }
2654 if (tline->type != TOK_ID)
2655 {
2656 error(ERR_NONFATAL,
2657 "`%s': parameter identifier expected",
2658 tline->text);
2659 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002660 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002661 }
2662 tline->type = TOK_SMAC_PARAM + nparam++;
2663 tline = tline->next;
2664 skip_white_(tline);
2665 if (tok_is_(tline, ","))
2666 {
2667 tline = tline->next;
2668 continue;
2669 }
2670 if (!tok_is_(tline, ")"))
2671 {
2672 error(ERR_NONFATAL,
2673 "`)' expected to terminate macro template");
2674 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002675 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002676 }
2677 break;
2678 }
2679 last = tline;
2680 tline = tline->next;
2681 }
2682 if (tok_type_(tline, TOK_WHITESPACE))
2683 last = tline, tline = tline->next;
2684 macro_start = NULL;
2685 last->next = NULL;
2686 t = tline;
2687 while (t)
2688 {
2689 if (t->type == TOK_ID)
2690 {
2691 for (tt = param_start; tt; tt = tt->next)
2692 if (tt->type >= TOK_SMAC_PARAM &&
2693 !strcmp(tt->text, t->text))
2694 t->type = tt->type;
2695 }
2696 tt = t->next;
2697 t->next = macro_start;
2698 macro_start = t;
2699 t = tt;
2700 }
2701 /*
2702 * Good. We now have a macro name, a parameter count, and a
2703 * token list (in reverse order) for an expansion. We ought
2704 * to be OK just to create an SMacro, store it, and let
2705 * free_tlist have the rest of the line (which we have
2706 * carefully re-terminated after chopping off the expansion
2707 * from the end).
2708 */
2709 if (smacro_defined(ctx, mname, nparam, &smac, i == PP_DEFINE))
2710 {
2711 if (!smac)
2712 {
2713 error(ERR_WARNING,
2714 "single-line macro `%s' defined both with and"
2715 " without parameters", mname);
2716 free_tlist(origline);
2717 free_tlist(macro_start);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002718 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002719 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002720 else
2721 {
2722 /*
2723 * We're redefining, so we have to take over an
2724 * existing SMacro structure. This means freeing
2725 * what was already in it.
2726 */
2727 nasm_free(smac->name);
2728 free_tlist(smac->expansion);
2729 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002730 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002731 else
2732 {
2733 smac = nasm_malloc(sizeof(SMacro));
2734 smac->next = *smhead;
2735 *smhead = smac;
2736 }
2737 smac->name = nasm_strdup(mname);
2738 smac->casesense = ((i == PP_DEFINE) || (i == PP_XDEFINE));
2739 smac->nparam = nparam;
2740 smac->expansion = macro_start;
2741 smac->in_progress = FALSE;
2742 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002743 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002744
2745 case PP_UNDEF:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002746 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002747 skip_white_(tline);
2748 tline = expand_id(tline);
2749 if (!tline || (tline->type != TOK_ID &&
2750 (tline->type != TOK_PREPROC_ID ||
2751 tline->text[1] != '$')))
2752 {
2753 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
2754 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002755 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002756 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002757 if (tline->next)
2758 {
2759 error(ERR_WARNING,
2760 "trailing garbage after macro name ignored");
2761 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002762
H. Peter Anvin734b1882002-04-30 21:01:08 +00002763 /* Find the context that symbol belongs to */
2764 ctx = get_ctx(tline->text, FALSE);
2765 if (!ctx)
2766 smhead = &smacros[hash(tline->text)];
2767 else
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002768 smhead = &ctx->localmac;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002769
H. Peter Anvin734b1882002-04-30 21:01:08 +00002770 mname = tline->text;
2771 last = tline;
2772 last->next = NULL;
2773
2774 /*
2775 * We now have a macro name... go hunt for it.
2776 */
2777 while (smacro_defined(ctx, mname, -1, &smac, 1))
2778 {
2779 /* Defined, so we need to find its predecessor and nuke it */
2780 SMacro **s;
2781 for (s = smhead; *s && *s != smac; s = &(*s)->next);
2782 if (*s)
2783 {
2784 *s = smac->next;
2785 nasm_free(smac->name);
2786 free_tlist(smac->expansion);
2787 nasm_free(smac);
2788 }
2789 }
2790 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002791 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002792
2793 case PP_STRLEN:
2794 tline = tline->next;
2795 skip_white_(tline);
2796 tline = expand_id(tline);
2797 if (!tline || (tline->type != TOK_ID &&
2798 (tline->type != TOK_PREPROC_ID ||
2799 tline->text[1] != '$')))
2800 {
2801 error(ERR_NONFATAL,
2802 "`%%strlen' expects a macro identifier as first parameter");
2803 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002804 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002805 }
2806 ctx = get_ctx(tline->text, FALSE);
2807 if (!ctx)
2808 smhead = &smacros[hash(tline->text)];
2809 else
2810 smhead = &ctx->localmac;
2811 mname = tline->text;
2812 last = tline;
2813 tline = expand_smacro(tline->next);
2814 last->next = NULL;
2815
2816 t = tline;
2817 while (tok_type_(t, TOK_WHITESPACE))
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002818 t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002819 /* t should now point to the string */
2820 if (t->type != TOK_STRING)
2821 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002822 error(ERR_NONFATAL,
2823 "`%%strlen` requires string as second parameter");
2824 free_tlist(tline);
2825 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002826 return DIRECTIVE_FOUND;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002827 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002828
H. Peter Anvin734b1882002-04-30 21:01:08 +00002829 macro_start = nasm_malloc(sizeof(*macro_start));
2830 macro_start->next = NULL;
2831 make_tok_num(macro_start, strlen(t->text) - 2);
2832 macro_start->mac = NULL;
2833
2834 /*
2835 * We now have a macro name, an implicit parameter count of
2836 * zero, and a numeric token to use as an expansion. Create
2837 * and store an SMacro.
2838 */
2839 if (smacro_defined(ctx, mname, 0, &smac, i == PP_STRLEN))
2840 {
2841 if (!smac)
2842 error(ERR_WARNING,
2843 "single-line macro `%s' defined both with and"
2844 " without parameters", mname);
2845 else
2846 {
2847 /*
2848 * We're redefining, so we have to take over an
2849 * existing SMacro structure. This means freeing
2850 * what was already in it.
2851 */
2852 nasm_free(smac->name);
2853 free_tlist(smac->expansion);
2854 }
2855 }
2856 else
2857 {
2858 smac = nasm_malloc(sizeof(SMacro));
2859 smac->next = *smhead;
2860 *smhead = smac;
2861 }
2862 smac->name = nasm_strdup(mname);
2863 smac->casesense = (i == PP_STRLEN);
2864 smac->nparam = 0;
2865 smac->expansion = macro_start;
2866 smac->in_progress = FALSE;
2867 free_tlist(tline);
2868 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002869 return DIRECTIVE_FOUND;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002870
H. Peter Anvin734b1882002-04-30 21:01:08 +00002871 case PP_SUBSTR:
2872 tline = tline->next;
2873 skip_white_(tline);
2874 tline = expand_id(tline);
2875 if (!tline || (tline->type != TOK_ID &&
2876 (tline->type != TOK_PREPROC_ID ||
2877 tline->text[1] != '$')))
2878 {
2879 error(ERR_NONFATAL,
2880 "`%%substr' expects a macro identifier as first parameter");
2881 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002882 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002883 }
2884 ctx = get_ctx(tline->text, FALSE);
2885 if (!ctx)
2886 smhead = &smacros[hash(tline->text)];
2887 else
2888 smhead = &ctx->localmac;
2889 mname = tline->text;
2890 last = tline;
2891 tline = expand_smacro(tline->next);
2892 last->next = NULL;
2893
2894 t = tline->next;
2895 while (tok_type_(t, TOK_WHITESPACE))
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002896 t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002897
2898 /* t should now point to the string */
2899 if (t->type != TOK_STRING)
2900 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002901 error(ERR_NONFATAL,
2902 "`%%substr` requires string as second parameter");
2903 free_tlist(tline);
2904 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002905 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002906 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002907
H. Peter Anvin734b1882002-04-30 21:01:08 +00002908 tt = t->next;
2909 tptr = &tt;
2910 tokval.t_type = TOKEN_INVALID;
2911 evalresult =
2912 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2913 if (!evalresult)
2914 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002915 free_tlist(tline);
2916 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002917 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002918 }
2919 if (!is_simple(evalresult))
2920 {
2921 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002922 free_tlist(tline);
2923 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002924 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002925 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002926
H. Peter Anvin734b1882002-04-30 21:01:08 +00002927 macro_start = nasm_malloc(sizeof(*macro_start));
2928 macro_start->next = NULL;
2929 macro_start->text = nasm_strdup("'''");
2930 if (evalresult->value > 0
2931 && evalresult->value < strlen(t->text) - 1)
2932 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002933 macro_start->text[1] = t->text[evalresult->value];
H. Peter Anvin734b1882002-04-30 21:01:08 +00002934 }
2935 else
2936 {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002937 macro_start->text[2] = '\0';
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002938 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002939 macro_start->type = TOK_STRING;
2940 macro_start->mac = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002941
H. Peter Anvin734b1882002-04-30 21:01:08 +00002942 /*
2943 * We now have a macro name, an implicit parameter count of
2944 * zero, and a numeric token to use as an expansion. Create
2945 * and store an SMacro.
2946 */
2947 if (smacro_defined(ctx, mname, 0, &smac, i == PP_SUBSTR))
2948 {
2949 if (!smac)
2950 error(ERR_WARNING,
2951 "single-line macro `%s' defined both with and"
2952 " without parameters", mname);
2953 else
2954 {
2955 /*
2956 * We're redefining, so we have to take over an
2957 * existing SMacro structure. This means freeing
2958 * what was already in it.
2959 */
2960 nasm_free(smac->name);
2961 free_tlist(smac->expansion);
2962 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002963 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002964 else
2965 {
2966 smac = nasm_malloc(sizeof(SMacro));
2967 smac->next = *smhead;
2968 *smhead = smac;
2969 }
2970 smac->name = nasm_strdup(mname);
2971 smac->casesense = (i == PP_SUBSTR);
2972 smac->nparam = 0;
2973 smac->expansion = macro_start;
2974 smac->in_progress = FALSE;
2975 free_tlist(tline);
2976 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002977 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002978
2979
2980 case PP_ASSIGN:
2981 case PP_IASSIGN:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002982 tline = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002983 skip_white_(tline);
2984 tline = expand_id(tline);
2985 if (!tline || (tline->type != TOK_ID &&
2986 (tline->type != TOK_PREPROC_ID ||
2987 tline->text[1] != '$')))
2988 {
2989 error(ERR_NONFATAL,
2990 "`%%%sassign' expects a macro identifier",
2991 (i == PP_IASSIGN ? "i" : ""));
2992 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00002993 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002994 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002995 ctx = get_ctx(tline->text, FALSE);
2996 if (!ctx)
2997 smhead = &smacros[hash(tline->text)];
2998 else
2999 smhead = &ctx->localmac;
3000 mname = tline->text;
3001 last = tline;
3002 tline = expand_smacro(tline->next);
3003 last->next = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003004
H. Peter Anvin734b1882002-04-30 21:01:08 +00003005 t = tline;
3006 tptr = &t;
3007 tokval.t_type = TOKEN_INVALID;
3008 evalresult =
3009 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3010 free_tlist(tline);
3011 if (!evalresult)
3012 {
3013 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00003014 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003015 }
3016
3017 if (tokval.t_type)
3018 error(ERR_WARNING,
3019 "trailing garbage after expression ignored");
3020
3021 if (!is_simple(evalresult))
3022 {
3023 error(ERR_NONFATAL,
3024 "non-constant value given to `%%%sassign'",
3025 (i == PP_IASSIGN ? "i" : ""));
3026 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00003027 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003028 }
3029
3030 macro_start = nasm_malloc(sizeof(*macro_start));
3031 macro_start->next = NULL;
3032 make_tok_num(macro_start, reloc_value(evalresult));
3033 macro_start->mac = NULL;
3034
3035 /*
3036 * We now have a macro name, an implicit parameter count of
3037 * zero, and a numeric token to use as an expansion. Create
3038 * and store an SMacro.
3039 */
3040 if (smacro_defined(ctx, mname, 0, &smac, i == PP_ASSIGN))
3041 {
3042 if (!smac)
3043 error(ERR_WARNING,
3044 "single-line macro `%s' defined both with and"
3045 " without parameters", mname);
3046 else
3047 {
3048 /*
3049 * We're redefining, so we have to take over an
3050 * existing SMacro structure. This means freeing
3051 * what was already in it.
3052 */
3053 nasm_free(smac->name);
3054 free_tlist(smac->expansion);
3055 }
3056 }
3057 else
3058 {
3059 smac = nasm_malloc(sizeof(SMacro));
3060 smac->next = *smhead;
3061 *smhead = smac;
3062 }
3063 smac->name = nasm_strdup(mname);
3064 smac->casesense = (i == PP_ASSIGN);
3065 smac->nparam = 0;
3066 smac->expansion = macro_start;
3067 smac->in_progress = FALSE;
3068 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00003069 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003070
3071 case PP_LINE:
3072 /*
3073 * Syntax is `%line nnn[+mmm] [filename]'
3074 */
3075 tline = tline->next;
3076 skip_white_(tline);
3077 if (!tok_type_(tline, TOK_NUMBER))
3078 {
3079 error(ERR_NONFATAL, "`%%line' expects line number");
3080 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00003081 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003082 }
3083 k = readnum(tline->text, &j);
3084 m = 1;
3085 tline = tline->next;
3086 if (tok_is_(tline, "+"))
3087 {
3088 tline = tline->next;
3089 if (!tok_type_(tline, TOK_NUMBER))
3090 {
3091 error(ERR_NONFATAL, "`%%line' expects line increment");
3092 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00003093 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003094 }
3095 m = readnum(tline->text, &j);
3096 tline = tline->next;
3097 }
3098 skip_white_(tline);
3099 src_set_linnum(k);
3100 istk->lineinc = m;
3101 if (tline)
3102 {
3103 nasm_free(src_set_fname(detoken(tline, FALSE)));
3104 }
3105 free_tlist(origline);
Ed Beroset3ab3f412002-06-11 03:31:49 +00003106 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003107
3108 default:
3109 error(ERR_FATAL,
3110 "preprocessor directive `%s' not yet implemented",
3111 directives[i]);
3112 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003113 }
Ed Beroset3ab3f412002-06-11 03:31:49 +00003114 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003115}
3116
3117/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00003118 * Ensure that a macro parameter contains a condition code and
3119 * nothing else. Return the condition code index if so, or -1
3120 * otherwise.
3121 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003122static int
3123find_cc(Token * t)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003124{
H. Peter Anvin76690a12002-04-30 20:52:49 +00003125 Token *tt;
3126 int i, j, k, m;
3127
H. Peter Anvineba20a72002-04-30 20:53:55 +00003128 skip_white_(t);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003129 if (t->type != TOK_ID)
3130 return -1;
3131 tt = t->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003132 skip_white_(tt);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003133 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
3134 return -1;
3135
3136 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +00003137 j = elements(conditions);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003138 while (j - i > 1)
3139 {
3140 k = (j + i) / 2;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003141 m = nasm_stricmp(t->text, conditions[k]);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003142 if (m == 0)
3143 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00003144 i = k;
3145 j = -2;
3146 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003147 }
3148 else if (m < 0)
3149 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00003150 j = k;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003151 }
3152 else
H. Peter Anvin76690a12002-04-30 20:52:49 +00003153 i = k;
3154 }
3155 if (j != -2)
3156 return -1;
3157 return i;
3158}
3159
3160/*
3161 * Expand MMacro-local things: parameter references (%0, %n, %+n,
3162 * %-n) and MMacro-local identifiers (%%foo).
3163 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003164static Token *
3165expand_mmac_params(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003166{
H. Peter Anvin734b1882002-04-30 21:01:08 +00003167 Token *t, *tt, **tail, *thead;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003168
3169 tail = &thead;
3170 thead = NULL;
3171
H. Peter Anvin734b1882002-04-30 21:01:08 +00003172 while (tline)
3173 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00003174 if (tline->type == TOK_PREPROC_ID &&
H. Peter Anvin734b1882002-04-30 21:01:08 +00003175 (((tline->text[1] == '+' || tline->text[1] == '-')
3176 && tline->text[2]) || tline->text[1] == '%'
3177 || (tline->text[1] >= '0' && tline->text[1] <= '9')))
3178 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00003179 char *text = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003180 int type = 0, cc; /* type = 0 to placate optimisers */
H. Peter Anvin76690a12002-04-30 20:52:49 +00003181 char tmpbuf[30];
3182 int n, i;
3183 MMacro *mac;
3184
3185 t = tline;
3186 tline = tline->next;
3187
3188 mac = istk->mstk;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003189 while (mac && !mac->name) /* avoid mistaking %reps for macros */
H. Peter Anvin76690a12002-04-30 20:52:49 +00003190 mac = mac->next_active;
3191 if (!mac)
3192 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003193 else
3194 switch (t->text[1])
3195 {
3196 /*
3197 * We have to make a substitution of one of the
3198 * forms %1, %-1, %+1, %%foo, %0.
3199 */
3200 case '0':
3201 type = TOK_NUMBER;
3202 sprintf(tmpbuf, "%d", mac->nparam);
3203 text = nasm_strdup(tmpbuf);
3204 break;
3205 case '%':
3206 type = TOK_ID;
3207 sprintf(tmpbuf, "..@%lu.", mac->unique);
3208 text = nasm_strcat(tmpbuf, t->text + 2);
3209 break;
3210 case '-':
3211 n = atoi(t->text + 2) - 1;
3212 if (n >= mac->nparam)
3213 tt = NULL;
3214 else
3215 {
3216 if (mac->nparam > 1)
3217 n = (n + mac->rotate) % mac->nparam;
3218 tt = mac->params[n];
3219 }
3220 cc = find_cc(tt);
3221 if (cc == -1)
3222 {
3223 error(ERR_NONFATAL,
3224 "macro parameter %d is not a condition code",
3225 n + 1);
3226 text = NULL;
3227 }
3228 else
3229 {
3230 type = TOK_ID;
3231 if (inverse_ccs[cc] == -1)
3232 {
3233 error(ERR_NONFATAL,
3234 "condition code `%s' is not invertible",
3235 conditions[cc]);
3236 text = NULL;
3237 }
3238 else
3239 text =
3240 nasm_strdup(conditions[inverse_ccs
3241 [cc]]);
3242 }
3243 break;
3244 case '+':
3245 n = atoi(t->text + 2) - 1;
3246 if (n >= mac->nparam)
3247 tt = NULL;
3248 else
3249 {
3250 if (mac->nparam > 1)
3251 n = (n + mac->rotate) % mac->nparam;
3252 tt = mac->params[n];
3253 }
3254 cc = find_cc(tt);
3255 if (cc == -1)
3256 {
3257 error(ERR_NONFATAL,
3258 "macro parameter %d is not a condition code",
3259 n + 1);
3260 text = NULL;
3261 }
3262 else
3263 {
3264 type = TOK_ID;
3265 text = nasm_strdup(conditions[cc]);
3266 }
3267 break;
3268 default:
3269 n = atoi(t->text + 1) - 1;
3270 if (n >= mac->nparam)
3271 tt = NULL;
3272 else
3273 {
3274 if (mac->nparam > 1)
3275 n = (n + mac->rotate) % mac->nparam;
3276 tt = mac->params[n];
3277 }
3278 if (tt)
3279 {
3280 for (i = 0; i < mac->paramlen[n]; i++)
3281 {
3282 *tail =
3283 new_Token(NULL, tt->type, tt->text,
3284 0);
3285 tail = &(*tail)->next;
3286 tt = tt->next;
3287 }
3288 }
3289 text = NULL; /* we've done it here */
3290 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003291 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003292 if (!text)
3293 {
3294 delete_Token(t);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003295 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003296 else
3297 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003298 *tail = t;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003299 tail = &t->next;
3300 t->type = type;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003301 nasm_free(t->text);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003302 t->text = text;
3303 t->mac = NULL;
3304 }
3305 continue;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003306 }
3307 else
3308 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00003309 t = *tail = tline;
3310 tline = tline->next;
3311 t->mac = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003312 tail = &t->next;
3313 }
3314 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00003315 *tail = NULL;
3316 t = thead;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003317 for (; t && (tt = t->next) != NULL; t = t->next)
3318 switch (t->type)
3319 {
3320 case TOK_WHITESPACE:
3321 if (tt->type == TOK_WHITESPACE)
3322 {
3323 t->next = delete_Token(tt);
3324 }
3325 break;
3326 case TOK_ID:
3327 if (tt->type == TOK_ID || tt->type == TOK_NUMBER)
3328 {
3329 char *tmp = nasm_strcat(t->text, tt->text);
3330 nasm_free(t->text);
3331 t->text = tmp;
3332 t->next = delete_Token(tt);
3333 }
3334 break;
3335 case TOK_NUMBER:
3336 if (tt->type == TOK_NUMBER)
3337 {
3338 char *tmp = nasm_strcat(t->text, tt->text);
3339 nasm_free(t->text);
3340 t->text = tmp;
3341 t->next = delete_Token(tt);
3342 }
3343 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003344 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003345
H. Peter Anvin76690a12002-04-30 20:52:49 +00003346 return thead;
3347}
3348
3349/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003350 * Expand all single-line macro calls made in the given line.
3351 * Return the expanded version of the line. The original is deemed
3352 * to be destroyed in the process. (In reality we'll just move
3353 * Tokens from input to output a lot of the time, rather than
3354 * actually bothering to destroy and replicate.)
3355 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003356static Token *
3357expand_smacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003358{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003359 Token *t, *tt, *mstart, **tail, *thead;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003360 SMacro *head = NULL, *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003361 Token **params;
3362 int *paramsize;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003363 int nparam, sparam, brackets, rescan;
3364 Token *org_tline = tline;
3365 Context *ctx;
3366 char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003367
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003368 /*
3369 * Trick: we should avoid changing the start token pointer since it can
3370 * be contained in "next" field of other token. Because of this
3371 * we allocate a copy of first token and work with it; at the end of
3372 * routine we copy it back
3373 */
3374 if (org_tline)
3375 {
H. Peter Anvin734b1882002-04-30 21:01:08 +00003376 tline =
3377 new_Token(org_tline->next, org_tline->type, org_tline->text,
3378 0);
3379 tline->mac = org_tline->mac;
H. Peter Anvince616072002-04-30 21:02:23 +00003380 nasm_free(org_tline->text);
3381 org_tline->text = NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003382 }
3383
H. Peter Anvin734b1882002-04-30 21:01:08 +00003384 again:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003385 tail = &thead;
3386 thead = NULL;
3387
H. Peter Anvin734b1882002-04-30 21:01:08 +00003388 while (tline)
3389 { /* main token loop */
3390 if ((mname = tline->text))
3391 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003392 /* if this token is a local macro, look in local context */
3393 if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
H. Peter Anvin734b1882002-04-30 21:01:08 +00003394 ctx = get_ctx(mname, TRUE);
3395 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003396 ctx = NULL;
3397 if (!ctx)
3398 head = smacros[hash(mname)];
3399 else
H. Peter Anvineba20a72002-04-30 20:53:55 +00003400 head = ctx->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003401 /*
3402 * We've hit an identifier. As in is_mmacro below, we first
3403 * check whether the identifier is a single-line macro at
3404 * all, then think about checking for parameters if
3405 * necessary.
3406 */
H. Peter Anvineba20a72002-04-30 20:53:55 +00003407 for (m = head; m; m = m->next)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003408 if (!mstrcmp(m->name, mname, m->casesense))
H. Peter Anvineba20a72002-04-30 20:53:55 +00003409 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003410 if (m)
3411 {
3412 mstart = tline;
3413 params = NULL;
3414 paramsize = NULL;
3415 if (m->nparam == 0)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003416 {
H. Peter Anvin734b1882002-04-30 21:01:08 +00003417 /*
3418 * Simple case: the macro is parameterless. Discard the
3419 * one token that the macro call took, and push the
3420 * expansion back on the to-do stack.
3421 */
3422 if (!m->expansion)
3423 {
3424 if (!strcmp("__FILE__", m->name))
3425 {
3426 long num = 0;
3427 src_get(&num, &(tline->text));
3428 nasm_quote(&(tline->text));
3429 tline->type = TOK_STRING;
3430 continue;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003431 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003432 if (!strcmp("__LINE__", m->name))
3433 {
3434 nasm_free(tline->text);
3435 make_tok_num(tline, src_get_linnum());
3436 continue;
3437 }
3438 tline = delete_Token(tline);
3439 continue;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003440 }
3441 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003442 else
3443 {
3444 /*
3445 * Complicated case: at least one macro with this name
3446 * exists and takes parameters. We must find the
3447 * parameters in the call, count them, find the SMacro
3448 * that corresponds to that form of the macro call, and
3449 * substitute for the parameters when we expand. What a
3450 * pain.
3451 */
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00003452 /*tline = tline->next;
3453 skip_white_(tline);*/
3454 do {
3455 t = tline->next;
3456 while (tok_type_(t, TOK_SMAC_END))
3457 {
3458 t->mac->in_progress = FALSE;
3459 t->text = NULL;
3460 t = tline->next = delete_Token(t);
3461 }
3462 tline = t;
3463 } while (tok_type_(tline, TOK_WHITESPACE));
H. Peter Anvin734b1882002-04-30 21:01:08 +00003464 if (!tok_is_(tline, "("))
3465 {
3466 /*
3467 * This macro wasn't called with parameters: ignore
3468 * the call. (Behaviour borrowed from gnu cpp.)
3469 */
3470 tline = mstart;
3471 m = NULL;
3472 }
3473 else
3474 {
3475 int paren = 0;
3476 int white = 0;
3477 brackets = 0;
3478 nparam = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003479 sparam = PARAM_DELTA;
3480 params = nasm_malloc(sparam * sizeof(Token *));
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00003481 params[0] = tline->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003482 paramsize = nasm_malloc(sparam * sizeof(int));
3483 paramsize[0] = 0;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00003484 while (TRUE)
H. Peter Anvin734b1882002-04-30 21:01:08 +00003485 { /* parameter loop */
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00003486 /*
3487 * For some unusual expansions
3488 * which concatenates function call
3489 */
3490 t = tline->next;
3491 while (tok_type_(t, TOK_SMAC_END))
3492 {
3493 t->mac->in_progress = FALSE;
3494 t->text = NULL;
3495 t = tline->next = delete_Token(t);
3496 }
3497 tline = t;
3498
H. Peter Anvin734b1882002-04-30 21:01:08 +00003499 if (!tline)
3500 {
3501 error(ERR_NONFATAL,
3502 "macro call expects terminating `)'");
3503 break;
3504 }
3505 if (tline->type == TOK_WHITESPACE
3506 && brackets <= 0)
3507 {
3508 if (paramsize[nparam])
3509 white++;
3510 else
3511 params[nparam] = tline->next;
3512 continue; /* parameter loop */
3513 }
3514 if (tline->type == TOK_OTHER
3515 && tline->text[1] == 0)
3516 {
3517 char ch = tline->text[0];
3518 if (ch == ',' && !paren && brackets <= 0)
3519 {
3520 if (++nparam >= sparam)
3521 {
3522 sparam += PARAM_DELTA;
3523 params = nasm_realloc(params,
3524 sparam * sizeof(Token *));
3525 paramsize = nasm_realloc(paramsize,
3526 sparam * sizeof(int));
3527 }
3528 params[nparam] = tline->next;
3529 paramsize[nparam] = 0;
3530 white = 0;
3531 continue; /* parameter loop */
3532 }
3533 if (ch == '{' &&
3534 (brackets > 0 || (brackets == 0 &&
3535 !paramsize[nparam])))
3536 {
3537 if (!(brackets++))
3538 {
3539 params[nparam] = tline->next;
3540 continue; /* parameter loop */
3541 }
3542 }
3543 if (ch == '}' && brackets > 0)
3544 if (--brackets == 0)
3545 {
3546 brackets = -1;
3547 continue; /* parameter loop */
3548 }
3549 if (ch == '(' && !brackets)
3550 paren++;
3551 if (ch == ')' && brackets <= 0)
3552 if (--paren < 0)
3553 break;
3554 }
3555 if (brackets < 0)
3556 {
3557 brackets = 0;
3558 error(ERR_NONFATAL, "braces do not "
3559 "enclose all of macro parameter");
3560 }
3561 paramsize[nparam] += white + 1;
3562 white = 0;
3563 } /* parameter loop */
3564 nparam++;
3565 while (m && (m->nparam != nparam ||
3566 mstrcmp(m->name, mname,
3567 m->casesense)))
3568 m = m->next;
3569 if (!m)
3570 error(ERR_WARNING | ERR_WARN_MNP,
3571 "macro `%s' exists, "
3572 "but not taking %d parameters",
3573 mstart->text, nparam);
3574 }
3575 }
3576 if (m && m->in_progress)
3577 m = NULL;
3578 if (!m) /* in progess or didn't find '(' or wrong nparam */
3579 {
3580 /*
3581 * Design question: should we handle !tline, which
3582 * indicates missing ')' here, or expand those
3583 * macros anyway, which requires the (t) test a few
3584 * lines down?
3585 */
3586 nasm_free(params);
3587 nasm_free(paramsize);
3588 tline = mstart;
3589 }
3590 else
3591 {
3592 /*
3593 * Expand the macro: we are placed on the last token of the
3594 * call, so that we can easily split the call from the
3595 * following tokens. We also start by pushing an SMAC_END
3596 * token for the cycle removal.
3597 */
3598 t = tline;
3599 if (t)
3600 {
3601 tline = t->next;
3602 t->next = NULL;
3603 }
3604 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
3605 tt->mac = m;
3606 m->in_progress = TRUE;
3607 tline = tt;
3608 for (t = m->expansion; t; t = t->next)
3609 {
3610 if (t->type >= TOK_SMAC_PARAM)
3611 {
3612 Token *pcopy = tline, **ptail = &pcopy;
3613 Token *ttt, *pt;
3614 int i;
3615
3616 ttt = params[t->type - TOK_SMAC_PARAM];
3617 for (i = paramsize[t->type - TOK_SMAC_PARAM];
3618 --i >= 0;)
3619 {
3620 pt = *ptail =
3621 new_Token(tline, ttt->type, ttt->text,
3622 0);
3623 ptail = &pt->next;
3624 ttt = ttt->next;
3625 }
3626 tline = pcopy;
3627 }
3628 else
3629 {
3630 tt = new_Token(tline, t->type, t->text, 0);
3631 tline = tt;
3632 }
3633 }
3634
3635 /*
3636 * Having done that, get rid of the macro call, and clean
3637 * up the parameters.
3638 */
3639 nasm_free(params);
3640 nasm_free(paramsize);
3641 free_tlist(mstart);
3642 continue; /* main token loop */
3643 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003644 }
3645 }
3646
H. Peter Anvin734b1882002-04-30 21:01:08 +00003647 if (tline->type == TOK_SMAC_END)
3648 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003649 tline->mac->in_progress = FALSE;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003650 tline = delete_Token(tline);
3651 }
3652 else
3653 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003654 t = *tail = tline;
3655 tline = tline->next;
3656 t->mac = NULL;
3657 t->next = NULL;
3658 tail = &t->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003659 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003660 }
3661
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003662 /*
3663 * Now scan the entire line and look for successive TOK_IDs that resulted
3664 * after expansion (they can't be produced by tokenise()). The successive
3665 * TOK_IDs should be concatenated.
3666 * Also we look for %+ tokens and concatenate the tokens before and after
3667 * them (without white spaces in between).
3668 */
3669 t = thead;
3670 rescan = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003671 while (t)
3672 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003673 while (t && t->type != TOK_ID && t->type != TOK_PREPROC_ID)
3674 t = t->next;
3675 if (!t || !t->next)
3676 break;
3677 if (t->next->type == TOK_ID ||
H. Peter Anvin734b1882002-04-30 21:01:08 +00003678 t->next->type == TOK_PREPROC_ID ||
3679 t->next->type == TOK_NUMBER)
3680 {
3681 char *p = nasm_strcat(t->text, t->next->text);
3682 nasm_free(t->text);
3683 t->next = delete_Token(t->next);
3684 t->text = p;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003685 rescan = 1;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003686 }
3687 else if (t->next->type == TOK_WHITESPACE && t->next->next &&
3688 t->next->next->type == TOK_PREPROC_ID &&
3689 strcmp(t->next->next->text, "%+") == 0)
3690 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003691 /* free the next whitespace, the %+ token and next whitespace */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003692 int i;
3693 for (i = 1; i <= 3; i++)
3694 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003695 if (!t->next || (i != 2 && t->next->type != TOK_WHITESPACE))
3696 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003697 t->next = delete_Token(t->next);
3698 } /* endfor */
3699 }
3700 else
3701 t = t->next;
3702 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003703 /* If we concatenaded something, re-scan the line for macros */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003704 if (rescan)
3705 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003706 tline = thead;
3707 goto again;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003708 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003709
3710 if (org_tline)
3711 {
H. Peter Anvin734b1882002-04-30 21:01:08 +00003712 if (thead)
3713 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003714 *org_tline = *thead;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003715 /* since we just gave text to org_line, don't free it */
3716 thead->text = NULL;
3717 delete_Token(thead);
3718 }
3719 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003720 {
3721 /* the expression expanded to empty line;
3722 we can't return NULL for some reasons
3723 we just set the line to a single WHITESPACE token. */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003724 memset(org_tline, 0, sizeof(*org_tline));
3725 org_tline->text = NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003726 org_tline->type = TOK_WHITESPACE;
3727 }
3728 thead = org_tline;
3729 }
3730
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003731 return thead;
3732}
3733
3734/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003735 * Similar to expand_smacro but used exclusively with macro identifiers
3736 * right before they are fetched in. The reason is that there can be
3737 * identifiers consisting of several subparts. We consider that if there
3738 * are more than one element forming the name, user wants a expansion,
3739 * otherwise it will be left as-is. Example:
3740 *
3741 * %define %$abc cde
3742 *
3743 * the identifier %$abc will be left as-is so that the handler for %define
3744 * will suck it and define the corresponding value. Other case:
3745 *
3746 * %define _%$abc cde
3747 *
3748 * In this case user wants name to be expanded *before* %define starts
3749 * working, so we'll expand %$abc into something (if it has a value;
3750 * otherwise it will be left as-is) then concatenate all successive
3751 * PP_IDs into one.
3752 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003753static Token *
3754expand_id(Token * tline)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003755{
3756 Token *cur, *oldnext = NULL;
3757
H. Peter Anvin734b1882002-04-30 21:01:08 +00003758 if (!tline || !tline->next)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003759 return tline;
3760
3761 cur = tline;
3762 while (cur->next &&
H. Peter Anvin734b1882002-04-30 21:01:08 +00003763 (cur->next->type == TOK_ID ||
3764 cur->next->type == TOK_PREPROC_ID || cur->next->type == TOK_NUMBER))
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003765 cur = cur->next;
3766
3767 /* If identifier consists of just one token, don't expand */
3768 if (cur == tline)
3769 return tline;
3770
H. Peter Anvin734b1882002-04-30 21:01:08 +00003771 if (cur)
3772 {
3773 oldnext = cur->next; /* Detach the tail past identifier */
3774 cur->next = NULL; /* so that expand_smacro stops here */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003775 }
3776
H. Peter Anvin734b1882002-04-30 21:01:08 +00003777 tline = expand_smacro(tline);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003778
H. Peter Anvin734b1882002-04-30 21:01:08 +00003779 if (cur)
3780 {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003781 /* expand_smacro possibly changhed tline; re-scan for EOL */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003782 cur = tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003783 while (cur && cur->next)
3784 cur = cur->next;
3785 if (cur)
3786 cur->next = oldnext;
3787 }
3788
3789 return tline;
3790}
3791
3792/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003793 * Determine whether the given line constitutes a multi-line macro
3794 * call, and return the MMacro structure called if so. Doesn't have
3795 * to check for an initial label - that's taken care of in
3796 * expand_mmacro - but must check numbers of parameters. Guaranteed
3797 * to be called with tline->type == TOK_ID, so the putative macro
3798 * name is easy to find.
3799 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003800static MMacro *
3801is_mmacro(Token * tline, Token *** params_array)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003802{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003803 MMacro *head, *m;
3804 Token **params;
3805 int nparam;
3806
3807 head = mmacros[hash(tline->text)];
3808
3809 /*
3810 * Efficiency: first we see if any macro exists with the given
3811 * name. If not, we can return NULL immediately. _Then_ we
3812 * count the parameters, and then we look further along the
3813 * list if necessary to find the proper MMacro.
3814 */
3815 for (m = head; m; m = m->next)
3816 if (!mstrcmp(m->name, tline->text, m->casesense))
3817 break;
3818 if (!m)
3819 return NULL;
3820
3821 /*
3822 * OK, we have a potential macro. Count and demarcate the
3823 * parameters.
3824 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003825 count_mmac_params(tline->next, &nparam, &params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003826
3827 /*
3828 * So we know how many parameters we've got. Find the MMacro
3829 * structure that handles this number.
3830 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003831 while (m)
3832 {
3833 if (m->nparam_min <= nparam && (m->plus || nparam <= m->nparam_max))
3834 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003835 /*
3836 * This one is right. Just check if cycle removal
3837 * prohibits us using it before we actually celebrate...
3838 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003839 if (m->in_progress)
3840 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003841#if 0
H. Peter Anvin734b1882002-04-30 21:01:08 +00003842 error(ERR_NONFATAL,
3843 "self-reference in multi-line macro `%s'", m->name);
H. Peter Anvineba20a72002-04-30 20:53:55 +00003844#endif
H. Peter Anvin734b1882002-04-30 21:01:08 +00003845 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003846 return NULL;
3847 }
3848 /*
3849 * It's right, and we can use it. Add its default
3850 * parameters to the end of our list if necessary.
3851 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003852 if (m->defaults && nparam < m->nparam_min + m->ndefs)
3853 {
3854 params =
3855 nasm_realloc(params,
3856 ((m->nparam_min + m->ndefs + 1) * sizeof(*params)));
3857 while (nparam < m->nparam_min + m->ndefs)
3858 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003859 params[nparam] = m->defaults[nparam - m->nparam_min];
3860 nparam++;
3861 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003862 }
3863 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00003864 * If we've gone over the maximum parameter count (and
3865 * we're in Plus mode), ignore parameters beyond
3866 * nparam_max.
3867 */
3868 if (m->plus && nparam > m->nparam_max)
3869 nparam = m->nparam_max;
3870 /*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003871 * Then terminate the parameter list, and leave.
3872 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003873 if (!params)
3874 { /* need this special case */
H. Peter Anvin76690a12002-04-30 20:52:49 +00003875 params = nasm_malloc(sizeof(*params));
3876 nparam = 0;
3877 }
3878 params[nparam] = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003879 *params_array = params;
3880 return m;
3881 }
3882 /*
3883 * This one wasn't right: look for the next one with the
3884 * same name.
3885 */
3886 for (m = m->next; m; m = m->next)
3887 if (!mstrcmp(m->name, tline->text, m->casesense))
3888 break;
3889 }
3890
3891 /*
3892 * After all that, we didn't find one with the right number of
3893 * parameters. Issue a warning, and fail to expand the macro.
3894 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003895 error(ERR_WARNING | ERR_WARN_MNP,
3896 "macro `%s' exists, but not taking %d parameters",
3897 tline->text, nparam);
3898 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003899 return NULL;
3900}
3901
3902/*
3903 * Expand the multi-line macro call made by the given line, if
3904 * there is one to be expanded. If there is, push the expansion on
H. Peter Anvineba20a72002-04-30 20:53:55 +00003905 * istk->expansion and return 1. Otherwise return 0.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003906 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003907static int
3908expand_mmacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003909{
3910 Token *startline = tline;
3911 Token *label = NULL;
3912 int dont_prepend = 0;
3913 Token **params, *t, *tt;
3914 MMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003915 Line *l, *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003916 int i, nparam, *paramlen;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003917
3918 t = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003919 skip_white_(t);
H. Peter Anvindce1e2f2002-04-30 21:06:37 +00003920/* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
3921 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003922 return 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003923 m = is_mmacro(t, &params);
3924 if (!m)
3925 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003926 Token *last;
3927 /*
3928 * We have an id which isn't a macro call. We'll assume
3929 * it might be a label; we'll also check to see if a
3930 * colon follows it. Then, if there's another id after
3931 * that lot, we'll check it again for macro-hood.
3932 */
3933 label = last = t;
3934 t = t->next;
3935 if (tok_type_(t, TOK_WHITESPACE))
3936 last = t, t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003937 if (tok_is_(t, ":"))
3938 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003939 dont_prepend = 1;
3940 last = t, t = t->next;
3941 if (tok_type_(t, TOK_WHITESPACE))
3942 last = t, t = t->next;
3943 }
3944 if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
3945 return 0;
3946 last->next = NULL;
3947 tline = t;
3948 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003949
3950 /*
3951 * Fix up the parameters: this involves stripping leading and
3952 * trailing whitespace, then stripping braces if they are
3953 * present.
3954 */
H. Peter Anvineba20a72002-04-30 20:53:55 +00003955 for (nparam = 0; params[nparam]; nparam++)
3956 ;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003957 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003958
H. Peter Anvin734b1882002-04-30 21:01:08 +00003959 for (i = 0; params[i]; i++)
3960 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003961 int brace = FALSE;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003962 int comma = (!m->plus || i < nparam - 1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003963
3964 t = params[i];
H. Peter Anvineba20a72002-04-30 20:53:55 +00003965 skip_white_(t);
3966 if (tok_is_(t, "{"))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003967 t = t->next, brace = TRUE, comma = FALSE;
3968 params[i] = t;
3969 paramlen[i] = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003970 while (t)
3971 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003972 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
H. Peter Anvin734b1882002-04-30 21:01:08 +00003973 break; /* ... because we have hit a comma */
H. Peter Anvineba20a72002-04-30 20:53:55 +00003974 if (comma && t->type == TOK_WHITESPACE && tok_is_(t->next, ","))
H. Peter Anvin734b1882002-04-30 21:01:08 +00003975 break; /* ... or a space then a comma */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003976 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
H. Peter Anvin734b1882002-04-30 21:01:08 +00003977 break; /* ... or a brace */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003978 t = t->next;
3979 paramlen[i]++;
3980 }
3981 }
3982
3983 /*
3984 * OK, we have a MMacro structure together with a set of
3985 * parameters. We must now go through the expansion and push
H. Peter Anvin76690a12002-04-30 20:52:49 +00003986 * copies of each Line on to istk->expansion. Substitution of
3987 * parameter tokens and macro-local tokens doesn't get done
3988 * until the single-line macro substitution process; this is
3989 * because delaying them allows us to change the semantics
3990 * later through %rotate.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003991 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00003992 * First, push an end marker on to istk->expansion, mark this
3993 * macro as in progress, and set up its invocation-specific
3994 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003995 */
3996 ll = nasm_malloc(sizeof(Line));
3997 ll->next = istk->expansion;
3998 ll->finishes = m;
3999 ll->first = NULL;
4000 istk->expansion = ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004001
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004002 m->in_progress = TRUE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004003 m->params = params;
4004 m->iline = tline;
4005 m->nparam = nparam;
4006 m->rotate = 0;
4007 m->paramlen = paramlen;
4008 m->unique = unique++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004009 m->lineno = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004010
4011 m->next_active = istk->mstk;
4012 istk->mstk = m;
4013
H. Peter Anvin734b1882002-04-30 21:01:08 +00004014 for (l = m->expansion; l; l = l->next)
4015 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004016 Token **tail;
4017
4018 ll = nasm_malloc(sizeof(Line));
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004019 ll->finishes = NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004020 ll->next = istk->expansion;
4021 istk->expansion = ll;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004022 tail = &ll->first;
4023
H. Peter Anvin734b1882002-04-30 21:01:08 +00004024 for (t = l->first; t; t = t->next)
4025 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00004026 Token *x = t;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004027 if (t->type == TOK_PREPROC_ID &&
4028 t->text[1] == '0' && t->text[2] == '0')
H. Peter Anvineba20a72002-04-30 20:53:55 +00004029 {
4030 dont_prepend = -1;
4031 x = label;
4032 if (!x)
4033 continue;
4034 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004035 tt = *tail = new_Token(NULL, x->type, x->text, 0);
H. Peter Anvin76690a12002-04-30 20:52:49 +00004036 tail = &tt->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004037 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00004038 *tail = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004039 }
4040
4041 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +00004042 * If we had a label, push it on as the first line of
4043 * the macro expansion.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004044 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00004045 if (label)
4046 {
4047 if (dont_prepend < 0)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004048 free_tlist(startline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004049 else
4050 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00004051 ll = nasm_malloc(sizeof(Line));
4052 ll->finishes = NULL;
4053 ll->next = istk->expansion;
4054 istk->expansion = ll;
4055 ll->first = startline;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004056 if (!dont_prepend)
4057 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00004058 while (label->next)
4059 label = label->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004060 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004061 }
H. Peter Anvin87bc6192002-04-30 20:53:16 +00004062 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004063 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004064
H. Peter Anvin734b1882002-04-30 21:01:08 +00004065 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004066
H. Peter Anvineba20a72002-04-30 20:53:55 +00004067 return 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004068}
4069
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004070/*
4071 * Since preprocessor always operate only on the line that didn't
4072 * arrived yet, we should always use ERR_OFFBY1. Also since user
4073 * won't want to see same error twice (preprocessing is done once
4074 * per pass) we will want to show errors only during pass one.
4075 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00004076static void
Ed Beroset168c9c02002-05-17 03:10:13 +00004077error(int severity, const char *fmt, ...)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004078{
4079 va_list arg;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004080 char buff[1024];
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004081
4082 /* If we're in a dead branch of IF or something like it, ignore the error */
H. Peter Anvin77ba0c62002-05-14 03:18:53 +00004083 if (istk && istk->conds && !emitting(istk->conds->state))
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004084 return;
4085
H. Peter Anvin734b1882002-04-30 21:01:08 +00004086 va_start(arg, fmt);
4087 vsprintf(buff, fmt, arg);
4088 va_end(arg);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004089
H. Peter Anvin77ba0c62002-05-14 03:18:53 +00004090 if (istk && istk->mstk && istk->mstk->name)
H. Peter Anvin99941bf2002-05-14 17:44:03 +00004091 _error(severity | ERR_PASS1, "(%s:%d) %s", istk->mstk->name,
H. Peter Anvin734b1882002-04-30 21:01:08 +00004092 istk->mstk->lineno, buff);
Ed Beroset168c9c02002-05-17 03:10:13 +00004093 else
H. Peter Anvin99941bf2002-05-14 17:44:03 +00004094 _error(severity | ERR_PASS1, "%s", buff);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004095}
4096
H. Peter Anvin734b1882002-04-30 21:01:08 +00004097static void
4098pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
4099 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004100{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004101 int h;
4102
H. Peter Anvin99941bf2002-05-14 17:44:03 +00004103 _error = errfunc;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004104 cstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004105 istk = nasm_malloc(sizeof(Include));
4106 istk->next = NULL;
4107 istk->conds = NULL;
4108 istk->expansion = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004109 istk->mstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004110 istk->fp = fopen(file, "r");
H. Peter Anvineba20a72002-04-30 20:53:55 +00004111 istk->fname = NULL;
4112 src_set_fname(nasm_strdup(file));
4113 src_set_linnum(0);
4114 istk->lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004115 if (!istk->fp)
H. Peter Anvin734b1882002-04-30 21:01:08 +00004116 error(ERR_FATAL | ERR_NOFILE, "unable to open input file `%s'", file);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004117 defining = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004118 for (h = 0; h < NHASH; h++)
4119 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004120 mmacros[h] = NULL;
4121 smacros[h] = NULL;
4122 }
4123 unique = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004124 if (tasm_compatible_mode) {
4125 stdmacpos = stdmac;
4126 } else {
4127 stdmacpos = &stdmac[TASM_MACRO_COUNT];
4128 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00004129 any_extrastdmac = (extrastdmac != NULL);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004130 list = listgen;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004131 evaluate = eval;
4132 pass = apass;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004133}
4134
H. Peter Anvin734b1882002-04-30 21:01:08 +00004135static char *
4136pp_getline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004137{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004138 char *line;
4139 Token *tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004140
H. Peter Anvin734b1882002-04-30 21:01:08 +00004141 while (1)
4142 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004143 /*
4144 * Fetch a tokenised line, either from the macro-expansion
4145 * buffer or from the input file.
4146 */
4147 tline = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004148 while (istk->expansion && istk->expansion->finishes)
4149 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004150 Line *l = istk->expansion;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004151 if (!l->finishes->name && l->finishes->in_progress > 1)
4152 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00004153 Line *ll;
4154
4155 /*
4156 * This is a macro-end marker for a macro with no
4157 * name, which means it's not really a macro at all
4158 * but a %rep block, and the `in_progress' field is
4159 * more than 1, meaning that we still need to
4160 * repeat. (1 means the natural last repetition; 0
4161 * means termination by %exitrep.) We have
4162 * therefore expanded up to the %endrep, and must
4163 * push the whole block on to the expansion buffer
4164 * again. We don't bother to remove the macro-end
4165 * marker: we'd only have to generate another one
4166 * if we did.
4167 */
4168 l->finishes->in_progress--;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004169 for (l = l->finishes->expansion; l; l = l->next)
4170 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00004171 Token *t, *tt, **tail;
4172
4173 ll = nasm_malloc(sizeof(Line));
4174 ll->next = istk->expansion;
4175 ll->finishes = NULL;
4176 ll->first = NULL;
4177 tail = &ll->first;
4178
H. Peter Anvin734b1882002-04-30 21:01:08 +00004179 for (t = l->first; t; t = t->next)
4180 {
4181 if (t->text || t->type == TOK_WHITESPACE)
4182 {
4183 tt = *tail = new_Token(NULL, t->type, t->text, 0);
H. Peter Anvin76690a12002-04-30 20:52:49 +00004184 tail = &tt->next;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004185 }
4186 }
4187
4188 istk->expansion = ll;
4189 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004190 }
4191 else
4192 {
H. Peter Anvin87bc6192002-04-30 20:53:16 +00004193 /*
4194 * Check whether a `%rep' was started and not ended
4195 * within this macro expansion. This can happen and
4196 * should be detected. It's a fatal error because
4197 * I'm too confused to work out how to recover
4198 * sensibly from it.
4199 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00004200 if (defining)
4201 {
H. Peter Anvin87bc6192002-04-30 20:53:16 +00004202 if (defining->name)
H. Peter Anvin734b1882002-04-30 21:01:08 +00004203 error(ERR_PANIC, "defining with name in expansion");
H. Peter Anvinb64535f2002-04-30 20:55:37 +00004204 else if (istk->mstk->name)
H. Peter Anvin734b1882002-04-30 21:01:08 +00004205 error(ERR_FATAL, "`%%rep' without `%%endrep' within"
4206 " expansion of macro `%s'", istk->mstk->name);
H. Peter Anvin87bc6192002-04-30 20:53:16 +00004207 }
4208
H. Peter Anvin734b1882002-04-30 21:01:08 +00004209 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +00004210 * FIXME: investigate the relationship at this point between
4211 * istk->mstk and l->finishes
4212 */
4213 {
4214 MMacro *m = istk->mstk;
4215 istk->mstk = m->next_active;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004216 if (m->name)
4217 {
H. Peter Anvineba20a72002-04-30 20:53:55 +00004218 /*
4219 * This was a real macro call, not a %rep, and
4220 * therefore the parameter information needs to
4221 * be freed.
4222 */
4223 nasm_free(m->params);
4224 free_tlist(m->iline);
4225 nasm_free(m->paramlen);
4226 l->finishes->in_progress = FALSE;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004227 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00004228 else
4229 free_mmacro(m);
H. Peter Anvin76690a12002-04-30 20:52:49 +00004230 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00004231 istk->expansion = l->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004232 nasm_free(l);
4233 list->downlevel(LIST_MACRO);
H. Peter Anvin76690a12002-04-30 20:52:49 +00004234 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004235 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004236 while (1)
4237 { /* until we get a line we can use */
H. Peter Anvineba20a72002-04-30 20:53:55 +00004238
H. Peter Anvin734b1882002-04-30 21:01:08 +00004239 if (istk->expansion)
4240 { /* from a macro expansion */
H. Peter Anvineba20a72002-04-30 20:53:55 +00004241 char *p;
4242 Line *l = istk->expansion;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004243 if (istk->mstk)
4244 istk->mstk->lineno++;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004245 tline = l->first;
4246 istk->expansion = l->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004247 nasm_free(l);
4248 p = detoken(tline, FALSE);
4249 list->line(LIST_MACRO, p);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004250 nasm_free(p);
4251 break;
4252 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004253 line = read_line();
H. Peter Anvin734b1882002-04-30 21:01:08 +00004254 if (line)
4255 { /* from the current input file */
H. Peter Anvineba20a72002-04-30 20:53:55 +00004256 line = prepreproc(line);
4257 tline = tokenise(line);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004258 nasm_free(line);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004259 break;
4260 }
4261 /*
4262 * The current file has ended; work down the istk
4263 */
4264 {
4265 Include *i = istk;
4266 fclose(i->fp);
4267 if (i->conds)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004268 error(ERR_FATAL, "expected `%%endif' before end of file");
Ed Beroset168c9c02002-05-17 03:10:13 +00004269 /* only set line and file name if there's a next node */
4270 if (i->next)
4271 {
4272 src_set_linnum(i->lineno);
4273 nasm_free(src_set_fname(i->fname));
4274 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00004275 istk = i->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004276 list->downlevel(LIST_INCLUDE);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004277 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004278 if (!istk)
4279 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004280 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004281 }
4282
4283 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00004284 * We must expand MMacro parameters and MMacro-local labels
4285 * _before_ we plunge into directive processing, to cope
4286 * with things like `%define something %1' such as STRUC
4287 * uses. Unless we're _defining_ a MMacro, in which case
4288 * those tokens should be left alone to go into the
H. Peter Anvineba20a72002-04-30 20:53:55 +00004289 * definition; and unless we're in a non-emitting
4290 * condition, in which case we don't want to meddle with
4291 * anything.
H. Peter Anvin76690a12002-04-30 20:52:49 +00004292 */
H. Peter Anvineba20a72002-04-30 20:53:55 +00004293 if (!defining && !(istk->conds && !emitting(istk->conds->state)))
H. Peter Anvin76690a12002-04-30 20:52:49 +00004294 tline = expand_mmac_params(tline);
4295
4296 /*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004297 * Check the line to see if it's a preprocessor directive.
4298 */
Ed Beroset3ab3f412002-06-11 03:31:49 +00004299 if (do_directive(tline) == DIRECTIVE_FOUND)
H. Peter Anvin734b1882002-04-30 21:01:08 +00004300 {
4301 continue;
4302 }
4303 else if (defining)
4304 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004305 /*
4306 * We're defining a multi-line macro. We emit nothing
H. Peter Anvineba20a72002-04-30 20:53:55 +00004307 * at all, and just
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004308 * shove the tokenised line on to the macro definition.
4309 */
4310 Line *l = nasm_malloc(sizeof(Line));
4311 l->next = defining->expansion;
4312 l->first = tline;
4313 l->finishes = FALSE;
4314 defining->expansion = l;
4315 continue;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004316 }
4317 else if (istk->conds && !emitting(istk->conds->state))
4318 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004319 /*
4320 * We're in a non-emitting branch of a condition block.
4321 * Emit nothing at all, not even a blank line: when we
4322 * emerge from the condition we'll give a line-number
4323 * directive so we keep our place correctly.
4324 */
4325 free_tlist(tline);
4326 continue;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004327 }
4328 else if (istk->mstk && !istk->mstk->in_progress)
4329 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00004330 /*
4331 * We're in a %rep block which has been terminated, so
4332 * we're walking through to the %endrep without
4333 * emitting anything. Emit nothing at all, not even a
4334 * blank line: when we emerge from the %rep block we'll
4335 * give a line-number directive so we keep our place
4336 * correctly.
4337 */
4338 free_tlist(tline);
4339 continue;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004340 }
4341 else
4342 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004343 tline = expand_smacro(tline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004344 if (!expand_mmacro(tline))
4345 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004346 /*
4347 * De-tokenise the line again, and emit it.
4348 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004349 line = detoken(tline, TRUE);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004350 free_tlist(tline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004351 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004352 }
4353 else
4354 {
4355 continue; /* expand_mmacro calls free_tlist */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004356 }
4357 }
4358 }
4359
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004360 return line;
4361}
4362
H. Peter Anvin734b1882002-04-30 21:01:08 +00004363static void
H. Peter Anvince616072002-04-30 21:02:23 +00004364pp_cleanup(int pass)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004365{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004366 int h;
4367
H. Peter Anvin734b1882002-04-30 21:01:08 +00004368 if (defining)
4369 {
4370 error(ERR_NONFATAL, "end of file while still defining macro `%s'",
4371 defining->name);
4372 free_mmacro(defining);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004373 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004374 while (cstk)
4375 ctx_pop();
H. Peter Anvin734b1882002-04-30 21:01:08 +00004376 for (h = 0; h < NHASH; h++)
4377 {
4378 while (mmacros[h])
4379 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004380 MMacro *m = mmacros[h];
4381 mmacros[h] = mmacros[h]->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004382 free_mmacro(m);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004383 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004384 while (smacros[h])
4385 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004386 SMacro *s = smacros[h];
4387 smacros[h] = smacros[h]->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004388 nasm_free(s->name);
4389 free_tlist(s->expansion);
4390 nasm_free(s);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004391 }
4392 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004393 while (istk)
4394 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004395 Include *i = istk;
4396 istk = istk->next;
4397 fclose(i->fp);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004398 nasm_free(i->fname);
4399 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004400 }
4401 while (cstk)
4402 ctx_pop();
H. Peter Anvince616072002-04-30 21:02:23 +00004403 if (pass == 0)
4404 {
4405 free_llist(predef);
4406 delete_Blocks();
4407 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004408}
4409
H. Peter Anvin734b1882002-04-30 21:01:08 +00004410void
4411pp_include_path(char *path)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004412{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004413 IncPath *i;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00004414/* by alexfru: order of path inclusion fixed (was reverse order) */
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004415 i = nasm_malloc(sizeof(IncPath));
4416 i->path = nasm_strdup(path);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00004417 i->next = NULL;
4418
4419 if (ipath != NULL)
4420 {
4421 IncPath *j = ipath;
4422 while (j->next != NULL)
4423 j = j->next;
4424 j->next = i;
4425 }
4426 else
4427 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004428 ipath = i;
4429}
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00004430}
4431
4432/*
4433 * added by alexfru:
4434 *
4435 * This function is used to "export" the include paths, e.g.
4436 * the paths specified in the '-I' command switch.
4437 * The need for such exporting is due to the 'incbin' directive,
4438 * which includes raw binary files (unlike '%include', which
4439 * includes text source files). It would be real nice to be
4440 * able to specify paths to search for incbin'ned files also.
4441 * So, this is a simple workaround.
4442 *
4443 * The function use is simple:
4444 *
4445 * The 1st call (with NULL argument) returns a pointer to the 1st path
4446 * (char** type) or NULL if none include paths available.
4447 *
4448 * All subsequent calls take as argument the value returned by this
4449 * function last. The return value is either the next path
4450 * (char** type) or NULL if the end of the paths list is reached.
4451 *
4452 * It is maybe not the best way to do things, but I didn't want
4453 * to export too much, just one or two functions and no types or
4454 * variables exported.
4455 *
4456 * Can't say I like the current situation with e.g. this path list either,
4457 * it seems to be never deallocated after creation...
4458 */
4459char**
4460pp_get_include_path_ptr (char **pPrevPath)
4461{
4462/* This macro returns offset of a member of a structure */
4463#define GetMemberOffset(StructType,MemberName)\
4464 ((size_t)&((StructType*)0)->MemberName)
4465 IncPath *i;
4466
4467 if (pPrevPath == NULL)
4468 {
4469 if(ipath != NULL)
4470 return &ipath->path;
4471 else
4472 return NULL;
4473 }
4474 i = (IncPath*) ((char*)pPrevPath - GetMemberOffset(IncPath,path));
4475 i = i->next;
4476 if (i != NULL)
4477 return &i->path;
4478 else
4479 return NULL;
4480#undef GetMemberOffset
4481}
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004482
H. Peter Anvin734b1882002-04-30 21:01:08 +00004483void
4484pp_pre_include(char *fname)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004485{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004486 Token *inc, *space, *name;
4487 Line *l;
4488
H. Peter Anvin734b1882002-04-30 21:01:08 +00004489 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
4490 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
4491 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004492
4493 l = nasm_malloc(sizeof(Line));
4494 l->next = predef;
4495 l->first = inc;
4496 l->finishes = FALSE;
4497 predef = l;
4498}
4499
H. Peter Anvin734b1882002-04-30 21:01:08 +00004500void
4501pp_pre_define(char *definition)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004502{
4503 Token *def, *space;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004504 Line *l;
4505 char *equals;
4506
4507 equals = strchr(definition, '=');
H. Peter Anvin734b1882002-04-30 21:01:08 +00004508 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4509 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004510 if (equals)
4511 *equals = ' ';
H. Peter Anvineba20a72002-04-30 20:53:55 +00004512 space->next = tokenise(definition);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004513 if (equals)
4514 *equals = '=';
4515
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004516 l = nasm_malloc(sizeof(Line));
4517 l->next = predef;
4518 l->first = def;
4519 l->finishes = FALSE;
4520 predef = l;
4521}
4522
H. Peter Anvin734b1882002-04-30 21:01:08 +00004523void
4524pp_pre_undefine(char *definition)
H. Peter Anvin620515a2002-04-30 20:57:38 +00004525{
4526 Token *def, *space;
4527 Line *l;
4528
H. Peter Anvin734b1882002-04-30 21:01:08 +00004529 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4530 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
Frank Kotlerd3523022003-06-14 12:12:26 +00004531 space->next = tokenise(definition);
H. Peter Anvin620515a2002-04-30 20:57:38 +00004532
4533 l = nasm_malloc(sizeof(Line));
4534 l->next = predef;
4535 l->first = def;
4536 l->finishes = FALSE;
4537 predef = l;
4538}
4539
H. Peter Anvin734b1882002-04-30 21:01:08 +00004540void
H. Peter Anvinbfebdb02002-09-12 02:23:54 +00004541pp_extra_stdmac(const char **macros)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004542{
H. Peter Anvin76690a12002-04-30 20:52:49 +00004543 extrastdmac = macros;
4544}
4545
H. Peter Anvin734b1882002-04-30 21:01:08 +00004546static void
4547make_tok_num(Token * tok, long val)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004548{
4549 char numbuf[20];
4550 sprintf(numbuf, "%ld", val);
4551 tok->text = nasm_strdup(numbuf);
4552 tok->type = TOK_NUMBER;
4553}
4554
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004555Preproc nasmpp = {
4556 pp_reset,
4557 pp_getline,
4558 pp_cleanup
4559};