preproc.c
上传用户:yuppie_zhu
上传日期:2007-01-08
资源大小:535k
文件大小:83k
源码类别:

编译器/解释器

开发平台:

C/C++

  1. /* preproc.c   macro preprocessor for the Netwide Assembler
  2.  *
  3.  * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  4.  * Julian Hall. All rights reserved. The software is
  5.  * redistributable under the licence given in the file "Licence"
  6.  * distributed in the NASM archive.
  7.  *
  8.  * initial version 18/iii/97 by Simon Tatham
  9.  */
  10. /* Typical flow of text through preproc
  11.  *
  12.  * pp_getline gets tokenised lines, either
  13.  *
  14.  *   from a macro expansion
  15.  *
  16.  * or
  17.  *   {
  18.  *   read_line  gets raw text from stdmacpos, or predef, or current input file
  19.  *   tokenise   converts to tokens
  20.  *   }
  21.  *
  22.  * expand_mmac_params is used to expand %1 etc., unless a macro is being
  23.  * defined or a false conditional is being processed
  24.  * (%0, %1, %+1, %-1, %%foo
  25.  *
  26.  * do_directive checks for directives
  27.  *
  28.  * expand_smacro is used to expand single line macros
  29.  *
  30.  * expand_mmacro is used to expand multi-line macros
  31.  *
  32.  * detoken is used to convert the line back to text
  33.  */
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <stddef.h>
  37. #include <string.h>
  38. #include <ctype.h>
  39. #include <limits.h>
  40. #include "nasm.h"
  41. #include "nasmlib.h"
  42. typedef struct SMacro SMacro;
  43. typedef struct MMacro MMacro;
  44. typedef struct Context Context;
  45. typedef struct Token Token;
  46. typedef struct Line Line;
  47. typedef struct Include Include;
  48. typedef struct Cond Cond;
  49. typedef struct IncPath IncPath;
  50. /*
  51.  * Store the definition of a single-line macro.
  52.  */
  53. struct SMacro {
  54.     SMacro *next;
  55.     char *name;
  56.     int casesense;
  57.     int nparam;
  58.     int in_progress;
  59.     Token *expansion;
  60. };
  61. /*
  62.  * Store the definition of a multi-line macro. This is also used to
  63.  * store the interiors of `%rep...%endrep' blocks, which are
  64.  * effectively self-re-invoking multi-line macros which simply
  65.  * don't have a name or bother to appear in the hash tables. %rep
  66.  * blocks are signified by having a NULL `name' field.
  67.  *
  68.  * In a MMacro describing a `%rep' block, the `in_progress' field
  69.  * isn't merely boolean, but gives the number of repeats left to
  70.  * run.
  71.  *
  72.  * The `next' field is used for storing MMacros in hash tables; the
  73.  * `next_active' field is for stacking them on istk entries.
  74.  *
  75.  * When a MMacro is being expanded, `params', `iline', `nparam',
  76.  * `paramlen', `rotate' and `unique' are local to the invocation.
  77.  */
  78. struct MMacro {
  79.     MMacro *next;
  80.     char *name;
  81.     int casesense;
  82.     int nparam_min, nparam_max;
  83.     int plus;        /* is the last parameter greedy? */
  84.     int nolist;        /* is this macro listing-inhibited? */
  85.     int in_progress;
  86.     Token *dlist;        /* All defaults as one list */
  87.     Token **defaults;        /* Parameter default pointers */
  88.     int ndefs;        /* number of default parameters */
  89.     Line *expansion;
  90.     MMacro *next_active;
  91.     MMacro *rep_nest;        /* used for nesting %rep */
  92.     Token **params;        /* actual parameters */
  93.     Token *iline;        /* invocation line */
  94.     int nparam, rotate, *paramlen;
  95.     unsigned long unique;
  96. };
  97. /*
  98.  * The context stack is composed of a linked list of these.
  99.  */
  100. struct Context {
  101.     Context *next;
  102.     SMacro *localmac;
  103.     char *name;
  104.     unsigned long number;
  105. };
  106. /*
  107.  * This is the internal form which we break input lines up into.
  108.  * Typically stored in linked lists.
  109.  *
  110.  * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
  111.  * necessarily used as-is, but is intended to denote the number of
  112.  * the substituted parameter. So in the definition
  113.  *
  114.  *     %define a(x,y) ( (x) & ~(y) )
  115.  * 
  116.  * the token representing `x' will have its type changed to
  117.  * TOK_SMAC_PARAM, but the one representing `y' will be
  118.  * TOK_SMAC_PARAM+1.
  119.  *
  120.  * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
  121.  * which doesn't need quotes around it. Used in the pre-include
  122.  * mechanism as an alternative to trying to find a sensible type of
  123.  * quote to use on the filename we were passed.
  124.  */
  125. struct Token {
  126.     Token *next;
  127.     char *text;
  128.     SMacro *mac;        /* associated macro for TOK_SMAC_END */
  129.     int type;
  130. };
  131. enum {
  132.     TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING,
  133.     TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_SMAC_PARAM,
  134.     TOK_INTERNAL_STRING
  135. };
  136. /*
  137.  * Multi-line macro definitions are stored as a linked list of
  138.  * these, which is essentially a container to allow several linked
  139.  * lists of Tokens.
  140.  * 
  141.  * Note that in this module, linked lists are treated as stacks
  142.  * wherever possible. For this reason, Lines are _pushed_ on to the
  143.  * `expansion' field in MMacro structures, so that the linked list,
  144.  * if walked, would give the macro lines in reverse order; this
  145.  * means that we can walk the list when expanding a macro, and thus
  146.  * push the lines on to the `expansion' field in _istk_ in reverse
  147.  * order (so that when popped back off they are in the right
  148.  * order). It may seem cockeyed, and it relies on my design having
  149.  * an even number of steps in, but it works...
  150.  *
  151.  * Some of these structures, rather than being actual lines, are
  152.  * markers delimiting the end of the expansion of a given macro.
  153.  * This is for use in the cycle-tracking and %rep-handling code.
  154.  * Such structures have `finishes' non-NULL, and `first' NULL. All
  155.  * others have `finishes' NULL, but `first' may still be NULL if
  156.  * the line is blank.
  157.  */
  158. struct Line {
  159.     Line *next;
  160.     MMacro *finishes;
  161.     Token *first;
  162. };
  163. /*
  164.  * To handle an arbitrary level of file inclusion, we maintain a
  165.  * stack (ie linked list) of these things.
  166.  */
  167. struct Include {
  168.     Include *next;
  169.     FILE *fp;
  170.     Cond *conds;
  171.     Line *expansion;
  172.     char *fname;
  173.     int lineno, lineinc;
  174.     MMacro *mstk;        /* stack of active macros/reps */
  175. };
  176. /*
  177.  * Include search path. This is simply a list of strings which get
  178.  * prepended, in turn, to the name of an include file, in an
  179.  * attempt to find the file if it's not in the current directory.
  180.  */
  181. struct IncPath {
  182.     IncPath *next;
  183.     char *path;
  184. };
  185. /*
  186.  * Conditional assembly: we maintain a separate stack of these for
  187.  * each level of file inclusion. (The only reason we keep the
  188.  * stacks separate is to ensure that a stray `%endif' in a file
  189.  * included from within the true branch of a `%if' won't terminate
  190.  * it and cause confusion: instead, rightly, it'll cause an error.)
  191.  */
  192. struct Cond {
  193.     Cond *next;
  194.     int state;
  195. };
  196. enum {
  197.     /*
  198.      * These states are for use just after %if or %elif: IF_TRUE
  199.      * means the condition has evaluated to truth so we are
  200.      * currently emitting, whereas IF_FALSE means we are not
  201.      * currently emitting but will start doing so if a %else comes
  202.      * up. In these states, all directives are admissible: %elif,
  203.      * %else and %endif. (And of course %if.)
  204.      */
  205.     COND_IF_TRUE, COND_IF_FALSE,
  206.     /*
  207.      * These states come up after a %else: ELSE_TRUE means we're
  208.      * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
  209.      * any %elif or %else will cause an error.
  210.      */
  211.     COND_ELSE_TRUE, COND_ELSE_FALSE,
  212.     /*
  213.      * This state means that we're not emitting now, and also that
  214.      * nothing until %endif will be emitted at all. It's for use in
  215.      * two circumstances: (i) when we've had our moment of emission
  216.      * and have now started seeing %elifs, and (ii) when the
  217.      * condition construct in question is contained within a
  218.      * non-emitting branch of a larger condition construct.
  219.      */
  220.     COND_NEVER
  221. };
  222. #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
  223. /*
  224.  * Condition codes. Note that we use c_ prefix not C_ because C_ is
  225.  * used in nasm.h for the "real" condition codes. At _this_ level,
  226.  * we treat CXZ and ECXZ as condition codes, albeit non-invertible
  227.  * ones, so we need a different enum...
  228.  */
  229. static char *conditions[] = {
  230.     "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
  231.     "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
  232.     "np", "ns", "nz", "o", "p", "pe", "po", "s", "z"
  233. };
  234. enum {
  235.     c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
  236.     c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
  237.     c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_S, c_Z
  238. };
  239. static int inverse_ccs[] = {
  240.     c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
  241.     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,
  242.     c_Z, c_NO, c_NP, c_PO, c_PE, c_NS, c_NZ
  243. };
  244. /*
  245.  * Directive names.
  246.  */
  247. static char *directives[] = {
  248.     "%assign", "%clear", "%define", "%elif", "%elifctx", "%elifdef",
  249.     "%elifid", "%elifidn", "%elifidni", "%elifnctx", "%elifndef",
  250.     "%elifnid", "%elifnidn", "%elifnidni", "%elifnnum", "%elifnstr",
  251.     "%elifnum", "%elifstr", "%else", "%endif", "%endm", "%endmacro",
  252.     "%endrep", "%error", "%exitrep", "%iassign", "%idefine", "%if",
  253.     "%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifnctx",
  254.     "%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnnum",
  255.     "%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include", "%line",
  256.     "%macro", "%pop", "%push", "%rep", "%repl", "%rotate", "%undef"
  257. };
  258. enum {
  259.     PP_ASSIGN, PP_CLEAR, PP_DEFINE, PP_ELIF, PP_ELIFCTX, PP_ELIFDEF,
  260.     PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFNCTX, PP_ELIFNDEF,
  261.     PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNNUM, PP_ELIFNSTR,
  262.     PP_ELIFNUM, PP_ELIFSTR, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO,
  263.     PP_ENDREP, PP_ERROR, PP_EXITREP, PP_IASSIGN, PP_IDEFINE, PP_IF,
  264.     PP_IFCTX, PP_IFDEF, PP_IFID, PP_IFIDN, PP_IFIDNI, PP_IFNCTX,
  265.     PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNNUM,
  266.     PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE, PP_LINE,
  267.     PP_MACRO, PP_POP, PP_PUSH, PP_REP, PP_REPL, PP_ROTATE, PP_UNDEF
  268. };
  269. static Context *cstk;
  270. static Include *istk;
  271. static IncPath *ipath = NULL;
  272. static efunc error;
  273. static evalfunc evaluate;
  274. static int pass; /* HACK: pass 0 = generate dependencies only */
  275. static unsigned long unique;        /* unique identifier numbers */
  276. static Line *predef = NULL;
  277. static ListGen *list;
  278. /*
  279.  * The number of hash values we use for the macro lookup tables.
  280.  * FIXME: We should *really* be able to configure this at run time,
  281.  * or even have the hash table automatically expanding when necessary.
  282.  */
  283. #define NHASH 31
  284. /*
  285.  * The current set of multi-line macros we have defined.
  286.  */
  287. static MMacro *mmacros[NHASH];
  288. /*
  289.  * The current set of single-line macros we have defined.
  290.  */
  291. static SMacro *smacros[NHASH];
  292. /*
  293.  * The multi-line macro we are currently defining, or the %rep
  294.  * block we are currently reading, if any.
  295.  */
  296. static MMacro *defining;
  297. /*
  298.  * The number of macro parameters to allocate space for at a time.
  299.  */
  300. #define PARAM_DELTA 16
  301. /*
  302.  * The standard macro set: defined as `static char *stdmac[]'. Also
  303.  * gives our position in the macro set, when we're processing it.
  304.  */
  305. #include "macros.c"
  306. static char **stdmacpos;
  307. /*
  308.  * The extra standard macros that come from the object format, if
  309.  * any.
  310.  */
  311. static char **extrastdmac = NULL;
  312. int any_extrastdmac;
  313. /*
  314.  * Forward declarations.
  315.  */
  316. static Token *expand_mmac_params (Token *tline);
  317. static Token *expand_smacro (Token *tline);
  318. static void   make_tok_num(Token *tok, long val);
  319. /*
  320.  * Macros for safe checking of token pointers, avoid *(NULL)
  321.  */
  322. #define tok_type_(x,t) ((x) && (x)->type == (t))
  323. #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
  324. #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
  325. #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
  326. /*
  327.  * The pre-preprocessing stage... This function translates line
  328.  * number indications as they emerge from GNU cpp (`# lineno "file"
  329.  * flags') into NASM preprocessor line number indications (`%line
  330.  * lineno file').
  331.  */
  332. static char *prepreproc(char *line) 
  333. {
  334.     int lineno, fnlen;
  335.     char *fname, *oldline;
  336.     if (line[0] == '#' && line[1] == ' ') {
  337. oldline = line;
  338. fname = oldline+2;
  339. lineno = atoi(fname);
  340. fname += strspn(fname, "0123456789 ");
  341. if (*fname == '"')
  342.     fname++;
  343. fnlen = strcspn(fname, """);
  344. line = nasm_malloc(20+fnlen);
  345. sprintf(line, "%%line %d %.*s", lineno, fnlen, fname);
  346. nasm_free (oldline);
  347.     }
  348.     return line;
  349. }
  350. /*
  351.  * The hash function for macro lookups. Note that due to some
  352.  * macros having case-insensitive names, the hash function must be
  353.  * invariant under case changes. We implement this by applying a
  354.  * perfectly normal hash function to the uppercase of the string.
  355.  */
  356. static int hash(char *s) 
  357. {
  358.     unsigned int h = 0;
  359.     int i = 0;
  360.     /*
  361.      * Powers of three, mod 31.
  362.      */
  363.     static const int multipliers[] = {
  364. 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10,
  365. 30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21
  366.     };
  367.     while (*s) {
  368. h += multipliers[i] * (unsigned char) (toupper(*s));
  369. s++;
  370. if (++i >= sizeof(multipliers)/sizeof(*multipliers))
  371.     i = 0;
  372.     }
  373.     h %= NHASH;
  374.     return h;
  375. }
  376. /*
  377.  * Free a linked list of tokens.
  378.  */
  379. static void free_tlist (Token *list) 
  380. {
  381.     Token *t;
  382.     while (list) {
  383. t = list;
  384. list = list->next;
  385. nasm_free (t->text);
  386. nasm_free (t);
  387.     }
  388. }
  389. /*
  390.  * Free a linked list of lines.
  391.  */
  392. static void free_llist (Line *list) 
  393. {
  394.     Line *l;
  395.     while (list) {
  396. l = list;
  397. list = list->next;
  398. free_tlist (l->first);
  399. nasm_free (l);
  400.     }
  401. }
  402. /*
  403.  * Free an MMacro
  404.  */
  405. static void free_mmacro (MMacro *m) 
  406. {
  407.     nasm_free (m->name);
  408.     free_tlist (m->dlist);
  409.     nasm_free (m->defaults);
  410.     free_llist (m->expansion);
  411.     nasm_free (m);
  412. }
  413. /*
  414.  * Pop the context stack.
  415.  */
  416. static void ctx_pop (void) 
  417. {
  418.     Context *c = cstk;
  419.     SMacro *smac, *s;
  420.     cstk = cstk->next;
  421.     smac = c->localmac;
  422.     while (smac) {
  423. s = smac;
  424. smac = smac->next;
  425. nasm_free (s->name);
  426. free_tlist (s->expansion);
  427. nasm_free (s);
  428.     }
  429.     nasm_free (c->name);
  430.     nasm_free (c);
  431. }
  432. #define BUF_DELTA 512
  433. /*
  434.  * Read a line from the top file in istk, handling multiple CR/LFs
  435.  * at the end of the line read, and handling spurious ^Zs. Will
  436.  * return lines from the standard macro set if this has not already
  437.  * been done.
  438.  */
  439. static char *read_line (void) 
  440. {
  441.     char *buffer, *p, *q;
  442.     int bufsize;
  443.     if (stdmacpos) {
  444. if (*stdmacpos) {
  445.     char *ret = nasm_strdup(*stdmacpos++);
  446.     if (!*stdmacpos && any_extrastdmac) 
  447.     {
  448. stdmacpos = extrastdmac;
  449. any_extrastdmac = FALSE;
  450. return ret;
  451.     }
  452.     /*
  453.      * Nasty hack: here we push the contents of `predef' on
  454.      * to the top-level expansion stack, since this is the
  455.      * most convenient way to implement the pre-include and
  456.      * pre-define features.
  457.      */
  458.     if (!*stdmacpos) 
  459.     {
  460. Line *pd, *l;
  461. Token *head, **tail, *t, *tt;
  462. for (pd = predef; pd; pd = pd->next) {
  463.     head = NULL;
  464.     tail = &head;
  465.     for (t = pd->first; t; t = t->next) {
  466. tt = *tail = nasm_malloc(sizeof(Token));
  467. tt->next = NULL;
  468. tail = &tt->next;
  469. tt->type = t->type;
  470. tt->text = nasm_strdup(t->text);
  471. tt->mac = t->mac;   /* always NULL here, in fact */
  472.     }
  473.     l = nasm_malloc(sizeof(Line));
  474.     l->next = istk->expansion;
  475.     l->first = head;
  476.     l->finishes = FALSE;
  477.     istk->expansion = l;
  478. }
  479.     }
  480.     return ret;
  481. else {
  482.     stdmacpos = NULL;
  483. }
  484.     }
  485.     bufsize = BUF_DELTA;
  486.     buffer = nasm_malloc(BUF_DELTA);
  487.     p = buffer;
  488.     while (1) {
  489. q = fgets(p, bufsize-(p-buffer), istk->fp);
  490. if (!q)
  491.     break;
  492. p += strlen(p);
  493. if (p > buffer && p[-1] == 'n') {
  494.     break;
  495. }
  496. if (p-buffer > bufsize-10) {
  497.     long offset = p-buffer;
  498.     bufsize += BUF_DELTA;
  499.     buffer = nasm_realloc(buffer, bufsize);
  500.     p = buffer+offset;        /* prevent stale-pointer problems */
  501. }
  502.     }
  503.     if (!q && p == buffer) {
  504. nasm_free (buffer);
  505. return NULL;
  506.     }
  507.     src_set_linnum(src_get_linnum() + istk->lineinc);
  508.     /*
  509.      * Play safe: remove CRs as well as LFs, if any of either are
  510.      * present at the end of the line.
  511.      */
  512.     while (--p >= buffer && (*p == 'n' || *p == 'r'))
  513. *p = '';
  514.     /*
  515.      * Handle spurious ^Z, which may be inserted into source files
  516.      * by some file transfer utilities.
  517.      */
  518.     buffer[strcspn(buffer, "32")] = '';
  519.     list->line (LIST_READ, buffer);
  520.     return buffer;
  521. }
  522. /*
  523.  * Tokenise a line of text. This is a very simple process since we
  524.  * don't need to parse the value out of e.g. numeric tokens: we
  525.  * simply split one string into many.
  526.  */
  527. static Token *tokenise (char *line) 
  528. {
  529.     char *p = line;
  530.     int type;
  531.     Token *list = NULL;
  532.     Token *t, **tail = &list;
  533.     while (*line) {
  534. p = line;
  535. if (*p == '%' && ( isdigit(p[1]) || 
  536.       ((p[1] == '-' || p[1] == '+') && isdigit(p[2]))))
  537. {
  538.     p++;
  539.     do {
  540. p++;
  541.     } while (isdigit(*p));
  542.     type = TOK_PREPROC_ID;
  543. }
  544. else if (*p == '%' && p[1] == '{') {
  545.     p += 2;
  546.     while (*p && *p != '}') {
  547. p[-1] = *p;
  548. p++;
  549.     }
  550.     p[-1] = '';
  551.     if (*p) p++;
  552.     type = TOK_PREPROC_ID;
  553. }
  554. else if (*p == '%' && (isidchar(p[1]) ||
  555.   ((p[1] == '!' || p[1] == '%' || p[1] == '$') &&
  556.   isidchar(p[2]))))
  557. {
  558.     p++;
  559.     do {
  560. p++;
  561.     } while (isidchar(*p));
  562.     type = TOK_PREPROC_ID;
  563. }
  564. else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
  565.     type = TOK_ID;
  566.     p++;
  567.     while (*p && isidchar(*p))
  568. p++;
  569. }
  570. else if (*p == ''' || *p == '"') {
  571.     /*
  572.      * A string token.
  573.      */
  574.     char c = *p;
  575.     p++;
  576.     type = TOK_STRING;
  577.     while (*p && *p != c)
  578. p++;
  579.     if (*p) p++;
  580. else if (isnumstart(*p)) {
  581.     /*
  582.      * A number token.
  583.      */
  584.     type = TOK_NUMBER;
  585.     p++;
  586.     while (*p && isnumchar(*p))
  587. p++;
  588. else if (isspace(*p)) {
  589.     type = TOK_WHITESPACE;
  590.     p++;
  591.     while (*p && isspace(*p))
  592. p++;
  593.     /*
  594.      * Whitespace just before end-of-line is discarded by
  595.      * pretending it's a comment; whitespace just before a
  596.      * comment gets lumped into the comment.
  597.      */
  598.     if (!*p || *p == ';') {
  599. type = TOK_COMMENT;
  600. while (*p) p++;
  601.     }
  602. else if (*p == ';') {
  603.     type = TOK_COMMENT;
  604.     while (*p) p++;
  605. else {
  606.     /*
  607.      * Anything else is an operator of some kind. We check
  608.      * for all the double-character operators (>>, <<, //,
  609.      * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
  610.      * else is a single-character operator.
  611.      */
  612.     type = TOK_OTHER;
  613.     if ((p[0] == '>' && p[1] == '>') ||
  614. (p[0] == '<' && p[1] == '<') ||
  615. (p[0] == '/' && p[1] == '/') ||
  616. (p[0] == '%' && p[1] == '%') ||
  617. (p[0] == '<' && p[1] == '=') ||
  618. (p[0] == '>' && p[1] == '=') ||
  619. (p[0] == '=' && p[1] == '=') ||
  620. (p[0] == '!' && p[1] == '=') ||
  621. (p[0] == '<' && p[1] == '>') ||
  622. (p[0] == '&' && p[1] == '&') ||
  623. (p[0] == '|' && p[1] == '|') ||
  624. (p[0] == '^' && p[1] == '^'))
  625.     {
  626. p++;
  627.     }
  628.     p++;
  629. }
  630. if (type != TOK_COMMENT) {
  631.     *tail = t = nasm_malloc (sizeof(Token));
  632.     tail = &t->next;
  633.     t->next = NULL;
  634.     t->type = type;
  635.     t->text = nasm_malloc(1+p-line);
  636.     strncpy(t->text, line, p-line);
  637.     t->text[p-line] = '';
  638. }
  639. line = p;
  640.     }
  641.     return list;
  642. }
  643. /*
  644.  * Convert a line of tokens back into text.
  645.  */
  646. char *detoken (Token *tlist) 
  647. {
  648.     Token *t;
  649.     int len;
  650.     char *line, *p;
  651.     len = 0;
  652.     for (t = tlist; t; t = t->next) {
  653. if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
  654.     char *p = getenv(t->text+2);
  655.     nasm_free (t->text);
  656.     if (p)
  657. t->text = nasm_strdup(p);
  658.     else
  659. t->text = NULL;
  660. }
  661. if (t->text)
  662.     len += strlen(t->text);
  663.     }
  664.     p = line = nasm_malloc(len+1);
  665.     for (t = tlist; t; t = t->next) {
  666. if (t->text) {
  667.     strcpy (p, t->text);
  668.     p += strlen(p);
  669. }
  670.     }
  671.     *p = '';
  672.     return line;
  673. }
  674. /*
  675.  * A scanner, suitable for use by the expression evaluator, which
  676.  * operates on a line of Tokens. Expects a pointer to a pointer to
  677.  * the first token in the line to be passed in as its private_data
  678.  * field.
  679.  */
  680. static int ppscan(void *private_data, struct tokenval *tokval) 
  681. {
  682.     Token **tlineptr = private_data;
  683.     Token *tline;
  684.     do {
  685. tline = *tlineptr;
  686. *tlineptr = tline ? tline->next : NULL;
  687.     } while (tline && (tline->type == TOK_WHITESPACE ||
  688.        tline->type == TOK_COMMENT));
  689.     if (!tline)
  690. return tokval->t_type = TOKEN_EOS;
  691.     if (tline->text[0] == '$' && !tline->text[1])
  692. return tokval->t_type = TOKEN_HERE;
  693.     if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[1])
  694. return tokval->t_type = TOKEN_BASE;
  695.     if (tline->type == TOK_ID) {
  696. tokval->t_charptr = tline->text;
  697. if (tline->text[0] == '$') {
  698.     tokval->t_charptr++;
  699.     return tokval->t_type = TOKEN_ID;
  700. }
  701. /*
  702.  * This is the only special case we actually need to worry
  703.  * about in this restricted context.
  704.  */
  705. if (!nasm_stricmp(tline->text, "seg"))
  706.     return tokval->t_type = TOKEN_SEG;
  707. return tokval->t_type = TOKEN_ID;
  708.     }
  709.     if (tline->type == TOK_NUMBER) {
  710. int rn_error;
  711. tokval->t_integer = readnum(tline->text, &rn_error);
  712. if (rn_error)
  713.     return tokval->t_type = TOKEN_ERRNUM;
  714. tokval->t_charptr = NULL;
  715. return tokval->t_type = TOKEN_NUM;
  716.     }
  717.     if (tline->type == TOK_STRING) {
  718. int rn_warn;
  719. char q, *r;
  720. int l;
  721. r = tline->text;
  722. q = *r++;
  723. l = strlen(r);
  724. if (l == 0 || r[l-1] != q)
  725.     return tokval->t_type = TOKEN_ERRNUM;
  726. tokval->t_integer = readstrnum(r, l-1, &rn_warn);
  727. if (rn_warn)
  728.     error(ERR_WARNING|ERR_PASS1,
  729.   "character constant too long");
  730. tokval->t_charptr = NULL;
  731. return tokval->t_type = TOKEN_NUM;
  732.     }
  733.     if (tline->type == TOK_OTHER) {
  734. if (!strcmp(tline->text, "<<")) return tokval->t_type = TOKEN_SHL;
  735. if (!strcmp(tline->text, ">>")) return tokval->t_type = TOKEN_SHR;
  736. if (!strcmp(tline->text, "//")) return tokval->t_type = TOKEN_SDIV;
  737. if (!strcmp(tline->text, "%%")) return tokval->t_type = TOKEN_SMOD;
  738. if (!strcmp(tline->text, "==")) return tokval->t_type = TOKEN_EQ;
  739. if (!strcmp(tline->text, "<>")) return tokval->t_type = TOKEN_NE;
  740. if (!strcmp(tline->text, "!=")) return tokval->t_type = TOKEN_NE;
  741. if (!strcmp(tline->text, "<=")) return tokval->t_type = TOKEN_LE;
  742. if (!strcmp(tline->text, ">=")) return tokval->t_type = TOKEN_GE;
  743. if (!strcmp(tline->text, "&&")) return tokval->t_type = TOKEN_DBL_AND;
  744. if (!strcmp(tline->text, "^^")) return tokval->t_type = TOKEN_DBL_XOR;
  745. if (!strcmp(tline->text, "||")) return tokval->t_type = TOKEN_DBL_OR;
  746.     }
  747.     /*
  748.      * We have no other options: just return the first character of
  749.      * the token text.
  750.      */
  751.     return tokval->t_type = tline->text[0];
  752. }
  753. /*
  754.  * Return the Context structure associated with a %$ token. Return
  755.  * NULL, having _already_ reported an error condition, if the
  756.  * context stack isn't deep enough for the supplied number of $
  757.  * signs.
  758.  */
  759. static Context *get_ctx (char *name) 
  760. {
  761.     Context *ctx;
  762.     int i;
  763.     if (!cstk) {
  764. error (ERR_NONFATAL, "`%s': context stack is empty", name);
  765. return NULL;
  766.     }
  767.     i = 1;
  768.     ctx = cstk;
  769.     while (name[i+1] == '$') {
  770. i++;
  771. ctx = ctx->next;
  772. if (!ctx) {
  773.     error (ERR_NONFATAL, "`%s': context stack is only"
  774.    " %d level%s deep", name, i-1, (i==2 ? "" : "s"));
  775.     return NULL;
  776. }
  777.     }
  778.     return ctx;
  779. }
  780. /*
  781.  * Compare a string to the name of an existing macro; this is a
  782.  * simple wrapper which calls either strcmp or nasm_stricmp
  783.  * depending on the value of the `casesense' parameter.
  784.  */
  785. static int mstrcmp(char *p, char *q, int casesense) 
  786. {
  787.     return casesense ? strcmp(p,q) : nasm_stricmp(p,q);
  788. }
  789. /*
  790.  * Open an include file. This routine must always return a valid
  791.  * file pointer if it returns - it's responsible for throwing an
  792.  * ERR_FATAL and bombing out completely if not. It should also try
  793.  * the include path one by one until it finds the file or reaches
  794.  * the end of the path.
  795.  */
  796. static FILE *inc_fopen(char *file) 
  797. {
  798.     FILE *fp;
  799.     char *prefix = "", *combine;
  800.     IncPath *ip = ipath;
  801.     static int namelen = 0;
  802.     while (1) {
  803. combine = nasm_strcat(prefix,file);
  804. fp = fopen(combine, "r");
  805. if (pass == 0 && fp)
  806. {
  807.   namelen += strlen(combine) + 1;
  808.   if (namelen > 62)
  809.   {
  810.     printf(" \n  ");
  811.     namelen = 2;
  812.   }
  813.   printf(" %s", combine);
  814. }
  815. nasm_free (combine);
  816. if (fp)
  817.     return fp;
  818. if (!ip)
  819.     break;
  820. prefix = ip->path;
  821. ip = ip->next;
  822.     }
  823.     error (ERR_FATAL,
  824.    "unable to open include file `%s'", file);
  825.     return NULL;        /* never reached - placate compilers */
  826. }
  827. /*
  828.  * Determine if we should warn on defining a single-line macro of
  829.  * name `name', with `nparam' parameters. If nparam is 0 or -1, will
  830.  * return TRUE if _any_ single-line macro of that name is defined.
  831.  * Otherwise, will return TRUE if a single-line macro with either
  832.  * `nparam' or no parameters is defined.
  833.  *
  834.  * If a macro with precisely the right number of parameters is
  835.  * defined, or nparam is -1, the address of the definition structure
  836.  * will be returned in `defn'; otherwise NULL will be returned. If `defn'
  837.  * is NULL, no action will be taken regarding its contents, and no
  838.  * error will occur.
  839.  *
  840.  * Note that this is also called with nparam zero to resolve
  841.  * `ifdef'.
  842.  */
  843. static int smacro_defined (char *name, int nparam, SMacro **defn, int nocase) 
  844. {
  845.     SMacro *m;
  846.     Context *ctx;
  847.     char *p;
  848.     if (name[0] == '%' && name[1] == '$') {
  849. ctx = get_ctx (name);
  850. if (!ctx)
  851.     return FALSE;        /* got to return _something_ */
  852. m = ctx->localmac;
  853. p = name+1;
  854. p += strspn(p, "$");
  855.     } else {
  856. m = smacros[hash(name)];
  857. p = name;
  858.     }
  859.     while (m) {
  860. if (!mstrcmp(m->name, p, m->casesense & nocase) &&
  861.     (nparam <= 0 || m->nparam == 0 || nparam == m->nparam)) {
  862.     if (defn) {
  863. if (nparam == m->nparam || nparam == -1)
  864.     *defn = m;
  865. else
  866.     *defn = NULL;
  867.     }
  868.     return TRUE;
  869. }
  870. m = m->next;
  871.     }
  872.     return FALSE;
  873. }
  874. /*
  875.  * Count and mark off the parameters in a multi-line macro call.
  876.  * This is called both from within the multi-line macro expansion
  877.  * code, and also to mark off the default parameters when provided
  878.  * in a %macro definition line.
  879.  */
  880. static void count_mmac_params (Token *t, int *nparam, Token ***params) 
  881. {
  882.     int paramsize, brace;
  883.     *nparam = paramsize = 0;
  884.     *params = NULL;
  885.     while (t) {
  886. if (*nparam >= paramsize) {
  887.     paramsize += PARAM_DELTA;
  888.     *params = nasm_realloc(*params, sizeof(**params) * paramsize);
  889. }
  890. skip_white_(t);
  891. brace = FALSE;
  892. if (tok_is_(t, "{"))
  893.     brace = TRUE;
  894. (*params)[(*nparam)++] = t;
  895. while (tok_isnt_(t, brace ? "}" : ","))
  896.     t = t->next;
  897. if (t) {        /* got a comma/brace */
  898.     t = t->next;
  899.     if (brace) {
  900. /*
  901.  * Now we've found the closing brace, look further
  902.  * for the comma.
  903.  */
  904. skip_white_(t);
  905. if (tok_isnt_(t, ",")) {
  906.     error (ERR_NONFATAL,
  907.    "braces do not enclose all of macro parameter");
  908.     while (tok_isnt_(t, ","))
  909. t = t->next;
  910. }
  911. if (t)
  912.     t = t->next;        /* eat the comma */
  913.     }
  914. }
  915.     }
  916. }
  917. /*
  918.  * Determine whether one of the various `if' conditions is true or
  919.  * not.
  920.  *
  921.  * We must free the tline we get passed.
  922.  */
  923. static int if_condition (Token *tline, int i) 
  924. {
  925.     int    j, casesense;
  926.     Token  * t, * tt, ** tptr, * origline;
  927.     struct tokenval tokval;
  928.     expr   * evalresult;
  929.     origline = tline;
  930.     switch (i) {
  931.       case PP_IFCTX: case PP_ELIFCTX:
  932.       case PP_IFNCTX: case PP_ELIFNCTX:
  933. j = FALSE;        /* have we matched yet? */
  934. if (!cstk)
  935.     error(ERR_FATAL,
  936.   "`%s': context stack is empty", directives[i]);
  937. else while (tline) {
  938.     skip_white_(tline);
  939.     if (!tline || tline->type != TOK_ID) {
  940. error(ERR_NONFATAL,
  941.       "`%s' expects context identifiers", directives[i]);
  942. free_tlist (origline);
  943. return -1;
  944.     }
  945.     if (!nasm_stricmp(tline->text, cstk->name))
  946. j = TRUE;
  947.     tline = tline->next;
  948. }
  949. if (i == PP_IFNCTX || i == PP_ELIFNCTX)
  950.     j = !j;
  951. free_tlist (origline);
  952. return j;
  953.       case PP_IFDEF: case PP_ELIFDEF:
  954.       case PP_IFNDEF: case PP_ELIFNDEF:
  955. j = FALSE;        /* have we matched yet? */
  956. while (tline) {
  957.     skip_white_(tline);
  958.     if (!tline || (tline->type != TOK_ID &&
  959.    (tline->type != TOK_PREPROC_ID ||
  960.     tline->text[1] != '$'))) {
  961. error(ERR_NONFATAL,
  962.       "`%%if%sdef' expects macro identifiers",
  963.       (i==PP_ELIFNDEF ? "n" : ""));
  964. free_tlist (origline);
  965. return -1;
  966.     }
  967.     if (smacro_defined(tline->text, 0, NULL, 1))
  968. j = TRUE;
  969. tline = tline->next;
  970. }
  971. if (i == PP_IFNDEF || i == PP_ELIFNDEF)
  972.     j = !j;
  973. free_tlist (origline);
  974. return j;
  975.       case PP_IFIDN: case PP_ELIFIDN: case PP_IFNIDN: case PP_ELIFNIDN:
  976.       case PP_IFIDNI: case PP_ELIFIDNI: case PP_IFNIDNI: case PP_ELIFNIDNI:
  977. tline = expand_smacro(tline);
  978. t = tt = tline;
  979. while (tok_isnt_(tt, ","))
  980.     tt = tt->next;
  981. if (!tt) {
  982.     error(ERR_NONFATAL, "`%s' expects two comma-separated arguments",
  983.   directives[i]);
  984.     free_tlist (tline);
  985.     return -1;
  986. }
  987. tt = tt->next;
  988. casesense = (i == PP_IFIDN || i == PP_ELIFIDN ||
  989.      i == PP_IFNIDN || i == PP_ELIFNIDN);
  990. j = TRUE;        /* assume equality unless proved not */
  991. while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
  992.     if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
  993. error(ERR_NONFATAL, "`%s': more than one comma on line",
  994.       directives[i]);
  995. free_tlist (tline);
  996. return -1;
  997.     }
  998.     if (t->type == TOK_WHITESPACE) {
  999. t = t->next;
  1000. continue;
  1001.     } else if (tt->type == TOK_WHITESPACE) {
  1002. tt = tt->next;
  1003. continue;
  1004.     } else if (tt->type != t->type ||
  1005.        (casesense ? strcmp(tt->text, t->text) :
  1006. nasm_stricmp(tt->text, t->text))) {
  1007. j = FALSE;        /* found mismatching tokens */
  1008. break;
  1009.     } else {
  1010. t = t->next;
  1011. tt = tt->next;
  1012. continue;
  1013.     }
  1014. }
  1015. if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
  1016.     j = FALSE;        /* trailing gunk on one end or other */
  1017. if (i == PP_IFNIDN || i == PP_ELIFNIDN ||
  1018.     i == PP_IFNIDNI || i == PP_ELIFNIDNI)
  1019.     j = !j;
  1020. free_tlist (tline);
  1021. return j;
  1022.       case PP_IFID: case PP_ELIFID: case PP_IFNID: case PP_ELIFNID:
  1023.       case PP_IFNUM: case PP_ELIFNUM: case PP_IFNNUM: case PP_ELIFNNUM:
  1024.       case PP_IFSTR: case PP_ELIFSTR: case PP_IFNSTR: case PP_ELIFNSTR:
  1025. tline = expand_smacro(tline);
  1026. t = tline;
  1027. while (tok_type_(t, TOK_WHITESPACE))
  1028.     t = t->next;
  1029. j = FALSE;        /* placate optimiser */
  1030. if (t) switch (i) {
  1031.   case PP_IFID: case PP_ELIFID: case PP_IFNID: case PP_ELIFNID:
  1032.     j = (t->type == TOK_ID);
  1033.     break;
  1034.   case PP_IFNUM: case PP_ELIFNUM: case PP_IFNNUM: case PP_ELIFNNUM:
  1035.     j = (t->type == TOK_NUMBER);
  1036.     break;
  1037.   case PP_IFSTR: case PP_ELIFSTR: case PP_IFNSTR: case PP_ELIFNSTR:
  1038.     j = (t->type == TOK_STRING);
  1039.     break;
  1040. }
  1041. if (i == PP_IFNID || i == PP_ELIFNID ||
  1042.     i == PP_IFNNUM || i == PP_ELIFNNUM ||
  1043.     i == PP_IFNSTR || i == PP_ELIFNSTR)
  1044.     j = !j;
  1045. free_tlist (tline);
  1046. return j;
  1047.       case PP_IF: case PP_ELIF:
  1048. t = tline = expand_smacro(tline);
  1049. tptr = &t;
  1050. tokval.t_type = TOKEN_INVALID;
  1051. evalresult = evaluate (ppscan, tptr, &tokval,
  1052.        NULL, pass | 0x10, error, NULL);
  1053. free_tlist (tline);
  1054. if (!evalresult)
  1055.     return -1;
  1056. if (tokval.t_type)
  1057.     error(ERR_WARNING,
  1058.   "trailing garbage after expression ignored");
  1059. if (!is_simple(evalresult)) {
  1060.     error(ERR_NONFATAL,
  1061.   "non-constant value given to `%s'", directives[i]);
  1062.     return -1;
  1063. }
  1064. return reloc_value(evalresult) != 0;
  1065.       default:
  1066. error(ERR_FATAL,
  1067.       "preprocessor directive `%s' not yet implemented",
  1068.       directives[i]);
  1069. free_tlist (origline);
  1070. return -1;        /* yeah, right */
  1071.     }
  1072. }
  1073. /*
  1074.  * Find out if a line contains a preprocessor directive, and deal
  1075.  * with it if so.
  1076.  * 
  1077.  * If a directive _is_ found, we are expected to free_tlist() the
  1078.  * line.
  1079.  *
  1080.  * Return values go like this:
  1081.  * 
  1082.  * bit 0 is set if a directive was found (so the line gets freed)
  1083.  */
  1084. static int do_directive (Token *tline) 
  1085. {
  1086.     int i, j, k, m, nparam, nolist;
  1087.     char *p, *mname;
  1088.     Include *inc;
  1089.     Context *ctx;
  1090.     Cond *cond;
  1091.     SMacro *smac, **smhead;
  1092.     MMacro *mmac;
  1093.     Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
  1094.     Line *l;
  1095.     struct tokenval tokval;
  1096.     expr *evalresult;
  1097.     MMacro *tmp_defining; /* Used when manipulating rep_nest */
  1098.     origline = tline;
  1099.     skip_white_(tline);
  1100.     if (!tok_type_(tline, TOK_PREPROC_ID) ||
  1101. (tline->text[1]=='%' || tline->text[1]=='$' || tline->text[1]=='!'))
  1102. return 0;
  1103.     i = -1;
  1104.     j = sizeof(directives)/sizeof(*directives);
  1105.     while (j-i > 1) {
  1106. k = (j+i) / 2;
  1107. m = nasm_stricmp(tline->text, directives[k]);
  1108. if (m == 0) {
  1109.     i = k;
  1110.     j = -2;
  1111.     break;
  1112. } else if (m < 0) {
  1113.     j = k;
  1114. } else
  1115.     i = k;
  1116.     }
  1117.     /*
  1118.      * If we're in a non-emitting branch of a condition construct,
  1119.      * or walking to the end of an already terminated %rep block,
  1120.      * we should ignore all directives except for condition
  1121.      * directives.
  1122.      */
  1123.     if (((istk->conds && !emitting(istk->conds->state)) ||
  1124.  (istk->mstk && !istk->mstk->in_progress)) &&
  1125. i != PP_IF && i != PP_ELIF &&
  1126. i != PP_IFCTX && i != PP_ELIFCTX &&
  1127. i != PP_IFDEF && i != PP_ELIFDEF &&
  1128. i != PP_IFID && i != PP_ELIFID &&
  1129. i != PP_IFIDN && i != PP_ELIFIDN &&
  1130. i != PP_IFIDNI && i != PP_ELIFIDNI &&
  1131. i != PP_IFNCTX && i != PP_ELIFNCTX &&
  1132. i != PP_IFNDEF && i != PP_ELIFNDEF &&
  1133. i != PP_IFNID && i != PP_ELIFNID &&
  1134. i != PP_IFNIDN && i != PP_ELIFNIDN &&
  1135. i != PP_IFNIDNI && i != PP_ELIFNIDNI &&
  1136. i != PP_IFNNUM && i != PP_ELIFNNUM &&
  1137. i != PP_IFNSTR && i != PP_ELIFNSTR &&
  1138. i != PP_IFNUM && i != PP_ELIFNUM &&
  1139. i != PP_IFSTR && i != PP_ELIFSTR &&
  1140. i != PP_ELSE && i != PP_ENDIF)
  1141.     {
  1142. return 0;
  1143.     }
  1144.     /*
  1145.      * If we're defining a macro or reading a %rep block, we should
  1146.      * ignore all directives except for %macro/%imacro (which
  1147.      * generate an error), %endm/%endmacro, and (only if we're in a
  1148.      * %rep block) %endrep. If we're in a %rep block, another %rep
  1149.      * causes an error, so should be let through.
  1150.      */
  1151.     if (defining && i != PP_MACRO && i != PP_IMACRO &&
  1152. i != PP_ENDMACRO && i != PP_ENDM &&
  1153. (defining->name || (i != PP_ENDREP && i != PP_REP)))
  1154.     {
  1155. return 0;
  1156.     }
  1157.     if (j != -2) {
  1158. error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
  1159.       tline->text);
  1160. return 0;        /* didn't get it */
  1161.     }
  1162.     switch (i) {
  1163.       case PP_CLEAR:
  1164. if (tline->next)
  1165.     error(ERR_WARNING,
  1166.   "trailing garbage after `%%clear' ignored");
  1167. for (j=0; j<NHASH; j++) {
  1168.     while (mmacros[j]) {
  1169. MMacro *m = mmacros[j];
  1170. mmacros[j] = m->next;
  1171. free_mmacro(m);
  1172.     }
  1173.     while (smacros[j]) {
  1174. SMacro *s = smacros[j];
  1175. smacros[j] = smacros[j]->next;
  1176. nasm_free (s->name);
  1177. free_tlist (s->expansion);
  1178. nasm_free (s);
  1179.     }
  1180. }
  1181. free_tlist (origline);
  1182. return 3;
  1183.       case PP_INCLUDE:
  1184. tline = tline->next;
  1185. skip_white_(tline);
  1186. if (!tline || (tline->type != TOK_STRING &&
  1187.        tline->type != TOK_INTERNAL_STRING)) 
  1188. {
  1189.     error(ERR_NONFATAL, "`%%include' expects a file name");
  1190.     free_tlist (origline);
  1191.     return 3;        /* but we did _something_ */
  1192. }
  1193. if (tline->next)
  1194.     error(ERR_WARNING,
  1195.   "trailing garbage after `%%include' ignored");
  1196. if (tline->type != TOK_INTERNAL_STRING) {
  1197.     p = tline->text+1;        /* point past the quote to the name */
  1198.     p[strlen(p)-1] = '';     /* remove the trailing quote */
  1199. } else
  1200.     p = tline->text;        /* internal_string is easier */
  1201. inc = nasm_malloc(sizeof(Include));
  1202. inc->next = istk;
  1203. inc->conds = NULL;
  1204. inc->fp = inc_fopen(p);
  1205. inc->fname = src_set_fname(nasm_strdup(p));
  1206. inc->lineno = src_set_linnum(0);
  1207. inc->lineinc = 1;
  1208. inc->expansion = NULL;
  1209. inc->mstk = NULL;
  1210. istk = inc;
  1211. list->uplevel (LIST_INCLUDE);
  1212. free_tlist (origline);
  1213. return 5;
  1214.       case PP_PUSH:
  1215. tline = tline->next;
  1216. skip_white_(tline);
  1217. if (!tok_type_(tline, TOK_ID)) {
  1218.     error(ERR_NONFATAL,
  1219.   "`%%push' expects a context identifier");
  1220.     free_tlist (origline);
  1221.     return 3;        /* but we did _something_ */
  1222. }
  1223. if (tline->next)
  1224.     error(ERR_WARNING,
  1225.   "trailing garbage after `%%push' ignored");
  1226. ctx = nasm_malloc(sizeof(Context));
  1227. ctx->next = cstk;
  1228. ctx->localmac = NULL;
  1229. ctx->name = nasm_strdup(tline->text);
  1230. ctx->number = unique++;
  1231. cstk = ctx;
  1232. free_tlist (origline);
  1233. break;
  1234.       case PP_REPL:
  1235. tline = tline->next;
  1236. skip_white_(tline);
  1237. if (!tok_type_(tline, TOK_ID)) {
  1238.     error(ERR_NONFATAL,
  1239.   "`%%repl' expects a context identifier");
  1240.     free_tlist (origline);
  1241.     return 3;        /* but we did _something_ */
  1242. }
  1243. if (tline->next)
  1244.     error(ERR_WARNING,
  1245.   "trailing garbage after `%%repl' ignored");
  1246. if (!cstk)
  1247.     error(ERR_NONFATAL,
  1248.   "`%%repl': context stack is empty");
  1249. else {
  1250.     nasm_free (cstk->name);
  1251.     cstk->name = nasm_strdup(tline->text);
  1252. }
  1253. free_tlist (origline);
  1254. break;
  1255.       case PP_POP:
  1256. if (tline->next)
  1257.     error(ERR_WARNING,
  1258.   "trailing garbage after `%%pop' ignored");
  1259. if (!cstk)
  1260.     error(ERR_NONFATAL,
  1261.   "`%%pop': context stack is already empty");
  1262. else
  1263.     ctx_pop();
  1264. free_tlist (origline);
  1265. break;
  1266.       case PP_ERROR:
  1267. tline->next = expand_smacro (tline->next);
  1268. tline = tline->next;
  1269. skip_white_(tline);
  1270. if (tok_type_(tline, TOK_STRING)) {
  1271.     p = tline->text+1;        /* point past the quote to the name */
  1272.     p[strlen(p)-1] = '';     /* remove the trailing quote */
  1273.     error(ERR_NONFATAL, "user error: %s", p);
  1274. } else {
  1275.     p = detoken(tline);
  1276.     error(ERR_WARNING, "user error: %s", p);
  1277.     nasm_free(p);
  1278. }
  1279. free_tlist (origline);
  1280. break;
  1281.       case PP_IF:
  1282.       case PP_IFCTX:
  1283.       case PP_IFDEF:
  1284.       case PP_IFID:
  1285.       case PP_IFIDN:
  1286.       case PP_IFIDNI:
  1287.       case PP_IFNCTX:
  1288.       case PP_IFNDEF:
  1289.       case PP_IFNID:
  1290.       case PP_IFNIDN:
  1291.       case PP_IFNIDNI:
  1292.       case PP_IFNNUM:
  1293.       case PP_IFNSTR:
  1294.       case PP_IFNUM:
  1295.       case PP_IFSTR:
  1296. if (istk->conds && !emitting(istk->conds->state))
  1297.     j = COND_NEVER;
  1298. else {
  1299.     j = if_condition(tline->next, i);
  1300.     tline->next = NULL;        /* it got freed */
  1301.     free_tlist (origline);
  1302.     if (j < 0)
  1303. /*
  1304.  * Bogus expression in %if, but we should pretend
  1305.  * it was OK anyway, so that we don't get an error
  1306.  * cascade on the subsequent %else / %endif.
  1307.  */
  1308. j = COND_NEVER;
  1309.     else
  1310. j = j ? COND_IF_TRUE : COND_IF_FALSE;
  1311. }
  1312. cond = nasm_malloc(sizeof(Cond));
  1313. cond->next = istk->conds;
  1314. cond->state = j;
  1315. istk->conds = cond;
  1316. return (j == COND_IF_TRUE ? 3 : 1);
  1317.       case PP_ELIF:
  1318.       case PP_ELIFCTX:
  1319.       case PP_ELIFDEF:
  1320.       case PP_ELIFID:
  1321.       case PP_ELIFIDN:
  1322.       case PP_ELIFIDNI:
  1323.       case PP_ELIFNCTX:
  1324.       case PP_ELIFNDEF:
  1325.       case PP_ELIFNID:
  1326.       case PP_ELIFNIDN:
  1327.       case PP_ELIFNIDNI:
  1328.       case PP_ELIFNNUM:
  1329.       case PP_ELIFNSTR:
  1330.       case PP_ELIFNUM:
  1331.       case PP_ELIFSTR:
  1332. if (!istk->conds)
  1333.     error(ERR_FATAL, "`%s': no matching `%%if'",
  1334.   directives[i]);
  1335. if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
  1336.     istk->conds->state = COND_NEVER;
  1337. else {
  1338.     j = if_condition(expand_mmac_params(tline->next), i);
  1339.     tline->next = NULL;        /* it got freed */
  1340.     free_tlist (origline);
  1341.     if (j < 0)
  1342. /*
  1343.  * The expression was bogus, but let's make
  1344.  * %endif not complain about missing %if
  1345.  */
  1346. j = COND_NEVER;
  1347.     else
  1348. istk->conds->state = j ? COND_IF_TRUE : COND_IF_FALSE;
  1349. }
  1350. return (istk->conds->state == COND_IF_TRUE ? 5 : 1);
  1351.       case PP_ELSE:
  1352. if (tline->next)
  1353.     error(ERR_WARNING,
  1354.   "trailing garbage after `%%else' ignored");
  1355. if (!istk->conds)
  1356.     error(ERR_FATAL,
  1357.   "`%%else': no matching `%%if'");
  1358. if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
  1359.     istk->conds->state = COND_ELSE_FALSE;
  1360. else
  1361.     istk->conds->state = COND_ELSE_TRUE;
  1362. free_tlist (origline);
  1363. return 5;
  1364.       case PP_ENDIF:
  1365. if (tline->next)
  1366.     error(ERR_WARNING,
  1367.   "trailing garbage after `%%endif' ignored");
  1368. if (!istk->conds)
  1369.     error(ERR_FATAL,
  1370.   "`%%endif': no matching `%%if'");
  1371. cond = istk->conds;
  1372. istk->conds = cond->next;
  1373. nasm_free (cond);
  1374. free_tlist (origline);
  1375. return 5;
  1376.       case PP_MACRO:
  1377.       case PP_IMACRO:
  1378. if (defining)
  1379.     error (ERR_FATAL,
  1380.    "`%%%smacro': already defining a macro",
  1381.    (i == PP_IMACRO ? "i" : ""));
  1382. tline = tline->next;
  1383. skip_white_(tline);
  1384. if (!tok_type_(tline, TOK_ID)) {
  1385.     error (ERR_NONFATAL,
  1386.    "`%%%smacro' expects a macro name",
  1387.    (i == PP_IMACRO ? "i" : ""));
  1388.     return 3;
  1389. }
  1390. defining = nasm_malloc(sizeof(MMacro));
  1391. defining->name = nasm_strdup(tline->text);
  1392. defining->casesense = (i == PP_MACRO);
  1393. defining->plus = FALSE;
  1394. defining->nolist = FALSE;
  1395. defining->in_progress = FALSE;
  1396. defining->rep_nest = NULL;
  1397. tline = tline->next;
  1398. skip_white_(tline);
  1399. if (!tok_type_(tline, TOK_NUMBER)) {
  1400.     error (ERR_NONFATAL,
  1401.    "`%%%smacro' expects a parameter count",
  1402.    (i == PP_IMACRO ? "i" : ""));
  1403.     defining->nparam_min = defining->nparam_max = 0;
  1404. } else {
  1405.     defining->nparam_min = defining->nparam_max =
  1406. readnum(tline->text, &j);
  1407.     if (j)
  1408. error (ERR_NONFATAL,
  1409.        "unable to parse parameter count `%s'", tline->text);
  1410. }
  1411. if (tline && tok_is_(tline->next, "-")) {
  1412.     tline = tline->next->next;
  1413.     if (tok_is_(tline, "*"))
  1414. defining->nparam_max = INT_MAX;
  1415.     else if (!tok_type_(tline, TOK_NUMBER))
  1416. error (ERR_NONFATAL,
  1417.        "`%%%smacro' expects a parameter count after `-'",
  1418.        (i == PP_IMACRO ? "i" : ""));
  1419.     else {
  1420. defining->nparam_max = readnum(tline->text, &j);
  1421. if (j)
  1422.     error (ERR_NONFATAL,
  1423.    "unable to parse parameter count `%s'",
  1424.    tline->text);
  1425. if (defining->nparam_min > defining->nparam_max)
  1426.     error (ERR_NONFATAL,
  1427.    "minimum parameter count exceeds maximum");
  1428.     }
  1429. }
  1430. if (tline && tok_is_(tline->next, "+")) {
  1431.     tline = tline->next;
  1432.     defining->plus = TRUE;
  1433. }
  1434. if (tline && tok_type_(tline->next, TOK_ID) &&
  1435.     !nasm_stricmp(tline->next->text, ".nolist")) 
  1436. {
  1437.     tline = tline->next;
  1438.     defining->nolist = TRUE;
  1439. }
  1440. mmac = mmacros[hash(defining->name)];
  1441. while (mmac) {
  1442.     if (!strcmp(mmac->name, defining->name) &&
  1443. (mmac->nparam_min<=defining->nparam_max || defining->plus) &&
  1444. (defining->nparam_min<=mmac->nparam_max || mmac->plus)) 
  1445.     {
  1446. error (ERR_WARNING,
  1447.        "redefining multi-line macro `%s'", defining->name);
  1448. break;
  1449.     }
  1450.     mmac = mmac->next;
  1451. }
  1452. /*
  1453.  * Handle default parameters.
  1454.  */
  1455. if (tline && tline->next) {
  1456.     defining->dlist = tline->next;
  1457.     tline->next = NULL;
  1458.     count_mmac_params (defining->dlist, &defining->ndefs,
  1459.        &defining->defaults);
  1460. } else {
  1461.     defining->dlist = NULL;
  1462.     defining->defaults = NULL;
  1463. }
  1464. defining->expansion = NULL;
  1465. free_tlist (origline);
  1466. return 1;
  1467.       case PP_ENDM:
  1468.       case PP_ENDMACRO:
  1469. if (!defining) {
  1470.     error (ERR_NONFATAL, "`%s': not defining a macro",
  1471.    tline->text);
  1472.     return 3;
  1473. }
  1474. k = hash(defining->name);
  1475. defining->next = mmacros[k];
  1476. mmacros[k] = defining;
  1477. defining = NULL;
  1478. free_tlist (origline);
  1479. return 5;
  1480.       case PP_ROTATE:
  1481. if (tline->next && tline->next->type == TOK_WHITESPACE)
  1482.     tline = tline->next;
  1483. t = expand_smacro(tline->next);
  1484. tline->next = NULL;
  1485. free_tlist (origline);
  1486. tline = t;
  1487. tptr = &t;
  1488. tokval.t_type = TOKEN_INVALID;
  1489. evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
  1490. free_tlist (tline);
  1491. if (!evalresult)
  1492.     return 3;
  1493. if (tokval.t_type)
  1494.     error(ERR_WARNING,
  1495.   "trailing garbage after expression ignored");
  1496. if (!is_simple(evalresult)) {
  1497.     error(ERR_NONFATAL,
  1498.   "non-constant value given to `%%rotate'");
  1499.     return 3;
  1500. }
  1501. mmac = istk->mstk;
  1502. while (mmac && !mmac->name)    /* avoid mistaking %reps for macros */
  1503.     mmac = mmac->next_active;
  1504. if (!mmac)
  1505.     error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
  1506. mmac->rotate = mmac->rotate + reloc_value(evalresult);
  1507. if (mmac->rotate < 0)
  1508.     mmac->rotate = mmac->nparam - (-mmac->rotate) % mmac->nparam;
  1509. mmac->rotate %= mmac->nparam;
  1510. return 1;
  1511.       case PP_REP:
  1512. nolist = FALSE;
  1513. tline = tline->next;
  1514. if (tline->next && tline->next->type == TOK_WHITESPACE)
  1515.     tline = tline->next;
  1516. if (tline->next && tline->next->type == TOK_ID &&
  1517.     !nasm_stricmp(tline->next->text, ".nolist")) {
  1518.     tline = tline->next;
  1519.     nolist = TRUE;
  1520. }
  1521. t = expand_smacro(tline->next);
  1522. tline->next = NULL;
  1523. free_tlist (origline);
  1524. tline = t;
  1525. tptr = &t;
  1526. tokval.t_type = TOKEN_INVALID;
  1527. evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
  1528. free_tlist (tline);
  1529. if (!evalresult)
  1530.     return 3;
  1531. if (tokval.t_type)
  1532.     error(ERR_WARNING,
  1533.   "trailing garbage after expression ignored");
  1534. if (!is_simple(evalresult)) {
  1535.     error(ERR_NONFATAL,
  1536.   "non-constant value given to `%%rep'");
  1537.     return 3;
  1538. }
  1539. tmp_defining = defining;
  1540. defining = nasm_malloc(sizeof(MMacro));
  1541. defining->name = NULL;        /* flags this macro as a %rep block */
  1542. defining->casesense = 0;
  1543. defining->plus = FALSE;
  1544. defining->nolist = nolist;
  1545. defining->in_progress = reloc_value(evalresult) + 1;
  1546. defining->nparam_min = defining->nparam_max = 0;
  1547. defining->defaults = NULL;
  1548. defining->dlist = NULL;
  1549. defining->expansion = NULL;
  1550. defining->next_active = istk->mstk;
  1551. defining->rep_nest = tmp_defining;
  1552. return 1;
  1553.       case PP_ENDREP:
  1554. if (!defining || defining->name) {
  1555.     error (ERR_NONFATAL,
  1556.    "`%%endrep': no matching `%%rep'");
  1557.     return 3;
  1558. }
  1559. /*
  1560.  * Now we have a "macro" defined - although it has no name
  1561.  * and we won't be entering it in the hash tables - we must
  1562.  * push a macro-end marker for it on to istk->expansion.
  1563.  * After that, it will take care of propagating itself (a
  1564.  * macro-end marker line for a macro which is really a %rep
  1565.  * block will cause the macro to be re-expanded, complete
  1566.  * with another macro-end marker to ensure the process
  1567.  * continues) until the whole expansion is forcibly removed
  1568.  * from istk->expansion by a %exitrep.
  1569.  */
  1570.      l = nasm_malloc(sizeof(Line));
  1571. l->next = istk->expansion;
  1572. l->finishes = defining;
  1573. l->first = NULL;
  1574. istk->expansion = l;
  1575. istk->mstk = defining;
  1576. list->uplevel (defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
  1577. tmp_defining = defining;
  1578. defining = defining->rep_nest;
  1579. free_tlist (origline);
  1580. return 1;
  1581.       case PP_EXITREP:
  1582. /*
  1583.  * We must search along istk->expansion until we hit a
  1584.  * macro-end marker for a macro with no name. Then we set
  1585.  * its `in_progress' flag to 0.
  1586.  */
  1587. for (l = istk->expansion; l; l = l->next)
  1588.     if (l->finishes && !l->finishes->name)
  1589. break;
  1590. if (l)
  1591.     l->finishes->in_progress = 0;
  1592. else
  1593.     error (ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
  1594. free_tlist (origline);
  1595. return 1;
  1596.       case PP_DEFINE:
  1597.       case PP_IDEFINE:
  1598. tline = tline->next;
  1599. skip_white_(tline);
  1600. if (!tline || (tline->type != TOK_ID &&
  1601.        (tline->type != TOK_PREPROC_ID ||
  1602. tline->text[1] != '$'))) {
  1603.     error (ERR_NONFATAL,
  1604.    "`%%%sdefine' expects a macro identifier",
  1605.    (i == PP_IDEFINE ? "i" : ""));
  1606.     free_tlist (origline);
  1607.     return 3;
  1608. }
  1609. mname = tline->text;
  1610. if (tline->type == TOK_ID) {
  1611.     p = tline->text;
  1612.     smhead = &smacros[hash(mname)];
  1613. } else {
  1614.     ctx = get_ctx (tline->text);
  1615.     if (ctx == NULL)
  1616. return 3;
  1617.     else {
  1618. p = tline->text+1;
  1619. p += strspn(p, "$");
  1620. smhead = &ctx->localmac;
  1621.     }
  1622. }
  1623. last = tline;
  1624. param_start = tline = tline->next;
  1625. nparam = 0;
  1626. if (tok_is_(tline, "(")) {
  1627.     /*
  1628.      * This macro has parameters.
  1629.      */
  1630.     tline = tline->next;
  1631.     while (1) {
  1632. skip_white_(tline);
  1633. if (!tline) {
  1634.     error (ERR_NONFATAL,
  1635.    "parameter identifier expected");
  1636.     free_tlist (origline);
  1637.     return 3;
  1638. }
  1639. if (tline->type != TOK_ID) {
  1640.     error (ERR_NONFATAL,
  1641.    "`%s': parameter identifier expected",
  1642.    tline->text);
  1643.     free_tlist (origline);
  1644.     return 3;
  1645. }
  1646. tline->type = TOK_SMAC_PARAM + nparam++;
  1647. tline = tline->next;
  1648. skip_white_(tline);
  1649. if (tok_is_(tline, ",")) {
  1650.     tline = tline->next;
  1651.     continue;
  1652. }
  1653. if (!tok_is_(tline, ")")) {
  1654.     error (ERR_NONFATAL,
  1655.    "`)' expected to terminate macro template");
  1656.     free_tlist (origline);
  1657.     return 3;
  1658. }
  1659. break;
  1660.     }
  1661.     last = tline;
  1662.     tline = tline->next;
  1663. }
  1664. if (tok_type_(tline, TOK_WHITESPACE))
  1665.     last = tline, tline = tline->next;
  1666. macro_start = NULL;
  1667. last->next = NULL;
  1668. t = tline;
  1669. while (t) {
  1670.     if (t->type == TOK_ID) {
  1671. for (tt = param_start; tt; tt = tt->next)
  1672.     if (tt->type >= TOK_SMAC_PARAM &&
  1673. !strcmp(tt->text, t->text))
  1674. t->type = tt->type;
  1675.     }
  1676.     tt = t->next;
  1677.     t->next = macro_start;
  1678.     macro_start = t;
  1679.     t = tt;
  1680. }
  1681. /*
  1682.  * Good. We now have a macro name, a parameter count, and a
  1683.  * token list (in reverse order) for an expansion. We ought
  1684.  * to be OK just to create an SMacro, store it, and let
  1685.  * free_tlist have the rest of the line (which we have
  1686.  * carefully re-terminated after chopping off the expansion
  1687.  * from the end).
  1688.  */
  1689. if (smacro_defined (mname, nparam, &smac, i==PP_DEFINE)) {
  1690.     if (!smac) {
  1691. error (ERR_WARNING,
  1692.        "single-line macro `%s' defined both with and"
  1693.        " without parameters", mname);
  1694. free_tlist (origline);
  1695. free_tlist (macro_start);
  1696. return 3;
  1697.     } else {
  1698. /*
  1699.  * We're redefining, so we have to take over an
  1700.  * existing SMacro structure. This means freeing
  1701.  * what was already in it.
  1702.  */
  1703. nasm_free (smac->name);
  1704. free_tlist (smac->expansion);
  1705.     }
  1706. } else {
  1707.     smac = nasm_malloc(sizeof(SMacro));
  1708.     smac->next = *smhead;
  1709.     *smhead = smac;
  1710. }
  1711. smac->name = nasm_strdup(p);
  1712. smac->casesense = (i == PP_DEFINE);
  1713. smac->nparam = nparam;
  1714. smac->expansion = macro_start;
  1715. smac->in_progress = FALSE;
  1716. free_tlist (origline);
  1717. return 3;
  1718.     case PP_UNDEF:
  1719. tline = tline->next;
  1720. skip_white_(tline);
  1721. if (!tline || (tline->type != TOK_ID &&
  1722.        (tline->type != TOK_PREPROC_ID ||
  1723. tline->text[1] != '$'))) {
  1724.     error (ERR_NONFATAL,
  1725.    "`%%undef' expects a macro identifier");
  1726.     free_tlist (origline);
  1727.     return 3;
  1728. }
  1729. mname = tline->text;
  1730. if (tline->type == TOK_ID) {
  1731.     p = tline->text;
  1732.     smhead = &smacros[hash(mname)];
  1733. } else {
  1734.     ctx = get_ctx (tline->text);
  1735.     if (ctx == NULL) {
  1736. free_tlist (origline);
  1737. return 3;
  1738.     } else {
  1739. p = tline->text+1;
  1740. p += strspn(p, "$");
  1741. smhead = &ctx->localmac;
  1742.     }
  1743. }
  1744. last = tline;
  1745. tline = tline->next;
  1746. last->next = NULL;
  1747. if (tline)
  1748.     error(ERR_WARNING,
  1749.   "trailing garbage after macro name ignored");
  1750. /*
  1751.  * We now have a macro name... go hunt for it.
  1752.  */
  1753. while (smacro_defined (mname, -1, &smac, 1)) {
  1754.   /* Defined, so we need to find its predecessor and nuke it */
  1755.   SMacro **s;
  1756.   for ( s = smhead ; *s && *s != smac ; s = &(*s)->next );
  1757.   if ( *s ) {
  1758.     *s = smac->next;
  1759.     nasm_free(smac->name);
  1760.     free_tlist(smac->expansion);
  1761.     nasm_free(smac);
  1762.   }
  1763. }
  1764. return 3;
  1765.       case PP_ASSIGN:
  1766.       case PP_IASSIGN:
  1767. tline = tline->next;
  1768. skip_white_(tline);
  1769. if (!tline || (tline->type != TOK_ID &&
  1770.        (tline->type != TOK_PREPROC_ID ||
  1771. tline->text[1] != '$'))) {
  1772.     error (ERR_NONFATAL,
  1773.    "`%%%sassign' expects a macro identifier",
  1774.    (i == PP_IASSIGN ? "i" : ""));
  1775.     free_tlist (origline);
  1776.     return 3;
  1777. }
  1778. mname = tline->text;
  1779. if (tline->type == TOK_ID) {
  1780.     p = tline->text;
  1781.     smhead = &smacros[hash(mname)];
  1782. } else {
  1783.     ctx = get_ctx (tline->text);
  1784.     if (ctx == NULL) {
  1785. free_tlist (origline);
  1786. return 3;
  1787.     } else {
  1788. p = tline->text+1;
  1789. p += strspn(p, "$");
  1790. smhead = &ctx->localmac;
  1791.     }
  1792. }
  1793. last = tline;
  1794. tline = tline->next;
  1795. last->next = NULL;
  1796. tline = expand_smacro (tline);
  1797. t = tline;
  1798. tptr = &t;
  1799. tokval.t_type = TOKEN_INVALID;
  1800. evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
  1801. free_tlist (tline);
  1802. if (!evalresult) {
  1803.     free_tlist (origline);
  1804.     return 3;
  1805. }
  1806. if (tokval.t_type)
  1807.     error(ERR_WARNING,
  1808.   "trailing garbage after expression ignored");
  1809. if (!is_simple(evalresult)) {
  1810.     error(ERR_NONFATAL,
  1811.   "non-constant value given to `%%%sassign'",
  1812.   (i == PP_IASSIGN ? "i" : ""));
  1813.     free_tlist (origline);
  1814.     return 3;
  1815. }
  1816. macro_start = nasm_malloc(sizeof(*macro_start));
  1817. macro_start->next = NULL;
  1818. make_tok_num(macro_start, reloc_value(evalresult));
  1819. macro_start->mac = NULL;
  1820. /*
  1821.  * We now have a macro name, an implicit parameter count of
  1822.  * zero, and a numeric token to use as an expansion. Create
  1823.  * and store an SMacro.
  1824.  */
  1825. if (smacro_defined (mname, 0, &smac, i==PP_ASSIGN)) {
  1826.     if (!smac)
  1827. error (ERR_WARNING,
  1828.        "single-line macro `%s' defined both with and"
  1829.        " without parameters", mname);
  1830.     else {
  1831. /*
  1832.  * We're redefining, so we have to take over an
  1833.  * existing SMacro structure. This means freeing
  1834.  * what was already in it.
  1835.  */
  1836. nasm_free (smac->name);
  1837. free_tlist (smac->expansion);
  1838.     }
  1839. else {
  1840.     smac = nasm_malloc(sizeof(SMacro));
  1841.     smac->next = *smhead;
  1842.     *smhead = smac;
  1843. }
  1844. smac->name = nasm_strdup(p);
  1845. smac->casesense = (i == PP_ASSIGN);
  1846. smac->nparam = 0;
  1847. smac->expansion = macro_start;
  1848. smac->in_progress = FALSE;
  1849. free_tlist (origline);
  1850. return 3;
  1851.       case PP_LINE:
  1852. /*
  1853.  * Syntax is `%line nnn[+mmm] [filename]'
  1854.  */
  1855. tline = tline->next;
  1856. skip_white_(tline);
  1857. if (!tok_type_(tline, TOK_NUMBER)) {
  1858.     error (ERR_NONFATAL, "`%%line' expects line number");
  1859.     free_tlist (origline);
  1860.     return 3;
  1861. }
  1862. k = readnum(tline->text, &j);
  1863. m = 1;
  1864. tline = tline->next;
  1865. if (tok_is_(tline, "+")) {
  1866.     tline = tline->next;
  1867.     if (!tok_type_(tline, TOK_NUMBER)) {
  1868. error (ERR_NONFATAL,
  1869.        "`%%line' expects line increment");
  1870. free_tlist (origline);
  1871. return 3;
  1872.     }
  1873.     m = readnum(tline->text, &j);
  1874.     tline = tline->next;
  1875. }
  1876. skip_white_(tline);
  1877. src_set_linnum(k);
  1878. istk->lineinc = m;
  1879. if (tline) {
  1880.     nasm_free ( src_set_fname ( detoken(tline) ) );
  1881. }
  1882. free_tlist (origline);
  1883. return 5;
  1884.       default:
  1885. error(ERR_FATAL,
  1886.       "preprocessor directive `%s' not yet implemented",
  1887.       directives[i]);
  1888. break;
  1889.     }
  1890.     return 3;
  1891. }
  1892. /*
  1893.  * Ensure that a macro parameter contains a condition code and
  1894.  * nothing else. Return the condition code index if so, or -1
  1895.  * otherwise.
  1896.  */
  1897. static int find_cc (Token *t) 
  1898. {
  1899.     Token *tt;
  1900.     int i, j, k, m;
  1901.     skip_white_(t);
  1902.     if (t->type != TOK_ID)
  1903. return -1;
  1904.     tt = t->next;
  1905.     skip_white_(tt);
  1906.     if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
  1907. return -1;
  1908.     i = -1;
  1909.     j = sizeof(conditions)/sizeof(*conditions);
  1910.     while (j-i > 1) {
  1911. k = (j+i) / 2;
  1912. m = nasm_stricmp(t->text, conditions[k]);
  1913. if (m == 0) {
  1914.     i = k;
  1915.     j = -2;
  1916.     break;
  1917. } else if (m < 0) {
  1918.     j = k;
  1919. } else
  1920.     i = k;
  1921.     }
  1922.     if (j != -2)
  1923. return -1;
  1924.     return i;
  1925. }
  1926. /*
  1927.  * Expand MMacro-local things: parameter references (%0, %n, %+n,
  1928.  * %-n) and MMacro-local identifiers (%%foo).
  1929.  */
  1930. static Token *expand_mmac_params (Token *tline) 
  1931. {
  1932.     Token *t, *tt, *ttt, **tail, *thead;
  1933.     tail = &thead;
  1934.     thead = NULL;
  1935.     while (tline) {
  1936. if (tline->type == TOK_PREPROC_ID &&
  1937.     (tline->text[1] == '+' || tline->text[1] == '-' ||
  1938.      tline->text[1] == '%' ||
  1939.      (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
  1940.     char *text = NULL;
  1941.     int type = 0, cc;        /* type = 0 to placate optimisers */
  1942.     char tmpbuf[30];
  1943.     int n, i;
  1944.     MMacro *mac;
  1945.     t = tline;
  1946.     tline = tline->next;
  1947.     mac = istk->mstk;
  1948.     while (mac && !mac->name)  /* avoid mistaking %reps for macros */
  1949. mac = mac->next_active;
  1950.     if (!mac)
  1951. error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
  1952.     else switch (t->text[1]) {
  1953. /*
  1954.  * We have to make a substitution of one of the
  1955.  * forms %1, %-1, %+1, %%foo, %0.
  1956.  */
  1957.       case '0':
  1958. type = TOK_NUMBER;
  1959. sprintf(tmpbuf, "%d", mac->nparam);
  1960. text = nasm_strdup(tmpbuf);
  1961. break;
  1962.       case '%':
  1963. type = TOK_ID;
  1964. sprintf(tmpbuf, "..@%lu.", mac->unique);
  1965. text = nasm_strcat(tmpbuf, t->text+2);
  1966. break;
  1967.       case '-':
  1968. n = atoi(t->text+2)-1;
  1969. if (n >= mac->nparam)
  1970.     tt = NULL;
  1971. else {
  1972.     if (mac->nparam > 1)
  1973. n = (n + mac->rotate) % mac->nparam;
  1974.     tt = mac->params[n];
  1975. }
  1976. cc = find_cc (tt);
  1977. if (cc == -1) {
  1978.     error (ERR_NONFATAL,
  1979.    "macro parameter %d is not a condition code",
  1980.    n+1);
  1981.     text = NULL;
  1982. } else {
  1983.     type = TOK_ID;
  1984.     if (inverse_ccs[cc] == -1) {
  1985. error (ERR_NONFATAL,
  1986.        "condition code `%s' is not invertible",
  1987.        conditions[cc]);
  1988. text = NULL;
  1989.     } else
  1990. text = nasm_strdup(conditions[inverse_ccs[cc]]);
  1991. }
  1992. break;
  1993.       case '+':
  1994. n = atoi(t->text+2)-1;
  1995. if (n >= mac->nparam)
  1996.     tt = NULL;
  1997. else {
  1998.     if (mac->nparam > 1)
  1999. n = (n + mac->rotate) % mac->nparam;
  2000.     tt = mac->params[n];
  2001. }
  2002. cc = find_cc (tt);
  2003. if (cc == -1) {
  2004.     error (ERR_NONFATAL,
  2005.    "macro parameter %d is not a condition code",
  2006.    n+1);
  2007.     text = NULL;
  2008. } else {
  2009.     type = TOK_ID;
  2010.     text = nasm_strdup(conditions[cc]);
  2011. }
  2012. break;
  2013.       default:
  2014. n = atoi(t->text+1)-1;
  2015. if (n >= mac->nparam)
  2016.     tt = NULL;
  2017. else {
  2018.     if (mac->nparam > 1)
  2019. n = (n + mac->rotate) % mac->nparam;
  2020.     tt = mac->params[n];
  2021. }
  2022. if (tt) {
  2023.     for (i=0; i<mac->paramlen[n]; i++) {
  2024. ttt = *tail = nasm_malloc(sizeof(Token));
  2025. tail = &ttt->next;
  2026. ttt->type = tt->type;
  2027. ttt->text = nasm_strdup(tt->text);
  2028. ttt->mac = NULL;
  2029. tt = tt->next;
  2030.     }
  2031. }
  2032. text = NULL;       /* we've done it here */
  2033. break;
  2034.     }
  2035.     nasm_free (t->text);
  2036.     if (!text) {
  2037. nasm_free (t);
  2038.     } else {
  2039. *tail = t;
  2040. tail = &t->next;
  2041. t->type = type;
  2042. t->text = text;
  2043. t->mac = NULL;
  2044.     }
  2045.     continue;
  2046. } else {
  2047.     t = *tail = tline;
  2048.     tline = tline->next;
  2049.     t->mac = NULL;
  2050.     tail = &t->next;
  2051. }
  2052.     }
  2053.     *tail = NULL;
  2054.     t = thead;
  2055.     for (; t && (tt=t->next)!=NULL ; t = t->next)
  2056. switch (t->type) {
  2057. case TOK_WHITESPACE:
  2058.     if (tt->type == TOK_WHITESPACE) {
  2059. t->next = tt->next;
  2060. nasm_free(tt->text);
  2061. nasm_free(tt); 
  2062.     }
  2063.     break;
  2064. case TOK_ID:
  2065.     if (tt->type == TOK_ID || tt->type == TOK_NUMBER) {
  2066. char *tmp = nasm_strcat(t->text, tt->text);
  2067. nasm_free(t->text);
  2068. t->text = tmp;
  2069. t->next = tt->next;
  2070. nasm_free(tt->text);
  2071. nasm_free(tt); 
  2072.     }
  2073.     break;
  2074. case TOK_NUMBER:
  2075.     if (tt->type == TOK_NUMBER) {
  2076. char *tmp = nasm_strcat(t->text, tt->text);
  2077. nasm_free(t->text);
  2078. t->text = tmp;
  2079. t->next = tt->next;
  2080. nasm_free(tt->text);
  2081. nasm_free(tt); 
  2082.     }
  2083.     break;
  2084. }
  2085.     return thead;
  2086. }
  2087. /*
  2088.  * Expand all single-line macro calls made in the given line.
  2089.  * Return the expanded version of the line. The original is deemed
  2090.  * to be destroyed in the process. (In reality we'll just move
  2091.  * Tokens from input to output a lot of the time, rather than
  2092.  * actually bothering to destroy and replicate.)
  2093.  */
  2094. static Token *expand_smacro (Token *tline) 
  2095. {
  2096.     Token *t, *tt, *mstart, **tail, *thead;
  2097.     SMacro *head = NULL, *m;
  2098.     Token **params;
  2099.     int *paramsize;
  2100.     int nparam, sparam, brackets;
  2101.     char *p;
  2102.     tail = &thead;
  2103.     thead = NULL;
  2104.     while (tline) {  /* main token loop */
  2105. p = NULL;
  2106. if (tline->type == TOK_ID) {
  2107.     head = smacros[hash(tline->text)];
  2108.     p = tline->text;
  2109. } else if (tline->type == TOK_PREPROC_ID && tline->text[1] == '$') {
  2110.     Context *ctx = get_ctx (tline->text);
  2111.     if (ctx) {
  2112. head = ctx->localmac;
  2113. p = tline->text+2;
  2114. p += strspn(p, "$");
  2115.     }
  2116. }
  2117. if (p) {
  2118. /*
  2119.  * We've hit an identifier. As in is_mmacro below, we first
  2120.  * check whether the identifier is a single-line macro at
  2121.  * all, then think about checking for parameters if
  2122.  * necessary.
  2123.  */
  2124.     for (m = head; m; m = m->next)
  2125. if (!mstrcmp(m->name, p, m->casesense))
  2126.     break;
  2127.     if (m) {
  2128.       mstart = tline;
  2129.       params = NULL;
  2130.       paramsize = NULL;
  2131.       if (m->nparam == 0) {
  2132. /*
  2133.    * Simple case: the macro is parameterless. Discard the
  2134.  * one token that the macro call took, and push the
  2135.  * expansion back on the to-do stack.
  2136.  */
  2137. if (!m->expansion) 
  2138. {
  2139.     if (!strcmp("__FILE__", m->name)) {
  2140. long num=0;
  2141. src_get(&num, &(tline->text));
  2142. nasm_quote(&(tline->text));
  2143. tline->type = TOK_STRING;
  2144. continue;
  2145.     }
  2146.     if (!strcmp("__LINE__", m->name)) {
  2147. nasm_free(tline->text);
  2148. make_tok_num(tline, src_get_linnum());
  2149. continue;
  2150.     }
  2151.     t = tline;
  2152.     tline = tline->next;
  2153.     nasm_free (t->text);
  2154.     nasm_free (t);
  2155.     continue;
  2156. }
  2157.       } 
  2158.       else {
  2159.   /*
  2160.    * Complicated case: at least one macro with this name
  2161.    * exists and takes parameters. We must find the
  2162.    * parameters in the call, count them, find the SMacro
  2163.    * that corresponds to that form of the macro call, and
  2164.    * substitute for the parameters when we expand. What a
  2165.    * pain.
  2166.    */
  2167.   tline = tline->next;
  2168.   skip_white_(tline);
  2169.   if (!tok_is_(tline, "(")) {
  2170.       /*
  2171.        * This macro wasn't called with parameters: ignore
  2172.        * the call. (Behaviour borrowed from gnu cpp.)
  2173.        */
  2174.       tline = mstart;
  2175.       m = NULL;
  2176.   } 
  2177.   else {
  2178.       int paren = 0;
  2179.       int white = 0;
  2180.       brackets = 0;
  2181.       nparam = 0;
  2182.       tline = tline->next;
  2183.       sparam = PARAM_DELTA;
  2184.       params = nasm_malloc (sparam*sizeof(Token *));
  2185.       params[0] = tline;
  2186.       paramsize = nasm_malloc (sparam*sizeof(int));
  2187.       paramsize[0] = 0;
  2188.       for (;;tline = tline->next) {    /* parameter loop */
  2189.   if (!tline) {
  2190.       error(ERR_NONFATAL,
  2191.     "macro call expects terminating `)'");
  2192.       break;
  2193.   }
  2194.   if (tline->type == TOK_WHITESPACE && brackets<=0) {
  2195.       if (paramsize[nparam])
  2196.   white++;
  2197.       else
  2198.   params[nparam] = tline->next;
  2199.       continue;    /* parameter loop */
  2200.   }
  2201.   if (tline->type == TOK_OTHER && tline->text[1]==0) {
  2202.       char ch = tline->text[0];
  2203.       if (ch == ',' && !paren && brackets<=0) {
  2204.   if (++nparam >= sparam) {
  2205.       sparam += PARAM_DELTA;
  2206.       params = nasm_realloc (params, 
  2207.      sparam*sizeof(Token *));
  2208.       paramsize = nasm_realloc (paramsize,
  2209.      sparam*sizeof(int));
  2210.   }
  2211.   params[nparam] = tline->next;
  2212.   paramsize[nparam] = 0;
  2213.   white = 0;
  2214.   continue; /* parameter loop */
  2215.       }
  2216.       if (ch == '{' && 
  2217.   (brackets>0 || (brackets==0 &&
  2218.   !paramsize[nparam])))
  2219.       {
  2220.   if (!(brackets++))
  2221.   {
  2222.       params[nparam] = tline->next;
  2223.       continue; /* parameter loop */
  2224.   }
  2225.       }
  2226.       if (ch == '}' && brackets>0)
  2227.   if (--brackets == 0) {
  2228.       brackets = -1;
  2229.       continue; /* parameter loop */
  2230.   }
  2231.       if (ch == '(' && !brackets)
  2232.   paren++;
  2233.       if (ch == ')' && brackets<=0)
  2234.   if (--paren < 0)
  2235.       break;
  2236.   }
  2237.   if (brackets<0) {
  2238.       brackets = 0;
  2239.       error (ERR_NONFATAL, "braces do not "
  2240.      "enclose all of macro parameter");
  2241.   }
  2242.   paramsize[nparam] += white+1;
  2243.   white = 0;
  2244.       } /* parameter loop */
  2245.       nparam++;
  2246.       while (m && (m->nparam != nparam ||
  2247.    mstrcmp(m->name, p, m->casesense)))
  2248.   m = m->next;
  2249.       if (!m)
  2250.   error (ERR_WARNING|ERR_WARN_MNP, 
  2251.  "macro `%s' exists, "
  2252.  "but not taking %d parameters",
  2253.  mstart->text, nparam);
  2254.   }
  2255.       }
  2256.       if (m && m->in_progress)
  2257.   m = NULL;
  2258.       if (!m)   /* in progess or didn't find '(' or wrong nparam */
  2259.       {
  2260.                   /* 
  2261.    * Design question: should we handle !tline, which
  2262.    * indicates missing ')' here, or expand those
  2263.    * macros anyway, which requires the (t) test a few
  2264.    * lines down?  
  2265.    */
  2266.   nasm_free (params);
  2267.   nasm_free (paramsize);
  2268.   tline = mstart;
  2269.       } 
  2270.       else {
  2271. /*
  2272.  * Expand the macro: we are placed on the last token of the
  2273.  * call, so that we can easily split the call from the
  2274.  * following tokens. We also start by pushing an SMAC_END
  2275.  * token for the cycle removal.
  2276.  */
  2277. t = tline;
  2278. if (t) {
  2279.     tline = t->next;
  2280.     t->next = NULL;
  2281. }
  2282. tt = nasm_malloc(sizeof(Token));
  2283. tt->type = TOK_SMAC_END;
  2284. tt->text = NULL;
  2285. tt->mac = m;
  2286. m->in_progress = TRUE;
  2287. tt->next = tline;
  2288. tline = tt;
  2289. for (t = m->expansion; t; t = t->next) {
  2290.     if (t->type >= TOK_SMAC_PARAM) {
  2291. Token *pcopy = tline, **ptail = &pcopy;
  2292. Token *ttt, *pt;
  2293. int i;
  2294. ttt = params[t->type - TOK_SMAC_PARAM];
  2295. for (i=paramsize[t->type-TOK_SMAC_PARAM]; --i>=0;) {
  2296.     pt = *ptail = nasm_malloc(sizeof(Token));
  2297.     pt->next = tline;
  2298.     ptail = &pt->next;
  2299.     pt->text = nasm_strdup(ttt->text);
  2300.     pt->type = ttt->type;
  2301.     pt->mac = NULL;
  2302.     ttt = ttt->next;
  2303. }
  2304. tline = pcopy;
  2305.     } else {
  2306. tt = nasm_malloc(sizeof(Token));
  2307. tt->type = t->type;
  2308. tt->text = nasm_strdup(t->text);
  2309. tt->mac = NULL;
  2310. tt->next = tline;
  2311. tline = tt;
  2312.     }
  2313. }
  2314. /*
  2315.  * Having done that, get rid of the macro call, and clean
  2316.  * up the parameters.
  2317.  */
  2318. nasm_free (params);
  2319. nasm_free (paramsize);
  2320. free_tlist (mstart);
  2321. continue;  /* main token loop */
  2322.       }
  2323.     }
  2324. }
  2325. if (tline->type == TOK_SMAC_END) {
  2326.     tline->mac->in_progress = FALSE;
  2327.     t = tline;
  2328.     tline = tline->next;
  2329.     nasm_free (t);
  2330. } else {
  2331.     t = *tail = tline;
  2332.     tline = tline->next;
  2333.     t->mac = NULL;
  2334.     t->next = NULL;
  2335.     tail = &t->next;
  2336.     if (t->type == TOK_PREPROC_ID && t->text[1] == '$') {
  2337. Context *c = get_ctx (t->text);
  2338. char *p, *q, buffer[40];
  2339. t->type = TOK_ID;
  2340. if (c) {
  2341.     q = t->text+1;
  2342.     q += strspn(q, "$");
  2343.     sprintf(buffer, "..@%lu.", c->number);
  2344.     p = nasm_strcat (buffer,q);
  2345.     nasm_free (t->text);
  2346.     t->text = p;
  2347. }
  2348.     }
  2349. }
  2350.     }
  2351.     return thead;
  2352. }
  2353. /*
  2354.  * Determine whether the given line constitutes a multi-line macro
  2355.  * call, and return the MMacro structure called if so. Doesn't have
  2356.  * to check for an initial label - that's taken care of in
  2357.  * expand_mmacro - but must check numbers of parameters. Guaranteed
  2358.  * to be called with tline->type == TOK_ID, so the putative macro
  2359.  * name is easy to find.
  2360.  */
  2361. static MMacro *is_mmacro (Token *tline, Token ***params_array) 
  2362. {
  2363.     MMacro *head, *m;
  2364.     Token **params;
  2365.     int nparam;
  2366.     head = mmacros[hash(tline->text)];
  2367.     /*
  2368.      * Efficiency: first we see if any macro exists with the given
  2369.      * name. If not, we can return NULL immediately. _Then_ we
  2370.      * count the parameters, and then we look further along the
  2371.      * list if necessary to find the proper MMacro.
  2372.      */
  2373.     for (m = head; m; m = m->next)
  2374. if (!mstrcmp(m->name, tline->text, m->casesense))
  2375.     break;
  2376.     if (!m)
  2377. return NULL;
  2378.     /*
  2379.      * OK, we have a potential macro. Count and demarcate the
  2380.      * parameters.
  2381.      */
  2382.     count_mmac_params (tline->next, &nparam, &params);
  2383.     /*
  2384.      * So we know how many parameters we've got. Find the MMacro
  2385.      * structure that handles this number.
  2386.      */
  2387.     while (m) {
  2388. if (m->nparam_min <= nparam && (m->plus || nparam <= m->nparam_max)) {
  2389.     /*
  2390.      * This one is right. Just check if cycle removal
  2391.      * prohibits us using it before we actually celebrate...
  2392.      */
  2393.     if (m->in_progress) {
  2394. #if 0
  2395. error (ERR_NONFATAL,
  2396.        "self-reference in multi-line macro `%s'",
  2397.        m->name);
  2398. #endif
  2399. nasm_free (params);
  2400. return NULL;
  2401.     }
  2402.     /*
  2403.      * It's right, and we can use it. Add its default
  2404.      * parameters to the end of our list if necessary.
  2405.      */
  2406.     if (m->defaults && nparam < m->nparam_min + m->ndefs) {
  2407. params = nasm_realloc (params, ((m->nparam_min+m->ndefs+1) *
  2408. sizeof(*params)));
  2409. while (nparam < m->nparam_min + m->ndefs) {
  2410.     params[nparam] = m->defaults[nparam - m->nparam_min];
  2411.     nparam++;
  2412. }
  2413.     }
  2414.     /*
  2415.      * If we've gone over the maximum parameter count (and
  2416.      * we're in Plus mode), ignore parameters beyond
  2417.      * nparam_max.
  2418.      */
  2419.     if (m->plus && nparam > m->nparam_max)
  2420. nparam = m->nparam_max;
  2421.     /*
  2422.      * Then terminate the parameter list, and leave.
  2423.      */
  2424.     if (!params) {        /* need this special case */
  2425. params = nasm_malloc(sizeof(*params));
  2426. nparam = 0;
  2427.     }
  2428.     params[nparam] = NULL;
  2429.     *params_array = params;
  2430.     return m;
  2431. }
  2432. /*
  2433.  * This one wasn't right: look for the next one with the
  2434.  * same name.
  2435.  */
  2436. for (m = m->next; m; m = m->next)
  2437.     if (!mstrcmp(m->name, tline->text, m->casesense))
  2438. break;
  2439.     }
  2440.     /*
  2441.      * After all that, we didn't find one with the right number of
  2442.      * parameters. Issue a warning, and fail to expand the macro.
  2443.      */
  2444.     error (ERR_WARNING|ERR_WARN_MNP,
  2445.    "macro `%s' exists, but not taking %d parameters",
  2446.    tline->text, nparam);
  2447.     nasm_free (params);
  2448.     return NULL;
  2449. }
  2450. /*
  2451.  * Expand the multi-line macro call made by the given line, if
  2452.  * there is one to be expanded. If there is, push the expansion on
  2453.  * istk->expansion and return 1. Otherwise return 0.
  2454.  */
  2455. static int expand_mmacro (Token *tline) 
  2456. {
  2457.     Token *startline = tline;
  2458.     Token *label = NULL;
  2459.     int dont_prepend = 0;
  2460.     Token **params, *t, *tt;
  2461.     MMacro *m;
  2462.     Line *l, *ll;
  2463.     int i, nparam, *paramlen;
  2464.     t = tline;
  2465.     skip_white_(t);
  2466.     if (!tok_type_(t, TOK_ID))
  2467. return 0;
  2468.     m = is_mmacro (t, &params);
  2469.     if (!m) {
  2470. Token *last;
  2471. /*
  2472.  * We have an id which isn't a macro call. We'll assume
  2473.  * it might be a label; we'll also check to see if a
  2474.  * colon follows it. Then, if there's another id after
  2475.  * that lot, we'll check it again for macro-hood.
  2476.  */
  2477. label = last = t;
  2478. t = t->next;
  2479. if (tok_type_(t, TOK_WHITESPACE))
  2480.     last = t, t = t->next;
  2481. if (tok_is_(t, ":")) {
  2482.     dont_prepend = 1;
  2483.     last = t, t = t->next;
  2484.     if (tok_type_(t, TOK_WHITESPACE))
  2485. last = t, t = t->next;
  2486. }
  2487. if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
  2488.     return 0;
  2489. last->next = NULL;
  2490. tline = t;
  2491.     }
  2492.     /*
  2493.      * Fix up the parameters: this involves stripping leading and
  2494.      * trailing whitespace, then stripping braces if they are
  2495.      * present.
  2496.      */
  2497.     for (nparam = 0; params[nparam]; nparam++)
  2498. ;
  2499.     paramlen = nparam ? nasm_malloc(nparam*sizeof(*paramlen)) : NULL;
  2500.     for (i = 0; params[i]; i++) {
  2501. int brace = FALSE;
  2502. int comma = (!m->plus || i < nparam-1);
  2503. t = params[i];
  2504. skip_white_(t);
  2505. if (tok_is_(t, "{"))
  2506.     t = t->next, brace = TRUE, comma = FALSE;
  2507. params[i] = t;
  2508. paramlen[i] = 0;
  2509. while (t) {
  2510.     if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
  2511. break;        /* ... because we have hit a comma */
  2512.     if (comma && t->type == TOK_WHITESPACE && tok_is_(t->next, ","))
  2513. break;        /* ... or a space then a comma */
  2514.     if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
  2515. break;        /* ... or a brace */
  2516.     t = t->next;
  2517.     paramlen[i]++;
  2518. }
  2519.     }
  2520.     /*
  2521.      * OK, we have a MMacro structure together with a set of
  2522.      * parameters. We must now go through the expansion and push
  2523.      * copies of each Line on to istk->expansion. Substitution of
  2524.      * parameter tokens and macro-local tokens doesn't get done
  2525.      * until the single-line macro substitution process; this is
  2526.      * because delaying them allows us to change the semantics
  2527.      * later through %rotate.
  2528.      *
  2529.      * First, push an end marker on to istk->expansion, mark this
  2530.      * macro as in progress, and set up its invocation-specific
  2531.      * variables.
  2532.      */
  2533.     ll = nasm_malloc(sizeof(Line));
  2534.     ll->next = istk->expansion;
  2535.     ll->finishes = m;
  2536.     ll->first = NULL;
  2537.     istk->expansion = ll;
  2538.     m->in_progress = TRUE;
  2539.     m->params = params;
  2540.     m->iline = tline;
  2541.     m->nparam = nparam;
  2542.     m->rotate = 0;
  2543.     m->paramlen = paramlen;
  2544.     m->unique = unique++;
  2545.     m->next_active = istk->mstk;
  2546.     istk->mstk = m;
  2547.     for (l = m->expansion; l; l = l->next) {
  2548. Token **tail;
  2549. ll = nasm_malloc(sizeof(Line));
  2550. ll->finishes = NULL;
  2551. ll->next = istk->expansion;
  2552. istk->expansion = ll;
  2553. tail = &ll->first;
  2554. for (t = l->first; t; t = t->next) {
  2555.     Token *x = t;
  2556.     if (t->type == TOK_PREPROC_ID && 
  2557. t->text[1]=='0' && t->text[2]=='0') 
  2558.     {
  2559. dont_prepend = -1;
  2560. x = label;
  2561. if (!x)
  2562.     continue;
  2563.     }
  2564.     tt = *tail = nasm_malloc(sizeof(Token));
  2565.     tail = &tt->next;
  2566.     tt->type = x->type;
  2567.     tt->text = nasm_strdup(x->text);
  2568.     tt->mac = NULL;
  2569. }
  2570. *tail = NULL;
  2571.     }
  2572.     /*
  2573.      * If we had a label, push it on as the first line of
  2574.      * the macro expansion.
  2575.      */
  2576.     if (label)
  2577. if (dont_prepend<0)
  2578.     free_tlist(startline);
  2579. else {
  2580.     ll = nasm_malloc(sizeof(Line));
  2581.     ll->finishes = NULL;
  2582.     ll->next = istk->expansion;
  2583.     istk->expansion = ll;
  2584.     ll->first = startline;
  2585.     if (!dont_prepend) {
  2586. while (label->next)
  2587.     label = label->next;
  2588. label->next = tt = nasm_malloc(sizeof(Token));
  2589. tt->next = NULL;
  2590. tt->mac = NULL;
  2591. tt->type = TOK_OTHER;
  2592. tt->text = nasm_strdup(":");
  2593.     }
  2594. }
  2595.     list->uplevel (m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
  2596.     return 1;
  2597. }
  2598. static void pp_reset (char *file, int apass, efunc errfunc, evalfunc eval,
  2599.       ListGen *listgen) 
  2600. {
  2601.     int h;
  2602.     error = errfunc;
  2603.     cstk = NULL;
  2604.     istk = nasm_malloc(sizeof(Include));
  2605.     istk->next = NULL;
  2606.     istk->conds = NULL;
  2607.     istk->expansion = NULL;
  2608.     istk->mstk = NULL;
  2609.     istk->fp = fopen(file, "r");
  2610.     istk->fname = NULL;
  2611.     src_set_fname(nasm_strdup(file));
  2612.     src_set_linnum(0);
  2613.     istk->lineinc = 1;
  2614.     if (!istk->fp)
  2615. error (ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'", file);
  2616.     defining = NULL;
  2617.     for (h=0; h<NHASH; h++) {
  2618. mmacros[h] = NULL;
  2619. smacros[h] = NULL;
  2620.     }
  2621.     unique = 0;
  2622.     stdmacpos = stdmac;
  2623.     any_extrastdmac = (extrastdmac != NULL);
  2624.     list = listgen;
  2625.     evaluate = eval;
  2626.     pass = apass;
  2627. }
  2628. static char *pp_getline (void) 
  2629. {
  2630.     char *line;
  2631.     Token *tline;
  2632.     int ret;
  2633.     while (1) {
  2634. /*
  2635.  * Fetch a tokenised line, either from the macro-expansion
  2636.  * buffer or from the input file.
  2637.  */
  2638. tline = NULL;
  2639. while (istk->expansion && istk->expansion->finishes) {
  2640.     Line *l = istk->expansion;
  2641.     if (!l->finishes->name && l->finishes->in_progress > 1) {
  2642. Line *ll;
  2643. /*
  2644.  * This is a macro-end marker for a macro with no
  2645.  * name, which means it's not really a macro at all
  2646.  * but a %rep block, and the `in_progress' field is
  2647.  * more than 1, meaning that we still need to
  2648.  * repeat. (1 means the natural last repetition; 0
  2649.  * means termination by %exitrep.) We have
  2650.  * therefore expanded up to the %endrep, and must
  2651.  * push the whole block on to the expansion buffer
  2652.  * again. We don't bother to remove the macro-end
  2653.  * marker: we'd only have to generate another one
  2654.  * if we did.
  2655.  */
  2656. l->finishes->in_progress--;
  2657. for (l = l->finishes->expansion; l; l = l->next) {
  2658.     Token *t, *tt, **tail;
  2659.     ll = nasm_malloc(sizeof(Line));
  2660.     ll->next = istk->expansion;
  2661.     ll->finishes = NULL;
  2662.     ll->first = NULL;
  2663.     tail = &ll->first;
  2664.     for (t = l->first; t; t = t->next) {
  2665. if (t->text) {
  2666.     tt = *tail = nasm_malloc(sizeof(Token));
  2667.     tt->next = NULL;
  2668.     tail = &tt->next;
  2669.     tt->type = t->type;
  2670.     tt->text = nasm_strdup(t->text);
  2671.     tt->mac = NULL;
  2672. }
  2673.     }
  2674.     istk->expansion = ll;
  2675. }
  2676.     } else {
  2677. /*
  2678.  * Check whether a `%rep' was started and not ended
  2679.  * within this macro expansion. This can happen and
  2680.  * should be detected. It's a fatal error because
  2681.  * I'm too confused to work out how to recover
  2682.  * sensibly from it.
  2683.  */
  2684. if (defining) {
  2685.     if (defining->name)
  2686. error (ERR_PANIC,
  2687.        "defining with name in expansion");
  2688.     else if (istk->mstk->name)
  2689. error (ERR_FATAL, "`%%rep' without `%%endrep' within"
  2690.        " expansion of macro `%s'", istk->mstk->name);
  2691. }
  2692.                 /*
  2693.  * FIXME:  investigate the relationship at this point between
  2694.  * istk->mstk and l->finishes
  2695.  */
  2696. {
  2697.     MMacro *m = istk->mstk;
  2698.     istk->mstk = m->next_active;
  2699.     if (m->name) {
  2700. /*
  2701.  * This was a real macro call, not a %rep, and
  2702.  * therefore the parameter information needs to
  2703.  * be freed.
  2704.  */
  2705. nasm_free(m->params);
  2706. free_tlist(m->iline);
  2707. nasm_free(m->paramlen);
  2708. l->finishes->in_progress = FALSE;
  2709.     } 
  2710.     else
  2711. free_mmacro(m);
  2712. }
  2713. istk->expansion = l->next;
  2714. nasm_free (l);
  2715. list->downlevel (LIST_MACRO);
  2716.     }
  2717. }
  2718. while (1) {  /* until we get a line we can use */
  2719.     if (istk->expansion) {   /* from a macro expansion */
  2720. char *p;
  2721. Line *l = istk->expansion;
  2722. tline = l->first;
  2723. istk->expansion = l->next;
  2724. nasm_free (l);
  2725. p = detoken(tline);
  2726. list->line (LIST_MACRO, p);
  2727. nasm_free(p);
  2728. break;
  2729.     }
  2730.     line = read_line();
  2731.     if (line) {    /* from the current input file */
  2732. line = prepreproc(line);
  2733. tline = tokenise(line);
  2734. nasm_free (line);
  2735. break;
  2736.     }
  2737.     /*
  2738.      * The current file has ended; work down the istk
  2739.      */
  2740.     {
  2741. Include *i = istk;
  2742. fclose(i->fp);
  2743. if (i->conds)
  2744.     error(ERR_FATAL, "expected `%%endif' before end of file");
  2745. istk = i->next;
  2746. list->downlevel (LIST_INCLUDE);
  2747. src_set_linnum(i->lineno);
  2748. nasm_free ( src_set_fname(i->fname) );
  2749. nasm_free (i);
  2750. if (!istk)
  2751.     return NULL;
  2752.     }
  2753. }
  2754. /*
  2755.  * We must expand MMacro parameters and MMacro-local labels
  2756.  * _before_ we plunge into directive processing, to cope
  2757.  * with things like `%define something %1' such as STRUC
  2758.  * uses. Unless we're _defining_ a MMacro, in which case
  2759.  * those tokens should be left alone to go into the
  2760.  * definition; and unless we're in a non-emitting
  2761.  * condition, in which case we don't want to meddle with
  2762.  * anything.
  2763.  */
  2764. if (!defining && !(istk->conds && !emitting(istk->conds->state)))
  2765.     tline = expand_mmac_params(tline);
  2766. /*
  2767.  * Check the line to see if it's a preprocessor directive.
  2768.  */
  2769. ret = do_directive(tline);
  2770. if (ret & 1) {
  2771. continue;
  2772. } else if (defining) {
  2773.     /*
  2774.      * We're defining a multi-line macro. We emit nothing
  2775.      * at all, and just
  2776.      * shove the tokenised line on to the macro definition.
  2777.      */
  2778.     Line *l = nasm_malloc(sizeof(Line));
  2779.     l->next = defining->expansion;
  2780.     l->first = tline;
  2781.     l->finishes = FALSE;
  2782.     defining->expansion = l;
  2783.     continue;
  2784. } else if (istk->conds && !emitting(istk->conds->state)) {
  2785.     /*
  2786.      * We're in a non-emitting branch of a condition block.
  2787.      * Emit nothing at all, not even a blank line: when we
  2788.      * emerge from the condition we'll give a line-number
  2789.      * directive so we keep our place correctly.
  2790.      */
  2791.     free_tlist(tline);
  2792.     continue;
  2793. } else if (istk->mstk && !istk->mstk->in_progress) {
  2794.     /*
  2795.      * We're in a %rep block which has been terminated, so
  2796.      * we're walking through to the %endrep without
  2797.      * emitting anything. Emit nothing at all, not even a
  2798.      * blank line: when we emerge from the %rep block we'll
  2799.      * give a line-number directive so we keep our place
  2800.      * correctly.
  2801.      */
  2802.     free_tlist(tline);
  2803.     continue;
  2804. } else {
  2805.     tline = expand_smacro(tline);
  2806.     ret = expand_mmacro(tline);
  2807.     if (!ret) {
  2808. /*
  2809.  * De-tokenise the line again, and emit it.
  2810.  */
  2811. line = detoken(tline);
  2812. free_tlist (tline);
  2813. break;
  2814.     } else {
  2815. continue;        /* expand_mmacro calls free_tlist */
  2816.     }
  2817. }
  2818.     }
  2819.     return line;
  2820. }
  2821. static void pp_cleanup (void) 
  2822. {
  2823.     int h;
  2824.     if (defining) {
  2825. error (ERR_NONFATAL, "end of file while still defining macro `%s'",
  2826.        defining->name);
  2827. free_mmacro (defining);
  2828.     }
  2829.     while (cstk)
  2830. ctx_pop();
  2831.     for (h=0; h<NHASH; h++) {
  2832. while (mmacros[h]) {
  2833.     MMacro *m = mmacros[h];
  2834.     mmacros[h] = mmacros[h]->next;
  2835.     free_mmacro(m);
  2836. }
  2837. while (smacros[h]) {
  2838.     SMacro *s = smacros[h];
  2839.     smacros[h] = smacros[h]->next;
  2840.     nasm_free (s->name);
  2841.     free_tlist (s->expansion);
  2842.     nasm_free (s);
  2843. }
  2844.     }
  2845.     while (istk) {
  2846. Include *i = istk;
  2847. istk = istk->next;
  2848. fclose(i->fp);
  2849. nasm_free (i->fname);
  2850. nasm_free (i);
  2851.     }
  2852.     while (cstk)
  2853. ctx_pop();
  2854. }
  2855. void pp_include_path (char *path) 
  2856. {
  2857.     IncPath *i;
  2858.     i = nasm_malloc(sizeof(IncPath));
  2859.     i->path = nasm_strdup(path);
  2860.     i->next = ipath;
  2861.     ipath = i;
  2862. }
  2863. void pp_pre_include (char *fname) 
  2864. {
  2865.     Token *inc, *space, *name;
  2866.     Line *l;
  2867.     inc = nasm_malloc(sizeof(Token));
  2868.     inc->next = space = nasm_malloc(sizeof(Token));
  2869.     space->next = name = nasm_malloc(sizeof(Token));
  2870.     name->next = NULL;
  2871.     inc->type = TOK_PREPROC_ID;
  2872.     inc->text = nasm_strdup("%include");
  2873.     space->type = TOK_WHITESPACE;
  2874.     space->text = nasm_strdup(" ");
  2875.     name->type = TOK_INTERNAL_STRING;
  2876.     name->text = nasm_strdup(fname);
  2877.     inc->mac = space->mac = name->mac = NULL;
  2878.     l = nasm_malloc(sizeof(Line));
  2879.     l->next = predef;
  2880.     l->first = inc;
  2881.     l->finishes = FALSE;
  2882.     predef = l;
  2883. }
  2884. void pp_pre_define (char *definition) 
  2885. {
  2886.     Token *def, *space;
  2887.     Line *l;
  2888.     char *equals;
  2889.     equals = strchr(definition, '=');
  2890.     def = nasm_malloc(sizeof(Token));
  2891.     def->next = space = nasm_malloc(sizeof(Token));
  2892.     if (equals)
  2893. *equals = ' ';
  2894.     space->next = tokenise(definition);
  2895.     if (equals)
  2896. *equals = '=';
  2897.     def->type = TOK_PREPROC_ID;
  2898.     def->text = nasm_strdup("%define");
  2899.     space->type = TOK_WHITESPACE;
  2900.     space->text = nasm_strdup(" ");
  2901.     def->mac = space->mac = NULL;
  2902.     l = nasm_malloc(sizeof(Line));
  2903.     l->next = predef;
  2904.     l->first = def;
  2905.     l->finishes = FALSE;
  2906.     predef = l;
  2907. }
  2908. void pp_pre_undefine (char *definition) 
  2909. {
  2910.     Token *def, *space;
  2911.     Line *l;
  2912.     def = nasm_malloc(sizeof(Token));
  2913.     def->next = space = nasm_malloc(sizeof(Token));
  2914.     space->next = tokenise(definition);
  2915.     def->type = TOK_PREPROC_ID;
  2916.     def->text = nasm_strdup("%undef");
  2917.     space->type = TOK_WHITESPACE;
  2918.     space->text = nasm_strdup(" ");
  2919.     def->mac = space->mac = NULL;
  2920.     l = nasm_malloc(sizeof(Line));
  2921.     l->next = predef;
  2922.     l->first = def;
  2923.     l->finishes = FALSE;
  2924.     predef = l;
  2925. }
  2926. void pp_extra_stdmac (char **macros) 
  2927. {
  2928.     extrastdmac = macros;
  2929. }
  2930. static void make_tok_num(Token *tok, long val)
  2931. {
  2932.     char numbuf[20];
  2933.     sprintf(numbuf, "%ld", val);
  2934.     tok->text = nasm_strdup(numbuf);
  2935.     tok->type = TOK_NUMBER;
  2936. }
  2937. Preproc nasmpp = {
  2938.     pp_reset,
  2939.     pp_getline,
  2940.     pp_cleanup
  2941. };