home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / nasm097s.zip / PREPROC.C < prev    next >
C/C++ Source or Header  |  1997-11-20  |  85KB  |  3,002 lines

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