NASM 0.98.17
[nasm/avx512.git] / preproc.c
blob4ec382697e90814d2223c74d7043f3735e67d174
1 /* preproc.c macro preprocessor for the Netwide Assembler
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the licence given in the file "Licence"
6 * distributed in the NASM archive.
8 * initial version 18/iii/97 by Simon Tatham
9 */
11 /* Typical flow of text through preproc
13 * pp_getline gets tokenised lines, either
15 * from a macro expansion
17 * or
18 * {
19 * read_line gets raw text from stdmacpos, or predef, or current input file
20 * tokenise converts to tokens
21 * }
23 * expand_mmac_params is used to expand %1 etc., unless a macro is being
24 * defined or a false conditional is being processed
25 * (%0, %1, %+1, %-1, %%foo
27 * do_directive checks for directives
29 * expand_smacro is used to expand single line macros
31 * expand_mmacro is used to expand multi-line macros
33 * detoken is used to convert the line back to text
36 #include <stdio.h>
37 #include <stdarg.h>
38 #include <stdlib.h>
39 #include <stddef.h>
40 #include <string.h>
41 #include <ctype.h>
42 #include <limits.h>
44 #include "nasm.h"
45 #include "nasmlib.h"
47 typedef struct SMacro SMacro;
48 typedef struct MMacro MMacro;
49 typedef struct Context Context;
50 typedef struct Token Token;
51 typedef struct Blocks Blocks;
52 typedef struct Line Line;
53 typedef struct Include Include;
54 typedef struct Cond Cond;
55 typedef struct IncPath IncPath;
58 * Store the definition of a single-line macro.
60 struct SMacro
62 SMacro *next;
63 char *name;
64 int casesense;
65 int nparam;
66 int in_progress;
67 Token *expansion;
71 * Store the definition of a multi-line macro. This is also used to
72 * store the interiors of `%rep...%endrep' blocks, which are
73 * effectively self-re-invoking multi-line macros which simply
74 * don't have a name or bother to appear in the hash tables. %rep
75 * blocks are signified by having a NULL `name' field.
77 * In a MMacro describing a `%rep' block, the `in_progress' field
78 * isn't merely boolean, but gives the number of repeats left to
79 * run.
81 * The `next' field is used for storing MMacros in hash tables; the
82 * `next_active' field is for stacking them on istk entries.
84 * When a MMacro is being expanded, `params', `iline', `nparam',
85 * `paramlen', `rotate' and `unique' are local to the invocation.
87 struct MMacro
89 MMacro *next;
90 char *name;
91 int casesense;
92 int nparam_min, nparam_max;
93 int plus; /* is the last parameter greedy? */
94 int nolist; /* is this macro listing-inhibited? */
95 int in_progress;
96 Token *dlist; /* All defaults as one list */
97 Token **defaults; /* Parameter default pointers */
98 int ndefs; /* number of default parameters */
99 Line *expansion;
101 MMacro *next_active;
102 MMacro *rep_nest; /* used for nesting %rep */
103 Token **params; /* actual parameters */
104 Token *iline; /* invocation line */
105 int nparam, rotate, *paramlen;
106 unsigned long unique;
107 int lineno; /* Current line number on expansion */
111 * The context stack is composed of a linked list of these.
113 struct Context
115 Context *next;
116 SMacro *localmac;
117 char *name;
118 unsigned long number;
122 * This is the internal form which we break input lines up into.
123 * Typically stored in linked lists.
125 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
126 * necessarily used as-is, but is intended to denote the number of
127 * the substituted parameter. So in the definition
129 * %define a(x,y) ( (x) & ~(y) )
131 * the token representing `x' will have its type changed to
132 * TOK_SMAC_PARAM, but the one representing `y' will be
133 * TOK_SMAC_PARAM+1.
135 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
136 * which doesn't need quotes around it. Used in the pre-include
137 * mechanism as an alternative to trying to find a sensible type of
138 * quote to use on the filename we were passed.
140 struct Token
142 Token *next;
143 char *text;
144 SMacro *mac; /* associated macro for TOK_SMAC_END */
145 int type;
147 enum
149 TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING,
150 TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_SMAC_PARAM,
151 TOK_INTERNAL_STRING
155 * Multi-line macro definitions are stored as a linked list of
156 * these, which is essentially a container to allow several linked
157 * lists of Tokens.
159 * Note that in this module, linked lists are treated as stacks
160 * wherever possible. For this reason, Lines are _pushed_ on to the
161 * `expansion' field in MMacro structures, so that the linked list,
162 * if walked, would give the macro lines in reverse order; this
163 * means that we can walk the list when expanding a macro, and thus
164 * push the lines on to the `expansion' field in _istk_ in reverse
165 * order (so that when popped back off they are in the right
166 * order). It may seem cockeyed, and it relies on my design having
167 * an even number of steps in, but it works...
169 * Some of these structures, rather than being actual lines, are
170 * markers delimiting the end of the expansion of a given macro.
171 * This is for use in the cycle-tracking and %rep-handling code.
172 * Such structures have `finishes' non-NULL, and `first' NULL. All
173 * others have `finishes' NULL, but `first' may still be NULL if
174 * the line is blank.
176 struct Line
178 Line *next;
179 MMacro *finishes;
180 Token *first;
184 * To handle an arbitrary level of file inclusion, we maintain a
185 * stack (ie linked list) of these things.
187 struct Include
189 Include *next;
190 FILE *fp;
191 Cond *conds;
192 Line *expansion;
193 char *fname;
194 int lineno, lineinc;
195 MMacro *mstk; /* stack of active macros/reps */
199 * Include search path. This is simply a list of strings which get
200 * prepended, in turn, to the name of an include file, in an
201 * attempt to find the file if it's not in the current directory.
203 struct IncPath
205 IncPath *next;
206 char *path;
210 * Conditional assembly: we maintain a separate stack of these for
211 * each level of file inclusion. (The only reason we keep the
212 * stacks separate is to ensure that a stray `%endif' in a file
213 * included from within the true branch of a `%if' won't terminate
214 * it and cause confusion: instead, rightly, it'll cause an error.)
216 struct Cond
218 Cond *next;
219 int state;
221 enum
224 * These states are for use just after %if or %elif: IF_TRUE
225 * means the condition has evaluated to truth so we are
226 * currently emitting, whereas IF_FALSE means we are not
227 * currently emitting but will start doing so if a %else comes
228 * up. In these states, all directives are admissible: %elif,
229 * %else and %endif. (And of course %if.)
231 COND_IF_TRUE, COND_IF_FALSE,
233 * These states come up after a %else: ELSE_TRUE means we're
234 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
235 * any %elif or %else will cause an error.
237 COND_ELSE_TRUE, COND_ELSE_FALSE,
239 * This state means that we're not emitting now, and also that
240 * nothing until %endif will be emitted at all. It's for use in
241 * two circumstances: (i) when we've had our moment of emission
242 * and have now started seeing %elifs, and (ii) when the
243 * condition construct in question is contained within a
244 * non-emitting branch of a larger condition construct.
246 COND_NEVER
248 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
251 * Condition codes. Note that we use c_ prefix not C_ because C_ is
252 * used in nasm.h for the "real" condition codes. At _this_ level,
253 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
254 * ones, so we need a different enum...
256 static char *conditions[] = {
257 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
258 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
259 "np", "ns", "nz", "o", "p", "pe", "po", "s", "z"
261 enum
263 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
264 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
265 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_S, c_Z
267 static int inverse_ccs[] = {
268 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
269 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,
270 c_Z, c_NO, c_NP, c_PO, c_PE, c_NS, c_NZ
274 * Directive names.
276 static char *directives[] = {
277 "%arg",
278 "%assign", "%clear", "%define", "%elif", "%elifctx", "%elifdef",
279 "%elifid", "%elifidn", "%elifidni", "%elifnctx", "%elifndef",
280 "%elifnid", "%elifnidn", "%elifnidni", "%elifnnum", "%elifnstr",
281 "%elifnum", "%elifstr", "%else", "%endif", "%endm", "%endmacro",
282 "%endrep", "%error", "%exitrep", "%iassign", "%idefine", "%if",
283 "%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifnctx",
284 "%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnnum",
285 "%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include",
286 "%ixdefine", "%line",
287 "%local",
288 "%macro", "%pop", "%push", "%rep", "%repl", "%rotate",
289 "%stacksize",
290 "%strlen", "%substr", "%undef", "%xdefine"
292 enum
294 PP_ARG,
295 PP_ASSIGN, PP_CLEAR, PP_DEFINE, PP_ELIF, PP_ELIFCTX, PP_ELIFDEF,
296 PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFNCTX, PP_ELIFNDEF,
297 PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNNUM, PP_ELIFNSTR,
298 PP_ELIFNUM, PP_ELIFSTR, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO,
299 PP_ENDREP, PP_ERROR, PP_EXITREP, PP_IASSIGN, PP_IDEFINE, PP_IF,
300 PP_IFCTX, PP_IFDEF, PP_IFID, PP_IFIDN, PP_IFIDNI, PP_IFNCTX,
301 PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNNUM,
302 PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE,
303 PP_IXDEFINE, PP_LINE,
304 PP_LOCAL,
305 PP_MACRO, PP_POP, PP_PUSH, PP_REP, PP_REPL, PP_ROTATE,
306 PP_STACKSIZE,
307 PP_STRLEN, PP_SUBSTR, PP_UNDEF, PP_XDEFINE
311 /* For TASM compatibility we need to be able to recognise TASM compatible
312 * conditional compilation directives. Using the NASM pre-processor does
313 * not work, so we look for them specifically from the following list and
314 * then jam in the equivalent NASM directive into the input stream.
317 #ifndef MAX
318 # define MAX(a,b) ( ((a) > (b)) ? (a) : (b))
319 #endif
321 enum
323 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
324 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
327 static char *tasm_directives[] = {
328 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
329 "ifndef", "include", "local"
332 static int StackSize = 4;
333 static char *StackPointer = "ebp";
334 static int ArgOffset = 8;
335 static int LocalOffset = 4;
338 static Context *cstk;
339 static Include *istk;
340 static IncPath *ipath = NULL;
342 static efunc __error; /* Pointer to client-provided error reporting function */
343 static evalfunc evaluate;
345 static int pass; /* HACK: pass 0 = generate dependencies only */
347 static unsigned long unique; /* unique identifier numbers */
349 static Line *predef = NULL;
351 static ListGen *list;
354 * The number of hash values we use for the macro lookup tables.
355 * FIXME: We should *really* be able to configure this at run time,
356 * or even have the hash table automatically expanding when necessary.
358 #define NHASH 31
361 * The current set of multi-line macros we have defined.
363 static MMacro *mmacros[NHASH];
366 * The current set of single-line macros we have defined.
368 static SMacro *smacros[NHASH];
371 * The multi-line macro we are currently defining, or the %rep
372 * block we are currently reading, if any.
374 static MMacro *defining;
377 * The number of macro parameters to allocate space for at a time.
379 #define PARAM_DELTA 16
382 * The standard macro set: defined as `static char *stdmac[]'. Also
383 * gives our position in the macro set, when we're processing it.
385 #include "macros.c"
386 static char **stdmacpos;
389 * The extra standard macros that come from the object format, if
390 * any.
392 static char **extrastdmac = NULL;
393 int any_extrastdmac;
396 * Tokens are allocated in blocks to improve speed
398 #define TOKEN_BLOCKSIZE 4096
399 static Token *freeTokens = NULL;
400 struct Blocks {
401 Blocks *next;
402 void *chunk;
405 static Blocks blocks = { NULL, NULL };
408 * Forward declarations.
410 static Token *expand_mmac_params(Token * tline);
411 static Token *expand_smacro(Token * tline);
412 static Token *expand_id(Token * tline);
413 static Context *get_ctx(char *name, int all_contexts);
414 static void make_tok_num(Token * tok, long val);
415 static void error(int severity, char *fmt, ...);
416 static void *new_Block(size_t size);
417 static void delete_Blocks(void);
418 static Token *new_Token(Token * next, int type, char *text, int txtlen);
419 static Token *delete_Token(Token * t);
422 * Macros for safe checking of token pointers, avoid *(NULL)
424 #define tok_type_(x,t) ((x) && (x)->type == (t))
425 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
426 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
427 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
429 /* Handle TASM specific directives, which do not contain a % in
430 * front of them. We do it here because I could not find any other
431 * place to do it for the moment, and it is a hack (ideally it would
432 * be nice to be able to use the NASM pre-processor to do it).
434 static char *
435 check_tasm_directive(char *line)
437 int i, j, k, m, len;
438 char *p = line, *oldline, oldchar;
440 /* Skip whitespace */
441 while (isspace(*p) && *p != 0)
442 p++;
444 /* Binary search for the directive name */
445 i = -1;
446 j = sizeof(tasm_directives) / sizeof(*tasm_directives);
447 len = 0;
448 while (!isspace(p[len]) && p[len] != 0)
449 len++;
450 if (len)
452 oldchar = p[len];
453 p[len] = 0;
454 while (j - i > 1)
456 k = (j + i) / 2;
457 m = nasm_stricmp(p, tasm_directives[k]);
458 if (m == 0)
460 /* We have found a directive, so jam a % in front of it
461 * so that NASM will then recognise it as one if it's own.
463 p[len] = oldchar;
464 len = strlen(p);
465 oldline = line;
466 line = nasm_malloc(len + 2);
467 line[0] = '%';
468 if (k == TM_IFDIFI)
470 /* NASM does not recognise IFDIFI, so we convert it to
471 * %ifdef BOGUS. This is not used in NASM comaptible
472 * code, but does need to parse for the TASM macro
473 * package.
475 strcpy(line + 1, "ifdef BOGUS");
477 else
479 memcpy(line + 1, p, len + 1);
481 nasm_free(oldline);
482 return line;
484 else if (m < 0)
486 j = k;
488 else
489 i = k;
491 p[len] = oldchar;
493 return line;
497 * The pre-preprocessing stage... This function translates line
498 * number indications as they emerge from GNU cpp (`# lineno "file"
499 * flags') into NASM preprocessor line number indications (`%line
500 * lineno file').
502 static char *
503 prepreproc(char *line)
505 int lineno, fnlen;
506 char *fname, *oldline;
508 if (line[0] == '#' && line[1] == ' ')
510 oldline = line;
511 fname = oldline + 2;
512 lineno = atoi(fname);
513 fname += strspn(fname, "0123456789 ");
514 if (*fname == '"')
515 fname++;
516 fnlen = strcspn(fname, "\"");
517 line = nasm_malloc(20 + fnlen);
518 sprintf(line, "%%line %d %.*s", lineno, fnlen, fname);
519 nasm_free(oldline);
521 if (tasm_compatible_mode)
522 return check_tasm_directive(line);
523 return line;
527 * The hash function for macro lookups. Note that due to some
528 * macros having case-insensitive names, the hash function must be
529 * invariant under case changes. We implement this by applying a
530 * perfectly normal hash function to the uppercase of the string.
532 static int
533 hash(char *s)
535 unsigned int h = 0;
536 int i = 0;
538 * Powers of three, mod 31.
540 static const int multipliers[] = {
541 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10,
542 30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21
546 while (*s)
548 h += multipliers[i] * (unsigned char) (toupper(*s));
549 s++;
550 if (++i >= sizeof(multipliers) / sizeof(*multipliers))
551 i = 0;
553 h %= NHASH;
554 return h;
558 * Free a linked list of tokens.
560 static void
561 free_tlist(Token * list)
563 while (list)
565 list = delete_Token(list);
570 * Free a linked list of lines.
572 static void
573 free_llist(Line * list)
575 Line *l;
576 while (list)
578 l = list;
579 list = list->next;
580 free_tlist(l->first);
581 nasm_free(l);
586 * Free an MMacro
588 static void
589 free_mmacro(MMacro * m)
591 nasm_free(m->name);
592 free_tlist(m->dlist);
593 nasm_free(m->defaults);
594 free_llist(m->expansion);
595 nasm_free(m);
599 * Pop the context stack.
601 static void
602 ctx_pop(void)
604 Context *c = cstk;
605 SMacro *smac, *s;
607 cstk = cstk->next;
608 smac = c->localmac;
609 while (smac)
611 s = smac;
612 smac = smac->next;
613 nasm_free(s->name);
614 free_tlist(s->expansion);
615 nasm_free(s);
617 nasm_free(c->name);
618 nasm_free(c);
621 #define BUF_DELTA 512
623 * Read a line from the top file in istk, handling multiple CR/LFs
624 * at the end of the line read, and handling spurious ^Zs. Will
625 * return lines from the standard macro set if this has not already
626 * been done.
628 static char *
629 read_line(void)
631 char *buffer, *p, *q;
632 int bufsize;
634 if (stdmacpos)
636 if (*stdmacpos)
638 char *ret = nasm_strdup(*stdmacpos++);
639 if (!*stdmacpos && any_extrastdmac)
641 stdmacpos = extrastdmac;
642 any_extrastdmac = FALSE;
643 return ret;
646 * Nasty hack: here we push the contents of `predef' on
647 * to the top-level expansion stack, since this is the
648 * most convenient way to implement the pre-include and
649 * pre-define features.
651 if (!*stdmacpos)
653 Line *pd, *l;
654 Token *head, **tail, *t;
656 for (pd = predef; pd; pd = pd->next)
658 head = NULL;
659 tail = &head;
660 for (t = pd->first; t; t = t->next)
662 *tail = new_Token(NULL, t->type, t->text, 0);
663 tail = &(*tail)->next;
665 l = nasm_malloc(sizeof(Line));
666 l->next = istk->expansion;
667 l->first = head;
668 l->finishes = FALSE;
669 istk->expansion = l;
672 return ret;
674 else
676 stdmacpos = NULL;
680 bufsize = BUF_DELTA;
681 buffer = nasm_malloc(BUF_DELTA);
682 p = buffer;
683 while (1)
685 q = fgets(p, bufsize - (p - buffer), istk->fp);
686 if (!q)
687 break;
688 p += strlen(p);
689 if (p > buffer && p[-1] == '\n')
691 break;
693 if (p - buffer > bufsize - 10)
695 long offset = p - buffer;
696 bufsize += BUF_DELTA;
697 buffer = nasm_realloc(buffer, bufsize);
698 p = buffer + offset; /* prevent stale-pointer problems */
702 if (!q && p == buffer)
704 nasm_free(buffer);
705 return NULL;
708 src_set_linnum(src_get_linnum() + istk->lineinc);
711 * Play safe: remove CRs as well as LFs, if any of either are
712 * present at the end of the line.
714 while (--p >= buffer && (*p == '\n' || *p == '\r'))
715 *p = '\0';
718 * Handle spurious ^Z, which may be inserted into source files
719 * by some file transfer utilities.
721 buffer[strcspn(buffer, "\032")] = '\0';
723 list->line(LIST_READ, buffer);
725 return buffer;
729 * Tokenise a line of text. This is a very simple process since we
730 * don't need to parse the value out of e.g. numeric tokens: we
731 * simply split one string into many.
733 static Token *
734 tokenise(char *line)
736 char *p = line;
737 int type;
738 Token *list = NULL;
739 Token *t, **tail = &list;
741 while (*line)
743 p = line;
744 if (*p == '%')
746 p++;
747 if ( isdigit(*p) ||
748 ((*p == '-' || *p == '+') && isdigit(p[1])) ||
749 ((*p == '+') && (isspace(p[1]) || !p[1])))
753 p++;
755 while (isdigit(*p));
756 type = TOK_PREPROC_ID;
758 else if (*p == '{')
760 p++;
761 while (*p && *p != '}')
763 p[-1] = *p;
764 p++;
766 p[-1] = '\0';
767 if (*p)
768 p++;
769 type = TOK_PREPROC_ID;
771 else if (isidchar(*p) ||
772 ((*p == '!' || *p == '%' || *p == '$') &&
773 isidchar(p[1])))
777 p++;
779 while (isidchar(*p));
780 type = TOK_PREPROC_ID;
782 else
784 type = TOK_OTHER;
785 if (*p == '%')
786 p++;
789 else if (isidstart(*p) || (*p == '$' && isidstart(p[1])))
791 type = TOK_ID;
792 p++;
793 while (*p && isidchar(*p))
794 p++;
796 else if (*p == '\'' || *p == '"')
799 * A string token.
801 char c = *p;
802 p++;
803 type = TOK_STRING;
804 while (*p && *p != c)
805 p++;
806 if (*p)
808 p++;
810 else
812 error(ERR_WARNING, "unterminated string");
815 else if (isnumstart(*p))
818 * A number token.
820 type = TOK_NUMBER;
821 p++;
822 while (*p && isnumchar(*p))
823 p++;
825 else if (isspace(*p))
827 type = TOK_WHITESPACE;
828 p++;
829 while (*p && isspace(*p))
830 p++;
832 * Whitespace just before end-of-line is discarded by
833 * pretending it's a comment; whitespace just before a
834 * comment gets lumped into the comment.
836 if (!*p || *p == ';')
838 type = TOK_COMMENT;
839 while (*p)
840 p++;
843 else if (*p == ';')
845 type = TOK_COMMENT;
846 while (*p)
847 p++;
849 else
852 * Anything else is an operator of some kind. We check
853 * for all the double-character operators (>>, <<, //,
854 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
855 * else is a single-character operator.
857 type = TOK_OTHER;
858 if ((p[0] == '>' && p[1] == '>') ||
859 (p[0] == '<' && p[1] == '<') ||
860 (p[0] == '/' && p[1] == '/') ||
861 (p[0] == '<' && p[1] == '=') ||
862 (p[0] == '>' && p[1] == '=') ||
863 (p[0] == '=' && p[1] == '=') ||
864 (p[0] == '!' && p[1] == '=') ||
865 (p[0] == '<' && p[1] == '>') ||
866 (p[0] == '&' && p[1] == '&') ||
867 (p[0] == '|' && p[1] == '|') ||
868 (p[0] == '^' && p[1] == '^'))
870 p++;
872 p++;
874 if (type != TOK_COMMENT)
876 *tail = t = new_Token(NULL, type, line, p - line);
877 tail = &t->next;
879 line = p;
881 return list;
885 * this function allocates a new managed block of memory and
886 * returns a pointer to the block. The managed blocks are
887 * deleted only all at once by the delete_Blocks function.
889 static void *
890 new_Block(size_t size)
892 Blocks *b = &blocks;
894 /* first, get to the end of the linked list */
895 while (b->next)
896 b = b->next;
897 /* now allocate the requested chunk */
898 b->chunk = nasm_malloc(size);
900 /* now allocate a new block for the next request */
901 b->next = nasm_malloc(sizeof(Blocks));
902 /* and initialize the contents of the new block */
903 b->next->next = NULL;
904 b->next->chunk = NULL;
905 return b->chunk;
909 * this function deletes all managed blocks of memory
911 static void
912 delete_Blocks(void)
914 Blocks *a,*b = &blocks;
917 * keep in mind that the first block, pointed to by blocks
918 * is a static and not dynamically allocated, so we don't
919 * free it.
921 while (b)
923 if (b->chunk)
924 nasm_free(b->chunk);
925 a = b;
926 b = b->next;
927 if (a != &blocks)
928 nasm_free(a);
933 * this function creates a new Token and passes a pointer to it
934 * back to the caller. It sets the type and text elements, and
935 * also the mac and next elements to NULL.
937 static Token *
938 new_Token(Token * next, int type, char *text, int txtlen)
940 Token *t;
941 int i;
943 if (freeTokens == NULL)
945 freeTokens = (Token *)new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
946 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
947 freeTokens[i].next = &freeTokens[i + 1];
948 freeTokens[i].next = NULL;
950 t = freeTokens;
951 freeTokens = t->next;
952 t->next = next;
953 t->mac = NULL;
954 t->type = type;
955 if (type == TOK_WHITESPACE || text == NULL)
957 t->text = NULL;
959 else
961 if (txtlen == 0)
962 txtlen = strlen(text);
963 t->text = nasm_malloc(1 + txtlen);
964 strncpy(t->text, text, txtlen);
965 t->text[txtlen] = '\0';
967 return t;
970 static Token *
971 delete_Token(Token * t)
973 Token *next = t->next;
974 nasm_free(t->text);
975 t->next = freeTokens;
976 freeTokens = t;
977 return next;
981 * Convert a line of tokens back into text.
982 * If expand_locals is not zero, identifiers of the form "%$*xxx"
983 * will be transformed into ..@ctxnum.xxx
985 static char *
986 detoken(Token * tlist, int expand_locals)
988 Token *t;
989 int len;
990 char *line, *p;
992 len = 0;
993 for (t = tlist; t; t = t->next)
995 if (t->type == TOK_PREPROC_ID && t->text[1] == '!')
997 char *p = getenv(t->text + 2);
998 nasm_free(t->text);
999 if (p)
1000 t->text = nasm_strdup(p);
1001 else
1002 t->text = NULL;
1004 /* Expand local macros here and not during preprocessing */
1005 if (expand_locals &&
1006 t->type == TOK_PREPROC_ID && t->text &&
1007 t->text[0] == '%' && t->text[1] == '$')
1009 Context *ctx = get_ctx(t->text, FALSE);
1010 if (ctx)
1012 char buffer[40];
1013 char *p, *q = t->text + 2;
1015 q += strspn(q, "$");
1016 sprintf(buffer, "..@%lu.", ctx->number);
1017 p = nasm_strcat(buffer, q);
1018 nasm_free(t->text);
1019 t->text = p;
1022 if (t->type == TOK_WHITESPACE)
1024 len++;
1026 else if (t->text)
1028 len += strlen(t->text);
1031 p = line = nasm_malloc(len + 1);
1032 for (t = tlist; t; t = t->next)
1034 if (t->type == TOK_WHITESPACE)
1036 *p = ' ';
1037 p++;
1038 *p = '\0';
1040 else if (t->text)
1042 strcpy(p, t->text);
1043 p += strlen(p);
1046 *p = '\0';
1047 return line;
1051 * A scanner, suitable for use by the expression evaluator, which
1052 * operates on a line of Tokens. Expects a pointer to a pointer to
1053 * the first token in the line to be passed in as its private_data
1054 * field.
1056 static int
1057 ppscan(void *private_data, struct tokenval *tokval)
1059 Token **tlineptr = private_data;
1060 Token *tline;
1064 tline = *tlineptr;
1065 *tlineptr = tline ? tline->next : NULL;
1067 while (tline && (tline->type == TOK_WHITESPACE ||
1068 tline->type == TOK_COMMENT));
1070 if (!tline)
1071 return tokval->t_type = TOKEN_EOS;
1073 if (tline->text[0] == '$' && !tline->text[1])
1074 return tokval->t_type = TOKEN_HERE;
1075 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[1])
1076 return tokval->t_type = TOKEN_BASE;
1078 if (tline->type == TOK_ID)
1080 tokval->t_charptr = tline->text;
1081 if (tline->text[0] == '$')
1083 tokval->t_charptr++;
1084 return tokval->t_type = TOKEN_ID;
1088 * This is the only special case we actually need to worry
1089 * about in this restricted context.
1091 if (!nasm_stricmp(tline->text, "seg"))
1092 return tokval->t_type = TOKEN_SEG;
1094 return tokval->t_type = TOKEN_ID;
1097 if (tline->type == TOK_NUMBER)
1099 int rn_error;
1101 tokval->t_integer = readnum(tline->text, &rn_error);
1102 if (rn_error)
1103 return tokval->t_type = TOKEN_ERRNUM;
1104 tokval->t_charptr = NULL;
1105 return tokval->t_type = TOKEN_NUM;
1108 if (tline->type == TOK_STRING)
1110 int rn_warn;
1111 char q, *r;
1112 int l;
1114 r = tline->text;
1115 q = *r++;
1116 l = strlen(r);
1118 if (l == 0 || r[l - 1] != q)
1119 return tokval->t_type = TOKEN_ERRNUM;
1120 tokval->t_integer = readstrnum(r, l - 1, &rn_warn);
1121 if (rn_warn)
1122 error(ERR_WARNING | ERR_PASS1, "character constant too long");
1123 tokval->t_charptr = NULL;
1124 return tokval->t_type = TOKEN_NUM;
1127 if (tline->type == TOK_OTHER)
1129 if (!strcmp(tline->text, "<<"))
1130 return tokval->t_type = TOKEN_SHL;
1131 if (!strcmp(tline->text, ">>"))
1132 return tokval->t_type = TOKEN_SHR;
1133 if (!strcmp(tline->text, "//"))
1134 return tokval->t_type = TOKEN_SDIV;
1135 if (!strcmp(tline->text, "%%"))
1136 return tokval->t_type = TOKEN_SMOD;
1137 if (!strcmp(tline->text, "=="))
1138 return tokval->t_type = TOKEN_EQ;
1139 if (!strcmp(tline->text, "<>"))
1140 return tokval->t_type = TOKEN_NE;
1141 if (!strcmp(tline->text, "!="))
1142 return tokval->t_type = TOKEN_NE;
1143 if (!strcmp(tline->text, "<="))
1144 return tokval->t_type = TOKEN_LE;
1145 if (!strcmp(tline->text, ">="))
1146 return tokval->t_type = TOKEN_GE;
1147 if (!strcmp(tline->text, "&&"))
1148 return tokval->t_type = TOKEN_DBL_AND;
1149 if (!strcmp(tline->text, "^^"))
1150 return tokval->t_type = TOKEN_DBL_XOR;
1151 if (!strcmp(tline->text, "||"))
1152 return tokval->t_type = TOKEN_DBL_OR;
1156 * We have no other options: just return the first character of
1157 * the token text.
1159 return tokval->t_type = tline->text[0];
1163 * Compare a string to the name of an existing macro; this is a
1164 * simple wrapper which calls either strcmp or nasm_stricmp
1165 * depending on the value of the `casesense' parameter.
1167 static int
1168 mstrcmp(char *p, char *q, int casesense)
1170 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
1174 * Return the Context structure associated with a %$ token. Return
1175 * NULL, having _already_ reported an error condition, if the
1176 * context stack isn't deep enough for the supplied number of $
1177 * signs.
1178 * If all_contexts == TRUE, contexts that enclose current are
1179 * also scanned for such smacro, until it is found; if not -
1180 * only the context that directly results from the number of $'s
1181 * in variable's name.
1183 static Context *
1184 get_ctx(char *name, int all_contexts)
1186 Context *ctx;
1187 SMacro *m;
1188 int i;
1190 if (!name || name[0] != '%' || name[1] != '$')
1191 return NULL;
1193 if (!cstk)
1195 error(ERR_NONFATAL, "`%s': context stack is empty", name);
1196 return NULL;
1199 for (i = strspn(name + 2, "$"), ctx = cstk; (i > 0) && ctx; i--)
1201 ctx = ctx->next;
1202 i--;
1204 if (!ctx)
1206 error(ERR_NONFATAL, "`%s': context stack is only"
1207 " %d level%s deep", name, i - 1, (i == 2 ? "" : "s"));
1208 return NULL;
1210 if (!all_contexts)
1211 return ctx;
1215 /* Search for this smacro in found context */
1216 m = ctx->localmac;
1217 while (m)
1219 if (!mstrcmp(m->name, name, m->casesense))
1220 return ctx;
1221 m = m->next;
1223 ctx = ctx->next;
1225 while (ctx);
1226 return NULL;
1229 /* Add a slash to the end of a path if it is missing. We use the
1230 * forward slash to make it compatible with Unix systems.
1232 static void
1233 backslash(char *s)
1235 int pos = strlen(s);
1236 if (s[pos - 1] != '\\' && s[pos - 1] != '/')
1238 s[pos] = '/';
1239 s[pos + 1] = '\0';
1244 * Open an include file. This routine must always return a valid
1245 * file pointer if it returns - it's responsible for throwing an
1246 * ERR_FATAL and bombing out completely if not. It should also try
1247 * the include path one by one until it finds the file or reaches
1248 * the end of the path.
1250 static FILE *
1251 inc_fopen(char *file)
1253 FILE *fp;
1254 char *prefix = "", *combine;
1255 IncPath *ip = ipath;
1256 static int namelen = 0;
1257 int len = strlen(file);
1259 while (1)
1261 combine = nasm_malloc(strlen(prefix) + 1 + len + 1);
1262 strcpy(combine, prefix);
1263 if (prefix[0] != 0)
1264 backslash(combine);
1265 strcat(combine, file);
1266 fp = fopen(combine, "r");
1267 if (pass == 0 && fp)
1269 namelen += strlen(combine) + 1;
1270 if (namelen > 62)
1272 printf(" \\\n ");
1273 namelen = 2;
1275 printf(" %s", combine);
1277 nasm_free(combine);
1278 if (fp)
1279 return fp;
1280 if (!ip)
1281 break;
1282 prefix = ip->path;
1283 ip = ip->next;
1286 error(ERR_FATAL, "unable to open include file `%s'", file);
1287 return NULL; /* never reached - placate compilers */
1291 * Determine if we should warn on defining a single-line macro of
1292 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1293 * return TRUE if _any_ single-line macro of that name is defined.
1294 * Otherwise, will return TRUE if a single-line macro with either
1295 * `nparam' or no parameters is defined.
1297 * If a macro with precisely the right number of parameters is
1298 * defined, or nparam is -1, the address of the definition structure
1299 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1300 * is NULL, no action will be taken regarding its contents, and no
1301 * error will occur.
1303 * Note that this is also called with nparam zero to resolve
1304 * `ifdef'.
1306 * If you already know which context macro belongs to, you can pass
1307 * the context pointer as first parameter; if you won't but name begins
1308 * with %$ the context will be automatically computed. If all_contexts
1309 * is true, macro will be searched in outer contexts as well.
1311 static int
1312 smacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn,
1313 int nocase)
1315 SMacro *m;
1317 if (ctx)
1318 m = ctx->localmac;
1319 else if (name[0] == '%' && name[1] == '$')
1321 if (cstk)
1322 ctx = get_ctx(name, FALSE);
1323 if (!ctx)
1324 return FALSE; /* got to return _something_ */
1325 m = ctx->localmac;
1327 else
1328 m = smacros[hash(name)];
1330 while (m)
1332 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
1333 (nparam <= 0 || m->nparam == 0 || nparam == m->nparam))
1335 if (defn)
1337 if (nparam == m->nparam || nparam == -1)
1338 *defn = m;
1339 else
1340 *defn = NULL;
1342 return TRUE;
1344 m = m->next;
1347 return FALSE;
1351 * Count and mark off the parameters in a multi-line macro call.
1352 * This is called both from within the multi-line macro expansion
1353 * code, and also to mark off the default parameters when provided
1354 * in a %macro definition line.
1356 static void
1357 count_mmac_params(Token * t, int *nparam, Token *** params)
1359 int paramsize, brace;
1361 *nparam = paramsize = 0;
1362 *params = NULL;
1363 while (t)
1365 if (*nparam >= paramsize)
1367 paramsize += PARAM_DELTA;
1368 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1370 skip_white_(t);
1371 brace = FALSE;
1372 if (tok_is_(t, "{"))
1373 brace = TRUE;
1374 (*params)[(*nparam)++] = t;
1375 while (tok_isnt_(t, brace ? "}" : ","))
1376 t = t->next;
1377 if (t)
1378 { /* got a comma/brace */
1379 t = t->next;
1380 if (brace)
1383 * Now we've found the closing brace, look further
1384 * for the comma.
1386 skip_white_(t);
1387 if (tok_isnt_(t, ","))
1389 error(ERR_NONFATAL,
1390 "braces do not enclose all of macro parameter");
1391 while (tok_isnt_(t, ","))
1392 t = t->next;
1394 if (t)
1395 t = t->next; /* eat the comma */
1402 * Determine whether one of the various `if' conditions is true or
1403 * not.
1405 * We must free the tline we get passed.
1407 static int
1408 if_condition(Token * tline, int i)
1410 int j, casesense;
1411 Token *t, *tt, **tptr, *origline;
1412 struct tokenval tokval;
1413 expr *evalresult;
1415 origline = tline;
1417 switch (i)
1419 case PP_IFCTX:
1420 case PP_ELIFCTX:
1421 case PP_IFNCTX:
1422 case PP_ELIFNCTX:
1423 j = FALSE; /* have we matched yet? */
1424 while (cstk && tline)
1426 skip_white_(tline);
1427 if (!tline || tline->type != TOK_ID)
1429 error(ERR_NONFATAL,
1430 "`%s' expects context identifiers",
1431 directives[i]);
1432 free_tlist(origline);
1433 return -1;
1435 if (!nasm_stricmp(tline->text, cstk->name))
1436 j = TRUE;
1437 tline = tline->next;
1439 if (i == PP_IFNCTX || i == PP_ELIFNCTX)
1440 j = !j;
1441 free_tlist(origline);
1442 return j;
1444 case PP_IFDEF:
1445 case PP_ELIFDEF:
1446 case PP_IFNDEF:
1447 case PP_ELIFNDEF:
1448 j = FALSE; /* have we matched yet? */
1449 while (tline)
1451 skip_white_(tline);
1452 if (!tline || (tline->type != TOK_ID &&
1453 (tline->type != TOK_PREPROC_ID ||
1454 tline->text[1] != '$')))
1456 error(ERR_NONFATAL,
1457 "`%%if%sdef' expects macro identifiers",
1458 (i == PP_ELIFNDEF ? "n" : ""));
1459 free_tlist(origline);
1460 return -1;
1462 if (smacro_defined(NULL, tline->text, 0, NULL, 1))
1463 j = TRUE;
1464 tline = tline->next;
1466 if (i == PP_IFNDEF || i == PP_ELIFNDEF)
1467 j = !j;
1468 free_tlist(origline);
1469 return j;
1471 case PP_IFIDN:
1472 case PP_ELIFIDN:
1473 case PP_IFNIDN:
1474 case PP_ELIFNIDN:
1475 case PP_IFIDNI:
1476 case PP_ELIFIDNI:
1477 case PP_IFNIDNI:
1478 case PP_ELIFNIDNI:
1479 tline = expand_smacro(tline);
1480 t = tt = tline;
1481 while (tok_isnt_(tt, ","))
1482 tt = tt->next;
1483 if (!tt)
1485 error(ERR_NONFATAL,
1486 "`%s' expects two comma-separated arguments",
1487 directives[i]);
1488 free_tlist(tline);
1489 return -1;
1491 tt = tt->next;
1492 casesense = (i == PP_IFIDN || i == PP_ELIFIDN ||
1493 i == PP_IFNIDN || i == PP_ELIFNIDN);
1494 j = TRUE; /* assume equality unless proved not */
1495 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt)
1497 if (tt->type == TOK_OTHER && !strcmp(tt->text, ","))
1499 error(ERR_NONFATAL, "`%s': more than one comma on line",
1500 directives[i]);
1501 free_tlist(tline);
1502 return -1;
1504 if (t->type == TOK_WHITESPACE)
1506 t = t->next;
1507 continue;
1509 else if (tt->type == TOK_WHITESPACE)
1511 tt = tt->next;
1512 continue;
1514 else if (tt->type != t->type ||
1515 mstrcmp(tt->text, t->text, casesense))
1517 j = FALSE; /* found mismatching tokens */
1518 break;
1520 else
1522 t = t->next;
1523 tt = tt->next;
1524 continue;
1527 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
1528 j = FALSE; /* trailing gunk on one end or other */
1529 if (i == PP_IFNIDN || i == PP_ELIFNIDN ||
1530 i == PP_IFNIDNI || i == PP_ELIFNIDNI)
1531 j = !j;
1532 free_tlist(tline);
1533 return j;
1535 case PP_IFID:
1536 case PP_ELIFID:
1537 case PP_IFNID:
1538 case PP_ELIFNID:
1539 case PP_IFNUM:
1540 case PP_ELIFNUM:
1541 case PP_IFNNUM:
1542 case PP_ELIFNNUM:
1543 case PP_IFSTR:
1544 case PP_ELIFSTR:
1545 case PP_IFNSTR:
1546 case PP_ELIFNSTR:
1547 tline = expand_smacro(tline);
1548 t = tline;
1549 while (tok_type_(t, TOK_WHITESPACE))
1550 t = t->next;
1551 j = FALSE; /* placate optimiser */
1552 if (t)
1553 switch (i)
1555 case PP_IFID:
1556 case PP_ELIFID:
1557 case PP_IFNID:
1558 case PP_ELIFNID:
1559 j = (t->type == TOK_ID);
1560 break;
1561 case PP_IFNUM:
1562 case PP_ELIFNUM:
1563 case PP_IFNNUM:
1564 case PP_ELIFNNUM:
1565 j = (t->type == TOK_NUMBER);
1566 break;
1567 case PP_IFSTR:
1568 case PP_ELIFSTR:
1569 case PP_IFNSTR:
1570 case PP_ELIFNSTR:
1571 j = (t->type == TOK_STRING);
1572 break;
1574 if (i == PP_IFNID || i == PP_ELIFNID ||
1575 i == PP_IFNNUM || i == PP_ELIFNNUM ||
1576 i == PP_IFNSTR || i == PP_ELIFNSTR)
1577 j = !j;
1578 free_tlist(tline);
1579 return j;
1581 case PP_IF:
1582 case PP_ELIF:
1583 t = tline = expand_smacro(tline);
1584 tptr = &t;
1585 tokval.t_type = TOKEN_INVALID;
1586 evalresult = evaluate(ppscan, tptr, &tokval,
1587 NULL, pass | CRITICAL, error, NULL);
1588 free_tlist(tline);
1589 if (!evalresult)
1590 return -1;
1591 if (tokval.t_type)
1592 error(ERR_WARNING,
1593 "trailing garbage after expression ignored");
1594 if (!is_simple(evalresult))
1596 error(ERR_NONFATAL,
1597 "non-constant value given to `%s'", directives[i]);
1598 return -1;
1600 return reloc_value(evalresult) != 0;
1602 default:
1603 error(ERR_FATAL,
1604 "preprocessor directive `%s' not yet implemented",
1605 directives[i]);
1606 free_tlist(origline);
1607 return -1; /* yeah, right */
1612 * Expand macros in a string. Used in %error and %include directives.
1613 * First tokenise the string, apply "expand_smacro" and then de-tokenise back.
1614 * The returned variable should ALWAYS be freed after usage.
1616 void
1617 expand_macros_in_string(char **p)
1619 Token *line = tokenise(*p);
1620 line = expand_smacro(line);
1621 *p = detoken(line, FALSE);
1625 * Find out if a line contains a preprocessor directive, and deal
1626 * with it if so.
1628 * If a directive _is_ found, we are expected to free_tlist() the
1629 * line.
1631 * Return values go like this:
1633 * bit 0 is set if a directive was found (so the line gets freed)
1635 static int
1636 do_directive(Token * tline)
1638 int i, j, k, m, nparam, nolist;
1639 int offset;
1640 char *p, *mname;
1641 Include *inc;
1642 Context *ctx;
1643 Cond *cond;
1644 SMacro *smac, **smhead;
1645 MMacro *mmac;
1646 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
1647 Line *l;
1648 struct tokenval tokval;
1649 expr *evalresult;
1650 MMacro *tmp_defining; /* Used when manipulating rep_nest */
1652 origline = tline;
1654 skip_white_(tline);
1655 if (!tok_type_(tline, TOK_PREPROC_ID) ||
1656 (tline->text[1] == '%' || tline->text[1] == '$'
1657 || tline->text[1] == '!'))
1658 return 0;
1660 i = -1;
1661 j = sizeof(directives) / sizeof(*directives);
1662 while (j - i > 1)
1664 k = (j + i) / 2;
1665 m = nasm_stricmp(tline->text, directives[k]);
1666 if (m == 0) {
1667 if (tasm_compatible_mode) {
1668 i = k;
1669 j = -2;
1670 } else if (k != PP_ARG && k != PP_LOCAL && k != PP_STACKSIZE) {
1671 i = k;
1672 j = -2;
1674 break;
1676 else if (m < 0) {
1677 j = k;
1679 else
1680 i = k;
1684 * If we're in a non-emitting branch of a condition construct,
1685 * or walking to the end of an already terminated %rep block,
1686 * we should ignore all directives except for condition
1687 * directives.
1689 if (((istk->conds && !emitting(istk->conds->state)) ||
1690 (istk->mstk && !istk->mstk->in_progress)) &&
1691 i != PP_IF && i != PP_ELIF &&
1692 i != PP_IFCTX && i != PP_ELIFCTX &&
1693 i != PP_IFDEF && i != PP_ELIFDEF &&
1694 i != PP_IFID && i != PP_ELIFID &&
1695 i != PP_IFIDN && i != PP_ELIFIDN &&
1696 i != PP_IFIDNI && i != PP_ELIFIDNI &&
1697 i != PP_IFNCTX && i != PP_ELIFNCTX &&
1698 i != PP_IFNDEF && i != PP_ELIFNDEF &&
1699 i != PP_IFNID && i != PP_ELIFNID &&
1700 i != PP_IFNIDN && i != PP_ELIFNIDN &&
1701 i != PP_IFNIDNI && i != PP_ELIFNIDNI &&
1702 i != PP_IFNNUM && i != PP_ELIFNNUM &&
1703 i != PP_IFNSTR && i != PP_ELIFNSTR &&
1704 i != PP_IFNUM && i != PP_ELIFNUM &&
1705 i != PP_IFSTR && i != PP_ELIFSTR && i != PP_ELSE && i != PP_ENDIF)
1707 return 0;
1711 * If we're defining a macro or reading a %rep block, we should
1712 * ignore all directives except for %macro/%imacro (which
1713 * generate an error), %endm/%endmacro, and (only if we're in a
1714 * %rep block) %endrep. If we're in a %rep block, another %rep
1715 * causes an error, so should be let through.
1717 if (defining && i != PP_MACRO && i != PP_IMACRO &&
1718 i != PP_ENDMACRO && i != PP_ENDM &&
1719 (defining->name || (i != PP_ENDREP && i != PP_REP)))
1721 return 0;
1724 if (j != -2)
1726 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
1727 tline->text);
1728 return 0; /* didn't get it */
1731 switch (i)
1733 case PP_STACKSIZE:
1734 /* Directive to tell NASM what the default stack size is. The
1735 * default is for a 16-bit stack, and this can be overriden with
1736 * %stacksize large.
1737 * the following form:
1739 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1741 tline = tline->next;
1742 if (tline && tline->type == TOK_WHITESPACE)
1743 tline = tline->next;
1744 if (!tline || tline->type != TOK_ID)
1746 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
1747 free_tlist(origline);
1748 return 3;
1750 if (nasm_stricmp(tline->text, "flat") == 0)
1752 /* All subsequent ARG directives are for a 32-bit stack */
1753 StackSize = 4;
1754 StackPointer = "ebp";
1755 ArgOffset = 8;
1756 LocalOffset = 4;
1758 else if (nasm_stricmp(tline->text, "large") == 0)
1760 /* All subsequent ARG directives are for a 16-bit stack,
1761 * far function call.
1763 StackSize = 2;
1764 StackPointer = "bp";
1765 ArgOffset = 4;
1766 LocalOffset = 2;
1768 else if (nasm_stricmp(tline->text, "small") == 0)
1770 /* All subsequent ARG directives are for a 16-bit stack,
1771 * far function call. We don't support near functions.
1773 StackSize = 2;
1774 StackPointer = "bp";
1775 ArgOffset = 6;
1776 LocalOffset = 2;
1778 else
1780 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
1781 free_tlist(origline);
1782 return 3;
1784 free_tlist(origline);
1785 return 3;
1787 case PP_ARG:
1788 /* TASM like ARG directive to define arguments to functions, in
1789 * the following form:
1791 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1793 offset = ArgOffset;
1796 char *arg, directive[256];
1797 int size = StackSize;
1799 /* Find the argument name */
1800 tline = tline->next;
1801 if (tline && tline->type == TOK_WHITESPACE)
1802 tline = tline->next;
1803 if (!tline || tline->type != TOK_ID)
1805 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
1806 free_tlist(origline);
1807 return 3;
1809 arg = tline->text;
1811 /* Find the argument size type */
1812 tline = tline->next;
1813 if (!tline || tline->type != TOK_OTHER
1814 || tline->text[0] != ':')
1816 error(ERR_NONFATAL,
1817 "Syntax error processing `%%arg' directive");
1818 free_tlist(origline);
1819 return 3;
1821 tline = tline->next;
1822 if (!tline || tline->type != TOK_ID)
1824 error(ERR_NONFATAL,
1825 "`%%arg' missing size type parameter");
1826 free_tlist(origline);
1827 return 3;
1830 /* Allow macro expansion of type parameter */
1831 tt = tokenise(tline->text);
1832 tt = expand_smacro(tt);
1833 if (nasm_stricmp(tt->text, "byte") == 0)
1835 size = MAX(StackSize, 1);
1837 else if (nasm_stricmp(tt->text, "word") == 0)
1839 size = MAX(StackSize, 2);
1841 else if (nasm_stricmp(tt->text, "dword") == 0)
1843 size = MAX(StackSize, 4);
1845 else if (nasm_stricmp(tt->text, "qword") == 0)
1847 size = MAX(StackSize, 8);
1849 else if (nasm_stricmp(tt->text, "tword") == 0)
1851 size = MAX(StackSize, 10);
1853 else
1855 error(ERR_NONFATAL,
1856 "Invalid size type for `%%arg' missing directive");
1857 free_tlist(tt);
1858 free_tlist(origline);
1859 return 3;
1861 free_tlist(tt);
1863 /* Now define the macro for the argument */
1864 sprintf(directive, "%%define %s (%s+%d)", arg, StackPointer,
1865 offset);
1866 do_directive(tokenise(directive));
1867 offset += size;
1869 /* Move to the next argument in the list */
1870 tline = tline->next;
1871 if (tline && tline->type == TOK_WHITESPACE)
1872 tline = tline->next;
1874 while (tline && tline->type == TOK_OTHER
1875 && tline->text[0] == ',');
1876 free_tlist(origline);
1877 return 3;
1879 case PP_LOCAL:
1880 /* TASM like LOCAL directive to define local variables for a
1881 * function, in the following form:
1883 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
1885 * The '= LocalSize' at the end is ignored by NASM, but is
1886 * required by TASM to define the local parameter size (and used
1887 * by the TASM macro package).
1889 offset = LocalOffset;
1892 char *local, directive[256];
1893 int size = StackSize;
1895 /* Find the argument name */
1896 tline = tline->next;
1897 if (tline && tline->type == TOK_WHITESPACE)
1898 tline = tline->next;
1899 if (!tline || tline->type != TOK_ID)
1901 error(ERR_NONFATAL,
1902 "`%%local' missing argument parameter");
1903 free_tlist(origline);
1904 return 3;
1906 local = tline->text;
1908 /* Find the argument size type */
1909 tline = tline->next;
1910 if (!tline || tline->type != TOK_OTHER
1911 || tline->text[0] != ':')
1913 error(ERR_NONFATAL,
1914 "Syntax error processing `%%local' directive");
1915 free_tlist(origline);
1916 return 3;
1918 tline = tline->next;
1919 if (!tline || tline->type != TOK_ID)
1921 error(ERR_NONFATAL,
1922 "`%%local' missing size type parameter");
1923 free_tlist(origline);
1924 return 3;
1927 /* Allow macro expansion of type parameter */
1928 tt = tokenise(tline->text);
1929 tt = expand_smacro(tt);
1930 if (nasm_stricmp(tt->text, "byte") == 0)
1932 size = MAX(StackSize, 1);
1934 else if (nasm_stricmp(tt->text, "word") == 0)
1936 size = MAX(StackSize, 2);
1938 else if (nasm_stricmp(tt->text, "dword") == 0)
1940 size = MAX(StackSize, 4);
1942 else if (nasm_stricmp(tt->text, "qword") == 0)
1944 size = MAX(StackSize, 8);
1946 else if (nasm_stricmp(tt->text, "tword") == 0)
1948 size = MAX(StackSize, 10);
1950 else
1952 error(ERR_NONFATAL,
1953 "Invalid size type for `%%local' missing directive");
1954 free_tlist(tt);
1955 free_tlist(origline);
1956 return 3;
1958 free_tlist(tt);
1960 /* Now define the macro for the argument */
1961 sprintf(directive, "%%define %s (%s-%d)", local, StackPointer,
1962 offset);
1963 do_directive(tokenise(directive));
1964 offset += size;
1966 /* Now define the assign to setup the enter_c macro correctly */
1967 sprintf(directive, "%%assign %%$localsize %%$localsize+%d",
1968 size);
1969 do_directive(tokenise(directive));
1971 /* Move to the next argument in the list */
1972 tline = tline->next;
1973 if (tline && tline->type == TOK_WHITESPACE)
1974 tline = tline->next;
1976 while (tline && tline->type == TOK_OTHER
1977 && tline->text[0] == ',');
1978 free_tlist(origline);
1979 return 3;
1981 case PP_CLEAR:
1982 if (tline->next)
1983 error(ERR_WARNING,
1984 "trailing garbage after `%%clear' ignored");
1985 for (j = 0; j < NHASH; j++)
1987 while (mmacros[j])
1989 MMacro *m = mmacros[j];
1990 mmacros[j] = m->next;
1991 free_mmacro(m);
1993 while (smacros[j])
1995 SMacro *s = smacros[j];
1996 smacros[j] = smacros[j]->next;
1997 nasm_free(s->name);
1998 free_tlist(s->expansion);
1999 nasm_free(s);
2002 free_tlist(origline);
2003 return 3;
2005 case PP_INCLUDE:
2006 tline = tline->next;
2007 skip_white_(tline);
2008 if (!tline || (tline->type != TOK_STRING &&
2009 tline->type != TOK_INTERNAL_STRING))
2011 error(ERR_NONFATAL, "`%%include' expects a file name");
2012 free_tlist(origline);
2013 return 3; /* but we did _something_ */
2015 if (tline->next)
2016 error(ERR_WARNING,
2017 "trailing garbage after `%%include' ignored");
2018 if (tline->type != TOK_INTERNAL_STRING)
2020 p = tline->text + 1; /* point past the quote to the name */
2021 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
2023 else
2024 p = tline->text; /* internal_string is easier */
2025 expand_macros_in_string(&p);
2026 inc = nasm_malloc(sizeof(Include));
2027 inc->next = istk;
2028 inc->conds = NULL;
2029 inc->fp = inc_fopen(p);
2030 inc->fname = src_set_fname(p);
2031 inc->lineno = src_set_linnum(0);
2032 inc->lineinc = 1;
2033 inc->expansion = NULL;
2034 inc->mstk = NULL;
2035 istk = inc;
2036 list->uplevel(LIST_INCLUDE);
2037 free_tlist(origline);
2038 return 5;
2040 case PP_PUSH:
2041 tline = tline->next;
2042 skip_white_(tline);
2043 tline = expand_id(tline);
2044 if (!tok_type_(tline, TOK_ID))
2046 error(ERR_NONFATAL, "`%%push' expects a context identifier");
2047 free_tlist(origline);
2048 return 3; /* but we did _something_ */
2050 if (tline->next)
2051 error(ERR_WARNING, "trailing garbage after `%%push' ignored");
2052 ctx = nasm_malloc(sizeof(Context));
2053 ctx->next = cstk;
2054 ctx->localmac = NULL;
2055 ctx->name = nasm_strdup(tline->text);
2056 ctx->number = unique++;
2057 cstk = ctx;
2058 free_tlist(origline);
2059 break;
2061 case PP_REPL:
2062 tline = tline->next;
2063 skip_white_(tline);
2064 tline = expand_id(tline);
2065 if (!tok_type_(tline, TOK_ID))
2067 error(ERR_NONFATAL, "`%%repl' expects a context identifier");
2068 free_tlist(origline);
2069 return 3; /* but we did _something_ */
2071 if (tline->next)
2072 error(ERR_WARNING, "trailing garbage after `%%repl' ignored");
2073 if (!cstk)
2074 error(ERR_NONFATAL, "`%%repl': context stack is empty");
2075 else
2077 nasm_free(cstk->name);
2078 cstk->name = nasm_strdup(tline->text);
2080 free_tlist(origline);
2081 break;
2083 case PP_POP:
2084 if (tline->next)
2085 error(ERR_WARNING, "trailing garbage after `%%pop' ignored");
2086 if (!cstk)
2087 error(ERR_NONFATAL,
2088 "`%%pop': context stack is already empty");
2089 else
2090 ctx_pop();
2091 free_tlist(origline);
2092 break;
2094 case PP_ERROR:
2095 tline->next = expand_smacro(tline->next);
2096 tline = tline->next;
2097 skip_white_(tline);
2098 if (tok_type_(tline, TOK_STRING))
2100 p = tline->text + 1; /* point past the quote to the name */
2101 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
2102 expand_macros_in_string(&p);
2103 error(ERR_NONFATAL, "%s", p);
2104 nasm_free(p);
2106 else
2108 p = detoken(tline, FALSE);
2109 error(ERR_WARNING, "%s", p);
2110 nasm_free(p);
2112 free_tlist(origline);
2113 break;
2115 case PP_IF:
2116 case PP_IFCTX:
2117 case PP_IFDEF:
2118 case PP_IFID:
2119 case PP_IFIDN:
2120 case PP_IFIDNI:
2121 case PP_IFNCTX:
2122 case PP_IFNDEF:
2123 case PP_IFNID:
2124 case PP_IFNIDN:
2125 case PP_IFNIDNI:
2126 case PP_IFNNUM:
2127 case PP_IFNSTR:
2128 case PP_IFNUM:
2129 case PP_IFSTR:
2130 if (istk->conds && !emitting(istk->conds->state))
2131 j = COND_NEVER;
2132 else
2134 j = if_condition(tline->next, i);
2135 tline->next = NULL; /* it got freed */
2136 free_tlist(origline);
2137 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2139 cond = nasm_malloc(sizeof(Cond));
2140 cond->next = istk->conds;
2141 cond->state = j;
2142 istk->conds = cond;
2143 return (j == COND_IF_TRUE ? 3 : 1);
2145 case PP_ELIF:
2146 case PP_ELIFCTX:
2147 case PP_ELIFDEF:
2148 case PP_ELIFID:
2149 case PP_ELIFIDN:
2150 case PP_ELIFIDNI:
2151 case PP_ELIFNCTX:
2152 case PP_ELIFNDEF:
2153 case PP_ELIFNID:
2154 case PP_ELIFNIDN:
2155 case PP_ELIFNIDNI:
2156 case PP_ELIFNNUM:
2157 case PP_ELIFNSTR:
2158 case PP_ELIFNUM:
2159 case PP_ELIFSTR:
2160 if (!istk->conds)
2161 error(ERR_FATAL, "`%s': no matching `%%if'", directives[i]);
2162 if (emitting(istk->conds->state)
2163 || istk->conds->state == COND_NEVER)
2164 istk->conds->state = COND_NEVER;
2165 else
2167 j = if_condition(expand_mmac_params(tline->next), i);
2168 tline->next = NULL; /* it got freed */
2169 free_tlist(origline);
2170 istk->conds->state =
2171 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2173 return (istk->conds->state == COND_IF_TRUE ? 5 : 1);
2175 case PP_ELSE:
2176 if (tline->next)
2177 error(ERR_WARNING, "trailing garbage after `%%else' ignored");
2178 if (!istk->conds)
2179 error(ERR_FATAL, "`%%else': no matching `%%if'");
2180 if (emitting(istk->conds->state)
2181 || istk->conds->state == COND_NEVER)
2182 istk->conds->state = COND_ELSE_FALSE;
2183 else
2184 istk->conds->state = COND_ELSE_TRUE;
2185 free_tlist(origline);
2186 return 5;
2188 case PP_ENDIF:
2189 if (tline->next)
2190 error(ERR_WARNING,
2191 "trailing garbage after `%%endif' ignored");
2192 if (!istk->conds)
2193 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2194 cond = istk->conds;
2195 istk->conds = cond->next;
2196 nasm_free(cond);
2197 free_tlist(origline);
2198 return 5;
2200 case PP_MACRO:
2201 case PP_IMACRO:
2202 if (defining)
2203 error(ERR_FATAL,
2204 "`%%%smacro': already defining a macro",
2205 (i == PP_IMACRO ? "i" : ""));
2206 tline = tline->next;
2207 skip_white_(tline);
2208 tline = expand_id(tline);
2209 if (!tok_type_(tline, TOK_ID))
2211 error(ERR_NONFATAL,
2212 "`%%%smacro' expects a macro name",
2213 (i == PP_IMACRO ? "i" : ""));
2214 return 3;
2216 defining = nasm_malloc(sizeof(MMacro));
2217 defining->name = nasm_strdup(tline->text);
2218 defining->casesense = (i == PP_MACRO);
2219 defining->plus = FALSE;
2220 defining->nolist = FALSE;
2221 defining->in_progress = FALSE;
2222 defining->rep_nest = NULL;
2223 tline = expand_smacro(tline->next);
2224 skip_white_(tline);
2225 if (!tok_type_(tline, TOK_NUMBER))
2227 error(ERR_NONFATAL,
2228 "`%%%smacro' expects a parameter count",
2229 (i == PP_IMACRO ? "i" : ""));
2230 defining->nparam_min = defining->nparam_max = 0;
2232 else
2234 defining->nparam_min = defining->nparam_max =
2235 readnum(tline->text, &j);
2236 if (j)
2237 error(ERR_NONFATAL,
2238 "unable to parse parameter count `%s'",
2239 tline->text);
2241 if (tline && tok_is_(tline->next, "-"))
2243 tline = tline->next->next;
2244 if (tok_is_(tline, "*"))
2245 defining->nparam_max = INT_MAX;
2246 else if (!tok_type_(tline, TOK_NUMBER))
2247 error(ERR_NONFATAL,
2248 "`%%%smacro' expects a parameter count after `-'",
2249 (i == PP_IMACRO ? "i" : ""));
2250 else
2252 defining->nparam_max = readnum(tline->text, &j);
2253 if (j)
2254 error(ERR_NONFATAL,
2255 "unable to parse parameter count `%s'",
2256 tline->text);
2257 if (defining->nparam_min > defining->nparam_max)
2258 error(ERR_NONFATAL,
2259 "minimum parameter count exceeds maximum");
2262 if (tline && tok_is_(tline->next, "+"))
2264 tline = tline->next;
2265 defining->plus = TRUE;
2267 if (tline && tok_type_(tline->next, TOK_ID) &&
2268 !nasm_stricmp(tline->next->text, ".nolist"))
2270 tline = tline->next;
2271 defining->nolist = TRUE;
2273 mmac = mmacros[hash(defining->name)];
2274 while (mmac)
2276 if (!strcmp(mmac->name, defining->name) &&
2277 (mmac->nparam_min <= defining->nparam_max
2278 || defining->plus)
2279 && (defining->nparam_min <= mmac->nparam_max
2280 || mmac->plus))
2282 error(ERR_WARNING,
2283 "redefining multi-line macro `%s'",
2284 defining->name);
2285 break;
2287 mmac = mmac->next;
2290 * Handle default parameters.
2292 if (tline && tline->next)
2294 defining->dlist = tline->next;
2295 tline->next = NULL;
2296 count_mmac_params(defining->dlist, &defining->ndefs,
2297 &defining->defaults);
2299 else
2301 defining->dlist = NULL;
2302 defining->defaults = NULL;
2304 defining->expansion = NULL;
2305 free_tlist(origline);
2306 return 1;
2308 case PP_ENDM:
2309 case PP_ENDMACRO:
2310 if (!defining)
2312 error(ERR_NONFATAL, "`%s': not defining a macro",
2313 tline->text);
2314 return 3;
2316 k = hash(defining->name);
2317 defining->next = mmacros[k];
2318 mmacros[k] = defining;
2319 defining = NULL;
2320 free_tlist(origline);
2321 return 5;
2323 case PP_ROTATE:
2324 if (tline->next && tline->next->type == TOK_WHITESPACE)
2325 tline = tline->next;
2326 t = expand_smacro(tline->next);
2327 tline->next = NULL;
2328 free_tlist(origline);
2329 tline = t;
2330 tptr = &t;
2331 tokval.t_type = TOKEN_INVALID;
2332 evalresult =
2333 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2334 free_tlist(tline);
2335 if (!evalresult)
2336 return 3;
2337 if (tokval.t_type)
2338 error(ERR_WARNING,
2339 "trailing garbage after expression ignored");
2340 if (!is_simple(evalresult))
2342 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2343 return 3;
2345 mmac = istk->mstk;
2346 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2347 mmac = mmac->next_active;
2348 if (!mmac)
2349 error(ERR_NONFATAL,
2350 "`%%rotate' invoked outside a macro call");
2351 mmac->rotate = mmac->rotate + reloc_value(evalresult);
2352 if (mmac->rotate < 0)
2353 mmac->rotate = mmac->nparam - (-mmac->rotate) % mmac->nparam;
2354 mmac->rotate %= mmac->nparam;
2355 return 1;
2357 case PP_REP:
2358 nolist = FALSE;
2359 tline = tline->next;
2360 if (tline->next && tline->next->type == TOK_WHITESPACE)
2361 tline = tline->next;
2362 if (tline->next && tline->next->type == TOK_ID &&
2363 !nasm_stricmp(tline->next->text, ".nolist"))
2365 tline = tline->next;
2366 nolist = TRUE;
2368 t = expand_smacro(tline->next);
2369 tline->next = NULL;
2370 free_tlist(origline);
2371 tline = t;
2372 tptr = &t;
2373 tokval.t_type = TOKEN_INVALID;
2374 evalresult =
2375 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2376 free_tlist(tline);
2377 if (!evalresult)
2378 return 3;
2379 if (tokval.t_type)
2380 error(ERR_WARNING,
2381 "trailing garbage after expression ignored");
2382 if (!is_simple(evalresult))
2384 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2385 return 3;
2387 tmp_defining = defining;
2388 defining = nasm_malloc(sizeof(MMacro));
2389 defining->name = NULL; /* flags this macro as a %rep block */
2390 defining->casesense = 0;
2391 defining->plus = FALSE;
2392 defining->nolist = nolist;
2393 defining->in_progress = reloc_value(evalresult) + 1;
2394 defining->nparam_min = defining->nparam_max = 0;
2395 defining->defaults = NULL;
2396 defining->dlist = NULL;
2397 defining->expansion = NULL;
2398 defining->next_active = istk->mstk;
2399 defining->rep_nest = tmp_defining;
2400 return 1;
2402 case PP_ENDREP:
2403 if (!defining || defining->name)
2405 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2406 return 3;
2410 * Now we have a "macro" defined - although it has no name
2411 * and we won't be entering it in the hash tables - we must
2412 * push a macro-end marker for it on to istk->expansion.
2413 * After that, it will take care of propagating itself (a
2414 * macro-end marker line for a macro which is really a %rep
2415 * block will cause the macro to be re-expanded, complete
2416 * with another macro-end marker to ensure the process
2417 * continues) until the whole expansion is forcibly removed
2418 * from istk->expansion by a %exitrep.
2420 l = nasm_malloc(sizeof(Line));
2421 l->next = istk->expansion;
2422 l->finishes = defining;
2423 l->first = NULL;
2424 istk->expansion = l;
2426 istk->mstk = defining;
2428 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2429 tmp_defining = defining;
2430 defining = defining->rep_nest;
2431 free_tlist(origline);
2432 return 1;
2434 case PP_EXITREP:
2436 * We must search along istk->expansion until we hit a
2437 * macro-end marker for a macro with no name. Then we set
2438 * its `in_progress' flag to 0.
2440 for (l = istk->expansion; l; l = l->next)
2441 if (l->finishes && !l->finishes->name)
2442 break;
2444 if (l)
2445 l->finishes->in_progress = 0;
2446 else
2447 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2448 free_tlist(origline);
2449 return 1;
2451 case PP_XDEFINE:
2452 case PP_IXDEFINE:
2453 case PP_DEFINE:
2454 case PP_IDEFINE:
2455 tline = tline->next;
2456 skip_white_(tline);
2457 tline = expand_id(tline);
2458 if (!tline || (tline->type != TOK_ID &&
2459 (tline->type != TOK_PREPROC_ID ||
2460 tline->text[1] != '$')))
2462 error(ERR_NONFATAL,
2463 "`%%%s%sdefine' expects a macro identifier",
2464 ((i == PP_IDEFINE || i == PP_IXDEFINE) ? "i" : ""),
2465 ((i == PP_XDEFINE || i == PP_IXDEFINE) ? "x" : ""));
2466 free_tlist(origline);
2467 return 3;
2470 ctx = get_ctx(tline->text, FALSE);
2471 if (!ctx)
2472 smhead = &smacros[hash(tline->text)];
2473 else
2474 smhead = &ctx->localmac;
2475 mname = tline->text;
2476 last = tline;
2477 param_start = tline = tline->next;
2478 nparam = 0;
2480 /* Expand the macro definition now for %xdefine and %ixdefine */
2481 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2482 tline = expand_smacro(tline);
2484 if (tok_is_(tline, "("))
2487 * This macro has parameters.
2490 tline = tline->next;
2491 while (1)
2493 skip_white_(tline);
2494 if (!tline)
2496 error(ERR_NONFATAL, "parameter identifier expected");
2497 free_tlist(origline);
2498 return 3;
2500 if (tline->type != TOK_ID)
2502 error(ERR_NONFATAL,
2503 "`%s': parameter identifier expected",
2504 tline->text);
2505 free_tlist(origline);
2506 return 3;
2508 tline->type = TOK_SMAC_PARAM + nparam++;
2509 tline = tline->next;
2510 skip_white_(tline);
2511 if (tok_is_(tline, ","))
2513 tline = tline->next;
2514 continue;
2516 if (!tok_is_(tline, ")"))
2518 error(ERR_NONFATAL,
2519 "`)' expected to terminate macro template");
2520 free_tlist(origline);
2521 return 3;
2523 break;
2525 last = tline;
2526 tline = tline->next;
2528 if (tok_type_(tline, TOK_WHITESPACE))
2529 last = tline, tline = tline->next;
2530 macro_start = NULL;
2531 last->next = NULL;
2532 t = tline;
2533 while (t)
2535 if (t->type == TOK_ID)
2537 for (tt = param_start; tt; tt = tt->next)
2538 if (tt->type >= TOK_SMAC_PARAM &&
2539 !strcmp(tt->text, t->text))
2540 t->type = tt->type;
2542 tt = t->next;
2543 t->next = macro_start;
2544 macro_start = t;
2545 t = tt;
2548 * Good. We now have a macro name, a parameter count, and a
2549 * token list (in reverse order) for an expansion. We ought
2550 * to be OK just to create an SMacro, store it, and let
2551 * free_tlist have the rest of the line (which we have
2552 * carefully re-terminated after chopping off the expansion
2553 * from the end).
2555 if (smacro_defined(ctx, mname, nparam, &smac, i == PP_DEFINE))
2557 if (!smac)
2559 error(ERR_WARNING,
2560 "single-line macro `%s' defined both with and"
2561 " without parameters", mname);
2562 free_tlist(origline);
2563 free_tlist(macro_start);
2564 return 3;
2566 else
2569 * We're redefining, so we have to take over an
2570 * existing SMacro structure. This means freeing
2571 * what was already in it.
2573 nasm_free(smac->name);
2574 free_tlist(smac->expansion);
2577 else
2579 smac = nasm_malloc(sizeof(SMacro));
2580 smac->next = *smhead;
2581 *smhead = smac;
2583 smac->name = nasm_strdup(mname);
2584 smac->casesense = ((i == PP_DEFINE) || (i == PP_XDEFINE));
2585 smac->nparam = nparam;
2586 smac->expansion = macro_start;
2587 smac->in_progress = FALSE;
2588 free_tlist(origline);
2589 return 3;
2591 case PP_UNDEF:
2592 tline = tline->next;
2593 skip_white_(tline);
2594 tline = expand_id(tline);
2595 if (!tline || (tline->type != TOK_ID &&
2596 (tline->type != TOK_PREPROC_ID ||
2597 tline->text[1] != '$')))
2599 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
2600 free_tlist(origline);
2601 return 3;
2603 if (tline->next)
2605 error(ERR_WARNING,
2606 "trailing garbage after macro name ignored");
2609 /* Find the context that symbol belongs to */
2610 ctx = get_ctx(tline->text, FALSE);
2611 if (!ctx)
2612 smhead = &smacros[hash(tline->text)];
2613 else
2614 smhead = &ctx->localmac;
2616 mname = tline->text;
2617 last = tline;
2618 last->next = NULL;
2621 * We now have a macro name... go hunt for it.
2623 while (smacro_defined(ctx, mname, -1, &smac, 1))
2625 /* Defined, so we need to find its predecessor and nuke it */
2626 SMacro **s;
2627 for (s = smhead; *s && *s != smac; s = &(*s)->next);
2628 if (*s)
2630 *s = smac->next;
2631 nasm_free(smac->name);
2632 free_tlist(smac->expansion);
2633 nasm_free(smac);
2636 free_tlist(origline);
2637 return 3;
2639 case PP_STRLEN:
2640 tline = tline->next;
2641 skip_white_(tline);
2642 tline = expand_id(tline);
2643 if (!tline || (tline->type != TOK_ID &&
2644 (tline->type != TOK_PREPROC_ID ||
2645 tline->text[1] != '$')))
2647 error(ERR_NONFATAL,
2648 "`%%strlen' expects a macro identifier as first parameter");
2649 free_tlist(origline);
2650 return 3;
2652 ctx = get_ctx(tline->text, FALSE);
2653 if (!ctx)
2654 smhead = &smacros[hash(tline->text)];
2655 else
2656 smhead = &ctx->localmac;
2657 mname = tline->text;
2658 last = tline;
2659 tline = expand_smacro(tline->next);
2660 last->next = NULL;
2662 t = tline;
2663 while (tok_type_(t, TOK_WHITESPACE))
2664 t = t->next;
2665 /* t should now point to the string */
2666 if (t->type != TOK_STRING)
2668 error(ERR_NONFATAL,
2669 "`%%strlen` requires string as second parameter");
2670 free_tlist(tline);
2671 free_tlist(origline);
2672 return 3;
2675 macro_start = nasm_malloc(sizeof(*macro_start));
2676 macro_start->next = NULL;
2677 make_tok_num(macro_start, strlen(t->text) - 2);
2678 macro_start->mac = NULL;
2681 * We now have a macro name, an implicit parameter count of
2682 * zero, and a numeric token to use as an expansion. Create
2683 * and store an SMacro.
2685 if (smacro_defined(ctx, mname, 0, &smac, i == PP_STRLEN))
2687 if (!smac)
2688 error(ERR_WARNING,
2689 "single-line macro `%s' defined both with and"
2690 " without parameters", mname);
2691 else
2694 * We're redefining, so we have to take over an
2695 * existing SMacro structure. This means freeing
2696 * what was already in it.
2698 nasm_free(smac->name);
2699 free_tlist(smac->expansion);
2702 else
2704 smac = nasm_malloc(sizeof(SMacro));
2705 smac->next = *smhead;
2706 *smhead = smac;
2708 smac->name = nasm_strdup(mname);
2709 smac->casesense = (i == PP_STRLEN);
2710 smac->nparam = 0;
2711 smac->expansion = macro_start;
2712 smac->in_progress = FALSE;
2713 free_tlist(tline);
2714 free_tlist(origline);
2715 return 3;
2717 case PP_SUBSTR:
2718 tline = tline->next;
2719 skip_white_(tline);
2720 tline = expand_id(tline);
2721 if (!tline || (tline->type != TOK_ID &&
2722 (tline->type != TOK_PREPROC_ID ||
2723 tline->text[1] != '$')))
2725 error(ERR_NONFATAL,
2726 "`%%substr' expects a macro identifier as first parameter");
2727 free_tlist(origline);
2728 return 3;
2730 ctx = get_ctx(tline->text, FALSE);
2731 if (!ctx)
2732 smhead = &smacros[hash(tline->text)];
2733 else
2734 smhead = &ctx->localmac;
2735 mname = tline->text;
2736 last = tline;
2737 tline = expand_smacro(tline->next);
2738 last->next = NULL;
2740 t = tline->next;
2741 while (tok_type_(t, TOK_WHITESPACE))
2742 t = t->next;
2744 /* t should now point to the string */
2745 if (t->type != TOK_STRING)
2747 error(ERR_NONFATAL,
2748 "`%%substr` requires string as second parameter");
2749 free_tlist(tline);
2750 free_tlist(origline);
2751 return 3;
2754 tt = t->next;
2755 tptr = &tt;
2756 tokval.t_type = TOKEN_INVALID;
2757 evalresult =
2758 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2759 if (!evalresult)
2761 free_tlist(tline);
2762 free_tlist(origline);
2763 return 3;
2765 if (!is_simple(evalresult))
2767 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
2768 free_tlist(tline);
2769 free_tlist(origline);
2770 return 3;
2773 macro_start = nasm_malloc(sizeof(*macro_start));
2774 macro_start->next = NULL;
2775 macro_start->text = nasm_strdup("'''");
2776 if (evalresult->value > 0
2777 && evalresult->value < strlen(t->text) - 1)
2779 macro_start->text[1] = t->text[evalresult->value];
2781 else
2783 macro_start->text[2] = '\0';
2785 macro_start->type = TOK_STRING;
2786 macro_start->mac = NULL;
2789 * We now have a macro name, an implicit parameter count of
2790 * zero, and a numeric token to use as an expansion. Create
2791 * and store an SMacro.
2793 if (smacro_defined(ctx, mname, 0, &smac, i == PP_SUBSTR))
2795 if (!smac)
2796 error(ERR_WARNING,
2797 "single-line macro `%s' defined both with and"
2798 " without parameters", mname);
2799 else
2802 * We're redefining, so we have to take over an
2803 * existing SMacro structure. This means freeing
2804 * what was already in it.
2806 nasm_free(smac->name);
2807 free_tlist(smac->expansion);
2810 else
2812 smac = nasm_malloc(sizeof(SMacro));
2813 smac->next = *smhead;
2814 *smhead = smac;
2816 smac->name = nasm_strdup(mname);
2817 smac->casesense = (i == PP_SUBSTR);
2818 smac->nparam = 0;
2819 smac->expansion = macro_start;
2820 smac->in_progress = FALSE;
2821 free_tlist(tline);
2822 free_tlist(origline);
2823 return 3;
2826 case PP_ASSIGN:
2827 case PP_IASSIGN:
2828 tline = tline->next;
2829 skip_white_(tline);
2830 tline = expand_id(tline);
2831 if (!tline || (tline->type != TOK_ID &&
2832 (tline->type != TOK_PREPROC_ID ||
2833 tline->text[1] != '$')))
2835 error(ERR_NONFATAL,
2836 "`%%%sassign' expects a macro identifier",
2837 (i == PP_IASSIGN ? "i" : ""));
2838 free_tlist(origline);
2839 return 3;
2841 ctx = get_ctx(tline->text, FALSE);
2842 if (!ctx)
2843 smhead = &smacros[hash(tline->text)];
2844 else
2845 smhead = &ctx->localmac;
2846 mname = tline->text;
2847 last = tline;
2848 tline = expand_smacro(tline->next);
2849 last->next = NULL;
2851 t = tline;
2852 tptr = &t;
2853 tokval.t_type = TOKEN_INVALID;
2854 evalresult =
2855 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2856 free_tlist(tline);
2857 if (!evalresult)
2859 free_tlist(origline);
2860 return 3;
2863 if (tokval.t_type)
2864 error(ERR_WARNING,
2865 "trailing garbage after expression ignored");
2867 if (!is_simple(evalresult))
2869 error(ERR_NONFATAL,
2870 "non-constant value given to `%%%sassign'",
2871 (i == PP_IASSIGN ? "i" : ""));
2872 free_tlist(origline);
2873 return 3;
2876 macro_start = nasm_malloc(sizeof(*macro_start));
2877 macro_start->next = NULL;
2878 make_tok_num(macro_start, reloc_value(evalresult));
2879 macro_start->mac = NULL;
2882 * We now have a macro name, an implicit parameter count of
2883 * zero, and a numeric token to use as an expansion. Create
2884 * and store an SMacro.
2886 if (smacro_defined(ctx, mname, 0, &smac, i == PP_ASSIGN))
2888 if (!smac)
2889 error(ERR_WARNING,
2890 "single-line macro `%s' defined both with and"
2891 " without parameters", mname);
2892 else
2895 * We're redefining, so we have to take over an
2896 * existing SMacro structure. This means freeing
2897 * what was already in it.
2899 nasm_free(smac->name);
2900 free_tlist(smac->expansion);
2903 else
2905 smac = nasm_malloc(sizeof(SMacro));
2906 smac->next = *smhead;
2907 *smhead = smac;
2909 smac->name = nasm_strdup(mname);
2910 smac->casesense = (i == PP_ASSIGN);
2911 smac->nparam = 0;
2912 smac->expansion = macro_start;
2913 smac->in_progress = FALSE;
2914 free_tlist(origline);
2915 return 3;
2917 case PP_LINE:
2919 * Syntax is `%line nnn[+mmm] [filename]'
2921 tline = tline->next;
2922 skip_white_(tline);
2923 if (!tok_type_(tline, TOK_NUMBER))
2925 error(ERR_NONFATAL, "`%%line' expects line number");
2926 free_tlist(origline);
2927 return 3;
2929 k = readnum(tline->text, &j);
2930 m = 1;
2931 tline = tline->next;
2932 if (tok_is_(tline, "+"))
2934 tline = tline->next;
2935 if (!tok_type_(tline, TOK_NUMBER))
2937 error(ERR_NONFATAL, "`%%line' expects line increment");
2938 free_tlist(origline);
2939 return 3;
2941 m = readnum(tline->text, &j);
2942 tline = tline->next;
2944 skip_white_(tline);
2945 src_set_linnum(k);
2946 istk->lineinc = m;
2947 if (tline)
2949 nasm_free(src_set_fname(detoken(tline, FALSE)));
2951 free_tlist(origline);
2952 return 5;
2954 default:
2955 error(ERR_FATAL,
2956 "preprocessor directive `%s' not yet implemented",
2957 directives[i]);
2958 break;
2960 return 3;
2964 * Ensure that a macro parameter contains a condition code and
2965 * nothing else. Return the condition code index if so, or -1
2966 * otherwise.
2968 static int
2969 find_cc(Token * t)
2971 Token *tt;
2972 int i, j, k, m;
2974 skip_white_(t);
2975 if (t->type != TOK_ID)
2976 return -1;
2977 tt = t->next;
2978 skip_white_(tt);
2979 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
2980 return -1;
2982 i = -1;
2983 j = sizeof(conditions) / sizeof(*conditions);
2984 while (j - i > 1)
2986 k = (j + i) / 2;
2987 m = nasm_stricmp(t->text, conditions[k]);
2988 if (m == 0)
2990 i = k;
2991 j = -2;
2992 break;
2994 else if (m < 0)
2996 j = k;
2998 else
2999 i = k;
3001 if (j != -2)
3002 return -1;
3003 return i;
3007 * Expand MMacro-local things: parameter references (%0, %n, %+n,
3008 * %-n) and MMacro-local identifiers (%%foo).
3010 static Token *
3011 expand_mmac_params(Token * tline)
3013 Token *t, *tt, **tail, *thead;
3015 tail = &thead;
3016 thead = NULL;
3018 while (tline)
3020 if (tline->type == TOK_PREPROC_ID &&
3021 (((tline->text[1] == '+' || tline->text[1] == '-')
3022 && tline->text[2]) || tline->text[1] == '%'
3023 || (tline->text[1] >= '0' && tline->text[1] <= '9')))
3025 char *text = NULL;
3026 int type = 0, cc; /* type = 0 to placate optimisers */
3027 char tmpbuf[30];
3028 int n, i;
3029 MMacro *mac;
3031 t = tline;
3032 tline = tline->next;
3034 mac = istk->mstk;
3035 while (mac && !mac->name) /* avoid mistaking %reps for macros */
3036 mac = mac->next_active;
3037 if (!mac)
3038 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
3039 else
3040 switch (t->text[1])
3043 * We have to make a substitution of one of the
3044 * forms %1, %-1, %+1, %%foo, %0.
3046 case '0':
3047 type = TOK_NUMBER;
3048 sprintf(tmpbuf, "%d", mac->nparam);
3049 text = nasm_strdup(tmpbuf);
3050 break;
3051 case '%':
3052 type = TOK_ID;
3053 sprintf(tmpbuf, "..@%lu.", mac->unique);
3054 text = nasm_strcat(tmpbuf, t->text + 2);
3055 break;
3056 case '-':
3057 n = atoi(t->text + 2) - 1;
3058 if (n >= mac->nparam)
3059 tt = NULL;
3060 else
3062 if (mac->nparam > 1)
3063 n = (n + mac->rotate) % mac->nparam;
3064 tt = mac->params[n];
3066 cc = find_cc(tt);
3067 if (cc == -1)
3069 error(ERR_NONFATAL,
3070 "macro parameter %d is not a condition code",
3071 n + 1);
3072 text = NULL;
3074 else
3076 type = TOK_ID;
3077 if (inverse_ccs[cc] == -1)
3079 error(ERR_NONFATAL,
3080 "condition code `%s' is not invertible",
3081 conditions[cc]);
3082 text = NULL;
3084 else
3085 text =
3086 nasm_strdup(conditions[inverse_ccs
3087 [cc]]);
3089 break;
3090 case '+':
3091 n = atoi(t->text + 2) - 1;
3092 if (n >= mac->nparam)
3093 tt = NULL;
3094 else
3096 if (mac->nparam > 1)
3097 n = (n + mac->rotate) % mac->nparam;
3098 tt = mac->params[n];
3100 cc = find_cc(tt);
3101 if (cc == -1)
3103 error(ERR_NONFATAL,
3104 "macro parameter %d is not a condition code",
3105 n + 1);
3106 text = NULL;
3108 else
3110 type = TOK_ID;
3111 text = nasm_strdup(conditions[cc]);
3113 break;
3114 default:
3115 n = atoi(t->text + 1) - 1;
3116 if (n >= mac->nparam)
3117 tt = NULL;
3118 else
3120 if (mac->nparam > 1)
3121 n = (n + mac->rotate) % mac->nparam;
3122 tt = mac->params[n];
3124 if (tt)
3126 for (i = 0; i < mac->paramlen[n]; i++)
3128 *tail =
3129 new_Token(NULL, tt->type, tt->text,
3131 tail = &(*tail)->next;
3132 tt = tt->next;
3135 text = NULL; /* we've done it here */
3136 break;
3138 if (!text)
3140 delete_Token(t);
3142 else
3144 *tail = t;
3145 tail = &t->next;
3146 t->type = type;
3147 nasm_free(t->text);
3148 t->text = text;
3149 t->mac = NULL;
3151 continue;
3153 else
3155 t = *tail = tline;
3156 tline = tline->next;
3157 t->mac = NULL;
3158 tail = &t->next;
3161 *tail = NULL;
3162 t = thead;
3163 for (; t && (tt = t->next) != NULL; t = t->next)
3164 switch (t->type)
3166 case TOK_WHITESPACE:
3167 if (tt->type == TOK_WHITESPACE)
3169 t->next = delete_Token(tt);
3171 break;
3172 case TOK_ID:
3173 if (tt->type == TOK_ID || tt->type == TOK_NUMBER)
3175 char *tmp = nasm_strcat(t->text, tt->text);
3176 nasm_free(t->text);
3177 t->text = tmp;
3178 t->next = delete_Token(tt);
3180 break;
3181 case TOK_NUMBER:
3182 if (tt->type == TOK_NUMBER)
3184 char *tmp = nasm_strcat(t->text, tt->text);
3185 nasm_free(t->text);
3186 t->text = tmp;
3187 t->next = delete_Token(tt);
3189 break;
3192 return thead;
3196 * Expand all single-line macro calls made in the given line.
3197 * Return the expanded version of the line. The original is deemed
3198 * to be destroyed in the process. (In reality we'll just move
3199 * Tokens from input to output a lot of the time, rather than
3200 * actually bothering to destroy and replicate.)
3202 static Token *
3203 expand_smacro(Token * tline)
3205 Token *t, *tt, *mstart, **tail, *thead;
3206 SMacro *head = NULL, *m;
3207 Token **params;
3208 int *paramsize;
3209 int nparam, sparam, brackets, rescan;
3210 Token *org_tline = tline;
3211 Context *ctx;
3212 char *mname;
3215 * Trick: we should avoid changing the start token pointer since it can
3216 * be contained in "next" field of other token. Because of this
3217 * we allocate a copy of first token and work with it; at the end of
3218 * routine we copy it back
3220 if (org_tline)
3222 tline =
3223 new_Token(org_tline->next, org_tline->type, org_tline->text,
3225 tline->mac = org_tline->mac;
3226 nasm_free(org_tline->text);
3227 org_tline->text = NULL;
3230 again:
3231 tail = &thead;
3232 thead = NULL;
3234 while (tline)
3235 { /* main token loop */
3236 if ((mname = tline->text))
3238 /* if this token is a local macro, look in local context */
3239 if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
3240 ctx = get_ctx(mname, TRUE);
3241 else
3242 ctx = NULL;
3243 if (!ctx)
3244 head = smacros[hash(mname)];
3245 else
3246 head = ctx->localmac;
3248 * We've hit an identifier. As in is_mmacro below, we first
3249 * check whether the identifier is a single-line macro at
3250 * all, then think about checking for parameters if
3251 * necessary.
3253 for (m = head; m; m = m->next)
3254 if (!mstrcmp(m->name, mname, m->casesense))
3255 break;
3256 if (m)
3258 mstart = tline;
3259 params = NULL;
3260 paramsize = NULL;
3261 if (m->nparam == 0)
3264 * Simple case: the macro is parameterless. Discard the
3265 * one token that the macro call took, and push the
3266 * expansion back on the to-do stack.
3268 if (!m->expansion)
3270 if (!strcmp("__FILE__", m->name))
3272 long num = 0;
3273 src_get(&num, &(tline->text));
3274 nasm_quote(&(tline->text));
3275 tline->type = TOK_STRING;
3276 continue;
3278 if (!strcmp("__LINE__", m->name))
3280 nasm_free(tline->text);
3281 make_tok_num(tline, src_get_linnum());
3282 continue;
3284 tline = delete_Token(tline);
3285 continue;
3288 else
3291 * Complicated case: at least one macro with this name
3292 * exists and takes parameters. We must find the
3293 * parameters in the call, count them, find the SMacro
3294 * that corresponds to that form of the macro call, and
3295 * substitute for the parameters when we expand. What a
3296 * pain.
3298 tline = tline->next;
3299 skip_white_(tline);
3300 if (!tok_is_(tline, "("))
3303 * This macro wasn't called with parameters: ignore
3304 * the call. (Behaviour borrowed from gnu cpp.)
3306 tline = mstart;
3307 m = NULL;
3309 else
3311 int paren = 0;
3312 int white = 0;
3313 brackets = 0;
3314 nparam = 0;
3315 tline = tline->next;
3316 sparam = PARAM_DELTA;
3317 params = nasm_malloc(sparam * sizeof(Token *));
3318 params[0] = tline;
3319 paramsize = nasm_malloc(sparam * sizeof(int));
3320 paramsize[0] = 0;
3321 for (;; tline = tline->next)
3322 { /* parameter loop */
3323 if (!tline)
3325 error(ERR_NONFATAL,
3326 "macro call expects terminating `)'");
3327 break;
3329 if (tline->type == TOK_WHITESPACE
3330 && brackets <= 0)
3332 if (paramsize[nparam])
3333 white++;
3334 else
3335 params[nparam] = tline->next;
3336 continue; /* parameter loop */
3338 if (tline->type == TOK_OTHER
3339 && tline->text[1] == 0)
3341 char ch = tline->text[0];
3342 if (ch == ',' && !paren && brackets <= 0)
3344 if (++nparam >= sparam)
3346 sparam += PARAM_DELTA;
3347 params = nasm_realloc(params,
3348 sparam * sizeof(Token *));
3349 paramsize = nasm_realloc(paramsize,
3350 sparam * sizeof(int));
3352 params[nparam] = tline->next;
3353 paramsize[nparam] = 0;
3354 white = 0;
3355 continue; /* parameter loop */
3357 if (ch == '{' &&
3358 (brackets > 0 || (brackets == 0 &&
3359 !paramsize[nparam])))
3361 if (!(brackets++))
3363 params[nparam] = tline->next;
3364 continue; /* parameter loop */
3367 if (ch == '}' && brackets > 0)
3368 if (--brackets == 0)
3370 brackets = -1;
3371 continue; /* parameter loop */
3373 if (ch == '(' && !brackets)
3374 paren++;
3375 if (ch == ')' && brackets <= 0)
3376 if (--paren < 0)
3377 break;
3379 if (brackets < 0)
3381 brackets = 0;
3382 error(ERR_NONFATAL, "braces do not "
3383 "enclose all of macro parameter");
3385 paramsize[nparam] += white + 1;
3386 white = 0;
3387 } /* parameter loop */
3388 nparam++;
3389 while (m && (m->nparam != nparam ||
3390 mstrcmp(m->name, mname,
3391 m->casesense)))
3392 m = m->next;
3393 if (!m)
3394 error(ERR_WARNING | ERR_WARN_MNP,
3395 "macro `%s' exists, "
3396 "but not taking %d parameters",
3397 mstart->text, nparam);
3400 if (m && m->in_progress)
3401 m = NULL;
3402 if (!m) /* in progess or didn't find '(' or wrong nparam */
3405 * Design question: should we handle !tline, which
3406 * indicates missing ')' here, or expand those
3407 * macros anyway, which requires the (t) test a few
3408 * lines down?
3410 nasm_free(params);
3411 nasm_free(paramsize);
3412 tline = mstart;
3414 else
3417 * Expand the macro: we are placed on the last token of the
3418 * call, so that we can easily split the call from the
3419 * following tokens. We also start by pushing an SMAC_END
3420 * token for the cycle removal.
3422 t = tline;
3423 if (t)
3425 tline = t->next;
3426 t->next = NULL;
3428 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
3429 tt->mac = m;
3430 m->in_progress = TRUE;
3431 tline = tt;
3432 for (t = m->expansion; t; t = t->next)
3434 if (t->type >= TOK_SMAC_PARAM)
3436 Token *pcopy = tline, **ptail = &pcopy;
3437 Token *ttt, *pt;
3438 int i;
3440 ttt = params[t->type - TOK_SMAC_PARAM];
3441 for (i = paramsize[t->type - TOK_SMAC_PARAM];
3442 --i >= 0;)
3444 pt = *ptail =
3445 new_Token(tline, ttt->type, ttt->text,
3447 ptail = &pt->next;
3448 ttt = ttt->next;
3450 tline = pcopy;
3452 else
3454 tt = new_Token(tline, t->type, t->text, 0);
3455 tline = tt;
3460 * Having done that, get rid of the macro call, and clean
3461 * up the parameters.
3463 nasm_free(params);
3464 nasm_free(paramsize);
3465 free_tlist(mstart);
3466 continue; /* main token loop */
3471 if (tline->type == TOK_SMAC_END)
3473 tline->mac->in_progress = FALSE;
3474 tline = delete_Token(tline);
3476 else
3478 t = *tail = tline;
3479 tline = tline->next;
3480 t->mac = NULL;
3481 t->next = NULL;
3482 tail = &t->next;
3487 * Now scan the entire line and look for successive TOK_IDs that resulted
3488 * after expansion (they can't be produced by tokenise()). The successive
3489 * TOK_IDs should be concatenated.
3490 * Also we look for %+ tokens and concatenate the tokens before and after
3491 * them (without white spaces in between).
3493 t = thead;
3494 rescan = 0;
3495 while (t)
3497 while (t && t->type != TOK_ID && t->type != TOK_PREPROC_ID)
3498 t = t->next;
3499 if (!t || !t->next)
3500 break;
3501 if (t->next->type == TOK_ID ||
3502 t->next->type == TOK_PREPROC_ID ||
3503 t->next->type == TOK_NUMBER)
3505 char *p = nasm_strcat(t->text, t->next->text);
3506 nasm_free(t->text);
3507 t->next = delete_Token(t->next);
3508 t->text = p;
3509 rescan = 1;
3511 else if (t->next->type == TOK_WHITESPACE && t->next->next &&
3512 t->next->next->type == TOK_PREPROC_ID &&
3513 strcmp(t->next->next->text, "%+") == 0)
3515 /* free the next whitespace, the %+ token and next whitespace */
3516 int i;
3517 for (i = 1; i <= 3; i++)
3519 if (!t->next || (i != 2 && t->next->type != TOK_WHITESPACE))
3520 break;
3521 t->next = delete_Token(t->next);
3522 } /* endfor */
3524 else
3525 t = t->next;
3527 /* If we concatenaded something, re-scan the line for macros */
3528 if (rescan)
3530 tline = thead;
3531 goto again;
3534 if (org_tline)
3536 if (thead)
3538 *org_tline = *thead;
3539 /* since we just gave text to org_line, don't free it */
3540 thead->text = NULL;
3541 delete_Token(thead);
3543 else
3545 /* the expression expanded to empty line;
3546 we can't return NULL for some reasons
3547 we just set the line to a single WHITESPACE token. */
3548 memset(org_tline, 0, sizeof(*org_tline));
3549 org_tline->text = NULL;
3550 org_tline->type = TOK_WHITESPACE;
3552 thead = org_tline;
3555 return thead;
3559 * Similar to expand_smacro but used exclusively with macro identifiers
3560 * right before they are fetched in. The reason is that there can be
3561 * identifiers consisting of several subparts. We consider that if there
3562 * are more than one element forming the name, user wants a expansion,
3563 * otherwise it will be left as-is. Example:
3565 * %define %$abc cde
3567 * the identifier %$abc will be left as-is so that the handler for %define
3568 * will suck it and define the corresponding value. Other case:
3570 * %define _%$abc cde
3572 * In this case user wants name to be expanded *before* %define starts
3573 * working, so we'll expand %$abc into something (if it has a value;
3574 * otherwise it will be left as-is) then concatenate all successive
3575 * PP_IDs into one.
3577 static Token *
3578 expand_id(Token * tline)
3580 Token *cur, *oldnext = NULL;
3582 if (!tline || !tline->next)
3583 return tline;
3585 cur = tline;
3586 while (cur->next &&
3587 (cur->next->type == TOK_ID ||
3588 cur->next->type == TOK_PREPROC_ID || cur->next->type == TOK_NUMBER))
3589 cur = cur->next;
3591 /* If identifier consists of just one token, don't expand */
3592 if (cur == tline)
3593 return tline;
3595 if (cur)
3597 oldnext = cur->next; /* Detach the tail past identifier */
3598 cur->next = NULL; /* so that expand_smacro stops here */
3601 tline = expand_smacro(tline);
3603 if (cur)
3605 /* expand_smacro possibly changhed tline; re-scan for EOL */
3606 cur = tline;
3607 while (cur && cur->next)
3608 cur = cur->next;
3609 if (cur)
3610 cur->next = oldnext;
3613 return tline;
3617 * Determine whether the given line constitutes a multi-line macro
3618 * call, and return the MMacro structure called if so. Doesn't have
3619 * to check for an initial label - that's taken care of in
3620 * expand_mmacro - but must check numbers of parameters. Guaranteed
3621 * to be called with tline->type == TOK_ID, so the putative macro
3622 * name is easy to find.
3624 static MMacro *
3625 is_mmacro(Token * tline, Token *** params_array)
3627 MMacro *head, *m;
3628 Token **params;
3629 int nparam;
3631 head = mmacros[hash(tline->text)];
3634 * Efficiency: first we see if any macro exists with the given
3635 * name. If not, we can return NULL immediately. _Then_ we
3636 * count the parameters, and then we look further along the
3637 * list if necessary to find the proper MMacro.
3639 for (m = head; m; m = m->next)
3640 if (!mstrcmp(m->name, tline->text, m->casesense))
3641 break;
3642 if (!m)
3643 return NULL;
3646 * OK, we have a potential macro. Count and demarcate the
3647 * parameters.
3649 count_mmac_params(tline->next, &nparam, &params);
3652 * So we know how many parameters we've got. Find the MMacro
3653 * structure that handles this number.
3655 while (m)
3657 if (m->nparam_min <= nparam && (m->plus || nparam <= m->nparam_max))
3660 * This one is right. Just check if cycle removal
3661 * prohibits us using it before we actually celebrate...
3663 if (m->in_progress)
3665 #if 0
3666 error(ERR_NONFATAL,
3667 "self-reference in multi-line macro `%s'", m->name);
3668 #endif
3669 nasm_free(params);
3670 return NULL;
3673 * It's right, and we can use it. Add its default
3674 * parameters to the end of our list if necessary.
3676 if (m->defaults && nparam < m->nparam_min + m->ndefs)
3678 params =
3679 nasm_realloc(params,
3680 ((m->nparam_min + m->ndefs + 1) * sizeof(*params)));
3681 while (nparam < m->nparam_min + m->ndefs)
3683 params[nparam] = m->defaults[nparam - m->nparam_min];
3684 nparam++;
3688 * If we've gone over the maximum parameter count (and
3689 * we're in Plus mode), ignore parameters beyond
3690 * nparam_max.
3692 if (m->plus && nparam > m->nparam_max)
3693 nparam = m->nparam_max;
3695 * Then terminate the parameter list, and leave.
3697 if (!params)
3698 { /* need this special case */
3699 params = nasm_malloc(sizeof(*params));
3700 nparam = 0;
3702 params[nparam] = NULL;
3703 *params_array = params;
3704 return m;
3707 * This one wasn't right: look for the next one with the
3708 * same name.
3710 for (m = m->next; m; m = m->next)
3711 if (!mstrcmp(m->name, tline->text, m->casesense))
3712 break;
3716 * After all that, we didn't find one with the right number of
3717 * parameters. Issue a warning, and fail to expand the macro.
3719 error(ERR_WARNING | ERR_WARN_MNP,
3720 "macro `%s' exists, but not taking %d parameters",
3721 tline->text, nparam);
3722 nasm_free(params);
3723 return NULL;
3727 * Expand the multi-line macro call made by the given line, if
3728 * there is one to be expanded. If there is, push the expansion on
3729 * istk->expansion and return 1. Otherwise return 0.
3731 static int
3732 expand_mmacro(Token * tline)
3734 Token *startline = tline;
3735 Token *label = NULL;
3736 int dont_prepend = 0;
3737 Token **params, *t, *tt;
3738 MMacro *m;
3739 Line *l, *ll;
3740 int i, nparam, *paramlen;
3742 t = tline;
3743 skip_white_(t);
3744 if (!tok_type_(t, TOK_ID))
3745 return 0;
3746 m = is_mmacro(t, &params);
3747 if (!m)
3749 Token *last;
3751 * We have an id which isn't a macro call. We'll assume
3752 * it might be a label; we'll also check to see if a
3753 * colon follows it. Then, if there's another id after
3754 * that lot, we'll check it again for macro-hood.
3756 label = last = t;
3757 t = t->next;
3758 if (tok_type_(t, TOK_WHITESPACE))
3759 last = t, t = t->next;
3760 if (tok_is_(t, ":"))
3762 dont_prepend = 1;
3763 last = t, t = t->next;
3764 if (tok_type_(t, TOK_WHITESPACE))
3765 last = t, t = t->next;
3767 if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
3768 return 0;
3769 last->next = NULL;
3770 tline = t;
3774 * Fix up the parameters: this involves stripping leading and
3775 * trailing whitespace, then stripping braces if they are
3776 * present.
3778 for (nparam = 0; params[nparam]; nparam++)
3780 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
3782 for (i = 0; params[i]; i++)
3784 int brace = FALSE;
3785 int comma = (!m->plus || i < nparam - 1);
3787 t = params[i];
3788 skip_white_(t);
3789 if (tok_is_(t, "{"))
3790 t = t->next, brace = TRUE, comma = FALSE;
3791 params[i] = t;
3792 paramlen[i] = 0;
3793 while (t)
3795 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
3796 break; /* ... because we have hit a comma */
3797 if (comma && t->type == TOK_WHITESPACE && tok_is_(t->next, ","))
3798 break; /* ... or a space then a comma */
3799 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
3800 break; /* ... or a brace */
3801 t = t->next;
3802 paramlen[i]++;
3807 * OK, we have a MMacro structure together with a set of
3808 * parameters. We must now go through the expansion and push
3809 * copies of each Line on to istk->expansion. Substitution of
3810 * parameter tokens and macro-local tokens doesn't get done
3811 * until the single-line macro substitution process; this is
3812 * because delaying them allows us to change the semantics
3813 * later through %rotate.
3815 * First, push an end marker on to istk->expansion, mark this
3816 * macro as in progress, and set up its invocation-specific
3817 * variables.
3819 ll = nasm_malloc(sizeof(Line));
3820 ll->next = istk->expansion;
3821 ll->finishes = m;
3822 ll->first = NULL;
3823 istk->expansion = ll;
3825 m->in_progress = TRUE;
3826 m->params = params;
3827 m->iline = tline;
3828 m->nparam = nparam;
3829 m->rotate = 0;
3830 m->paramlen = paramlen;
3831 m->unique = unique++;
3832 m->lineno = 0;
3834 m->next_active = istk->mstk;
3835 istk->mstk = m;
3837 for (l = m->expansion; l; l = l->next)
3839 Token **tail;
3841 ll = nasm_malloc(sizeof(Line));
3842 ll->finishes = NULL;
3843 ll->next = istk->expansion;
3844 istk->expansion = ll;
3845 tail = &ll->first;
3847 for (t = l->first; t; t = t->next)
3849 Token *x = t;
3850 if (t->type == TOK_PREPROC_ID &&
3851 t->text[1] == '0' && t->text[2] == '0')
3853 dont_prepend = -1;
3854 x = label;
3855 if (!x)
3856 continue;
3858 tt = *tail = new_Token(NULL, x->type, x->text, 0);
3859 tail = &tt->next;
3861 *tail = NULL;
3865 * If we had a label, push it on as the first line of
3866 * the macro expansion.
3868 if (label)
3870 if (dont_prepend < 0)
3871 free_tlist(startline);
3872 else
3874 ll = nasm_malloc(sizeof(Line));
3875 ll->finishes = NULL;
3876 ll->next = istk->expansion;
3877 istk->expansion = ll;
3878 ll->first = startline;
3879 if (!dont_prepend)
3881 while (label->next)
3882 label = label->next;
3883 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
3888 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
3890 return 1;
3894 * Since preprocessor always operate only on the line that didn't
3895 * arrived yet, we should always use ERR_OFFBY1. Also since user
3896 * won't want to see same error twice (preprocessing is done once
3897 * per pass) we will want to show errors only during pass one.
3899 static void
3900 error(int severity, char *fmt, ...)
3902 va_list arg;
3903 char buff[1024];
3905 /* If we're in a dead branch of IF or something like it, ignore the error */
3906 if (istk->conds && !emitting(istk->conds->state))
3907 return;
3909 va_start(arg, fmt);
3910 vsprintf(buff, fmt, arg);
3911 va_end(arg);
3913 if (istk->mstk && istk->mstk->name)
3914 __error(severity | ERR_PASS1, "(%s:%d) %s", istk->mstk->name,
3915 istk->mstk->lineno, buff);
3916 else
3917 __error(severity | ERR_PASS1, "%s", buff);
3920 static void
3921 pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
3922 ListGen * listgen)
3924 int h;
3926 __error = errfunc;
3927 cstk = NULL;
3928 istk = nasm_malloc(sizeof(Include));
3929 istk->next = NULL;
3930 istk->conds = NULL;
3931 istk->expansion = NULL;
3932 istk->mstk = NULL;
3933 istk->fp = fopen(file, "r");
3934 istk->fname = NULL;
3935 src_set_fname(nasm_strdup(file));
3936 src_set_linnum(0);
3937 istk->lineinc = 1;
3938 if (!istk->fp)
3939 error(ERR_FATAL | ERR_NOFILE, "unable to open input file `%s'", file);
3940 defining = NULL;
3941 for (h = 0; h < NHASH; h++)
3943 mmacros[h] = NULL;
3944 smacros[h] = NULL;
3946 unique = 0;
3947 if (tasm_compatible_mode) {
3948 stdmacpos = stdmac;
3949 } else {
3950 stdmacpos = &stdmac[TASM_MACRO_COUNT];
3952 any_extrastdmac = (extrastdmac != NULL);
3953 list = listgen;
3954 evaluate = eval;
3955 pass = apass;
3958 static char *
3959 pp_getline(void)
3961 char *line;
3962 Token *tline;
3964 while (1)
3967 * Fetch a tokenised line, either from the macro-expansion
3968 * buffer or from the input file.
3970 tline = NULL;
3971 while (istk->expansion && istk->expansion->finishes)
3973 Line *l = istk->expansion;
3974 if (!l->finishes->name && l->finishes->in_progress > 1)
3976 Line *ll;
3979 * This is a macro-end marker for a macro with no
3980 * name, which means it's not really a macro at all
3981 * but a %rep block, and the `in_progress' field is
3982 * more than 1, meaning that we still need to
3983 * repeat. (1 means the natural last repetition; 0
3984 * means termination by %exitrep.) We have
3985 * therefore expanded up to the %endrep, and must
3986 * push the whole block on to the expansion buffer
3987 * again. We don't bother to remove the macro-end
3988 * marker: we'd only have to generate another one
3989 * if we did.
3991 l->finishes->in_progress--;
3992 for (l = l->finishes->expansion; l; l = l->next)
3994 Token *t, *tt, **tail;
3996 ll = nasm_malloc(sizeof(Line));
3997 ll->next = istk->expansion;
3998 ll->finishes = NULL;
3999 ll->first = NULL;
4000 tail = &ll->first;
4002 for (t = l->first; t; t = t->next)
4004 if (t->text || t->type == TOK_WHITESPACE)
4006 tt = *tail = new_Token(NULL, t->type, t->text, 0);
4007 tail = &tt->next;
4011 istk->expansion = ll;
4014 else
4017 * Check whether a `%rep' was started and not ended
4018 * within this macro expansion. This can happen and
4019 * should be detected. It's a fatal error because
4020 * I'm too confused to work out how to recover
4021 * sensibly from it.
4023 if (defining)
4025 if (defining->name)
4026 error(ERR_PANIC, "defining with name in expansion");
4027 else if (istk->mstk->name)
4028 error(ERR_FATAL, "`%%rep' without `%%endrep' within"
4029 " expansion of macro `%s'", istk->mstk->name);
4033 * FIXME: investigate the relationship at this point between
4034 * istk->mstk and l->finishes
4037 MMacro *m = istk->mstk;
4038 istk->mstk = m->next_active;
4039 if (m->name)
4042 * This was a real macro call, not a %rep, and
4043 * therefore the parameter information needs to
4044 * be freed.
4046 nasm_free(m->params);
4047 free_tlist(m->iline);
4048 nasm_free(m->paramlen);
4049 l->finishes->in_progress = FALSE;
4051 else
4052 free_mmacro(m);
4054 istk->expansion = l->next;
4055 nasm_free(l);
4056 list->downlevel(LIST_MACRO);
4059 while (1)
4060 { /* until we get a line we can use */
4062 if (istk->expansion)
4063 { /* from a macro expansion */
4064 char *p;
4065 Line *l = istk->expansion;
4066 if (istk->mstk)
4067 istk->mstk->lineno++;
4068 tline = l->first;
4069 istk->expansion = l->next;
4070 nasm_free(l);
4071 p = detoken(tline, FALSE);
4072 list->line(LIST_MACRO, p);
4073 nasm_free(p);
4074 break;
4076 line = read_line();
4077 if (line)
4078 { /* from the current input file */
4079 line = prepreproc(line);
4080 tline = tokenise(line);
4081 nasm_free(line);
4082 break;
4085 * The current file has ended; work down the istk
4088 Include *i = istk;
4089 fclose(i->fp);
4090 if (i->conds)
4091 error(ERR_FATAL, "expected `%%endif' before end of file");
4092 istk = i->next;
4093 list->downlevel(LIST_INCLUDE);
4094 src_set_linnum(i->lineno);
4095 nasm_free(src_set_fname(i->fname));
4096 nasm_free(i);
4097 if (!istk)
4098 return NULL;
4103 * We must expand MMacro parameters and MMacro-local labels
4104 * _before_ we plunge into directive processing, to cope
4105 * with things like `%define something %1' such as STRUC
4106 * uses. Unless we're _defining_ a MMacro, in which case
4107 * those tokens should be left alone to go into the
4108 * definition; and unless we're in a non-emitting
4109 * condition, in which case we don't want to meddle with
4110 * anything.
4112 if (!defining && !(istk->conds && !emitting(istk->conds->state)))
4113 tline = expand_mmac_params(tline);
4116 * Check the line to see if it's a preprocessor directive.
4118 if (do_directive(tline) & 1)
4120 continue;
4122 else if (defining)
4125 * We're defining a multi-line macro. We emit nothing
4126 * at all, and just
4127 * shove the tokenised line on to the macro definition.
4129 Line *l = nasm_malloc(sizeof(Line));
4130 l->next = defining->expansion;
4131 l->first = tline;
4132 l->finishes = FALSE;
4133 defining->expansion = l;
4134 continue;
4136 else if (istk->conds && !emitting(istk->conds->state))
4139 * We're in a non-emitting branch of a condition block.
4140 * Emit nothing at all, not even a blank line: when we
4141 * emerge from the condition we'll give a line-number
4142 * directive so we keep our place correctly.
4144 free_tlist(tline);
4145 continue;
4147 else if (istk->mstk && !istk->mstk->in_progress)
4150 * We're in a %rep block which has been terminated, so
4151 * we're walking through to the %endrep without
4152 * emitting anything. Emit nothing at all, not even a
4153 * blank line: when we emerge from the %rep block we'll
4154 * give a line-number directive so we keep our place
4155 * correctly.
4157 free_tlist(tline);
4158 continue;
4160 else
4162 tline = expand_smacro(tline);
4163 if (!expand_mmacro(tline))
4166 * De-tokenise the line again, and emit it.
4168 line = detoken(tline, TRUE);
4169 free_tlist(tline);
4170 break;
4172 else
4174 continue; /* expand_mmacro calls free_tlist */
4179 return line;
4182 static void
4183 pp_cleanup(int pass)
4185 int h;
4187 if (defining)
4189 error(ERR_NONFATAL, "end of file while still defining macro `%s'",
4190 defining->name);
4191 free_mmacro(defining);
4193 while (cstk)
4194 ctx_pop();
4195 for (h = 0; h < NHASH; h++)
4197 while (mmacros[h])
4199 MMacro *m = mmacros[h];
4200 mmacros[h] = mmacros[h]->next;
4201 free_mmacro(m);
4203 while (smacros[h])
4205 SMacro *s = smacros[h];
4206 smacros[h] = smacros[h]->next;
4207 nasm_free(s->name);
4208 free_tlist(s->expansion);
4209 nasm_free(s);
4212 while (istk)
4214 Include *i = istk;
4215 istk = istk->next;
4216 fclose(i->fp);
4217 nasm_free(i->fname);
4218 nasm_free(i);
4220 while (cstk)
4221 ctx_pop();
4222 if (pass == 0)
4224 free_llist(predef);
4225 delete_Blocks();
4229 void
4230 pp_include_path(char *path)
4232 IncPath *i;
4234 i = nasm_malloc(sizeof(IncPath));
4235 i->path = nasm_strdup(path);
4236 i->next = ipath;
4237 ipath = i;
4240 void
4241 pp_pre_include(char *fname)
4243 Token *inc, *space, *name;
4244 Line *l;
4246 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
4247 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
4248 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
4250 l = nasm_malloc(sizeof(Line));
4251 l->next = predef;
4252 l->first = inc;
4253 l->finishes = FALSE;
4254 predef = l;
4257 void
4258 pp_pre_define(char *definition)
4260 Token *def, *space;
4261 Line *l;
4262 char *equals;
4264 equals = strchr(definition, '=');
4265 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4266 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
4267 if (equals)
4268 *equals = ' ';
4269 space->next = tokenise(definition);
4270 if (equals)
4271 *equals = '=';
4273 l = nasm_malloc(sizeof(Line));
4274 l->next = predef;
4275 l->first = def;
4276 l->finishes = FALSE;
4277 predef = l;
4280 void
4281 pp_pre_undefine(char *definition)
4283 Token *def, *space;
4284 Line *l;
4286 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4287 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
4289 l = nasm_malloc(sizeof(Line));
4290 l->next = predef;
4291 l->first = def;
4292 l->finishes = FALSE;
4293 predef = l;
4296 void
4297 pp_extra_stdmac(char **macros)
4299 extrastdmac = macros;
4302 static void
4303 make_tok_num(Token * tok, long val)
4305 char numbuf[20];
4306 sprintf(numbuf, "%ld", val);
4307 tok->text = nasm_strdup(numbuf);
4308 tok->type = TOK_NUMBER;
4311 Preproc nasmpp = {
4312 pp_reset,
4313 pp_getline,
4314 pp_cleanup