blob: c34fa4f52a17a4b3b847984a36011fa03dcf0502 [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 *
Keith Kaniosb7a89542007-04-12 02:40:54 +000014 * pp_getline gets tokenized lines, either
H. Peter Anvin4836e332002-04-30 20:56:43 +000015 *
16 * from a macro expansion
17 *
18 * or
19 * {
20 * read_line gets raw text from stdmacpos, or predef, or current input file
Keith Kaniosb7a89542007-04-12 02:40:54 +000021 * tokenize converts to tokens
H. Peter Anvin4836e332002-04-30 20:56:43 +000022 * }
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>
Keith Kaniosb7a89542007-04-12 02:40:54 +000044#include <inttypes.h>
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000045
46#include "nasm.h"
47#include "nasmlib.h"
H. Peter Anvin4169a472007-09-12 01:29:43 +000048#include "preproc.h"
H. Peter Anvin97a23472007-09-16 17:57:25 -070049#include "hashtbl.h"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000050
51typedef struct SMacro SMacro;
52typedef struct MMacro MMacro;
53typedef struct Context Context;
54typedef struct Token Token;
H. Peter Anvince616072002-04-30 21:02:23 +000055typedef struct Blocks Blocks;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000056typedef struct Line Line;
57typedef struct Include Include;
58typedef struct Cond Cond;
H. Peter Anvin6768eb72002-04-30 20:52:26 +000059typedef struct IncPath IncPath;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000060
61/*
H. Peter Anvin97a23472007-09-16 17:57:25 -070062 * Note on the storage of both SMacro and MMacros: the hash table
63 * indexes them case-insensitively, and we then have to go through a
64 * linked list of potential case aliases (and, for MMacros, parameter
65 * ranges); this is to preserve the matching semantics of the earlier
66 * code. If the number of case aliases for a specific macro is a
67 * performance issue, you may want to reconsider your coding style.
68 */
69
70/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000071 * Store the definition of a single-line macro.
72 */
H. Peter Anvine2c80182005-01-15 22:15:51 +000073struct SMacro {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000074 SMacro *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +000075 char *name;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000076 int casesense;
77 int nparam;
78 int in_progress;
79 Token *expansion;
80};
81
82/*
H. Peter Anvin76690a12002-04-30 20:52:49 +000083 * Store the definition of a multi-line macro. This is also used to
84 * store the interiors of `%rep...%endrep' blocks, which are
85 * effectively self-re-invoking multi-line macros which simply
86 * don't have a name or bother to appear in the hash tables. %rep
87 * blocks are signified by having a NULL `name' field.
88 *
89 * In a MMacro describing a `%rep' block, the `in_progress' field
90 * isn't merely boolean, but gives the number of repeats left to
91 * run.
92 *
93 * The `next' field is used for storing MMacros in hash tables; the
94 * `next_active' field is for stacking them on istk entries.
95 *
96 * When a MMacro is being expanded, `params', `iline', `nparam',
97 * `paramlen', `rotate' and `unique' are local to the invocation.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000098 */
H. Peter Anvine2c80182005-01-15 22:15:51 +000099struct MMacro {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000100 MMacro *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000101 char *name;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000102 int casesense;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -0700103 int nparam_min, nparam_max;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000104 int plus; /* is the last parameter greedy? */
105 int nolist; /* is this macro listing-inhibited? */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000106 int in_progress;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000107 Token *dlist; /* All defaults as one list */
108 Token **defaults; /* Parameter default pointers */
109 int ndefs; /* number of default parameters */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000110 Line *expansion;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000111
112 MMacro *next_active;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000113 MMacro *rep_nest; /* used for nesting %rep */
114 Token **params; /* actual parameters */
115 Token *iline; /* invocation line */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000116 int nparam, rotate, *paramlen;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000117 uint32_t unique;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000118 int lineno; /* Current line number on expansion */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000119};
120
121/*
122 * The context stack is composed of a linked list of these.
123 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000124struct Context {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000125 Context *next;
126 SMacro *localmac;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000127 char *name;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000128 uint32_t number;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000129};
130
131/*
132 * This is the internal form which we break input lines up into.
133 * Typically stored in linked lists.
134 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000135 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
136 * necessarily used as-is, but is intended to denote the number of
137 * the substituted parameter. So in the definition
138 *
139 * %define a(x,y) ( (x) & ~(y) )
140 *
141 * the token representing `x' will have its type changed to
142 * TOK_SMAC_PARAM, but the one representing `y' will be
143 * TOK_SMAC_PARAM+1.
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000144 *
145 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
146 * which doesn't need quotes around it. Used in the pre-include
147 * mechanism as an alternative to trying to find a sensible type of
148 * quote to use on the filename we were passed.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000149 */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000150enum pp_token_type {
151 TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT, TOK_ID,
152 TOK_PREPROC_ID, TOK_STRING,
153 TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_SMAC_PARAM,
154 TOK_INTERNAL_STRING
155};
156
H. Peter Anvine2c80182005-01-15 22:15:51 +0000157struct Token {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000158 Token *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000159 char *text;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000160 SMacro *mac; /* associated macro for TOK_SMAC_END */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000161 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000162};
163
164/*
165 * Multi-line macro definitions are stored as a linked list of
166 * these, which is essentially a container to allow several linked
167 * lists of Tokens.
168 *
169 * Note that in this module, linked lists are treated as stacks
170 * wherever possible. For this reason, Lines are _pushed_ on to the
171 * `expansion' field in MMacro structures, so that the linked list,
172 * if walked, would give the macro lines in reverse order; this
173 * means that we can walk the list when expanding a macro, and thus
174 * push the lines on to the `expansion' field in _istk_ in reverse
175 * order (so that when popped back off they are in the right
176 * order). It may seem cockeyed, and it relies on my design having
177 * an even number of steps in, but it works...
178 *
179 * Some of these structures, rather than being actual lines, are
180 * markers delimiting the end of the expansion of a given macro.
H. Peter Anvin76690a12002-04-30 20:52:49 +0000181 * This is for use in the cycle-tracking and %rep-handling code.
182 * Such structures have `finishes' non-NULL, and `first' NULL. All
183 * others have `finishes' NULL, but `first' may still be NULL if
184 * the line is blank.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000185 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000186struct Line {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000187 Line *next;
188 MMacro *finishes;
189 Token *first;
190};
191
192/*
193 * To handle an arbitrary level of file inclusion, we maintain a
194 * stack (ie linked list) of these things.
195 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000196struct Include {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000197 Include *next;
198 FILE *fp;
199 Cond *conds;
200 Line *expansion;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000201 char *fname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000202 int lineno, lineinc;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000203 MMacro *mstk; /* stack of active macros/reps */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000204};
205
206/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000207 * Include search path. This is simply a list of strings which get
208 * prepended, in turn, to the name of an include file, in an
209 * attempt to find the file if it's not in the current directory.
210 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000211struct IncPath {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000212 IncPath *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000213 char *path;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000214};
215
216/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000217 * Conditional assembly: we maintain a separate stack of these for
218 * each level of file inclusion. (The only reason we keep the
219 * stacks separate is to ensure that a stray `%endif' in a file
220 * included from within the true branch of a `%if' won't terminate
221 * it and cause confusion: instead, rightly, it'll cause an error.)
222 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000223struct Cond {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000224 Cond *next;
225 int state;
226};
H. Peter Anvine2c80182005-01-15 22:15:51 +0000227enum {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000228 /*
229 * These states are for use just after %if or %elif: IF_TRUE
230 * means the condition has evaluated to truth so we are
231 * currently emitting, whereas IF_FALSE means we are not
232 * currently emitting but will start doing so if a %else comes
233 * up. In these states, all directives are admissible: %elif,
234 * %else and %endif. (And of course %if.)
235 */
236 COND_IF_TRUE, COND_IF_FALSE,
237 /*
238 * These states come up after a %else: ELSE_TRUE means we're
239 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
240 * any %elif or %else will cause an error.
241 */
242 COND_ELSE_TRUE, COND_ELSE_FALSE,
243 /*
244 * This state means that we're not emitting now, and also that
245 * nothing until %endif will be emitted at all. It's for use in
246 * two circumstances: (i) when we've had our moment of emission
247 * and have now started seeing %elifs, and (ii) when the
248 * condition construct in question is contained within a
249 * non-emitting branch of a larger condition construct.
250 */
251 COND_NEVER
252};
253#define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
254
Ed Beroset3ab3f412002-06-11 03:31:49 +0000255/*
256 * These defines are used as the possible return values for do_directive
257 */
258#define NO_DIRECTIVE_FOUND 0
259#define DIRECTIVE_FOUND 1
260
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000261/*
262 * Condition codes. Note that we use c_ prefix not C_ because C_ is
263 * used in nasm.h for the "real" condition codes. At _this_ level,
264 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
265 * ones, so we need a different enum...
266 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000267static const char *conditions[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000268 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
269 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
H. Peter Anvince9be342007-09-12 00:22:29 +0000270 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000271};
H. Peter Anvine2c80182005-01-15 22:15:51 +0000272enum {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000273 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
274 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
H. Peter Anvince9be342007-09-12 00:22:29 +0000275 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000276};
277static int inverse_ccs[] = {
278 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
279 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,
H. Peter Anvince9be342007-09-12 00:22:29 +0000280 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000281};
282
H. Peter Anvin76690a12002-04-30 20:52:49 +0000283/*
284 * Directive names.
285 */
H. Peter Anvin65747262002-05-07 00:10:05 +0000286/* If this is a an IF, ELIF, ELSE or ENDIF keyword */
H. Peter Anvin9bf0aa72007-09-12 02:12:07 +0000287static int is_condition(enum preproc_token arg)
H. Peter Anvin65747262002-05-07 00:10:05 +0000288{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000289 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
H. Peter Anvin65747262002-05-07 00:10:05 +0000290}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000291
292/* For TASM compatibility we need to be able to recognise TASM compatible
293 * conditional compilation directives. Using the NASM pre-processor does
294 * not work, so we look for them specifically from the following list and
295 * then jam in the equivalent NASM directive into the input stream.
296 */
297
298#ifndef MAX
299# define MAX(a,b) ( ((a) > (b)) ? (a) : (b))
300#endif
301
H. Peter Anvine2c80182005-01-15 22:15:51 +0000302enum {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000303 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
304 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
305};
306
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000307static const char *tasm_directives[] = {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000308 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
309 "ifndef", "include", "local"
310};
311
312static int StackSize = 4;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000313static char *StackPointer = "ebp";
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000314static int ArgOffset = 8;
315static int LocalOffset = 4;
316
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000317static Context *cstk;
318static Include *istk;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000319static IncPath *ipath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000320
H. Peter Anvine2c80182005-01-15 22:15:51 +0000321static efunc _error; /* Pointer to client-provided error reporting function */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000322static evalfunc evaluate;
323
H. Peter Anvine2c80182005-01-15 22:15:51 +0000324static int pass; /* HACK: pass 0 = generate dependencies only */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000325
Keith Kaniosb7a89542007-04-12 02:40:54 +0000326static uint32_t unique; /* unique identifier numbers */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000327
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000328static Line *predef = NULL;
329
330static ListGen *list;
331
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000332/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000333 * The current set of multi-line macros we have defined.
334 */
H. Peter Anvin97a23472007-09-16 17:57:25 -0700335static struct hash_table *mmacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000336
337/*
338 * The current set of single-line macros we have defined.
339 */
H. Peter Anvin97a23472007-09-16 17:57:25 -0700340static struct hash_table *smacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000341
342/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000343 * The multi-line macro we are currently defining, or the %rep
344 * block we are currently reading, if any.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000345 */
346static MMacro *defining;
347
348/*
349 * The number of macro parameters to allocate space for at a time.
350 */
351#define PARAM_DELTA 16
352
353/*
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000354 * The standard macro set: defined as `static char *stdmac[]'. Also
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000355 * gives our position in the macro set, when we're processing it.
356 */
357#include "macros.c"
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000358static const char **stdmacpos;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000359
360/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000361 * The extra standard macros that come from the object format, if
362 * any.
363 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000364static const char **extrastdmac = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000365int any_extrastdmac;
366
367/*
H. Peter Anvin734b1882002-04-30 21:01:08 +0000368 * Tokens are allocated in blocks to improve speed
369 */
370#define TOKEN_BLOCKSIZE 4096
371static Token *freeTokens = NULL;
H. Peter Anvince616072002-04-30 21:02:23 +0000372struct Blocks {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000373 Blocks *next;
374 void *chunk;
H. Peter Anvince616072002-04-30 21:02:23 +0000375};
376
377static Blocks blocks = { NULL, NULL };
H. Peter Anvin734b1882002-04-30 21:01:08 +0000378
379/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000380 * Forward declarations.
381 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000382static Token *expand_mmac_params(Token * tline);
383static Token *expand_smacro(Token * tline);
384static Token *expand_id(Token * tline);
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000385static Context *get_ctx(char *name, int all_contexts);
Keith Kaniosb7a89542007-04-12 02:40:54 +0000386static void make_tok_num(Token * tok, int32_t val);
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000387static void error(int severity, const char *fmt, ...);
H. Peter Anvince616072002-04-30 21:02:23 +0000388static void *new_Block(size_t size);
389static void delete_Blocks(void);
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000390static Token *new_Token(Token * next, enum pp_token_type type, char *text, int txtlen);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000391static Token *delete_Token(Token * t);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000392
393/*
394 * Macros for safe checking of token pointers, avoid *(NULL)
395 */
396#define tok_type_(x,t) ((x) && (x)->type == (t))
397#define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
398#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
399#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
H. Peter Anvin76690a12002-04-30 20:52:49 +0000400
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000401/* Handle TASM specific directives, which do not contain a % in
402 * front of them. We do it here because I could not find any other
403 * place to do it for the moment, and it is a hack (ideally it would
404 * be nice to be able to use the NASM pre-processor to do it).
405 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000406static char *check_tasm_directive(char *line)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000407{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000408 int32_t i, j, k, m, len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000409 char *p = line, *oldline, oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000410
411 /* Skip whitespace */
412 while (isspace(*p) && *p != 0)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000413 p++;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000414
415 /* Binary search for the directive name */
416 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +0000417 j = elements(tasm_directives);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000418 len = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000419 while (!isspace(p[len]) && p[len] != 0)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000420 len++;
421 if (len) {
422 oldchar = p[len];
423 p[len] = 0;
424 while (j - i > 1) {
425 k = (j + i) / 2;
426 m = nasm_stricmp(p, tasm_directives[k]);
427 if (m == 0) {
428 /* We have found a directive, so jam a % in front of it
429 * so that NASM will then recognise it as one if it's own.
430 */
431 p[len] = oldchar;
432 len = strlen(p);
433 oldline = line;
434 line = nasm_malloc(len + 2);
435 line[0] = '%';
436 if (k == TM_IFDIFI) {
437 /* NASM does not recognise IFDIFI, so we convert it to
438 * %ifdef BOGUS. This is not used in NASM comaptible
439 * code, but does need to parse for the TASM macro
440 * package.
441 */
442 strcpy(line + 1, "ifdef BOGUS");
443 } else {
444 memcpy(line + 1, p, len + 1);
445 }
446 nasm_free(oldline);
447 return line;
448 } else if (m < 0) {
449 j = k;
450 } else
451 i = k;
452 }
453 p[len] = oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000454 }
455 return line;
456}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000457
H. Peter Anvin76690a12002-04-30 20:52:49 +0000458/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000459 * The pre-preprocessing stage... This function translates line
460 * number indications as they emerge from GNU cpp (`# lineno "file"
461 * flags') into NASM preprocessor line number indications (`%line
462 * lineno file').
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000463 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000464static char *prepreproc(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000465{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000466 int lineno, fnlen;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000467 char *fname, *oldline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000468
H. Peter Anvine2c80182005-01-15 22:15:51 +0000469 if (line[0] == '#' && line[1] == ' ') {
470 oldline = line;
471 fname = oldline + 2;
472 lineno = atoi(fname);
473 fname += strspn(fname, "0123456789 ");
474 if (*fname == '"')
475 fname++;
476 fnlen = strcspn(fname, "\"");
477 line = nasm_malloc(20 + fnlen);
478 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
479 nasm_free(oldline);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000480 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000481 if (tasm_compatible_mode)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000482 return check_tasm_directive(line);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000483 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000484}
485
486/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000487 * Free a linked list of tokens.
488 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000489static void free_tlist(Token * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000490{
H. Peter Anvine2c80182005-01-15 22:15:51 +0000491 while (list) {
492 list = delete_Token(list);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000493 }
494}
495
496/*
497 * Free a linked list of lines.
498 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000499static void free_llist(Line * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000500{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000501 Line *l;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000502 while (list) {
503 l = list;
504 list = list->next;
505 free_tlist(l->first);
506 nasm_free(l);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000507 }
508}
509
510/*
H. Peter Anvineba20a72002-04-30 20:53:55 +0000511 * Free an MMacro
512 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000513static void free_mmacro(MMacro * m)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000514{
H. Peter Anvin734b1882002-04-30 21:01:08 +0000515 nasm_free(m->name);
516 free_tlist(m->dlist);
517 nasm_free(m->defaults);
518 free_llist(m->expansion);
519 nasm_free(m);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000520}
521
522/*
H. Peter Anvin97a23472007-09-16 17:57:25 -0700523 * Free all currently defined macros, and free the hash tables
524 */
525static void free_macros(void)
526{
527 struct hash_tbl_node *it;
528 const char *key;
529 SMacro *s;
530 MMacro *m;
531
532 it = NULL;
533 while ((s = hash_iterate(smacros, &it, &key)) != NULL) {
534 nasm_free((void *)key);
535 while (s) {
536 SMacro *ns = s->next;
537 nasm_free(s->name);
538 free_tlist(s->expansion);
539 nasm_free(s);
540 s = ns;
541 }
542 }
543 hash_free(smacros);
544
545 it = NULL;
546 while ((m = hash_iterate(mmacros, &it, &key)) != NULL) {
547 nasm_free((void *)key);
548 while (m) {
549 MMacro *nm = m->next;
550 free_mmacro(m);
551 m = nm;
552 }
553 }
554 hash_free(mmacros);
555}
556
557/*
558 * Initialize the hash tables
559 */
560static void init_macros(void)
561{
562 smacros = hash_init();
563 mmacros = hash_init();
564}
565
566/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000567 * Pop the context stack.
568 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000569static void ctx_pop(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000570{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000571 Context *c = cstk;
572 SMacro *smac, *s;
573
574 cstk = cstk->next;
575 smac = c->localmac;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000576 while (smac) {
577 s = smac;
578 smac = smac->next;
579 nasm_free(s->name);
580 free_tlist(s->expansion);
581 nasm_free(s);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000582 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000583 nasm_free(c->name);
584 nasm_free(c);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000585}
586
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000587#define BUF_DELTA 512
588/*
589 * Read a line from the top file in istk, handling multiple CR/LFs
590 * at the end of the line read, and handling spurious ^Zs. Will
591 * return lines from the standard macro set if this has not already
592 * been done.
593 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000594static char *read_line(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000595{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000596 char *buffer, *p, *q;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000597 int bufsize, continued_count;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000598
H. Peter Anvine2c80182005-01-15 22:15:51 +0000599 if (stdmacpos) {
600 if (*stdmacpos) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000601 char *ret = nasm_strdup(*stdmacpos++);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000602 if (!*stdmacpos && any_extrastdmac) {
603 stdmacpos = extrastdmac;
604 any_extrastdmac = FALSE;
605 return ret;
606 }
607 /*
608 * Nasty hack: here we push the contents of `predef' on
609 * to the top-level expansion stack, since this is the
610 * most convenient way to implement the pre-include and
611 * pre-define features.
612 */
613 if (!*stdmacpos) {
614 Line *pd, *l;
615 Token *head, **tail, *t;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000616
H. Peter Anvine2c80182005-01-15 22:15:51 +0000617 for (pd = predef; pd; pd = pd->next) {
618 head = NULL;
619 tail = &head;
620 for (t = pd->first; t; t = t->next) {
621 *tail = new_Token(NULL, t->type, t->text, 0);
622 tail = &(*tail)->next;
623 }
624 l = nasm_malloc(sizeof(Line));
625 l->next = istk->expansion;
626 l->first = head;
627 l->finishes = FALSE;
628 istk->expansion = l;
629 }
630 }
631 return ret;
632 } else {
633 stdmacpos = NULL;
634 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000635 }
636
637 bufsize = BUF_DELTA;
638 buffer = nasm_malloc(BUF_DELTA);
639 p = buffer;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000640 continued_count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000641 while (1) {
642 q = fgets(p, bufsize - (p - buffer), istk->fp);
643 if (!q)
644 break;
645 p += strlen(p);
646 if (p > buffer && p[-1] == '\n') {
647 /* Convert backslash-CRLF line continuation sequences into
648 nothing at all (for DOS and Windows) */
649 if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
650 p -= 3;
651 *p = 0;
652 continued_count++;
653 }
654 /* Also convert backslash-LF line continuation sequences into
655 nothing at all (for Unix) */
656 else if (((p - 1) > buffer) && (p[-2] == '\\')) {
657 p -= 2;
658 *p = 0;
659 continued_count++;
660 } else {
661 break;
662 }
663 }
664 if (p - buffer > bufsize - 10) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000665 int32_t offset = p - buffer;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000666 bufsize += BUF_DELTA;
667 buffer = nasm_realloc(buffer, bufsize);
668 p = buffer + offset; /* prevent stale-pointer problems */
669 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000670 }
671
H. Peter Anvine2c80182005-01-15 22:15:51 +0000672 if (!q && p == buffer) {
673 nasm_free(buffer);
674 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000675 }
676
H. Peter Anvine2c80182005-01-15 22:15:51 +0000677 src_set_linnum(src_get_linnum() + istk->lineinc +
678 (continued_count * istk->lineinc));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000679
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000680 /*
681 * Play safe: remove CRs as well as LFs, if any of either are
682 * present at the end of the line.
683 */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000684 while (--p >= buffer && (*p == '\n' || *p == '\r'))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000685 *p = '\0';
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000686
687 /*
688 * Handle spurious ^Z, which may be inserted into source files
689 * by some file transfer utilities.
690 */
691 buffer[strcspn(buffer, "\032")] = '\0';
692
H. Peter Anvin734b1882002-04-30 21:01:08 +0000693 list->line(LIST_READ, buffer);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000694
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000695 return buffer;
696}
697
698/*
Keith Kaniosb7a89542007-04-12 02:40:54 +0000699 * Tokenize a line of text. This is a very simple process since we
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000700 * don't need to parse the value out of e.g. numeric tokens: we
701 * simply split one string into many.
702 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000703static Token *tokenize(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000704{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000705 char *p = line;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000706 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000707 Token *list = NULL;
708 Token *t, **tail = &list;
709
H. Peter Anvine2c80182005-01-15 22:15:51 +0000710 while (*line) {
711 p = line;
712 if (*p == '%') {
713 p++;
714 if (isdigit(*p) ||
715 ((*p == '-' || *p == '+') && isdigit(p[1])) ||
716 ((*p == '+') && (isspace(p[1]) || !p[1]))) {
717 do {
718 p++;
719 }
720 while (isdigit(*p));
721 type = TOK_PREPROC_ID;
722 } else if (*p == '{') {
723 p++;
724 while (*p && *p != '}') {
725 p[-1] = *p;
726 p++;
727 }
728 p[-1] = '\0';
729 if (*p)
730 p++;
731 type = TOK_PREPROC_ID;
732 } else if (isidchar(*p) ||
733 ((*p == '!' || *p == '%' || *p == '$') &&
734 isidchar(p[1]))) {
735 do {
736 p++;
737 }
738 while (isidchar(*p));
739 type = TOK_PREPROC_ID;
740 } else {
741 type = TOK_OTHER;
742 if (*p == '%')
743 p++;
744 }
745 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
746 type = TOK_ID;
747 p++;
748 while (*p && isidchar(*p))
749 p++;
750 } else if (*p == '\'' || *p == '"') {
751 /*
752 * A string token.
753 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000754 char c = *p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000755 p++;
756 type = TOK_STRING;
757 while (*p && *p != c)
758 p++;
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +0000759
H. Peter Anvine2c80182005-01-15 22:15:51 +0000760 if (*p) {
761 p++;
762 } else {
763 error(ERR_WARNING, "unterminated string");
764 /* Handling unterminated strings by UNV */
765 /* type = -1; */
766 }
767 } else if (isnumstart(*p)) {
768 /*
769 * A number token.
770 */
771 type = TOK_NUMBER;
772 p++;
773 while (*p && isnumchar(*p))
774 p++;
775 } else if (isspace(*p)) {
776 type = TOK_WHITESPACE;
777 p++;
778 while (*p && isspace(*p))
779 p++;
780 /*
781 * Whitespace just before end-of-line is discarded by
782 * pretending it's a comment; whitespace just before a
783 * comment gets lumped into the comment.
784 */
785 if (!*p || *p == ';') {
786 type = TOK_COMMENT;
787 while (*p)
788 p++;
789 }
790 } else if (*p == ';') {
791 type = TOK_COMMENT;
792 while (*p)
793 p++;
794 } else {
795 /*
796 * Anything else is an operator of some kind. We check
797 * for all the double-character operators (>>, <<, //,
798 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000799 * else is a single-character operator.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000800 */
801 type = TOK_OTHER;
802 if ((p[0] == '>' && p[1] == '>') ||
803 (p[0] == '<' && p[1] == '<') ||
804 (p[0] == '/' && p[1] == '/') ||
805 (p[0] == '<' && p[1] == '=') ||
806 (p[0] == '>' && p[1] == '=') ||
807 (p[0] == '=' && p[1] == '=') ||
808 (p[0] == '!' && p[1] == '=') ||
809 (p[0] == '<' && p[1] == '>') ||
810 (p[0] == '&' && p[1] == '&') ||
811 (p[0] == '|' && p[1] == '|') ||
812 (p[0] == '^' && p[1] == '^')) {
813 p++;
814 }
815 p++;
816 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +0000817
H. Peter Anvine2c80182005-01-15 22:15:51 +0000818 /* Handling unterminated string by UNV */
819 /*if (type == -1)
820 {
821 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
822 t->text[p-line] = *line;
823 tail = &t->next;
824 }
825 else */
826 if (type != TOK_COMMENT) {
827 *tail = t = new_Token(NULL, type, line, p - line);
828 tail = &t->next;
829 }
830 line = p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000831 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000832 return list;
833}
834
H. Peter Anvince616072002-04-30 21:02:23 +0000835/*
836 * this function allocates a new managed block of memory and
837 * returns a pointer to the block. The managed blocks are
838 * deleted only all at once by the delete_Blocks function.
839 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000840static void *new_Block(size_t size)
H. Peter Anvince616072002-04-30 21:02:23 +0000841{
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000842 Blocks *b = &blocks;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000843
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000844 /* first, get to the end of the linked list */
845 while (b->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000846 b = b->next;
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000847 /* now allocate the requested chunk */
848 b->chunk = nasm_malloc(size);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000849
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000850 /* now allocate a new block for the next request */
851 b->next = nasm_malloc(sizeof(Blocks));
852 /* and initialize the contents of the new block */
853 b->next->next = NULL;
854 b->next->chunk = NULL;
855 return b->chunk;
H. Peter Anvince616072002-04-30 21:02:23 +0000856}
857
858/*
859 * this function deletes all managed blocks of memory
860 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000861static void delete_Blocks(void)
H. Peter Anvince616072002-04-30 21:02:23 +0000862{
H. Peter Anvine2c80182005-01-15 22:15:51 +0000863 Blocks *a, *b = &blocks;
H. Peter Anvince616072002-04-30 21:02:23 +0000864
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000865 /*
866 * keep in mind that the first block, pointed to by blocks
867 * is a static and not dynamically allocated, so we don't
868 * free it.
869 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000870 while (b) {
871 if (b->chunk)
872 nasm_free(b->chunk);
873 a = b;
874 b = b->next;
875 if (a != &blocks)
876 nasm_free(a);
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000877 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000878}
H. Peter Anvin734b1882002-04-30 21:01:08 +0000879
880/*
881 * this function creates a new Token and passes a pointer to it
882 * back to the caller. It sets the type and text elements, and
883 * also the mac and next elements to NULL.
884 */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000885static Token *new_Token(Token * next, enum pp_token_type type, char *text, int txtlen)
H. Peter Anvin734b1882002-04-30 21:01:08 +0000886{
887 Token *t;
888 int i;
889
H. Peter Anvine2c80182005-01-15 22:15:51 +0000890 if (freeTokens == NULL) {
891 freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
892 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
893 freeTokens[i].next = &freeTokens[i + 1];
894 freeTokens[i].next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000895 }
896 t = freeTokens;
897 freeTokens = t->next;
898 t->next = next;
899 t->mac = NULL;
900 t->type = type;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000901 if (type == TOK_WHITESPACE || text == NULL) {
902 t->text = NULL;
903 } else {
904 if (txtlen == 0)
905 txtlen = strlen(text);
906 t->text = nasm_malloc(1 + txtlen);
907 strncpy(t->text, text, txtlen);
908 t->text[txtlen] = '\0';
H. Peter Anvin734b1882002-04-30 21:01:08 +0000909 }
910 return t;
911}
912
H. Peter Anvine2c80182005-01-15 22:15:51 +0000913static Token *delete_Token(Token * t)
H. Peter Anvin734b1882002-04-30 21:01:08 +0000914{
915 Token *next = t->next;
916 nasm_free(t->text);
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000917 t->next = freeTokens;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000918 freeTokens = t;
919 return next;
920}
921
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000922/*
923 * Convert a line of tokens back into text.
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000924 * If expand_locals is not zero, identifiers of the form "%$*xxx"
925 * will be transformed into ..@ctxnum.xxx
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000926 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000927static char *detoken(Token * tlist, int expand_locals)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000928{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000929 Token *t;
930 int len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000931 char *line, *p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000932
933 len = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000934 for (t = tlist; t; t = t->next) {
935 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000936 char *p = getenv(t->text + 2);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000937 nasm_free(t->text);
938 if (p)
939 t->text = nasm_strdup(p);
940 else
941 t->text = NULL;
942 }
943 /* Expand local macros here and not during preprocessing */
944 if (expand_locals &&
945 t->type == TOK_PREPROC_ID && t->text &&
946 t->text[0] == '%' && t->text[1] == '$') {
947 Context *ctx = get_ctx(t->text, FALSE);
948 if (ctx) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000949 char buffer[40];
950 char *p, *q = t->text + 2;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000951
H. Peter Anvine2c80182005-01-15 22:15:51 +0000952 q += strspn(q, "$");
Keith Kanios93f2e9a2007-04-14 00:10:59 +0000953 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000954 p = nasm_strcat(buffer, q);
955 nasm_free(t->text);
956 t->text = p;
957 }
958 }
959 if (t->type == TOK_WHITESPACE) {
960 len++;
961 } else if (t->text) {
962 len += strlen(t->text);
963 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000964 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000965 p = line = nasm_malloc(len + 1);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000966 for (t = tlist; t; t = t->next) {
967 if (t->type == TOK_WHITESPACE) {
968 *p = ' ';
969 p++;
970 *p = '\0';
971 } else if (t->text) {
972 strcpy(p, t->text);
973 p += strlen(p);
974 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000975 }
976 *p = '\0';
977 return line;
978}
979
980/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000981 * A scanner, suitable for use by the expression evaluator, which
982 * operates on a line of Tokens. Expects a pointer to a pointer to
983 * the first token in the line to be passed in as its private_data
984 * field.
985 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000986static int ppscan(void *private_data, struct tokenval *tokval)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000987{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000988 Token **tlineptr = private_data;
989 Token *tline;
990
H. Peter Anvine2c80182005-01-15 22:15:51 +0000991 do {
992 tline = *tlineptr;
993 *tlineptr = tline ? tline->next : NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000994 }
995 while (tline && (tline->type == TOK_WHITESPACE ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000996 tline->type == TOK_COMMENT));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000997
998 if (!tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000999 return tokval->t_type = TOKEN_EOS;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001000
1001 if (tline->text[0] == '$' && !tline->text[1])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001002 return tokval->t_type = TOKEN_HERE;
H. Peter Anvin7cf897e2002-05-30 21:30:33 +00001003 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001004 return tokval->t_type = TOKEN_BASE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001005
H. Peter Anvine2c80182005-01-15 22:15:51 +00001006 if (tline->type == TOK_ID) {
1007 tokval->t_charptr = tline->text;
1008 if (tline->text[0] == '$') {
1009 tokval->t_charptr++;
1010 return tokval->t_type = TOKEN_ID;
1011 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001012
H. Peter Anvine2c80182005-01-15 22:15:51 +00001013 /*
1014 * This is the only special case we actually need to worry
1015 * about in this restricted context.
1016 */
1017 if (!nasm_stricmp(tline->text, "seg"))
1018 return tokval->t_type = TOKEN_SEG;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001019
H. Peter Anvine2c80182005-01-15 22:15:51 +00001020 return tokval->t_type = TOKEN_ID;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001021 }
1022
H. Peter Anvine2c80182005-01-15 22:15:51 +00001023 if (tline->type == TOK_NUMBER) {
1024 int rn_error;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001025
H. Peter Anvine2c80182005-01-15 22:15:51 +00001026 tokval->t_integer = readnum(tline->text, &rn_error);
1027 if (rn_error)
1028 return tokval->t_type = TOKEN_ERRNUM;
1029 tokval->t_charptr = NULL;
1030 return tokval->t_type = TOKEN_NUM;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001031 }
1032
H. Peter Anvine2c80182005-01-15 22:15:51 +00001033 if (tline->type == TOK_STRING) {
1034 int rn_warn;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001035 char q, *r;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001036 int l;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001037
H. Peter Anvine2c80182005-01-15 22:15:51 +00001038 r = tline->text;
1039 q = *r++;
1040 l = strlen(r);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001041
H. Peter Anvine2c80182005-01-15 22:15:51 +00001042 if (l == 0 || r[l - 1] != q)
1043 return tokval->t_type = TOKEN_ERRNUM;
1044 tokval->t_integer = readstrnum(r, l - 1, &rn_warn);
1045 if (rn_warn)
1046 error(ERR_WARNING | ERR_PASS1, "character constant too long");
1047 tokval->t_charptr = NULL;
1048 return tokval->t_type = TOKEN_NUM;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001049 }
1050
H. Peter Anvine2c80182005-01-15 22:15:51 +00001051 if (tline->type == TOK_OTHER) {
1052 if (!strcmp(tline->text, "<<"))
1053 return tokval->t_type = TOKEN_SHL;
1054 if (!strcmp(tline->text, ">>"))
1055 return tokval->t_type = TOKEN_SHR;
1056 if (!strcmp(tline->text, "//"))
1057 return tokval->t_type = TOKEN_SDIV;
1058 if (!strcmp(tline->text, "%%"))
1059 return tokval->t_type = TOKEN_SMOD;
1060 if (!strcmp(tline->text, "=="))
1061 return tokval->t_type = TOKEN_EQ;
1062 if (!strcmp(tline->text, "<>"))
1063 return tokval->t_type = TOKEN_NE;
1064 if (!strcmp(tline->text, "!="))
1065 return tokval->t_type = TOKEN_NE;
1066 if (!strcmp(tline->text, "<="))
1067 return tokval->t_type = TOKEN_LE;
1068 if (!strcmp(tline->text, ">="))
1069 return tokval->t_type = TOKEN_GE;
1070 if (!strcmp(tline->text, "&&"))
1071 return tokval->t_type = TOKEN_DBL_AND;
1072 if (!strcmp(tline->text, "^^"))
1073 return tokval->t_type = TOKEN_DBL_XOR;
1074 if (!strcmp(tline->text, "||"))
1075 return tokval->t_type = TOKEN_DBL_OR;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001076 }
1077
1078 /*
1079 * We have no other options: just return the first character of
1080 * the token text.
1081 */
1082 return tokval->t_type = tline->text[0];
1083}
1084
1085/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001086 * Compare a string to the name of an existing macro; this is a
1087 * simple wrapper which calls either strcmp or nasm_stricmp
1088 * depending on the value of the `casesense' parameter.
1089 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001090static int mstrcmp(char *p, char *q, int casesense)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001091{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001092 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001093}
1094
1095/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001096 * Return the Context structure associated with a %$ token. Return
1097 * NULL, having _already_ reported an error condition, if the
1098 * context stack isn't deep enough for the supplied number of $
1099 * signs.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001100 * If all_contexts == TRUE, contexts that enclose current are
1101 * also scanned for such smacro, until it is found; if not -
1102 * only the context that directly results from the number of $'s
1103 * in variable's name.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001104 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001105static Context *get_ctx(char *name, int all_contexts)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001106{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001107 Context *ctx;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001108 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001109 int i;
1110
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001111 if (!name || name[0] != '%' || name[1] != '$')
H. Peter Anvine2c80182005-01-15 22:15:51 +00001112 return NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001113
H. Peter Anvine2c80182005-01-15 22:15:51 +00001114 if (!cstk) {
1115 error(ERR_NONFATAL, "`%s': context stack is empty", name);
1116 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001117 }
1118
H. Peter Anvine2c80182005-01-15 22:15:51 +00001119 for (i = strspn(name + 2, "$"), ctx = cstk; (i > 0) && ctx; i--) {
1120 ctx = ctx->next;
H. Peter Anvindce1e2f2002-04-30 21:06:37 +00001121/* i--; Lino - 02/25/02 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001122 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001123 if (!ctx) {
1124 error(ERR_NONFATAL, "`%s': context stack is only"
1125 " %d level%s deep", name, i - 1, (i == 2 ? "" : "s"));
1126 return NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001127 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001128 if (!all_contexts)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001129 return ctx;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001130
H. Peter Anvine2c80182005-01-15 22:15:51 +00001131 do {
1132 /* Search for this smacro in found context */
1133 m = ctx->localmac;
1134 while (m) {
1135 if (!mstrcmp(m->name, name, m->casesense))
1136 return ctx;
1137 m = m->next;
1138 }
1139 ctx = ctx->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001140 }
1141 while (ctx);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001142 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001143}
1144
1145/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001146 * Open an include file. This routine must always return a valid
1147 * file pointer if it returns - it's responsible for throwing an
1148 * ERR_FATAL and bombing out completely if not. It should also try
1149 * the include path one by one until it finds the file or reaches
1150 * the end of the path.
1151 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001152static FILE *inc_fopen(char *file)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001153{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001154 FILE *fp;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001155 char *prefix = "", *combine;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001156 IncPath *ip = ipath;
H. Peter Anvin620515a2002-04-30 20:57:38 +00001157 static int namelen = 0;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001158 int len = strlen(file);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001159
H. Peter Anvine2c80182005-01-15 22:15:51 +00001160 while (1) {
1161 combine = nasm_malloc(strlen(prefix) + len + 1);
1162 strcpy(combine, prefix);
1163 strcat(combine, file);
1164 fp = fopen(combine, "r");
1165 if (pass == 0 && fp) {
1166 namelen += strlen(combine) + 1;
1167 if (namelen > 62) {
1168 printf(" \\\n ");
1169 namelen = 2;
1170 }
1171 printf(" %s", combine);
1172 }
1173 nasm_free(combine);
1174 if (fp)
1175 return fp;
1176 if (!ip)
1177 break;
1178 prefix = ip->path;
1179 ip = ip->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001180 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001181
H. Peter Anvin734b1882002-04-30 21:01:08 +00001182 error(ERR_FATAL, "unable to open include file `%s'", file);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001183 return NULL; /* never reached - placate compilers */
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001184}
1185
1186/*
H. Peter Anvin97a23472007-09-16 17:57:25 -07001187 * Search for a key in the hash index; adding it if necessary
1188 * (in which case we initialize the data pointer to NULL.)
1189 */
1190static void **
1191hash_findi_add(struct hash_table *hash, const char *str)
1192{
1193 struct hash_insert hi;
1194 void **r;
1195 char *strx;
1196
1197 r = hash_findi(hash, str, &hi);
1198 if (r)
1199 return r;
1200
1201 strx = nasm_strdup(str); /* Use a more efficient allocator here? */
1202 return hash_add(&hi, strx, NULL);
1203}
1204
1205/*
1206 * Like hash_findi, but returns the data element rather than a pointer
1207 * to it. Used only when not adding a new element, hence no third
1208 * argument.
1209 */
1210static void *
1211hash_findix(struct hash_table *hash, const char *str)
1212{
1213 void **p;
1214
1215 p = hash_findi(hash, str, NULL);
1216 return p ? *p : NULL;
1217}
1218
1219/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001220 * Determine if we should warn on defining a single-line macro of
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001221 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001222 * return TRUE if _any_ single-line macro of that name is defined.
1223 * Otherwise, will return TRUE if a single-line macro with either
1224 * `nparam' or no parameters is defined.
1225 *
1226 * If a macro with precisely the right number of parameters is
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001227 * defined, or nparam is -1, the address of the definition structure
1228 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001229 * is NULL, no action will be taken regarding its contents, and no
1230 * error will occur.
1231 *
1232 * Note that this is also called with nparam zero to resolve
1233 * `ifdef'.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001234 *
1235 * If you already know which context macro belongs to, you can pass
1236 * the context pointer as first parameter; if you won't but name begins
1237 * with %$ the context will be automatically computed. If all_contexts
1238 * is true, macro will be searched in outer contexts as well.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001239 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001240static int
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001241smacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001242 int nocase)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001243{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001244 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001245
H. Peter Anvin97a23472007-09-16 17:57:25 -07001246 if (ctx) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001247 m = ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001248 } else if (name[0] == '%' && name[1] == '$') {
1249 if (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001250 ctx = get_ctx(name, FALSE);
1251 if (!ctx)
1252 return FALSE; /* got to return _something_ */
1253 m = ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001254 } else {
1255 m = (SMacro *) hash_findix(smacros, name);
1256 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001257
H. Peter Anvine2c80182005-01-15 22:15:51 +00001258 while (m) {
1259 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
1260 (nparam <= 0 || m->nparam == 0 || nparam == m->nparam)) {
1261 if (defn) {
1262 if (nparam == m->nparam || nparam == -1)
1263 *defn = m;
1264 else
1265 *defn = NULL;
1266 }
1267 return TRUE;
1268 }
1269 m = m->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001270 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001271
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001272 return FALSE;
1273}
1274
1275/*
1276 * Count and mark off the parameters in a multi-line macro call.
1277 * This is called both from within the multi-line macro expansion
1278 * code, and also to mark off the default parameters when provided
1279 * in a %macro definition line.
1280 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001281static void count_mmac_params(Token * t, int *nparam, Token *** params)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001282{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001283 int paramsize, brace;
1284
1285 *nparam = paramsize = 0;
1286 *params = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001287 while (t) {
1288 if (*nparam >= paramsize) {
1289 paramsize += PARAM_DELTA;
1290 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1291 }
1292 skip_white_(t);
1293 brace = FALSE;
1294 if (tok_is_(t, "{"))
1295 brace = TRUE;
1296 (*params)[(*nparam)++] = t;
1297 while (tok_isnt_(t, brace ? "}" : ","))
1298 t = t->next;
1299 if (t) { /* got a comma/brace */
1300 t = t->next;
1301 if (brace) {
1302 /*
1303 * Now we've found the closing brace, look further
1304 * for the comma.
1305 */
1306 skip_white_(t);
1307 if (tok_isnt_(t, ",")) {
1308 error(ERR_NONFATAL,
1309 "braces do not enclose all of macro parameter");
1310 while (tok_isnt_(t, ","))
1311 t = t->next;
1312 }
1313 if (t)
1314 t = t->next; /* eat the comma */
1315 }
1316 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001317 }
1318}
1319
1320/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001321 * Determine whether one of the various `if' conditions is true or
1322 * not.
1323 *
1324 * We must free the tline we get passed.
1325 */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001326static int if_condition(Token * tline, enum preproc_token ct)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001327{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001328 enum pp_conditional i = PP_COND(ct);
1329 int j;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001330 Token *t, *tt, **tptr, *origline;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001331 struct tokenval tokval;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001332 expr *evalresult;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001333 enum pp_token_type needtype;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001334
1335 origline = tline;
1336
H. Peter Anvine2c80182005-01-15 22:15:51 +00001337 switch (i) {
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001338 case PPC_IFCTX:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001339 j = FALSE; /* have we matched yet? */
1340 while (cstk && tline) {
1341 skip_white_(tline);
1342 if (!tline || tline->type != TOK_ID) {
1343 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001344 "`%s' expects context identifiers", pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001345 free_tlist(origline);
1346 return -1;
1347 }
1348 if (!nasm_stricmp(tline->text, cstk->name))
1349 j = TRUE;
1350 tline = tline->next;
1351 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001352 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001353
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001354 case PPC_IFDEF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001355 j = FALSE; /* have we matched yet? */
1356 while (tline) {
1357 skip_white_(tline);
1358 if (!tline || (tline->type != TOK_ID &&
1359 (tline->type != TOK_PREPROC_ID ||
1360 tline->text[1] != '$'))) {
1361 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001362 "`%s' expects macro identifiers", pp_directives[ct]);
1363 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001364 }
1365 if (smacro_defined(NULL, tline->text, 0, NULL, 1))
1366 j = TRUE;
1367 tline = tline->next;
1368 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001369 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001370
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001371 case PPC_IFIDN:
1372 case PPC_IFIDNI:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001373 tline = expand_smacro(tline);
1374 t = tt = tline;
1375 while (tok_isnt_(tt, ","))
1376 tt = tt->next;
1377 if (!tt) {
1378 error(ERR_NONFATAL,
1379 "`%s' expects two comma-separated arguments",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001380 pp_directives[ct]);
1381 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001382 }
1383 tt = tt->next;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001384 j = TRUE; /* assume equality unless proved not */
1385 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1386 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1387 error(ERR_NONFATAL, "`%s': more than one comma on line",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001388 pp_directives[ct]);
1389 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001390 }
1391 if (t->type == TOK_WHITESPACE) {
1392 t = t->next;
1393 continue;
1394 }
1395 if (tt->type == TOK_WHITESPACE) {
1396 tt = tt->next;
1397 continue;
1398 }
1399 if (tt->type != t->type) {
1400 j = FALSE; /* found mismatching tokens */
1401 break;
1402 }
1403 /* Unify surrounding quotes for strings */
1404 if (t->type == TOK_STRING) {
1405 tt->text[0] = t->text[0];
1406 tt->text[strlen(tt->text) - 1] = t->text[0];
1407 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001408 if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001409 j = FALSE; /* found mismatching tokens */
1410 break;
1411 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001412
H. Peter Anvine2c80182005-01-15 22:15:51 +00001413 t = t->next;
1414 tt = tt->next;
1415 }
1416 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
1417 j = FALSE; /* trailing gunk on one end or other */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001418 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001419
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001420 case PPC_IFMACRO:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001421 {
1422 int found = 0;
1423 MMacro searching, *mmac;
H. Peter Anvin65747262002-05-07 00:10:05 +00001424
H. Peter Anvine2c80182005-01-15 22:15:51 +00001425 tline = tline->next;
1426 skip_white_(tline);
1427 tline = expand_id(tline);
1428 if (!tok_type_(tline, TOK_ID)) {
1429 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001430 "`%s' expects a macro name", pp_directives[ct]);
1431 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001432 }
1433 searching.name = nasm_strdup(tline->text);
1434 searching.casesense = (i == PP_MACRO);
1435 searching.plus = FALSE;
1436 searching.nolist = FALSE;
1437 searching.in_progress = FALSE;
1438 searching.rep_nest = NULL;
1439 searching.nparam_min = 0;
1440 searching.nparam_max = INT_MAX;
1441 tline = expand_smacro(tline->next);
1442 skip_white_(tline);
1443 if (!tline) {
1444 } else if (!tok_type_(tline, TOK_NUMBER)) {
1445 error(ERR_NONFATAL,
1446 "`%s' expects a parameter count or nothing",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001447 pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001448 } else {
1449 searching.nparam_min = searching.nparam_max =
1450 readnum(tline->text, &j);
1451 if (j)
1452 error(ERR_NONFATAL,
1453 "unable to parse parameter count `%s'",
1454 tline->text);
1455 }
1456 if (tline && tok_is_(tline->next, "-")) {
1457 tline = tline->next->next;
1458 if (tok_is_(tline, "*"))
1459 searching.nparam_max = INT_MAX;
1460 else if (!tok_type_(tline, TOK_NUMBER))
1461 error(ERR_NONFATAL,
1462 "`%s' expects a parameter count after `-'",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001463 pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001464 else {
1465 searching.nparam_max = readnum(tline->text, &j);
1466 if (j)
1467 error(ERR_NONFATAL,
1468 "unable to parse parameter count `%s'",
1469 tline->text);
1470 if (searching.nparam_min > searching.nparam_max)
1471 error(ERR_NONFATAL,
1472 "minimum parameter count exceeds maximum");
1473 }
1474 }
1475 if (tline && tok_is_(tline->next, "+")) {
1476 tline = tline->next;
1477 searching.plus = TRUE;
1478 }
H. Peter Anvin97a23472007-09-16 17:57:25 -07001479 mmac = (MMacro *) hash_findix(mmacros, searching.name);
1480 while (mmac) {
1481 if (!strcmp(mmac->name, searching.name) &&
1482 (mmac->nparam_min <= searching.nparam_max
1483 || searching.plus)
1484 && (searching.nparam_min <= mmac->nparam_max
1485 || mmac->plus)) {
1486 found = TRUE;
1487 break;
1488 }
1489 mmac = mmac->next;
1490 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001491 nasm_free(searching.name);
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001492 j = found;
1493 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001494 }
H. Peter Anvin65747262002-05-07 00:10:05 +00001495
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001496 case PPC_IFID:
1497 needtype = TOK_ID;
1498 goto iftype;
1499 case PPC_IFNUM:
1500 needtype = TOK_NUMBER;
1501 goto iftype;
1502 case PPC_IFSTR:
1503 needtype = TOK_STRING;
1504 goto iftype;
1505
1506 iftype:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001507 tline = expand_smacro(tline);
1508 t = tline;
1509 while (tok_type_(t, TOK_WHITESPACE))
1510 t = t->next;
1511 j = FALSE; /* placate optimiser */
1512 if (t)
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001513 j = t->type == needtype;
1514 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001515
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001516 case PPC_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001517 t = tline = expand_smacro(tline);
1518 tptr = &t;
1519 tokval.t_type = TOKEN_INVALID;
1520 evalresult = evaluate(ppscan, tptr, &tokval,
1521 NULL, pass | CRITICAL, error, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001522 if (!evalresult)
1523 return -1;
1524 if (tokval.t_type)
1525 error(ERR_WARNING,
1526 "trailing garbage after expression ignored");
1527 if (!is_simple(evalresult)) {
1528 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001529 "non-constant value given to `%s'", pp_directives[ct]);
1530 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001531 }
Chuck Crayne60ae75d2007-05-02 01:59:16 +00001532 j = reloc_value(evalresult) != 0;
Chuck Crayne60ae75d2007-05-02 01:59:16 +00001533 return j;
H. Peter Anvin95e28822007-09-12 04:20:08 +00001534
H. Peter Anvine2c80182005-01-15 22:15:51 +00001535 default:
1536 error(ERR_FATAL,
1537 "preprocessor directive `%s' not yet implemented",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001538 pp_directives[ct]);
1539 goto fail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001540 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001541
1542 free_tlist(origline);
1543 return j ^ PP_NEGATIVE(ct);
1544
1545fail:
1546 free_tlist(origline);
1547 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001548}
1549
1550/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001551 * Expand macros in a string. Used in %error and %include directives.
Keith Kaniosb7a89542007-04-12 02:40:54 +00001552 * First tokenize the string, apply "expand_smacro" and then de-tokenize back.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001553 * The returned variable should ALWAYS be freed after usage.
1554 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001555void expand_macros_in_string(char **p)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001556{
Keith Kaniosb7a89542007-04-12 02:40:54 +00001557 Token *line = tokenize(*p);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001558 line = expand_smacro(line);
1559 *p = detoken(line, FALSE);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001560}
1561
Ed Beroset3ab3f412002-06-11 03:31:49 +00001562/**
1563 * find and process preprocessor directive in passed line
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001564 * Find out if a line contains a preprocessor directive, and deal
1565 * with it if so.
1566 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00001567 * If a directive _is_ found, it is the responsibility of this routine
1568 * (and not the caller) to free_tlist() the line.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001569 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00001570 * @param tline a pointer to the current tokeninzed line linked list
1571 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001572 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001573 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001574static int do_directive(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001575{
H. Peter Anvin4169a472007-09-12 01:29:43 +00001576 enum preproc_token i;
1577 int j;
1578 int nparam, nolist;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -07001579 int k, m;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001580 int offset;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001581 char *p, *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001582 Include *inc;
1583 Context *ctx;
1584 Cond *cond;
1585 SMacro *smac, **smhead;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001586 MMacro *mmac, **mmhead;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001587 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
1588 Line *l;
1589 struct tokenval tokval;
1590 expr *evalresult;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001591 MMacro *tmp_defining; /* Used when manipulating rep_nest */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001592
1593 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001594
H. Peter Anvineba20a72002-04-30 20:53:55 +00001595 skip_white_(tline);
1596 if (!tok_type_(tline, TOK_PREPROC_ID) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001597 (tline->text[1] == '%' || tline->text[1] == '$'
1598 || tline->text[1] == '!'))
1599 return NO_DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001600
H. Peter Anvin4169a472007-09-12 01:29:43 +00001601 i = pp_token_hash(tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001602
1603 /*
1604 * If we're in a non-emitting branch of a condition construct,
H. Peter Anvin76690a12002-04-30 20:52:49 +00001605 * or walking to the end of an already terminated %rep block,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001606 * we should ignore all directives except for condition
1607 * directives.
1608 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001609 if (((istk->conds && !emitting(istk->conds->state)) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001610 (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
1611 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001612 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001613
1614 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001615 * If we're defining a macro or reading a %rep block, we should
1616 * ignore all directives except for %macro/%imacro (which
1617 * generate an error), %endm/%endmacro, and (only if we're in a
H. Peter Anvineba20a72002-04-30 20:53:55 +00001618 * %rep block) %endrep. If we're in a %rep block, another %rep
1619 * causes an error, so should be let through.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001620 */
1621 if (defining && i != PP_MACRO && i != PP_IMACRO &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001622 i != PP_ENDMACRO && i != PP_ENDM &&
1623 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
1624 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001625 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001626
H. Peter Anvin4169a472007-09-12 01:29:43 +00001627 switch (i) {
1628 case PP_INVALID:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001629 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
1630 tline->text);
1631 return NO_DIRECTIVE_FOUND; /* didn't get it */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001632
H. Peter Anvine2c80182005-01-15 22:15:51 +00001633 case PP_STACKSIZE:
1634 /* Directive to tell NASM what the default stack size is. The
1635 * default is for a 16-bit stack, and this can be overriden with
1636 * %stacksize large.
1637 * the following form:
1638 *
1639 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1640 */
1641 tline = tline->next;
1642 if (tline && tline->type == TOK_WHITESPACE)
1643 tline = tline->next;
1644 if (!tline || tline->type != TOK_ID) {
1645 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
1646 free_tlist(origline);
1647 return DIRECTIVE_FOUND;
1648 }
1649 if (nasm_stricmp(tline->text, "flat") == 0) {
1650 /* All subsequent ARG directives are for a 32-bit stack */
1651 StackSize = 4;
1652 StackPointer = "ebp";
1653 ArgOffset = 8;
1654 LocalOffset = 4;
1655 } else if (nasm_stricmp(tline->text, "large") == 0) {
1656 /* All subsequent ARG directives are for a 16-bit stack,
1657 * far function call.
1658 */
1659 StackSize = 2;
1660 StackPointer = "bp";
1661 ArgOffset = 4;
1662 LocalOffset = 2;
1663 } else if (nasm_stricmp(tline->text, "small") == 0) {
1664 /* All subsequent ARG directives are for a 16-bit stack,
1665 * far function call. We don't support near functions.
1666 */
1667 StackSize = 2;
1668 StackPointer = "bp";
1669 ArgOffset = 6;
1670 LocalOffset = 2;
1671 } else {
1672 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
1673 free_tlist(origline);
1674 return DIRECTIVE_FOUND;
1675 }
1676 free_tlist(origline);
1677 return DIRECTIVE_FOUND;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001678
H. Peter Anvine2c80182005-01-15 22:15:51 +00001679 case PP_ARG:
1680 /* TASM like ARG directive to define arguments to functions, in
1681 * the following form:
1682 *
1683 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1684 */
1685 offset = ArgOffset;
1686 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001687 char *arg, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00001688 int size = StackSize;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001689
H. Peter Anvine2c80182005-01-15 22:15:51 +00001690 /* Find the argument name */
1691 tline = tline->next;
1692 if (tline && tline->type == TOK_WHITESPACE)
1693 tline = tline->next;
1694 if (!tline || tline->type != TOK_ID) {
1695 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
1696 free_tlist(origline);
1697 return DIRECTIVE_FOUND;
1698 }
1699 arg = tline->text;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001700
H. Peter Anvine2c80182005-01-15 22:15:51 +00001701 /* Find the argument size type */
1702 tline = tline->next;
1703 if (!tline || tline->type != TOK_OTHER
1704 || tline->text[0] != ':') {
1705 error(ERR_NONFATAL,
1706 "Syntax error processing `%%arg' directive");
1707 free_tlist(origline);
1708 return DIRECTIVE_FOUND;
1709 }
1710 tline = tline->next;
1711 if (!tline || tline->type != TOK_ID) {
1712 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
1713 free_tlist(origline);
1714 return DIRECTIVE_FOUND;
1715 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001716
H. Peter Anvine2c80182005-01-15 22:15:51 +00001717 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001718 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001719 tt = expand_smacro(tt);
1720 if (nasm_stricmp(tt->text, "byte") == 0) {
1721 size = MAX(StackSize, 1);
1722 } else if (nasm_stricmp(tt->text, "word") == 0) {
1723 size = MAX(StackSize, 2);
1724 } else if (nasm_stricmp(tt->text, "dword") == 0) {
1725 size = MAX(StackSize, 4);
1726 } else if (nasm_stricmp(tt->text, "qword") == 0) {
1727 size = MAX(StackSize, 8);
1728 } else if (nasm_stricmp(tt->text, "tword") == 0) {
1729 size = MAX(StackSize, 10);
1730 } else {
1731 error(ERR_NONFATAL,
1732 "Invalid size type for `%%arg' missing directive");
1733 free_tlist(tt);
1734 free_tlist(origline);
1735 return DIRECTIVE_FOUND;
1736 }
1737 free_tlist(tt);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001738
H. Peter Anvine2c80182005-01-15 22:15:51 +00001739 /* Now define the macro for the argument */
1740 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
1741 arg, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001742 do_directive(tokenize(directive));
H. Peter Anvine2c80182005-01-15 22:15:51 +00001743 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001744
H. Peter Anvine2c80182005-01-15 22:15:51 +00001745 /* Move to the next argument in the list */
1746 tline = tline->next;
1747 if (tline && tline->type == TOK_WHITESPACE)
1748 tline = tline->next;
1749 }
1750 while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
1751 free_tlist(origline);
1752 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001753
H. Peter Anvine2c80182005-01-15 22:15:51 +00001754 case PP_LOCAL:
1755 /* TASM like LOCAL directive to define local variables for a
1756 * function, in the following form:
1757 *
1758 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
1759 *
1760 * The '= LocalSize' at the end is ignored by NASM, but is
1761 * required by TASM to define the local parameter size (and used
1762 * by the TASM macro package).
1763 */
1764 offset = LocalOffset;
1765 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001766 char *local, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00001767 int size = StackSize;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001768
H. Peter Anvine2c80182005-01-15 22:15:51 +00001769 /* Find the argument name */
1770 tline = tline->next;
1771 if (tline && tline->type == TOK_WHITESPACE)
1772 tline = tline->next;
1773 if (!tline || tline->type != TOK_ID) {
1774 error(ERR_NONFATAL,
1775 "`%%local' missing argument parameter");
1776 free_tlist(origline);
1777 return DIRECTIVE_FOUND;
1778 }
1779 local = tline->text;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001780
H. Peter Anvine2c80182005-01-15 22:15:51 +00001781 /* Find the argument size type */
1782 tline = tline->next;
1783 if (!tline || tline->type != TOK_OTHER
1784 || tline->text[0] != ':') {
1785 error(ERR_NONFATAL,
1786 "Syntax error processing `%%local' directive");
1787 free_tlist(origline);
1788 return DIRECTIVE_FOUND;
1789 }
1790 tline = tline->next;
1791 if (!tline || tline->type != TOK_ID) {
1792 error(ERR_NONFATAL,
1793 "`%%local' missing size type parameter");
1794 free_tlist(origline);
1795 return DIRECTIVE_FOUND;
1796 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001797
H. Peter Anvine2c80182005-01-15 22:15:51 +00001798 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001799 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001800 tt = expand_smacro(tt);
1801 if (nasm_stricmp(tt->text, "byte") == 0) {
1802 size = MAX(StackSize, 1);
1803 } else if (nasm_stricmp(tt->text, "word") == 0) {
1804 size = MAX(StackSize, 2);
1805 } else if (nasm_stricmp(tt->text, "dword") == 0) {
1806 size = MAX(StackSize, 4);
1807 } else if (nasm_stricmp(tt->text, "qword") == 0) {
1808 size = MAX(StackSize, 8);
1809 } else if (nasm_stricmp(tt->text, "tword") == 0) {
1810 size = MAX(StackSize, 10);
1811 } else {
1812 error(ERR_NONFATAL,
1813 "Invalid size type for `%%local' missing directive");
1814 free_tlist(tt);
1815 free_tlist(origline);
1816 return DIRECTIVE_FOUND;
1817 }
1818 free_tlist(tt);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001819
H. Peter Anvine2c80182005-01-15 22:15:51 +00001820 /* Now define the macro for the argument */
1821 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
1822 local, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001823 do_directive(tokenize(directive));
H. Peter Anvine2c80182005-01-15 22:15:51 +00001824 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001825
H. Peter Anvine2c80182005-01-15 22:15:51 +00001826 /* Now define the assign to setup the enter_c macro correctly */
1827 snprintf(directive, sizeof(directive),
1828 "%%assign %%$localsize %%$localsize+%d", size);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001829 do_directive(tokenize(directive));
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001830
H. Peter Anvine2c80182005-01-15 22:15:51 +00001831 /* Move to the next argument in the list */
1832 tline = tline->next;
1833 if (tline && tline->type == TOK_WHITESPACE)
1834 tline = tline->next;
1835 }
1836 while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
1837 free_tlist(origline);
1838 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001839
H. Peter Anvine2c80182005-01-15 22:15:51 +00001840 case PP_CLEAR:
1841 if (tline->next)
1842 error(ERR_WARNING, "trailing garbage after `%%clear' ignored");
H. Peter Anvin97a23472007-09-16 17:57:25 -07001843 free_macros();
1844 init_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001845 free_tlist(origline);
1846 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001847
H. Peter Anvine2c80182005-01-15 22:15:51 +00001848 case PP_INCLUDE:
1849 tline = tline->next;
1850 skip_white_(tline);
1851 if (!tline || (tline->type != TOK_STRING &&
1852 tline->type != TOK_INTERNAL_STRING)) {
1853 error(ERR_NONFATAL, "`%%include' expects a file name");
1854 free_tlist(origline);
1855 return DIRECTIVE_FOUND; /* but we did _something_ */
1856 }
1857 if (tline->next)
1858 error(ERR_WARNING,
1859 "trailing garbage after `%%include' ignored");
1860 if (tline->type != TOK_INTERNAL_STRING) {
1861 p = tline->text + 1; /* point past the quote to the name */
1862 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
1863 } else
1864 p = tline->text; /* internal_string is easier */
1865 expand_macros_in_string(&p);
1866 inc = nasm_malloc(sizeof(Include));
1867 inc->next = istk;
1868 inc->conds = NULL;
1869 inc->fp = inc_fopen(p);
1870 inc->fname = src_set_fname(p);
1871 inc->lineno = src_set_linnum(0);
1872 inc->lineinc = 1;
1873 inc->expansion = NULL;
1874 inc->mstk = NULL;
1875 istk = inc;
1876 list->uplevel(LIST_INCLUDE);
1877 free_tlist(origline);
1878 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001879
H. Peter Anvine2c80182005-01-15 22:15:51 +00001880 case PP_PUSH:
1881 tline = tline->next;
1882 skip_white_(tline);
1883 tline = expand_id(tline);
1884 if (!tok_type_(tline, TOK_ID)) {
1885 error(ERR_NONFATAL, "`%%push' expects a context identifier");
1886 free_tlist(origline);
1887 return DIRECTIVE_FOUND; /* but we did _something_ */
1888 }
1889 if (tline->next)
1890 error(ERR_WARNING, "trailing garbage after `%%push' ignored");
1891 ctx = nasm_malloc(sizeof(Context));
1892 ctx->next = cstk;
1893 ctx->localmac = NULL;
1894 ctx->name = nasm_strdup(tline->text);
1895 ctx->number = unique++;
1896 cstk = ctx;
1897 free_tlist(origline);
1898 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001899
H. Peter Anvine2c80182005-01-15 22:15:51 +00001900 case PP_REPL:
1901 tline = tline->next;
1902 skip_white_(tline);
1903 tline = expand_id(tline);
1904 if (!tok_type_(tline, TOK_ID)) {
1905 error(ERR_NONFATAL, "`%%repl' expects a context identifier");
1906 free_tlist(origline);
1907 return DIRECTIVE_FOUND; /* but we did _something_ */
1908 }
1909 if (tline->next)
1910 error(ERR_WARNING, "trailing garbage after `%%repl' ignored");
1911 if (!cstk)
1912 error(ERR_NONFATAL, "`%%repl': context stack is empty");
1913 else {
1914 nasm_free(cstk->name);
1915 cstk->name = nasm_strdup(tline->text);
1916 }
1917 free_tlist(origline);
1918 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001919
H. Peter Anvine2c80182005-01-15 22:15:51 +00001920 case PP_POP:
1921 if (tline->next)
1922 error(ERR_WARNING, "trailing garbage after `%%pop' ignored");
1923 if (!cstk)
1924 error(ERR_NONFATAL, "`%%pop': context stack is already empty");
1925 else
1926 ctx_pop();
1927 free_tlist(origline);
1928 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001929
H. Peter Anvine2c80182005-01-15 22:15:51 +00001930 case PP_ERROR:
1931 tline->next = expand_smacro(tline->next);
1932 tline = tline->next;
1933 skip_white_(tline);
1934 if (tok_type_(tline, TOK_STRING)) {
1935 p = tline->text + 1; /* point past the quote to the name */
1936 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
1937 expand_macros_in_string(&p);
1938 error(ERR_NONFATAL, "%s", p);
1939 nasm_free(p);
1940 } else {
1941 p = detoken(tline, FALSE);
1942 error(ERR_WARNING, "%s", p);
1943 nasm_free(p);
1944 }
1945 free_tlist(origline);
1946 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001947
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001948 CASE_PP_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001949 if (istk->conds && !emitting(istk->conds->state))
1950 j = COND_NEVER;
1951 else {
1952 j = if_condition(tline->next, i);
1953 tline->next = NULL; /* it got freed */
1954 free_tlist(origline);
1955 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
1956 }
1957 cond = nasm_malloc(sizeof(Cond));
1958 cond->next = istk->conds;
1959 cond->state = j;
1960 istk->conds = cond;
1961 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001962
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001963 CASE_PP_ELIF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001964 if (!istk->conds)
H. Peter Anvin4169a472007-09-12 01:29:43 +00001965 error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001966 if (emitting(istk->conds->state)
1967 || istk->conds->state == COND_NEVER)
1968 istk->conds->state = COND_NEVER;
1969 else {
1970 /*
1971 * IMPORTANT: In the case of %if, we will already have
1972 * called expand_mmac_params(); however, if we're
1973 * processing an %elif we must have been in a
1974 * non-emitting mode, which would have inhibited
1975 * the normal invocation of expand_mmac_params(). Therefore,
1976 * we have to do it explicitly here.
1977 */
1978 j = if_condition(expand_mmac_params(tline->next), i);
1979 tline->next = NULL; /* it got freed */
1980 free_tlist(origline);
1981 istk->conds->state =
1982 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
1983 }
1984 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001985
H. Peter Anvine2c80182005-01-15 22:15:51 +00001986 case PP_ELSE:
1987 if (tline->next)
1988 error(ERR_WARNING, "trailing garbage after `%%else' ignored");
1989 if (!istk->conds)
1990 error(ERR_FATAL, "`%%else': no matching `%%if'");
1991 if (emitting(istk->conds->state)
1992 || istk->conds->state == COND_NEVER)
1993 istk->conds->state = COND_ELSE_FALSE;
1994 else
1995 istk->conds->state = COND_ELSE_TRUE;
1996 free_tlist(origline);
1997 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001998
H. Peter Anvine2c80182005-01-15 22:15:51 +00001999 case PP_ENDIF:
2000 if (tline->next)
2001 error(ERR_WARNING, "trailing garbage after `%%endif' ignored");
2002 if (!istk->conds)
2003 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2004 cond = istk->conds;
2005 istk->conds = cond->next;
2006 nasm_free(cond);
2007 free_tlist(origline);
2008 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002009
H. Peter Anvine2c80182005-01-15 22:15:51 +00002010 case PP_MACRO:
2011 case PP_IMACRO:
2012 if (defining)
2013 error(ERR_FATAL,
2014 "`%%%smacro': already defining a macro",
2015 (i == PP_IMACRO ? "i" : ""));
2016 tline = tline->next;
2017 skip_white_(tline);
2018 tline = expand_id(tline);
2019 if (!tok_type_(tline, TOK_ID)) {
2020 error(ERR_NONFATAL,
2021 "`%%%smacro' expects a macro name",
2022 (i == PP_IMACRO ? "i" : ""));
2023 return DIRECTIVE_FOUND;
2024 }
2025 defining = nasm_malloc(sizeof(MMacro));
2026 defining->name = nasm_strdup(tline->text);
2027 defining->casesense = (i == PP_MACRO);
2028 defining->plus = FALSE;
2029 defining->nolist = FALSE;
2030 defining->in_progress = FALSE;
2031 defining->rep_nest = NULL;
2032 tline = expand_smacro(tline->next);
2033 skip_white_(tline);
2034 if (!tok_type_(tline, TOK_NUMBER)) {
2035 error(ERR_NONFATAL,
2036 "`%%%smacro' expects a parameter count",
2037 (i == PP_IMACRO ? "i" : ""));
2038 defining->nparam_min = defining->nparam_max = 0;
2039 } else {
2040 defining->nparam_min = defining->nparam_max =
2041 readnum(tline->text, &j);
2042 if (j)
2043 error(ERR_NONFATAL,
2044 "unable to parse parameter count `%s'", tline->text);
2045 }
2046 if (tline && tok_is_(tline->next, "-")) {
2047 tline = tline->next->next;
2048 if (tok_is_(tline, "*"))
2049 defining->nparam_max = INT_MAX;
2050 else if (!tok_type_(tline, TOK_NUMBER))
2051 error(ERR_NONFATAL,
2052 "`%%%smacro' expects a parameter count after `-'",
2053 (i == PP_IMACRO ? "i" : ""));
2054 else {
2055 defining->nparam_max = readnum(tline->text, &j);
2056 if (j)
2057 error(ERR_NONFATAL,
2058 "unable to parse parameter count `%s'",
2059 tline->text);
2060 if (defining->nparam_min > defining->nparam_max)
2061 error(ERR_NONFATAL,
2062 "minimum parameter count exceeds maximum");
2063 }
2064 }
2065 if (tline && tok_is_(tline->next, "+")) {
2066 tline = tline->next;
2067 defining->plus = TRUE;
2068 }
2069 if (tline && tok_type_(tline->next, TOK_ID) &&
2070 !nasm_stricmp(tline->next->text, ".nolist")) {
2071 tline = tline->next;
2072 defining->nolist = TRUE;
2073 }
H. Peter Anvin97a23472007-09-16 17:57:25 -07002074 mmac = (MMacro *) hash_findix(mmacros, defining->name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002075 while (mmac) {
2076 if (!strcmp(mmac->name, defining->name) &&
2077 (mmac->nparam_min <= defining->nparam_max
2078 || defining->plus)
2079 && (defining->nparam_min <= mmac->nparam_max
2080 || mmac->plus)) {
2081 error(ERR_WARNING,
2082 "redefining multi-line macro `%s'", defining->name);
2083 break;
2084 }
2085 mmac = mmac->next;
2086 }
2087 /*
2088 * Handle default parameters.
2089 */
2090 if (tline && tline->next) {
2091 defining->dlist = tline->next;
2092 tline->next = NULL;
2093 count_mmac_params(defining->dlist, &defining->ndefs,
2094 &defining->defaults);
2095 } else {
2096 defining->dlist = NULL;
2097 defining->defaults = NULL;
2098 }
2099 defining->expansion = NULL;
2100 free_tlist(origline);
2101 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002102
H. Peter Anvine2c80182005-01-15 22:15:51 +00002103 case PP_ENDM:
2104 case PP_ENDMACRO:
2105 if (!defining) {
2106 error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2107 return DIRECTIVE_FOUND;
2108 }
H. Peter Anvin97a23472007-09-16 17:57:25 -07002109 mmhead = (MMacro **) hash_findi_add(mmacros, defining->name);
2110 defining->next = *mmhead;
2111 *mmhead = defining;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002112 defining = NULL;
2113 free_tlist(origline);
2114 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002115
H. Peter Anvine2c80182005-01-15 22:15:51 +00002116 case PP_ROTATE:
2117 if (tline->next && tline->next->type == TOK_WHITESPACE)
2118 tline = tline->next;
2119 if (tline->next == NULL) {
2120 free_tlist(origline);
2121 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
2122 return DIRECTIVE_FOUND;
2123 }
2124 t = expand_smacro(tline->next);
2125 tline->next = NULL;
2126 free_tlist(origline);
2127 tline = t;
2128 tptr = &t;
2129 tokval.t_type = TOKEN_INVALID;
2130 evalresult =
2131 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2132 free_tlist(tline);
2133 if (!evalresult)
2134 return DIRECTIVE_FOUND;
2135 if (tokval.t_type)
2136 error(ERR_WARNING,
2137 "trailing garbage after expression ignored");
2138 if (!is_simple(evalresult)) {
2139 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2140 return DIRECTIVE_FOUND;
2141 }
2142 mmac = istk->mstk;
2143 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2144 mmac = mmac->next_active;
2145 if (!mmac) {
2146 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
2147 } else if (mmac->nparam == 0) {
2148 error(ERR_NONFATAL,
2149 "`%%rotate' invoked within macro without parameters");
2150 } else {
2151 mmac->rotate = mmac->rotate + reloc_value(evalresult);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002152
H. Peter Anvine2c80182005-01-15 22:15:51 +00002153 if (mmac->rotate < 0)
2154 mmac->rotate =
2155 mmac->nparam - (-mmac->rotate) % mmac->nparam;
2156 mmac->rotate %= mmac->nparam;
2157 }
2158 return DIRECTIVE_FOUND;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002159
H. Peter Anvine2c80182005-01-15 22:15:51 +00002160 case PP_REP:
2161 nolist = FALSE;
2162 do {
2163 tline = tline->next;
2164 } while (tok_type_(tline, TOK_WHITESPACE));
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002165
H. Peter Anvine2c80182005-01-15 22:15:51 +00002166 if (tok_type_(tline, TOK_ID) &&
2167 nasm_stricmp(tline->text, ".nolist") == 0) {
2168 nolist = TRUE;
2169 do {
2170 tline = tline->next;
2171 } while (tok_type_(tline, TOK_WHITESPACE));
2172 }
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002173
H. Peter Anvine2c80182005-01-15 22:15:51 +00002174 if (tline) {
2175 t = expand_smacro(tline);
2176 tptr = &t;
2177 tokval.t_type = TOKEN_INVALID;
2178 evalresult =
2179 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2180 if (!evalresult) {
2181 free_tlist(origline);
2182 return DIRECTIVE_FOUND;
2183 }
2184 if (tokval.t_type)
2185 error(ERR_WARNING,
2186 "trailing garbage after expression ignored");
2187 if (!is_simple(evalresult)) {
2188 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2189 return DIRECTIVE_FOUND;
2190 }
2191 i = (int)reloc_value(evalresult) + 1;
2192 } else {
2193 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
2194 i = 0;
2195 }
2196 free_tlist(origline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002197
H. Peter Anvine2c80182005-01-15 22:15:51 +00002198 tmp_defining = defining;
2199 defining = nasm_malloc(sizeof(MMacro));
2200 defining->name = NULL; /* flags this macro as a %rep block */
2201 defining->casesense = 0;
2202 defining->plus = FALSE;
2203 defining->nolist = nolist;
2204 defining->in_progress = i;
2205 defining->nparam_min = defining->nparam_max = 0;
2206 defining->defaults = NULL;
2207 defining->dlist = NULL;
2208 defining->expansion = NULL;
2209 defining->next_active = istk->mstk;
2210 defining->rep_nest = tmp_defining;
2211 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002212
H. Peter Anvine2c80182005-01-15 22:15:51 +00002213 case PP_ENDREP:
2214 if (!defining || defining->name) {
2215 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2216 return DIRECTIVE_FOUND;
2217 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002218
H. Peter Anvine2c80182005-01-15 22:15:51 +00002219 /*
2220 * Now we have a "macro" defined - although it has no name
2221 * and we won't be entering it in the hash tables - we must
2222 * push a macro-end marker for it on to istk->expansion.
2223 * After that, it will take care of propagating itself (a
2224 * macro-end marker line for a macro which is really a %rep
2225 * block will cause the macro to be re-expanded, complete
2226 * with another macro-end marker to ensure the process
2227 * continues) until the whole expansion is forcibly removed
2228 * from istk->expansion by a %exitrep.
2229 */
2230 l = nasm_malloc(sizeof(Line));
2231 l->next = istk->expansion;
2232 l->finishes = defining;
2233 l->first = NULL;
2234 istk->expansion = l;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002235
H. Peter Anvine2c80182005-01-15 22:15:51 +00002236 istk->mstk = defining;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002237
H. Peter Anvine2c80182005-01-15 22:15:51 +00002238 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2239 tmp_defining = defining;
2240 defining = defining->rep_nest;
2241 free_tlist(origline);
2242 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002243
H. Peter Anvine2c80182005-01-15 22:15:51 +00002244 case PP_EXITREP:
2245 /*
2246 * We must search along istk->expansion until we hit a
2247 * macro-end marker for a macro with no name. Then we set
2248 * its `in_progress' flag to 0.
2249 */
2250 for (l = istk->expansion; l; l = l->next)
2251 if (l->finishes && !l->finishes->name)
2252 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002253
H. Peter Anvine2c80182005-01-15 22:15:51 +00002254 if (l)
2255 l->finishes->in_progress = 0;
2256 else
2257 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2258 free_tlist(origline);
2259 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002260
H. Peter Anvine2c80182005-01-15 22:15:51 +00002261 case PP_XDEFINE:
2262 case PP_IXDEFINE:
2263 case PP_DEFINE:
2264 case PP_IDEFINE:
2265 tline = tline->next;
2266 skip_white_(tline);
2267 tline = expand_id(tline);
2268 if (!tline || (tline->type != TOK_ID &&
2269 (tline->type != TOK_PREPROC_ID ||
2270 tline->text[1] != '$'))) {
2271 error(ERR_NONFATAL,
2272 "`%%%s%sdefine' expects a macro identifier",
2273 ((i == PP_IDEFINE || i == PP_IXDEFINE) ? "i" : ""),
2274 ((i == PP_XDEFINE || i == PP_IXDEFINE) ? "x" : ""));
2275 free_tlist(origline);
2276 return DIRECTIVE_FOUND;
2277 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002278
H. Peter Anvine2c80182005-01-15 22:15:51 +00002279 ctx = get_ctx(tline->text, FALSE);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002280
H. Peter Anvine2c80182005-01-15 22:15:51 +00002281 mname = tline->text;
2282 last = tline;
2283 param_start = tline = tline->next;
2284 nparam = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002285
H. Peter Anvine2c80182005-01-15 22:15:51 +00002286 /* Expand the macro definition now for %xdefine and %ixdefine */
2287 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2288 tline = expand_smacro(tline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002289
H. Peter Anvine2c80182005-01-15 22:15:51 +00002290 if (tok_is_(tline, "(")) {
2291 /*
2292 * This macro has parameters.
2293 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002294
H. Peter Anvine2c80182005-01-15 22:15:51 +00002295 tline = tline->next;
2296 while (1) {
2297 skip_white_(tline);
2298 if (!tline) {
2299 error(ERR_NONFATAL, "parameter identifier expected");
2300 free_tlist(origline);
2301 return DIRECTIVE_FOUND;
2302 }
2303 if (tline->type != TOK_ID) {
2304 error(ERR_NONFATAL,
2305 "`%s': parameter identifier expected",
2306 tline->text);
2307 free_tlist(origline);
2308 return DIRECTIVE_FOUND;
2309 }
2310 tline->type = TOK_SMAC_PARAM + nparam++;
2311 tline = tline->next;
2312 skip_white_(tline);
2313 if (tok_is_(tline, ",")) {
2314 tline = tline->next;
2315 continue;
2316 }
2317 if (!tok_is_(tline, ")")) {
2318 error(ERR_NONFATAL,
2319 "`)' expected to terminate macro template");
2320 free_tlist(origline);
2321 return DIRECTIVE_FOUND;
2322 }
2323 break;
2324 }
2325 last = tline;
2326 tline = tline->next;
2327 }
2328 if (tok_type_(tline, TOK_WHITESPACE))
2329 last = tline, tline = tline->next;
2330 macro_start = NULL;
2331 last->next = NULL;
2332 t = tline;
2333 while (t) {
2334 if (t->type == TOK_ID) {
2335 for (tt = param_start; tt; tt = tt->next)
2336 if (tt->type >= TOK_SMAC_PARAM &&
2337 !strcmp(tt->text, t->text))
2338 t->type = tt->type;
2339 }
2340 tt = t->next;
2341 t->next = macro_start;
2342 macro_start = t;
2343 t = tt;
2344 }
2345 /*
2346 * Good. We now have a macro name, a parameter count, and a
2347 * token list (in reverse order) for an expansion. We ought
2348 * to be OK just to create an SMacro, store it, and let
2349 * free_tlist have the rest of the line (which we have
2350 * carefully re-terminated after chopping off the expansion
2351 * from the end).
2352 */
2353 if (smacro_defined(ctx, mname, nparam, &smac, i == PP_DEFINE)) {
2354 if (!smac) {
2355 error(ERR_WARNING,
2356 "single-line macro `%s' defined both with and"
2357 " without parameters", mname);
2358 free_tlist(origline);
2359 free_tlist(macro_start);
2360 return DIRECTIVE_FOUND;
2361 } else {
2362 /*
2363 * We're redefining, so we have to take over an
2364 * existing SMacro structure. This means freeing
2365 * what was already in it.
2366 */
2367 nasm_free(smac->name);
2368 free_tlist(smac->expansion);
2369 }
2370 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002371 if (!ctx)
2372 smhead = (SMacro **) hash_findi_add(smacros, mname);
2373 else
2374 smhead = &ctx->localmac;
2375
H. Peter Anvine2c80182005-01-15 22:15:51 +00002376 smac = nasm_malloc(sizeof(SMacro));
2377 smac->next = *smhead;
2378 *smhead = smac;
2379 }
2380 smac->name = nasm_strdup(mname);
2381 smac->casesense = ((i == PP_DEFINE) || (i == PP_XDEFINE));
2382 smac->nparam = nparam;
2383 smac->expansion = macro_start;
2384 smac->in_progress = FALSE;
2385 free_tlist(origline);
2386 return DIRECTIVE_FOUND;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002387
H. Peter Anvine2c80182005-01-15 22:15:51 +00002388 case PP_UNDEF:
2389 tline = tline->next;
2390 skip_white_(tline);
2391 tline = expand_id(tline);
2392 if (!tline || (tline->type != TOK_ID &&
2393 (tline->type != TOK_PREPROC_ID ||
2394 tline->text[1] != '$'))) {
2395 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
2396 free_tlist(origline);
2397 return DIRECTIVE_FOUND;
2398 }
2399 if (tline->next) {
2400 error(ERR_WARNING,
2401 "trailing garbage after macro name ignored");
2402 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002403
H. Peter Anvine2c80182005-01-15 22:15:51 +00002404 /* Find the context that symbol belongs to */
2405 ctx = get_ctx(tline->text, FALSE);
2406 if (!ctx)
H. Peter Anvin97a23472007-09-16 17:57:25 -07002407 smhead = (SMacro **) hash_findi(smacros, tline->text, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002408 else
2409 smhead = &ctx->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002410
H. Peter Anvin97a23472007-09-16 17:57:25 -07002411 if (smhead) {
2412 SMacro *s, **sp;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002413
H. Peter Anvin97a23472007-09-16 17:57:25 -07002414 mname = tline->text;
2415 last = tline;
2416 last->next = NULL;
2417
2418 /*
2419 * We now have a macro name... go hunt for it.
2420 */
2421 for (sp = smhead; *sp; sp = &(*sp)->next) {
2422 s = *sp;
2423 if (!mstrcmp(s->name, tline->text, s->casesense)) {
2424 *sp = s->next;
2425 nasm_free(s->name);
2426 free_tlist(s->expansion);
2427 nasm_free(s);
2428 }
2429 }
2430 free_tlist(origline);
2431 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002432 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002433
H. Peter Anvine2c80182005-01-15 22:15:51 +00002434 case PP_STRLEN:
2435 tline = tline->next;
2436 skip_white_(tline);
2437 tline = expand_id(tline);
2438 if (!tline || (tline->type != TOK_ID &&
2439 (tline->type != TOK_PREPROC_ID ||
2440 tline->text[1] != '$'))) {
2441 error(ERR_NONFATAL,
2442 "`%%strlen' expects a macro identifier as first parameter");
2443 free_tlist(origline);
2444 return DIRECTIVE_FOUND;
2445 }
2446 ctx = get_ctx(tline->text, FALSE);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002447
H. Peter Anvine2c80182005-01-15 22:15:51 +00002448 mname = tline->text;
2449 last = tline;
2450 tline = expand_smacro(tline->next);
2451 last->next = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002452
H. Peter Anvine2c80182005-01-15 22:15:51 +00002453 t = tline;
2454 while (tok_type_(t, TOK_WHITESPACE))
2455 t = t->next;
2456 /* t should now point to the string */
2457 if (t->type != TOK_STRING) {
2458 error(ERR_NONFATAL,
2459 "`%%strlen` requires string as second parameter");
2460 free_tlist(tline);
2461 free_tlist(origline);
2462 return DIRECTIVE_FOUND;
2463 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002464
H. Peter Anvine2c80182005-01-15 22:15:51 +00002465 macro_start = nasm_malloc(sizeof(*macro_start));
2466 macro_start->next = NULL;
2467 make_tok_num(macro_start, strlen(t->text) - 2);
2468 macro_start->mac = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002469
H. Peter Anvine2c80182005-01-15 22:15:51 +00002470 /*
2471 * We now have a macro name, an implicit parameter count of
2472 * zero, and a numeric token to use as an expansion. Create
2473 * and store an SMacro.
2474 */
2475 if (smacro_defined(ctx, mname, 0, &smac, i == PP_STRLEN)) {
2476 if (!smac)
2477 error(ERR_WARNING,
2478 "single-line macro `%s' defined both with and"
2479 " without parameters", mname);
2480 else {
2481 /*
2482 * We're redefining, so we have to take over an
2483 * existing SMacro structure. This means freeing
2484 * what was already in it.
2485 */
2486 nasm_free(smac->name);
2487 free_tlist(smac->expansion);
2488 }
2489 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002490 if (!ctx)
2491 smhead = (SMacro **) hash_findi_add(smacros, mname);
2492 else
2493 smhead = &ctx->localmac;
2494
H. Peter Anvine2c80182005-01-15 22:15:51 +00002495 smac = nasm_malloc(sizeof(SMacro));
2496 smac->next = *smhead;
2497 *smhead = smac;
2498 }
2499 smac->name = nasm_strdup(mname);
2500 smac->casesense = (i == PP_STRLEN);
2501 smac->nparam = 0;
2502 smac->expansion = macro_start;
2503 smac->in_progress = FALSE;
2504 free_tlist(tline);
2505 free_tlist(origline);
2506 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002507
H. Peter Anvine2c80182005-01-15 22:15:51 +00002508 case PP_SUBSTR:
2509 tline = tline->next;
2510 skip_white_(tline);
2511 tline = expand_id(tline);
2512 if (!tline || (tline->type != TOK_ID &&
2513 (tline->type != TOK_PREPROC_ID ||
2514 tline->text[1] != '$'))) {
2515 error(ERR_NONFATAL,
2516 "`%%substr' expects a macro identifier as first parameter");
2517 free_tlist(origline);
2518 return DIRECTIVE_FOUND;
2519 }
2520 ctx = get_ctx(tline->text, FALSE);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002521
H. Peter Anvine2c80182005-01-15 22:15:51 +00002522 mname = tline->text;
2523 last = tline;
2524 tline = expand_smacro(tline->next);
2525 last->next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002526
H. Peter Anvine2c80182005-01-15 22:15:51 +00002527 t = tline->next;
2528 while (tok_type_(t, TOK_WHITESPACE))
2529 t = t->next;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002530
H. Peter Anvine2c80182005-01-15 22:15:51 +00002531 /* t should now point to the string */
2532 if (t->type != TOK_STRING) {
2533 error(ERR_NONFATAL,
2534 "`%%substr` requires string as second parameter");
2535 free_tlist(tline);
2536 free_tlist(origline);
2537 return DIRECTIVE_FOUND;
2538 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002539
H. Peter Anvine2c80182005-01-15 22:15:51 +00002540 tt = t->next;
2541 tptr = &tt;
2542 tokval.t_type = TOKEN_INVALID;
2543 evalresult =
2544 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2545 if (!evalresult) {
2546 free_tlist(tline);
2547 free_tlist(origline);
2548 return DIRECTIVE_FOUND;
2549 }
2550 if (!is_simple(evalresult)) {
2551 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
2552 free_tlist(tline);
2553 free_tlist(origline);
2554 return DIRECTIVE_FOUND;
2555 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002556
H. Peter Anvine2c80182005-01-15 22:15:51 +00002557 macro_start = nasm_malloc(sizeof(*macro_start));
2558 macro_start->next = NULL;
2559 macro_start->text = nasm_strdup("'''");
2560 if (evalresult->value > 0
2561 && evalresult->value < strlen(t->text) - 1) {
2562 macro_start->text[1] = t->text[evalresult->value];
2563 } else {
2564 macro_start->text[2] = '\0';
2565 }
2566 macro_start->type = TOK_STRING;
2567 macro_start->mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002568
H. Peter Anvine2c80182005-01-15 22:15:51 +00002569 /*
2570 * We now have a macro name, an implicit parameter count of
2571 * zero, and a numeric token to use as an expansion. Create
2572 * and store an SMacro.
2573 */
2574 if (smacro_defined(ctx, mname, 0, &smac, i == PP_SUBSTR)) {
2575 if (!smac)
2576 error(ERR_WARNING,
2577 "single-line macro `%s' defined both with and"
2578 " without parameters", mname);
2579 else {
2580 /*
2581 * We're redefining, so we have to take over an
2582 * existing SMacro structure. This means freeing
2583 * what was already in it.
2584 */
2585 nasm_free(smac->name);
2586 free_tlist(smac->expansion);
2587 }
2588 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002589 if (!ctx)
2590 smhead = (SMacro **) hash_findi_add(smacros, tline->text);
2591 else
2592 smhead = &ctx->localmac;
2593
H. Peter Anvine2c80182005-01-15 22:15:51 +00002594 smac = nasm_malloc(sizeof(SMacro));
2595 smac->next = *smhead;
2596 *smhead = smac;
2597 }
2598 smac->name = nasm_strdup(mname);
2599 smac->casesense = (i == PP_SUBSTR);
2600 smac->nparam = 0;
2601 smac->expansion = macro_start;
2602 smac->in_progress = FALSE;
2603 free_tlist(tline);
2604 free_tlist(origline);
2605 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002606
H. Peter Anvine2c80182005-01-15 22:15:51 +00002607 case PP_ASSIGN:
2608 case PP_IASSIGN:
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 error(ERR_NONFATAL,
2616 "`%%%sassign' expects a macro identifier",
2617 (i == PP_IASSIGN ? "i" : ""));
2618 free_tlist(origline);
2619 return DIRECTIVE_FOUND;
2620 }
2621 ctx = get_ctx(tline->text, FALSE);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002622
H. Peter Anvine2c80182005-01-15 22:15:51 +00002623 mname = tline->text;
2624 last = tline;
2625 tline = expand_smacro(tline->next);
2626 last->next = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002627
H. Peter Anvine2c80182005-01-15 22:15:51 +00002628 t = tline;
2629 tptr = &t;
2630 tokval.t_type = TOKEN_INVALID;
2631 evalresult =
2632 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2633 free_tlist(tline);
2634 if (!evalresult) {
2635 free_tlist(origline);
2636 return DIRECTIVE_FOUND;
2637 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002638
H. Peter Anvine2c80182005-01-15 22:15:51 +00002639 if (tokval.t_type)
2640 error(ERR_WARNING,
2641 "trailing garbage after expression ignored");
H. Peter Anvin734b1882002-04-30 21:01:08 +00002642
H. Peter Anvine2c80182005-01-15 22:15:51 +00002643 if (!is_simple(evalresult)) {
2644 error(ERR_NONFATAL,
2645 "non-constant value given to `%%%sassign'",
2646 (i == PP_IASSIGN ? "i" : ""));
2647 free_tlist(origline);
2648 return DIRECTIVE_FOUND;
2649 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002650
H. Peter Anvine2c80182005-01-15 22:15:51 +00002651 macro_start = nasm_malloc(sizeof(*macro_start));
2652 macro_start->next = NULL;
2653 make_tok_num(macro_start, reloc_value(evalresult));
2654 macro_start->mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002655
H. Peter Anvine2c80182005-01-15 22:15:51 +00002656 /*
2657 * We now have a macro name, an implicit parameter count of
2658 * zero, and a numeric token to use as an expansion. Create
2659 * and store an SMacro.
2660 */
2661 if (smacro_defined(ctx, mname, 0, &smac, i == PP_ASSIGN)) {
2662 if (!smac)
2663 error(ERR_WARNING,
2664 "single-line macro `%s' defined both with and"
2665 " without parameters", mname);
2666 else {
2667 /*
2668 * We're redefining, so we have to take over an
2669 * existing SMacro structure. This means freeing
2670 * what was already in it.
2671 */
2672 nasm_free(smac->name);
2673 free_tlist(smac->expansion);
2674 }
2675 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002676 if (!ctx)
2677 smhead = (SMacro **) hash_findi_add(smacros, mname);
2678 else
2679 smhead = &ctx->localmac;
2680
H. Peter Anvine2c80182005-01-15 22:15:51 +00002681 smac = nasm_malloc(sizeof(SMacro));
2682 smac->next = *smhead;
2683 *smhead = smac;
2684 }
2685 smac->name = nasm_strdup(mname);
2686 smac->casesense = (i == PP_ASSIGN);
2687 smac->nparam = 0;
2688 smac->expansion = macro_start;
2689 smac->in_progress = FALSE;
2690 free_tlist(origline);
2691 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002692
H. Peter Anvine2c80182005-01-15 22:15:51 +00002693 case PP_LINE:
2694 /*
2695 * Syntax is `%line nnn[+mmm] [filename]'
2696 */
2697 tline = tline->next;
2698 skip_white_(tline);
2699 if (!tok_type_(tline, TOK_NUMBER)) {
2700 error(ERR_NONFATAL, "`%%line' expects line number");
2701 free_tlist(origline);
2702 return DIRECTIVE_FOUND;
2703 }
2704 k = readnum(tline->text, &j);
2705 m = 1;
2706 tline = tline->next;
2707 if (tok_is_(tline, "+")) {
2708 tline = tline->next;
2709 if (!tok_type_(tline, TOK_NUMBER)) {
2710 error(ERR_NONFATAL, "`%%line' expects line increment");
2711 free_tlist(origline);
2712 return DIRECTIVE_FOUND;
2713 }
2714 m = readnum(tline->text, &j);
2715 tline = tline->next;
2716 }
2717 skip_white_(tline);
2718 src_set_linnum(k);
2719 istk->lineinc = m;
2720 if (tline) {
2721 nasm_free(src_set_fname(detoken(tline, FALSE)));
2722 }
2723 free_tlist(origline);
2724 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002725
H. Peter Anvine2c80182005-01-15 22:15:51 +00002726 default:
2727 error(ERR_FATAL,
2728 "preprocessor directive `%s' not yet implemented",
H. Peter Anvin4169a472007-09-12 01:29:43 +00002729 pp_directives[i]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002730 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002731 }
Ed Beroset3ab3f412002-06-11 03:31:49 +00002732 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002733}
2734
2735/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002736 * Ensure that a macro parameter contains a condition code and
2737 * nothing else. Return the condition code index if so, or -1
2738 * otherwise.
2739 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002740static int find_cc(Token * t)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002741{
H. Peter Anvin76690a12002-04-30 20:52:49 +00002742 Token *tt;
2743 int i, j, k, m;
2744
H. Peter Anvineba20a72002-04-30 20:53:55 +00002745 skip_white_(t);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002746 if (t->type != TOK_ID)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002747 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002748 tt = t->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002749 skip_white_(tt);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002750 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002751 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002752
2753 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +00002754 j = elements(conditions);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002755 while (j - i > 1) {
2756 k = (j + i) / 2;
2757 m = nasm_stricmp(t->text, conditions[k]);
2758 if (m == 0) {
2759 i = k;
2760 j = -2;
2761 break;
2762 } else if (m < 0) {
2763 j = k;
2764 } else
2765 i = k;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002766 }
2767 if (j != -2)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002768 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002769 return i;
2770}
2771
2772/*
2773 * Expand MMacro-local things: parameter references (%0, %n, %+n,
2774 * %-n) and MMacro-local identifiers (%%foo).
2775 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002776static Token *expand_mmac_params(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002777{
H. Peter Anvin734b1882002-04-30 21:01:08 +00002778 Token *t, *tt, **tail, *thead;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002779
2780 tail = &thead;
2781 thead = NULL;
2782
H. Peter Anvine2c80182005-01-15 22:15:51 +00002783 while (tline) {
2784 if (tline->type == TOK_PREPROC_ID &&
2785 (((tline->text[1] == '+' || tline->text[1] == '-')
2786 && tline->text[2]) || tline->text[1] == '%'
2787 || (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002788 char *text = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002789 int type = 0, cc; /* type = 0 to placate optimisers */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002790 char tmpbuf[30];
H. Peter Anvine2c80182005-01-15 22:15:51 +00002791 int n, i;
2792 MMacro *mac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002793
H. Peter Anvine2c80182005-01-15 22:15:51 +00002794 t = tline;
2795 tline = tline->next;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002796
H. Peter Anvine2c80182005-01-15 22:15:51 +00002797 mac = istk->mstk;
2798 while (mac && !mac->name) /* avoid mistaking %reps for macros */
2799 mac = mac->next_active;
2800 if (!mac)
2801 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
2802 else
2803 switch (t->text[1]) {
2804 /*
2805 * We have to make a substitution of one of the
2806 * forms %1, %-1, %+1, %%foo, %0.
2807 */
2808 case '0':
2809 type = TOK_NUMBER;
2810 snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
2811 text = nasm_strdup(tmpbuf);
2812 break;
2813 case '%':
2814 type = TOK_ID;
Keith Kanios93f2e9a2007-04-14 00:10:59 +00002815 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu32".",
H. Peter Anvine2c80182005-01-15 22:15:51 +00002816 mac->unique);
2817 text = nasm_strcat(tmpbuf, t->text + 2);
2818 break;
2819 case '-':
2820 n = atoi(t->text + 2) - 1;
2821 if (n >= mac->nparam)
2822 tt = NULL;
2823 else {
2824 if (mac->nparam > 1)
2825 n = (n + mac->rotate) % mac->nparam;
2826 tt = mac->params[n];
2827 }
2828 cc = find_cc(tt);
2829 if (cc == -1) {
2830 error(ERR_NONFATAL,
2831 "macro parameter %d is not a condition code",
2832 n + 1);
2833 text = NULL;
2834 } else {
2835 type = TOK_ID;
2836 if (inverse_ccs[cc] == -1) {
2837 error(ERR_NONFATAL,
2838 "condition code `%s' is not invertible",
2839 conditions[cc]);
2840 text = NULL;
2841 } else
2842 text =
2843 nasm_strdup(conditions[inverse_ccs[cc]]);
2844 }
2845 break;
2846 case '+':
2847 n = atoi(t->text + 2) - 1;
2848 if (n >= mac->nparam)
2849 tt = NULL;
2850 else {
2851 if (mac->nparam > 1)
2852 n = (n + mac->rotate) % mac->nparam;
2853 tt = mac->params[n];
2854 }
2855 cc = find_cc(tt);
2856 if (cc == -1) {
2857 error(ERR_NONFATAL,
2858 "macro parameter %d is not a condition code",
2859 n + 1);
2860 text = NULL;
2861 } else {
2862 type = TOK_ID;
2863 text = nasm_strdup(conditions[cc]);
2864 }
2865 break;
2866 default:
2867 n = atoi(t->text + 1) - 1;
2868 if (n >= mac->nparam)
2869 tt = NULL;
2870 else {
2871 if (mac->nparam > 1)
2872 n = (n + mac->rotate) % mac->nparam;
2873 tt = mac->params[n];
2874 }
2875 if (tt) {
2876 for (i = 0; i < mac->paramlen[n]; i++) {
2877 *tail = new_Token(NULL, tt->type, tt->text, 0);
2878 tail = &(*tail)->next;
2879 tt = tt->next;
2880 }
2881 }
2882 text = NULL; /* we've done it here */
2883 break;
2884 }
2885 if (!text) {
2886 delete_Token(t);
2887 } else {
2888 *tail = t;
2889 tail = &t->next;
2890 t->type = type;
2891 nasm_free(t->text);
2892 t->text = text;
2893 t->mac = NULL;
2894 }
2895 continue;
2896 } else {
2897 t = *tail = tline;
2898 tline = tline->next;
2899 t->mac = NULL;
2900 tail = &t->next;
2901 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002902 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00002903 *tail = NULL;
2904 t = thead;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002905 for (; t && (tt = t->next) != NULL; t = t->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002906 switch (t->type) {
2907 case TOK_WHITESPACE:
2908 if (tt->type == TOK_WHITESPACE) {
2909 t->next = delete_Token(tt);
2910 }
2911 break;
2912 case TOK_ID:
2913 if (tt->type == TOK_ID || tt->type == TOK_NUMBER) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002914 char *tmp = nasm_strcat(t->text, tt->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002915 nasm_free(t->text);
2916 t->text = tmp;
2917 t->next = delete_Token(tt);
2918 }
2919 break;
2920 case TOK_NUMBER:
2921 if (tt->type == TOK_NUMBER) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002922 char *tmp = nasm_strcat(t->text, tt->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002923 nasm_free(t->text);
2924 t->text = tmp;
2925 t->next = delete_Token(tt);
2926 }
2927 break;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002928 default:
2929 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002930 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002931
H. Peter Anvin76690a12002-04-30 20:52:49 +00002932 return thead;
2933}
2934
2935/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002936 * Expand all single-line macro calls made in the given line.
2937 * Return the expanded version of the line. The original is deemed
2938 * to be destroyed in the process. (In reality we'll just move
2939 * Tokens from input to output a lot of the time, rather than
2940 * actually bothering to destroy and replicate.)
2941 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002942static Token *expand_smacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002943{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002944 Token *t, *tt, *mstart, **tail, *thead;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002945 SMacro *head = NULL, *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002946 Token **params;
2947 int *paramsize;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002948 int nparam, sparam, brackets, rescan;
2949 Token *org_tline = tline;
2950 Context *ctx;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002951 char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002952
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002953 /*
2954 * Trick: we should avoid changing the start token pointer since it can
2955 * be contained in "next" field of other token. Because of this
2956 * we allocate a copy of first token and work with it; at the end of
2957 * routine we copy it back
2958 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002959 if (org_tline) {
2960 tline =
2961 new_Token(org_tline->next, org_tline->type, org_tline->text,
2962 0);
2963 tline->mac = org_tline->mac;
2964 nasm_free(org_tline->text);
2965 org_tline->text = NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002966 }
2967
H. Peter Anvin734b1882002-04-30 21:01:08 +00002968 again:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002969 tail = &thead;
2970 thead = NULL;
2971
H. Peter Anvine2c80182005-01-15 22:15:51 +00002972 while (tline) { /* main token loop */
2973 if ((mname = tline->text)) {
2974 /* if this token is a local macro, look in local context */
2975 if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
2976 ctx = get_ctx(mname, TRUE);
2977 else
2978 ctx = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -07002979 if (!ctx) {
2980 head = (SMacro *) hash_findix(smacros, mname);
2981 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002982 head = ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07002983 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002984 /*
2985 * We've hit an identifier. As in is_mmacro below, we first
2986 * check whether the identifier is a single-line macro at
2987 * all, then think about checking for parameters if
2988 * necessary.
2989 */
H. Peter Anvin97a23472007-09-16 17:57:25 -07002990 for (m = head; m; m = m->next)
2991 if (!mstrcmp(m->name, mname, m->casesense))
2992 break;
2993 if (m) {
2994 mstart = tline;
2995 params = NULL;
2996 paramsize = NULL;
2997 if (m->nparam == 0) {
2998 /*
2999 * Simple case: the macro is parameterless. Discard the
3000 * one token that the macro call took, and push the
3001 * expansion back on the to-do stack.
3002 */
3003 if (!m->expansion) {
3004 if (!strcmp("__FILE__", m->name)) {
3005 int32_t num = 0;
3006 src_get(&num, &(tline->text));
3007 nasm_quote(&(tline->text));
3008 tline->type = TOK_STRING;
3009 continue;
3010 }
3011 if (!strcmp("__LINE__", m->name)) {
3012 nasm_free(tline->text);
3013 make_tok_num(tline, src_get_linnum());
3014 continue;
3015 }
3016 if (!strcmp("__BITS__", m->name)) {
3017 nasm_free(tline->text);
3018 make_tok_num(tline, globalbits);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003019 continue;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003020 }
3021 tline = delete_Token(tline);
3022 continue;
3023 }
3024 } else {
3025 /*
3026 * Complicated case: at least one macro with this name
H. Peter Anvine2c80182005-01-15 22:15:51 +00003027 * exists and takes parameters. We must find the
3028 * parameters in the call, count them, find the SMacro
3029 * that corresponds to that form of the macro call, and
3030 * substitute for the parameters when we expand. What a
3031 * pain.
3032 */
3033 /*tline = tline->next;
3034 skip_white_(tline); */
3035 do {
3036 t = tline->next;
3037 while (tok_type_(t, TOK_SMAC_END)) {
3038 t->mac->in_progress = FALSE;
3039 t->text = NULL;
3040 t = tline->next = delete_Token(t);
3041 }
3042 tline = t;
3043 } while (tok_type_(tline, TOK_WHITESPACE));
3044 if (!tok_is_(tline, "(")) {
3045 /*
3046 * This macro wasn't called with parameters: ignore
3047 * the call. (Behaviour borrowed from gnu cpp.)
3048 */
3049 tline = mstart;
3050 m = NULL;
3051 } else {
3052 int paren = 0;
3053 int white = 0;
3054 brackets = 0;
3055 nparam = 0;
3056 sparam = PARAM_DELTA;
3057 params = nasm_malloc(sparam * sizeof(Token *));
3058 params[0] = tline->next;
3059 paramsize = nasm_malloc(sparam * sizeof(int));
3060 paramsize[0] = 0;
3061 while (TRUE) { /* parameter loop */
3062 /*
3063 * For some unusual expansions
3064 * which concatenates function call
3065 */
3066 t = tline->next;
3067 while (tok_type_(t, TOK_SMAC_END)) {
3068 t->mac->in_progress = FALSE;
3069 t->text = NULL;
3070 t = tline->next = delete_Token(t);
3071 }
3072 tline = t;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00003073
H. Peter Anvine2c80182005-01-15 22:15:51 +00003074 if (!tline) {
3075 error(ERR_NONFATAL,
3076 "macro call expects terminating `)'");
3077 break;
3078 }
3079 if (tline->type == TOK_WHITESPACE
3080 && brackets <= 0) {
3081 if (paramsize[nparam])
3082 white++;
3083 else
3084 params[nparam] = tline->next;
3085 continue; /* parameter loop */
3086 }
3087 if (tline->type == TOK_OTHER
3088 && tline->text[1] == 0) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003089 char ch = tline->text[0];
H. Peter Anvine2c80182005-01-15 22:15:51 +00003090 if (ch == ',' && !paren && brackets <= 0) {
3091 if (++nparam >= sparam) {
3092 sparam += PARAM_DELTA;
3093 params = nasm_realloc(params,
3094 sparam *
3095 sizeof(Token
3096 *));
3097 paramsize =
3098 nasm_realloc(paramsize,
3099 sparam *
3100 sizeof(int));
3101 }
3102 params[nparam] = tline->next;
3103 paramsize[nparam] = 0;
3104 white = 0;
3105 continue; /* parameter loop */
3106 }
3107 if (ch == '{' &&
3108 (brackets > 0 || (brackets == 0 &&
3109 !paramsize[nparam])))
3110 {
3111 if (!(brackets++)) {
3112 params[nparam] = tline->next;
3113 continue; /* parameter loop */
3114 }
3115 }
3116 if (ch == '}' && brackets > 0)
3117 if (--brackets == 0) {
3118 brackets = -1;
3119 continue; /* parameter loop */
3120 }
3121 if (ch == '(' && !brackets)
3122 paren++;
3123 if (ch == ')' && brackets <= 0)
3124 if (--paren < 0)
3125 break;
3126 }
3127 if (brackets < 0) {
3128 brackets = 0;
3129 error(ERR_NONFATAL, "braces do not "
3130 "enclose all of macro parameter");
3131 }
3132 paramsize[nparam] += white + 1;
3133 white = 0;
3134 } /* parameter loop */
3135 nparam++;
3136 while (m && (m->nparam != nparam ||
3137 mstrcmp(m->name, mname,
3138 m->casesense)))
3139 m = m->next;
3140 if (!m)
3141 error(ERR_WARNING | ERR_WARN_MNP,
3142 "macro `%s' exists, "
3143 "but not taking %d parameters",
3144 mstart->text, nparam);
3145 }
3146 }
3147 if (m && m->in_progress)
3148 m = NULL;
3149 if (!m) { /* in progess or didn't find '(' or wrong nparam */
3150 /*
3151 * Design question: should we handle !tline, which
3152 * indicates missing ')' here, or expand those
3153 * macros anyway, which requires the (t) test a few
3154 * lines down?
3155 */
3156 nasm_free(params);
3157 nasm_free(paramsize);
3158 tline = mstart;
3159 } else {
3160 /*
3161 * Expand the macro: we are placed on the last token of the
3162 * call, so that we can easily split the call from the
3163 * following tokens. We also start by pushing an SMAC_END
3164 * token for the cycle removal.
3165 */
3166 t = tline;
3167 if (t) {
3168 tline = t->next;
3169 t->next = NULL;
3170 }
3171 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
3172 tt->mac = m;
3173 m->in_progress = TRUE;
3174 tline = tt;
3175 for (t = m->expansion; t; t = t->next) {
3176 if (t->type >= TOK_SMAC_PARAM) {
3177 Token *pcopy = tline, **ptail = &pcopy;
3178 Token *ttt, *pt;
3179 int i;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003180
H. Peter Anvine2c80182005-01-15 22:15:51 +00003181 ttt = params[t->type - TOK_SMAC_PARAM];
3182 for (i = paramsize[t->type - TOK_SMAC_PARAM];
3183 --i >= 0;) {
3184 pt = *ptail =
3185 new_Token(tline, ttt->type, ttt->text,
3186 0);
3187 ptail = &pt->next;
3188 ttt = ttt->next;
3189 }
3190 tline = pcopy;
3191 } else {
3192 tt = new_Token(tline, t->type, t->text, 0);
3193 tline = tt;
3194 }
3195 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003196
H. Peter Anvine2c80182005-01-15 22:15:51 +00003197 /*
3198 * Having done that, get rid of the macro call, and clean
3199 * up the parameters.
3200 */
3201 nasm_free(params);
3202 nasm_free(paramsize);
3203 free_tlist(mstart);
3204 continue; /* main token loop */
3205 }
3206 }
3207 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003208
H. Peter Anvine2c80182005-01-15 22:15:51 +00003209 if (tline->type == TOK_SMAC_END) {
3210 tline->mac->in_progress = FALSE;
3211 tline = delete_Token(tline);
3212 } else {
3213 t = *tail = tline;
3214 tline = tline->next;
3215 t->mac = NULL;
3216 t->next = NULL;
3217 tail = &t->next;
3218 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003219 }
3220
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003221 /*
3222 * Now scan the entire line and look for successive TOK_IDs that resulted
Keith Kaniosb7a89542007-04-12 02:40:54 +00003223 * after expansion (they can't be produced by tokenize()). The successive
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003224 * TOK_IDs should be concatenated.
3225 * Also we look for %+ tokens and concatenate the tokens before and after
3226 * them (without white spaces in between).
3227 */
3228 t = thead;
3229 rescan = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003230 while (t) {
3231 while (t && t->type != TOK_ID && t->type != TOK_PREPROC_ID)
3232 t = t->next;
3233 if (!t || !t->next)
3234 break;
3235 if (t->next->type == TOK_ID ||
3236 t->next->type == TOK_PREPROC_ID ||
3237 t->next->type == TOK_NUMBER) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003238 char *p = nasm_strcat(t->text, t->next->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003239 nasm_free(t->text);
3240 t->next = delete_Token(t->next);
3241 t->text = p;
3242 rescan = 1;
3243 } else if (t->next->type == TOK_WHITESPACE && t->next->next &&
3244 t->next->next->type == TOK_PREPROC_ID &&
3245 strcmp(t->next->next->text, "%+") == 0) {
3246 /* free the next whitespace, the %+ token and next whitespace */
3247 int i;
3248 for (i = 1; i <= 3; i++) {
3249 if (!t->next
3250 || (i != 2 && t->next->type != TOK_WHITESPACE))
3251 break;
3252 t->next = delete_Token(t->next);
3253 } /* endfor */
3254 } else
3255 t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003256 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003257 /* If we concatenaded something, re-scan the line for macros */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003258 if (rescan) {
3259 tline = thead;
3260 goto again;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003261 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003262
H. Peter Anvine2c80182005-01-15 22:15:51 +00003263 if (org_tline) {
3264 if (thead) {
3265 *org_tline = *thead;
3266 /* since we just gave text to org_line, don't free it */
3267 thead->text = NULL;
3268 delete_Token(thead);
3269 } else {
3270 /* the expression expanded to empty line;
3271 we can't return NULL for some reasons
3272 we just set the line to a single WHITESPACE token. */
3273 memset(org_tline, 0, sizeof(*org_tline));
3274 org_tline->text = NULL;
3275 org_tline->type = TOK_WHITESPACE;
3276 }
3277 thead = org_tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003278 }
3279
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003280 return thead;
3281}
3282
3283/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003284 * Similar to expand_smacro but used exclusively with macro identifiers
3285 * right before they are fetched in. The reason is that there can be
3286 * identifiers consisting of several subparts. We consider that if there
3287 * are more than one element forming the name, user wants a expansion,
3288 * otherwise it will be left as-is. Example:
3289 *
3290 * %define %$abc cde
3291 *
3292 * the identifier %$abc will be left as-is so that the handler for %define
3293 * will suck it and define the corresponding value. Other case:
3294 *
3295 * %define _%$abc cde
3296 *
3297 * In this case user wants name to be expanded *before* %define starts
3298 * working, so we'll expand %$abc into something (if it has a value;
3299 * otherwise it will be left as-is) then concatenate all successive
3300 * PP_IDs into one.
3301 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003302static Token *expand_id(Token * tline)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003303{
3304 Token *cur, *oldnext = NULL;
3305
H. Peter Anvin734b1882002-04-30 21:01:08 +00003306 if (!tline || !tline->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003307 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003308
3309 cur = tline;
3310 while (cur->next &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00003311 (cur->next->type == TOK_ID ||
3312 cur->next->type == TOK_PREPROC_ID
3313 || cur->next->type == TOK_NUMBER))
3314 cur = cur->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003315
3316 /* If identifier consists of just one token, don't expand */
3317 if (cur == tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003318 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003319
H. Peter Anvine2c80182005-01-15 22:15:51 +00003320 if (cur) {
3321 oldnext = cur->next; /* Detach the tail past identifier */
3322 cur->next = NULL; /* so that expand_smacro stops here */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003323 }
3324
H. Peter Anvin734b1882002-04-30 21:01:08 +00003325 tline = expand_smacro(tline);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003326
H. Peter Anvine2c80182005-01-15 22:15:51 +00003327 if (cur) {
3328 /* expand_smacro possibly changhed tline; re-scan for EOL */
3329 cur = tline;
3330 while (cur && cur->next)
3331 cur = cur->next;
3332 if (cur)
3333 cur->next = oldnext;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003334 }
3335
3336 return tline;
3337}
3338
3339/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003340 * Determine whether the given line constitutes a multi-line macro
3341 * call, and return the MMacro structure called if so. Doesn't have
3342 * to check for an initial label - that's taken care of in
3343 * expand_mmacro - but must check numbers of parameters. Guaranteed
3344 * to be called with tline->type == TOK_ID, so the putative macro
3345 * name is easy to find.
3346 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003347static MMacro *is_mmacro(Token * tline, Token *** params_array)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003348{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003349 MMacro *head, *m;
3350 Token **params;
3351 int nparam;
3352
H. Peter Anvin97a23472007-09-16 17:57:25 -07003353 head = (MMacro *) hash_findix(mmacros, tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003354
3355 /*
3356 * Efficiency: first we see if any macro exists with the given
3357 * name. If not, we can return NULL immediately. _Then_ we
3358 * count the parameters, and then we look further along the
3359 * list if necessary to find the proper MMacro.
3360 */
3361 for (m = head; m; m = m->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003362 if (!mstrcmp(m->name, tline->text, m->casesense))
3363 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003364 if (!m)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003365 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003366
3367 /*
3368 * OK, we have a potential macro. Count and demarcate the
3369 * parameters.
3370 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003371 count_mmac_params(tline->next, &nparam, &params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003372
3373 /*
3374 * So we know how many parameters we've got. Find the MMacro
3375 * structure that handles this number.
3376 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003377 while (m) {
3378 if (m->nparam_min <= nparam
3379 && (m->plus || nparam <= m->nparam_max)) {
3380 /*
3381 * This one is right. Just check if cycle removal
3382 * prohibits us using it before we actually celebrate...
3383 */
3384 if (m->in_progress) {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003385#if 0
H. Peter Anvine2c80182005-01-15 22:15:51 +00003386 error(ERR_NONFATAL,
3387 "self-reference in multi-line macro `%s'", m->name);
H. Peter Anvineba20a72002-04-30 20:53:55 +00003388#endif
H. Peter Anvine2c80182005-01-15 22:15:51 +00003389 nasm_free(params);
3390 return NULL;
3391 }
3392 /*
3393 * It's right, and we can use it. Add its default
3394 * parameters to the end of our list if necessary.
3395 */
3396 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
3397 params =
3398 nasm_realloc(params,
3399 ((m->nparam_min + m->ndefs +
3400 1) * sizeof(*params)));
3401 while (nparam < m->nparam_min + m->ndefs) {
3402 params[nparam] = m->defaults[nparam - m->nparam_min];
3403 nparam++;
3404 }
3405 }
3406 /*
3407 * If we've gone over the maximum parameter count (and
3408 * we're in Plus mode), ignore parameters beyond
3409 * nparam_max.
3410 */
3411 if (m->plus && nparam > m->nparam_max)
3412 nparam = m->nparam_max;
3413 /*
3414 * Then terminate the parameter list, and leave.
3415 */
3416 if (!params) { /* need this special case */
3417 params = nasm_malloc(sizeof(*params));
3418 nparam = 0;
3419 }
3420 params[nparam] = NULL;
3421 *params_array = params;
3422 return m;
3423 }
3424 /*
3425 * This one wasn't right: look for the next one with the
3426 * same name.
3427 */
3428 for (m = m->next; m; m = m->next)
3429 if (!mstrcmp(m->name, tline->text, m->casesense))
3430 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003431 }
3432
3433 /*
3434 * After all that, we didn't find one with the right number of
3435 * parameters. Issue a warning, and fail to expand the macro.
3436 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003437 error(ERR_WARNING | ERR_WARN_MNP,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003438 "macro `%s' exists, but not taking %d parameters",
3439 tline->text, nparam);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003440 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003441 return NULL;
3442}
3443
3444/*
3445 * Expand the multi-line macro call made by the given line, if
3446 * there is one to be expanded. If there is, push the expansion on
H. Peter Anvineba20a72002-04-30 20:53:55 +00003447 * istk->expansion and return 1. Otherwise return 0.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003448 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003449static int expand_mmacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003450{
3451 Token *startline = tline;
3452 Token *label = NULL;
3453 int dont_prepend = 0;
3454 Token **params, *t, *tt;
3455 MMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003456 Line *l, *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003457 int i, nparam, *paramlen;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003458
3459 t = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003460 skip_white_(t);
H. Peter Anvindce1e2f2002-04-30 21:06:37 +00003461/* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
3462 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
H. Peter Anvine2c80182005-01-15 22:15:51 +00003463 return 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003464 m = is_mmacro(t, &params);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003465 if (!m) {
3466 Token *last;
3467 /*
3468 * We have an id which isn't a macro call. We'll assume
3469 * it might be a label; we'll also check to see if a
3470 * colon follows it. Then, if there's another id after
3471 * that lot, we'll check it again for macro-hood.
3472 */
3473 label = last = t;
3474 t = t->next;
3475 if (tok_type_(t, TOK_WHITESPACE))
3476 last = t, t = t->next;
3477 if (tok_is_(t, ":")) {
3478 dont_prepend = 1;
3479 last = t, t = t->next;
3480 if (tok_type_(t, TOK_WHITESPACE))
3481 last = t, t = t->next;
3482 }
3483 if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
3484 return 0;
3485 last->next = NULL;
3486 tline = t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003487 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003488
3489 /*
3490 * Fix up the parameters: this involves stripping leading and
3491 * trailing whitespace, then stripping braces if they are
3492 * present.
3493 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003494 for (nparam = 0; params[nparam]; nparam++) ;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003495 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003496
H. Peter Anvine2c80182005-01-15 22:15:51 +00003497 for (i = 0; params[i]; i++) {
3498 int brace = FALSE;
3499 int comma = (!m->plus || i < nparam - 1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003500
H. Peter Anvine2c80182005-01-15 22:15:51 +00003501 t = params[i];
3502 skip_white_(t);
3503 if (tok_is_(t, "{"))
3504 t = t->next, brace = TRUE, comma = FALSE;
3505 params[i] = t;
3506 paramlen[i] = 0;
3507 while (t) {
3508 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
3509 break; /* ... because we have hit a comma */
3510 if (comma && t->type == TOK_WHITESPACE
3511 && tok_is_(t->next, ","))
3512 break; /* ... or a space then a comma */
3513 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
3514 break; /* ... or a brace */
3515 t = t->next;
3516 paramlen[i]++;
3517 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003518 }
3519
3520 /*
3521 * OK, we have a MMacro structure together with a set of
3522 * parameters. We must now go through the expansion and push
H. Peter Anvin76690a12002-04-30 20:52:49 +00003523 * copies of each Line on to istk->expansion. Substitution of
3524 * parameter tokens and macro-local tokens doesn't get done
3525 * until the single-line macro substitution process; this is
3526 * because delaying them allows us to change the semantics
3527 * later through %rotate.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003528 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00003529 * First, push an end marker on to istk->expansion, mark this
3530 * macro as in progress, and set up its invocation-specific
3531 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003532 */
3533 ll = nasm_malloc(sizeof(Line));
3534 ll->next = istk->expansion;
3535 ll->finishes = m;
3536 ll->first = NULL;
3537 istk->expansion = ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003538
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003539 m->in_progress = TRUE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003540 m->params = params;
3541 m->iline = tline;
3542 m->nparam = nparam;
3543 m->rotate = 0;
3544 m->paramlen = paramlen;
3545 m->unique = unique++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003546 m->lineno = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003547
3548 m->next_active = istk->mstk;
3549 istk->mstk = m;
3550
H. Peter Anvine2c80182005-01-15 22:15:51 +00003551 for (l = m->expansion; l; l = l->next) {
3552 Token **tail;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003553
H. Peter Anvine2c80182005-01-15 22:15:51 +00003554 ll = nasm_malloc(sizeof(Line));
3555 ll->finishes = NULL;
3556 ll->next = istk->expansion;
3557 istk->expansion = ll;
3558 tail = &ll->first;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003559
H. Peter Anvine2c80182005-01-15 22:15:51 +00003560 for (t = l->first; t; t = t->next) {
3561 Token *x = t;
3562 if (t->type == TOK_PREPROC_ID &&
3563 t->text[1] == '0' && t->text[2] == '0') {
3564 dont_prepend = -1;
3565 x = label;
3566 if (!x)
3567 continue;
3568 }
3569 tt = *tail = new_Token(NULL, x->type, x->text, 0);
3570 tail = &tt->next;
3571 }
3572 *tail = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003573 }
3574
3575 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +00003576 * If we had a label, push it on as the first line of
3577 * the macro expansion.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003578 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003579 if (label) {
3580 if (dont_prepend < 0)
3581 free_tlist(startline);
3582 else {
3583 ll = nasm_malloc(sizeof(Line));
3584 ll->finishes = NULL;
3585 ll->next = istk->expansion;
3586 istk->expansion = ll;
3587 ll->first = startline;
3588 if (!dont_prepend) {
3589 while (label->next)
3590 label = label->next;
3591 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
3592 }
3593 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003594 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003595
H. Peter Anvin734b1882002-04-30 21:01:08 +00003596 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003597
H. Peter Anvineba20a72002-04-30 20:53:55 +00003598 return 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003599}
3600
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003601/*
3602 * Since preprocessor always operate only on the line that didn't
3603 * arrived yet, we should always use ERR_OFFBY1. Also since user
3604 * won't want to see same error twice (preprocessing is done once
3605 * per pass) we will want to show errors only during pass one.
3606 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003607static void error(int severity, const char *fmt, ...)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003608{
3609 va_list arg;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003610 char buff[1024];
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003611
3612 /* If we're in a dead branch of IF or something like it, ignore the error */
H. Peter Anvin77ba0c62002-05-14 03:18:53 +00003613 if (istk && istk->conds && !emitting(istk->conds->state))
H. Peter Anvine2c80182005-01-15 22:15:51 +00003614 return;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003615
H. Peter Anvin734b1882002-04-30 21:01:08 +00003616 va_start(arg, fmt);
Ed Beroset19f927a2004-12-15 17:07:03 +00003617 vsnprintf(buff, sizeof(buff), fmt, arg);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003618 va_end(arg);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003619
H. Peter Anvin77ba0c62002-05-14 03:18:53 +00003620 if (istk && istk->mstk && istk->mstk->name)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003621 _error(severity | ERR_PASS1, "(%s:%d) %s", istk->mstk->name,
3622 istk->mstk->lineno, buff);
3623 else
3624 _error(severity | ERR_PASS1, "%s", buff);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003625}
3626
H. Peter Anvin734b1882002-04-30 21:01:08 +00003627static void
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003628pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003629 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003630{
H. Peter Anvin99941bf2002-05-14 17:44:03 +00003631 _error = errfunc;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003632 cstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003633 istk = nasm_malloc(sizeof(Include));
3634 istk->next = NULL;
3635 istk->conds = NULL;
3636 istk->expansion = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003637 istk->mstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003638 istk->fp = fopen(file, "r");
H. Peter Anvineba20a72002-04-30 20:53:55 +00003639 istk->fname = NULL;
3640 src_set_fname(nasm_strdup(file));
3641 src_set_linnum(0);
3642 istk->lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003643 if (!istk->fp)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003644 error(ERR_FATAL | ERR_NOFILE, "unable to open input file `%s'",
3645 file);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003646 defining = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003647 init_macros();
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003648 unique = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003649 if (tasm_compatible_mode) {
3650 stdmacpos = stdmac;
3651 } else {
3652 stdmacpos = &stdmac[TASM_MACRO_COUNT];
3653 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003654 any_extrastdmac = (extrastdmac != NULL);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003655 list = listgen;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003656 evaluate = eval;
3657 pass = apass;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003658}
3659
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003660static char *pp_getline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003661{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003662 char *line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003663 Token *tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003664
H. Peter Anvine2c80182005-01-15 22:15:51 +00003665 while (1) {
3666 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00003667 * Fetch a tokenized line, either from the macro-expansion
H. Peter Anvine2c80182005-01-15 22:15:51 +00003668 * buffer or from the input file.
3669 */
3670 tline = NULL;
3671 while (istk->expansion && istk->expansion->finishes) {
3672 Line *l = istk->expansion;
3673 if (!l->finishes->name && l->finishes->in_progress > 1) {
3674 Line *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003675
H. Peter Anvine2c80182005-01-15 22:15:51 +00003676 /*
3677 * This is a macro-end marker for a macro with no
3678 * name, which means it's not really a macro at all
3679 * but a %rep block, and the `in_progress' field is
3680 * more than 1, meaning that we still need to
3681 * repeat. (1 means the natural last repetition; 0
3682 * means termination by %exitrep.) We have
3683 * therefore expanded up to the %endrep, and must
3684 * push the whole block on to the expansion buffer
3685 * again. We don't bother to remove the macro-end
3686 * marker: we'd only have to generate another one
3687 * if we did.
3688 */
3689 l->finishes->in_progress--;
3690 for (l = l->finishes->expansion; l; l = l->next) {
3691 Token *t, *tt, **tail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003692
H. Peter Anvine2c80182005-01-15 22:15:51 +00003693 ll = nasm_malloc(sizeof(Line));
3694 ll->next = istk->expansion;
3695 ll->finishes = NULL;
3696 ll->first = NULL;
3697 tail = &ll->first;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003698
H. Peter Anvine2c80182005-01-15 22:15:51 +00003699 for (t = l->first; t; t = t->next) {
3700 if (t->text || t->type == TOK_WHITESPACE) {
3701 tt = *tail =
3702 new_Token(NULL, t->type, t->text, 0);
3703 tail = &tt->next;
3704 }
3705 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003706
H. Peter Anvine2c80182005-01-15 22:15:51 +00003707 istk->expansion = ll;
3708 }
3709 } else {
3710 /*
3711 * Check whether a `%rep' was started and not ended
3712 * within this macro expansion. This can happen and
3713 * should be detected. It's a fatal error because
3714 * I'm too confused to work out how to recover
3715 * sensibly from it.
3716 */
3717 if (defining) {
3718 if (defining->name)
3719 error(ERR_PANIC,
3720 "defining with name in expansion");
3721 else if (istk->mstk->name)
3722 error(ERR_FATAL,
3723 "`%%rep' without `%%endrep' within"
3724 " expansion of macro `%s'",
3725 istk->mstk->name);
3726 }
H. Peter Anvin87bc6192002-04-30 20:53:16 +00003727
H. Peter Anvine2c80182005-01-15 22:15:51 +00003728 /*
3729 * FIXME: investigate the relationship at this point between
3730 * istk->mstk and l->finishes
3731 */
3732 {
3733 MMacro *m = istk->mstk;
3734 istk->mstk = m->next_active;
3735 if (m->name) {
3736 /*
3737 * This was a real macro call, not a %rep, and
3738 * therefore the parameter information needs to
3739 * be freed.
3740 */
3741 nasm_free(m->params);
3742 free_tlist(m->iline);
3743 nasm_free(m->paramlen);
3744 l->finishes->in_progress = FALSE;
3745 } else
3746 free_mmacro(m);
3747 }
3748 istk->expansion = l->next;
3749 nasm_free(l);
3750 list->downlevel(LIST_MACRO);
3751 }
3752 }
3753 while (1) { /* until we get a line we can use */
H. Peter Anvineba20a72002-04-30 20:53:55 +00003754
H. Peter Anvine2c80182005-01-15 22:15:51 +00003755 if (istk->expansion) { /* from a macro expansion */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003756 char *p;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003757 Line *l = istk->expansion;
3758 if (istk->mstk)
3759 istk->mstk->lineno++;
3760 tline = l->first;
3761 istk->expansion = l->next;
3762 nasm_free(l);
3763 p = detoken(tline, FALSE);
3764 list->line(LIST_MACRO, p);
3765 nasm_free(p);
3766 break;
3767 }
3768 line = read_line();
3769 if (line) { /* from the current input file */
3770 line = prepreproc(line);
Keith Kaniosb7a89542007-04-12 02:40:54 +00003771 tline = tokenize(line);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003772 nasm_free(line);
3773 break;
3774 }
3775 /*
3776 * The current file has ended; work down the istk
3777 */
3778 {
3779 Include *i = istk;
3780 fclose(i->fp);
3781 if (i->conds)
3782 error(ERR_FATAL,
3783 "expected `%%endif' before end of file");
3784 /* only set line and file name if there's a next node */
3785 if (i->next) {
3786 src_set_linnum(i->lineno);
3787 nasm_free(src_set_fname(i->fname));
3788 }
3789 istk = i->next;
3790 list->downlevel(LIST_INCLUDE);
3791 nasm_free(i);
3792 if (!istk)
3793 return NULL;
3794 }
3795 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003796
H. Peter Anvine2c80182005-01-15 22:15:51 +00003797 /*
3798 * We must expand MMacro parameters and MMacro-local labels
3799 * _before_ we plunge into directive processing, to cope
3800 * with things like `%define something %1' such as STRUC
3801 * uses. Unless we're _defining_ a MMacro, in which case
3802 * those tokens should be left alone to go into the
3803 * definition; and unless we're in a non-emitting
3804 * condition, in which case we don't want to meddle with
3805 * anything.
3806 */
3807 if (!defining && !(istk->conds && !emitting(istk->conds->state)))
3808 tline = expand_mmac_params(tline);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003809
H. Peter Anvine2c80182005-01-15 22:15:51 +00003810 /*
3811 * Check the line to see if it's a preprocessor directive.
3812 */
3813 if (do_directive(tline) == DIRECTIVE_FOUND) {
3814 continue;
3815 } else if (defining) {
3816 /*
3817 * We're defining a multi-line macro. We emit nothing
3818 * at all, and just
Keith Kaniosb7a89542007-04-12 02:40:54 +00003819 * shove the tokenized line on to the macro definition.
H. Peter Anvine2c80182005-01-15 22:15:51 +00003820 */
3821 Line *l = nasm_malloc(sizeof(Line));
3822 l->next = defining->expansion;
3823 l->first = tline;
3824 l->finishes = FALSE;
3825 defining->expansion = l;
3826 continue;
3827 } else if (istk->conds && !emitting(istk->conds->state)) {
3828 /*
3829 * We're in a non-emitting branch of a condition block.
3830 * Emit nothing at all, not even a blank line: when we
3831 * emerge from the condition we'll give a line-number
3832 * directive so we keep our place correctly.
3833 */
3834 free_tlist(tline);
3835 continue;
3836 } else if (istk->mstk && !istk->mstk->in_progress) {
3837 /*
3838 * We're in a %rep block which has been terminated, so
3839 * we're walking through to the %endrep without
3840 * emitting anything. Emit nothing at all, not even a
3841 * blank line: when we emerge from the %rep block we'll
3842 * give a line-number directive so we keep our place
3843 * correctly.
3844 */
3845 free_tlist(tline);
3846 continue;
3847 } else {
3848 tline = expand_smacro(tline);
3849 if (!expand_mmacro(tline)) {
3850 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00003851 * De-tokenize the line again, and emit it.
H. Peter Anvine2c80182005-01-15 22:15:51 +00003852 */
3853 line = detoken(tline, TRUE);
3854 free_tlist(tline);
3855 break;
3856 } else {
3857 continue; /* expand_mmacro calls free_tlist */
3858 }
3859 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003860 }
3861
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003862 return line;
3863}
3864
H. Peter Anvine2c80182005-01-15 22:15:51 +00003865static void pp_cleanup(int pass)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003866{
H. Peter Anvine2c80182005-01-15 22:15:51 +00003867 if (defining) {
3868 error(ERR_NONFATAL, "end of file while still defining macro `%s'",
3869 defining->name);
3870 free_mmacro(defining);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003871 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003872 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003873 ctx_pop();
H. Peter Anvin97a23472007-09-16 17:57:25 -07003874 free_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00003875 while (istk) {
3876 Include *i = istk;
3877 istk = istk->next;
3878 fclose(i->fp);
3879 nasm_free(i->fname);
3880 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003881 }
3882 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003883 ctx_pop();
3884 if (pass == 0) {
3885 free_llist(predef);
3886 delete_Blocks();
3887 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003888}
3889
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003890void pp_include_path(char *path)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003891{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003892 IncPath *i;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003893/* by alexfru: order of path inclusion fixed (was reverse order) */
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003894 i = nasm_malloc(sizeof(IncPath));
3895 i->path = nasm_strdup(path);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003896 i->next = NULL;
3897
H. Peter Anvine2c80182005-01-15 22:15:51 +00003898 if (ipath != NULL) {
3899 IncPath *j = ipath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003900 while (j->next != NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003901 j = j->next;
3902 j->next = i;
3903 } else {
3904 ipath = i;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003905 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003906}
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003907
3908/*
3909 * added by alexfru:
3910 *
3911 * This function is used to "export" the include paths, e.g.
3912 * the paths specified in the '-I' command switch.
3913 * The need for such exporting is due to the 'incbin' directive,
3914 * which includes raw binary files (unlike '%include', which
3915 * includes text source files). It would be real nice to be
3916 * able to specify paths to search for incbin'ned files also.
3917 * So, this is a simple workaround.
3918 *
3919 * The function use is simple:
3920 *
3921 * The 1st call (with NULL argument) returns a pointer to the 1st path
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003922 * (char** type) or NULL if none include paths available.
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003923 *
3924 * All subsequent calls take as argument the value returned by this
3925 * function last. The return value is either the next path
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003926 * (char** type) or NULL if the end of the paths list is reached.
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003927 *
3928 * It is maybe not the best way to do things, but I didn't want
3929 * to export too much, just one or two functions and no types or
3930 * variables exported.
3931 *
3932 * Can't say I like the current situation with e.g. this path list either,
3933 * it seems to be never deallocated after creation...
3934 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003935char **pp_get_include_path_ptr(char **pPrevPath)
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003936{
3937/* This macro returns offset of a member of a structure */
3938#define GetMemberOffset(StructType,MemberName)\
3939 ((size_t)&((StructType*)0)->MemberName)
3940 IncPath *i;
3941
H. Peter Anvine2c80182005-01-15 22:15:51 +00003942 if (pPrevPath == NULL) {
3943 if (ipath != NULL)
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003944 return &ipath->path;
3945 else
3946 return NULL;
3947 }
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003948 i = (IncPath *) ((char *)pPrevPath - GetMemberOffset(IncPath, path));
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003949 i = i->next;
3950 if (i != NULL)
3951 return &i->path;
3952 else
3953 return NULL;
3954#undef GetMemberOffset
3955}
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003956
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003957void pp_pre_include(char *fname)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003958{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003959 Token *inc, *space, *name;
3960 Line *l;
3961
H. Peter Anvin734b1882002-04-30 21:01:08 +00003962 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
3963 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
3964 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003965
3966 l = nasm_malloc(sizeof(Line));
3967 l->next = predef;
3968 l->first = inc;
3969 l->finishes = FALSE;
3970 predef = l;
3971}
3972
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003973void pp_pre_define(char *definition)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003974{
3975 Token *def, *space;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003976 Line *l;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003977 char *equals;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003978
3979 equals = strchr(definition, '=');
H. Peter Anvin734b1882002-04-30 21:01:08 +00003980 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
3981 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003982 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003983 *equals = ' ';
Keith Kaniosb7a89542007-04-12 02:40:54 +00003984 space->next = tokenize(definition);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003985 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003986 *equals = '=';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003987
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003988 l = nasm_malloc(sizeof(Line));
3989 l->next = predef;
3990 l->first = def;
3991 l->finishes = FALSE;
3992 predef = l;
3993}
3994
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003995void pp_pre_undefine(char *definition)
H. Peter Anvin620515a2002-04-30 20:57:38 +00003996{
3997 Token *def, *space;
3998 Line *l;
3999
H. Peter Anvin734b1882002-04-30 21:01:08 +00004000 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4001 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
Keith Kaniosb7a89542007-04-12 02:40:54 +00004002 space->next = tokenize(definition);
H. Peter Anvin620515a2002-04-30 20:57:38 +00004003
4004 l = nasm_malloc(sizeof(Line));
4005 l->next = predef;
4006 l->first = def;
4007 l->finishes = FALSE;
4008 predef = l;
4009}
4010
Keith Kaniosb7a89542007-04-12 02:40:54 +00004011/*
4012 * Added by Keith Kanios:
4013 *
4014 * This function is used to assist with "runtime" preprocessor
4015 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
4016 *
4017 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
4018 * PASS A VALID STRING TO THIS FUNCTION!!!!!
4019 */
4020
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004021void pp_runtime(char *definition)
Keith Kaniosb7a89542007-04-12 02:40:54 +00004022{
4023 Token *def;
4024
4025 def = tokenize(definition);
4026 if(do_directive(def) == NO_DIRECTIVE_FOUND)
4027 free_tlist(def);
4028
4029}
4030
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004031void pp_extra_stdmac(const char **macros)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004032{
H. Peter Anvin76690a12002-04-30 20:52:49 +00004033 extrastdmac = macros;
4034}
4035
Keith Kaniosb7a89542007-04-12 02:40:54 +00004036static void make_tok_num(Token * tok, int32_t val)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004037{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004038 char numbuf[20];
Keith Kanios93f2e9a2007-04-14 00:10:59 +00004039 snprintf(numbuf, sizeof(numbuf), "%"PRId32"", val);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004040 tok->text = nasm_strdup(numbuf);
4041 tok->type = TOK_NUMBER;
4042}
4043
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004044Preproc nasmpp = {
4045 pp_reset,
4046 pp_getline,
4047 pp_cleanup
4048};