home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / nasm097s.zip / PARSER.C < prev    next >
C/C++ Source or Header  |  1997-12-05  |  20KB  |  635 lines

  1. /* parser.c   source line parser 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 27/iii/95 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.  
  17. #include "nasm.h"
  18. #include "nasmlib.h"
  19. #include "parser.h"
  20. #include "float.h"
  21.  
  22. static long reg_flags[] = {           /* sizes and special flags */
  23.     0, REG8, REG_AL, REG_AX, REG8, REG8, REG16, REG16, REG8, REG_CL,
  24.     REG_CREG, REG_CREG, REG_CREG, REG_CR4, REG_CS, REG_CX, REG8,
  25.     REG16, REG8, REG_DREG, REG_DREG, REG_DREG, REG_DREG, REG_DREG,
  26.     REG_DREG, REG_DESS, REG_DX, REG_EAX, REG32, REG32, REG_ECX,
  27.     REG32, REG32, REG_DESS, REG32, REG32, REG_FSGS, REG_FSGS,
  28.     MMXREG, MMXREG, MMXREG, MMXREG, MMXREG, MMXREG, MMXREG, MMXREG,
  29.     REG16, REG16, REG_DESS, FPU0, FPUREG, FPUREG, FPUREG, FPUREG,
  30.     FPUREG, FPUREG, FPUREG, REG_TREG, REG_TREG, REG_TREG, REG_TREG,
  31.     REG_TREG
  32. };
  33.  
  34. enum {                       /* special tokens */
  35.     S_BYTE, S_DWORD, S_FAR, S_LONG, S_NEAR, S_NOSPLIT, S_QWORD,
  36.     S_SHORT, S_TO, S_TWORD, S_WORD
  37. };
  38.  
  39. static int is_comma_next (void);
  40.  
  41. static int i;
  42. static struct tokenval tokval;
  43. static efunc error;
  44.  
  45. insn *parse_line (int pass, char *buffer, insn *result,
  46.           efunc errfunc, evalfunc evaluate, evalinfofunc einfo) {
  47.     int operand;
  48.     int critical;
  49.     struct eval_hints hints;
  50.  
  51.     result->forw_ref = FALSE;
  52.     error = errfunc;
  53.     einfo ("", 0L, 0L);
  54.  
  55.     stdscan_reset();
  56.     stdscan_bufptr = buffer;
  57.     i = stdscan(NULL, &tokval);
  58.  
  59.     result->eops = NULL;           /* must do this, whatever happens */
  60.     result->operands = 0;           /* must initialise this */
  61.  
  62.     if (i==0) {                   /* blank line - ignore */
  63.     result->label = NULL;           /* so, no label on it */
  64.     result->opcode = -1;           /* and no instruction either */
  65.     return result;
  66.     }
  67.     if (i != TOKEN_ID && i != TOKEN_INSN && i != TOKEN_PREFIX &&
  68.     (i!=TOKEN_REG || (REG_SREG & ~reg_flags[tokval.t_integer]))) {
  69.     error (ERR_NONFATAL, "label or instruction expected"
  70.            " at start of line");
  71.     result->label = NULL;
  72.     result->opcode = -1;
  73.     return result;
  74.     }
  75.  
  76.     if (i == TOKEN_ID) {           /* there's a label here */
  77.     result->label = tokval.t_charptr;
  78.     einfo (result->label, 0L, 0L);
  79.     i = stdscan(NULL, &tokval);
  80.     if (i == ':') {               /* skip over the optional colon */
  81.         i = stdscan(NULL, &tokval);
  82.     } else if (i == 0 && pass == 1) {
  83.         error (ERR_WARNING|ERR_WARN_OL,
  84.            "label alone on a line without a colon might be in error");
  85.     }
  86.     } else                   /* no label; so, moving swiftly on */
  87.     result->label = NULL;
  88.  
  89.     if (i==0) {
  90.     result->opcode = -1;           /* this line contains just a label */
  91.     return result;
  92.     }
  93.  
  94.     result->nprefix = 0;
  95.     result->times = 1L;
  96.  
  97.     while (i == TOKEN_PREFIX ||
  98.        (i==TOKEN_REG && !(REG_SREG & ~reg_flags[tokval.t_integer]))) {
  99.     /*
  100.      * Handle special case: the TIMES prefix.
  101.      */
  102.     if (i == TOKEN_PREFIX && tokval.t_integer == P_TIMES) {
  103.         expr *value;
  104.  
  105.         i = stdscan(NULL, &tokval);
  106.         value = evaluate (stdscan, NULL, &tokval, NULL, pass, error, NULL);
  107.         i = tokval.t_type;
  108.         if (!value) {           /* but, error in evaluator */
  109.         result->opcode = -1;   /* unrecoverable parse error: */
  110.         return result;           /* ignore this instruction */
  111.         }
  112.         if (!is_simple (value)) {
  113.         error (ERR_NONFATAL,
  114.                "non-constant argument supplied to TIMES");
  115.         result->times = 1L;
  116.         } else {
  117.         result->times = value->value;
  118.         if (value->value < 0)
  119.             error(ERR_NONFATAL, "TIMES value %d is negative",
  120.               value->value);
  121.         }
  122.     } else {
  123.         if (result->nprefix == MAXPREFIX)
  124.         error (ERR_NONFATAL,
  125.                "instruction has more than %d prefixes", MAXPREFIX);
  126.         else
  127.         result->prefixes[result->nprefix++] = tokval.t_integer;
  128.         i = stdscan(NULL, &tokval);
  129.     }
  130.     }
  131.  
  132.     if (i != TOKEN_INSN) {
  133.     if (result->nprefix > 0 && i == 0) {
  134.         /*
  135.          * Instruction prefixes are present, but no actual
  136.          * instruction. This is allowed: at this point we
  137.          * invent a notional instruction of RESB 0.
  138.          */
  139.         result->opcode = I_RESB;
  140.         result->operands = 1;
  141.         result->oprs[0].type = IMMEDIATE;
  142.         result->oprs[0].offset = 0L;
  143.         result->oprs[0].segment = result->oprs[0].wrt = NO_SEG;
  144.         return result;
  145.     } else {
  146.         error (ERR_NONFATAL, "parser: instruction expected");
  147.         result->opcode = -1;
  148.         return result;
  149.     }
  150.     }
  151.  
  152.     result->opcode = tokval.t_integer;
  153.     result->condition = tokval.t_inttwo;
  154.  
  155.     /*
  156.      * RESB, RESW and RESD cannot be satisfied with incorrectly
  157.      * evaluated operands, since the correct values _must_ be known
  158.      * on the first pass. Hence, even in pass one, we set the
  159.      * `critical' flag on calling evaluate(), so that it will bomb
  160.      * out on undefined symbols. Nasty, but there's nothing we can
  161.      * do about it.
  162.      *
  163.      * For the moment, EQU has the same difficulty, so we'll
  164.      * include that.
  165.      */
  166.     if (result->opcode == I_RESB ||
  167.     result->opcode == I_RESW ||
  168.     result->opcode == I_RESD ||
  169.     result->opcode == I_RESQ ||
  170.     result->opcode == I_REST ||
  171.     result->opcode == I_EQU)
  172.     critical = pass;
  173.     else
  174.     critical = (pass==2 ? 2 : 0);
  175.  
  176.     if (result->opcode == I_DB ||
  177.     result->opcode == I_DW ||
  178.     result->opcode == I_DD ||
  179.     result->opcode == I_DQ ||
  180.     result->opcode == I_DT ||
  181.     result->opcode == I_INCBIN) {
  182.     extop *eop, **tail = &result->eops, **fixptr;
  183.     int oper_num = 0;
  184.  
  185.     /*
  186.      * Begin to read the DB/DW/DD/DQ/DT operands.
  187.      */
  188.     while (1) {
  189.         i = stdscan(NULL, &tokval);
  190.         if (i == 0)
  191.         break;
  192.         fixptr = tail;
  193.         eop = *tail = nasm_malloc(sizeof(extop));
  194.         tail = &eop->next;
  195.         eop->next = NULL;
  196.         eop->type = EOT_NOTHING;
  197.         oper_num++;
  198.  
  199.         if (i == TOKEN_NUM && tokval.t_charptr && is_comma_next()) {
  200.         eop->type = EOT_DB_STRING;
  201.         eop->stringval = tokval.t_charptr;
  202.         eop->stringlen = tokval.t_inttwo;
  203.         i = stdscan(NULL, &tokval);       /* eat the comma */
  204.         continue;
  205.         }
  206.  
  207.         if (i == TOKEN_FLOAT || i == '-') {
  208.         long sign = +1L;
  209.  
  210.         if (i == '-') {
  211.             char *save = stdscan_bufptr;
  212.             i = stdscan(NULL, &tokval);
  213.             sign = -1L;
  214.             if (i != TOKEN_FLOAT) {
  215.             stdscan_bufptr = save;
  216.             i = tokval.t_type = '-';
  217.             }
  218.         }
  219.  
  220.         if (i == TOKEN_FLOAT) {
  221.             eop->type = EOT_DB_STRING;
  222.             if (result->opcode == I_DD)
  223.             eop->stringlen = 4;
  224.             else if (result->opcode == I_DQ)
  225.             eop->stringlen = 8;
  226.             else if (result->opcode == I_DT)
  227.             eop->stringlen = 10;
  228.             else {
  229.             error(ERR_NONFATAL, "floating-point constant"
  230.                   " encountered in `D%c' instruction",
  231.                   result->opcode == I_DW ? 'W' : 'B');
  232.             eop->type = EOT_NOTHING;
  233.             }
  234.             eop = nasm_realloc(eop, sizeof(extop)+eop->stringlen);
  235.             tail = &eop->next;
  236.             *fixptr = eop;
  237.             eop->stringval = (char *)eop + sizeof(extop);
  238.             if (!float_const (tokval.t_charptr, sign,
  239.                       (unsigned char *)eop->stringval,
  240.                       eop->stringlen, error))
  241.             eop->type = EOT_NOTHING;
  242.             i = stdscan(NULL, &tokval);       /* eat the comma */
  243.             continue;
  244.         }
  245.         }
  246.  
  247.         /* anything else */ {
  248.         expr *value;
  249.         value = evaluate (stdscan, NULL, &tokval, NULL,
  250.                   critical, error, NULL);
  251.         i = tokval.t_type;
  252.         if (!value) {           /* error in evaluator */
  253.             result->opcode = -1;/* unrecoverable parse error: */
  254.             return result;     /* ignore this instruction */
  255.         }
  256.         if (is_unknown(value)) {
  257.             eop->type = EOT_DB_NUMBER;
  258.             eop->offset = 0;   /* doesn't matter what we put */
  259.             eop->segment = eop->wrt = NO_SEG;   /* likewise */
  260.         } else if (is_reloc(value)) {
  261.             eop->type = EOT_DB_NUMBER;
  262.             eop->offset = reloc_value(value);
  263.             eop->segment = reloc_seg(value);
  264.             eop->wrt = reloc_wrt(value);
  265.         } else {
  266.             error (ERR_NONFATAL,
  267.                "operand %d: expression is not simple"
  268.                " or relocatable", oper_num);
  269.         }
  270.         }
  271.  
  272.         /*
  273.          * We're about to call stdscan(), which will eat the
  274.          * comma that we're currently sitting on between
  275.          * arguments. However, we'd better check first that it
  276.          * _is_ a comma.
  277.          */
  278.         if (i == 0)               /* also could be EOL */
  279.         break;
  280.         if (i != ',') {
  281.         error (ERR_NONFATAL, "comma expected after operand %d",
  282.                oper_num);
  283.         result->opcode = -1;/* unrecoverable parse error: */
  284.         return result;     /* ignore this instruction */
  285.         }
  286.     }
  287.  
  288.     if (result->opcode == I_INCBIN) {
  289.         /*
  290.          * Correct syntax for INCBIN is that there should be
  291.          * one string operand, followed by one or two numeric
  292.          * operands.
  293.          */
  294.         if (!result->eops || result->eops->type != EOT_DB_STRING)
  295.         error (ERR_NONFATAL, "`incbin' expects a file name");
  296.         else if (result->eops->next &&
  297.              result->eops->next->type != EOT_DB_NUMBER)
  298.         error (ERR_NONFATAL, "`incbin': second parameter is",
  299.                " non-numeric");
  300.         else if (result->eops->next && result->eops->next->next &&
  301.              result->eops->next->next->type != EOT_DB_NUMBER)
  302.         error (ERR_NONFATAL, "`incbin': third parameter is",
  303.                " non-numeric");
  304.         else if (result->eops->next && result->eops->next->next &&
  305.              result->eops->next->next->next)
  306.         error (ERR_NONFATAL, "`incbin': more than three parameters");
  307.         else
  308.         return result;
  309.         /*
  310.          * If we reach here, one of the above errors happened.
  311.          * Throw the instruction away.
  312.          */
  313.         result->opcode = -1;
  314.         return result;
  315.     }
  316.  
  317.     return result;
  318.     }
  319.  
  320.     /* right. Now we begin to parse the operands. There may be up to three
  321.      * of these, separated by commas, and terminated by a zero token. */
  322.  
  323.     for (operand = 0; operand < 3; operand++) {
  324.     expr *value;               /* used most of the time */
  325.     int mref;               /* is this going to be a memory ref? */
  326.     int bracket;               /* is it a [] mref, or a & mref? */
  327.  
  328.     result->oprs[operand].addr_size = 0;/* have to zero this whatever */
  329.     result->oprs[operand].eaflags = 0;   /* and this */
  330.     i = stdscan(NULL, &tokval);
  331.     if (i == 0) break;           /* end of operands: get out of here */
  332.     result->oprs[operand].type = 0;   /* so far, no override */
  333.     while (i == TOKEN_SPECIAL)    {/* size specifiers */
  334.         switch ((int)tokval.t_integer) {
  335.           case S_BYTE:
  336.         result->oprs[operand].type |= BITS8;
  337.         break;
  338.           case S_WORD:
  339.         result->oprs[operand].type |= BITS16;
  340.         break;
  341.           case S_DWORD:
  342.           case S_LONG:
  343.         result->oprs[operand].type |= BITS32;
  344.         break;
  345.           case S_QWORD:
  346.         result->oprs[operand].type |= BITS64;
  347.         break;
  348.           case S_TWORD:
  349.         result->oprs[operand].type |= BITS80;
  350.         break;
  351.           case S_TO:
  352.         result->oprs[operand].type |= TO;
  353.         break;
  354.           case S_FAR:
  355.         result->oprs[operand].type |= FAR;
  356.         break;
  357.           case S_NEAR:
  358.         result->oprs[operand].type |= NEAR;
  359.         break;
  360.           case S_SHORT:
  361.         result->oprs[operand].type |= SHORT;
  362.         break;
  363.         }
  364.         i = stdscan(NULL, &tokval);
  365.     }
  366.  
  367.     if (i == '[' || i == '&') {    /* memory reference */
  368.         mref = TRUE;
  369.         bracket = (i == '[');
  370.         i = stdscan(NULL, &tokval);        
  371.         if (i == TOKEN_SPECIAL) {  /* check for address size override */
  372.         switch ((int)tokval.t_integer) {
  373.           case S_NOSPLIT:
  374.             result->oprs[operand].eaflags |= EAF_TIMESTWO;
  375.             break;
  376.           case S_BYTE:
  377.             result->oprs[operand].eaflags |= EAF_BYTEOFFS;
  378.             break;
  379.           case S_WORD:
  380.             result->oprs[operand].addr_size = 16;
  381.             result->oprs[operand].eaflags |= EAF_WORDOFFS;
  382.             break;
  383.           case S_DWORD:
  384.           case S_LONG:
  385.             result->oprs[operand].addr_size = 32;
  386.             result->oprs[operand].eaflags |= EAF_WORDOFFS;
  387.             break;
  388.           default:
  389.             error (ERR_NONFATAL, "invalid size specification in"
  390.                " effective address");
  391.         }
  392.         i = stdscan(NULL, &tokval);
  393.         }
  394.     } else {               /* immediate operand, or register */
  395.         mref = FALSE;
  396.         bracket = FALSE;           /* placate optimisers */
  397.     }
  398.  
  399.     value = evaluate (stdscan, NULL, &tokval,
  400.               &result->forw_ref, critical, error, &hints);
  401.     i = tokval.t_type;
  402.     if (!value) {               /* error in evaluator */
  403.         result->opcode = -1;       /* unrecoverable parse error: */
  404.         return result;           /* ignore this instruction */
  405.     }
  406.     if (i == ':' && mref) {           /* it was seg:offset */
  407.         /*
  408.          * Process the segment override.
  409.          */
  410.         if (value[1].type!=0 || value->value!=1 ||
  411.         REG_SREG & ~reg_flags[value->type])
  412.         error (ERR_NONFATAL, "invalid segment override");
  413.         else if (result->nprefix == MAXPREFIX)
  414.         error (ERR_NONFATAL,
  415.                "instruction has more than %d prefixes",
  416.                MAXPREFIX);
  417.         else
  418.         result->prefixes[result->nprefix++] = value->type;
  419.  
  420.         i = stdscan(NULL, &tokval);           /* then skip the colon */
  421.         if (i == TOKEN_SPECIAL) {  /* another check for size override */
  422.         switch ((int)tokval.t_integer) {
  423.           case S_WORD:
  424.             result->oprs[operand].addr_size = 16;
  425.             break;
  426.           case S_DWORD:
  427.           case S_LONG:
  428.             result->oprs[operand].addr_size = 32;
  429.             break;
  430.           default:
  431.             error (ERR_NONFATAL, "invalid size specification in"
  432.                " effective address");
  433.         }
  434.         i = stdscan(NULL, &tokval);
  435.         }
  436.         value = evaluate (stdscan, NULL, &tokval,
  437.                   &result->forw_ref, critical, error, &hints);
  438.         i = tokval.t_type;
  439.         /* and get the offset */
  440.         if (!value) {           /* but, error in evaluator */
  441.         result->opcode = -1;   /* unrecoverable parse error: */
  442.         return result;           /* ignore this instruction */
  443.         }
  444.     }
  445.     if (mref && bracket) {           /* find ] at the end */
  446.         if (i != ']') {
  447.         error (ERR_NONFATAL, "parser: expecting ]");
  448.         do {               /* error recovery again */
  449.             i = stdscan(NULL, &tokval);
  450.         } while (i != 0 && i != ',');
  451.         } else               /* we got the required ] */
  452.         i = stdscan(NULL, &tokval);
  453.     } else {               /* immediate operand */
  454.         if (i != 0 && i != ',' && i != ':') {
  455.         error (ERR_NONFATAL, "comma or end of line expected");
  456.         do {               /* error recovery */
  457.             i = stdscan(NULL, &tokval);
  458.         } while (i != 0 && i != ',');
  459.         } else if (i == ':') {
  460.         result->oprs[operand].type |= COLON;
  461.         }
  462.     }
  463.  
  464.     /* now convert the exprs returned from evaluate() into operand
  465.      * descriptions... */
  466.  
  467.     if (mref) {               /* it's a memory reference */
  468.         expr *e = value;
  469.         int b, i, s;           /* basereg, indexreg, scale */
  470.         long o;               /* offset */
  471.  
  472.         b = i = -1, o = s = 0;
  473.         result->oprs[operand].hintbase = hints.base;
  474.         result->oprs[operand].hinttype = hints.type;
  475.  
  476.         if (e->type <= EXPR_REG_END) {   /* this bit's a register */
  477.         if (e->value == 1) /* in fact it can be basereg */
  478.             b = e->type;
  479.         else           /* no, it has to be indexreg */
  480.             i = e->type, s = e->value;
  481.         e++;
  482.         }
  483.         if (e->type && e->type <= EXPR_REG_END) {/* it's a 2nd register */
  484.         if (e->value != 1) {   /* it has to be indexreg */
  485.             if (i != -1) {     /* but it can't be */
  486.             error(ERR_NONFATAL, "invalid effective address");
  487.             result->opcode = -1;
  488.             return result;
  489.             } else
  490.             i = e->type, s = e->value;
  491.         } else {           /* it can be basereg */
  492.             if (b != -1)       /* or can it? */
  493.             i = e->type, s = 1;
  494.             else
  495.             b = e->type;
  496.         }
  497.         e++;
  498.         }
  499.         if (e->type != 0) {           /* is there an offset? */
  500.         if (e->type <= EXPR_REG_END) {/* in fact, is there an error? */
  501.             error (ERR_NONFATAL, "invalid effective address");
  502.             result->opcode = -1;
  503.             return result;
  504.         } else {
  505.             if (e->type == EXPR_UNKNOWN) {
  506.             o = 0;           /* doesn't matter what */
  507.             result->oprs[operand].wrt = NO_SEG;   /* nor this */
  508.             result->oprs[operand].segment = NO_SEG;  /* or this */
  509.             while (e->type) e++;   /* go to the end of the line */
  510.             } else {
  511.             if (e->type == EXPR_SIMPLE) {
  512.                 o = e->value;
  513.                 e++;
  514.             }
  515.             if (e->type == EXPR_WRT) {
  516.                 result->oprs[operand].wrt = e->value;
  517.                 e++;
  518.             } else
  519.                 result->oprs[operand].wrt = NO_SEG;
  520.             /*
  521.              * Look for a segment base type.
  522.              */
  523.             if (e->type && e->type < EXPR_SEGBASE) {
  524.                 error (ERR_NONFATAL, "invalid effective address");
  525.                 result->opcode = -1;
  526.                 return result;
  527.             }
  528.             while (e->type && e->value == 0)
  529.                 e++;
  530.             if (e->type && e->value != 1) {
  531.                 error (ERR_NONFATAL, "invalid effective address");
  532.                 result->opcode = -1;
  533.                 return result;
  534.             }
  535.             if (e->type) {
  536.                 result->oprs[operand].segment =
  537.                 e->type - EXPR_SEGBASE;
  538.                 e++;
  539.             } else
  540.                 result->oprs[operand].segment = NO_SEG;
  541.             while (e->type && e->value == 0)
  542.                 e++;
  543.             if (e->type) {
  544.                 error (ERR_NONFATAL, "invalid effective address");
  545.                 result->opcode = -1;
  546.                 return result;
  547.             }
  548.             }
  549.         }
  550.         } else {
  551.         o = 0;
  552.         result->oprs[operand].wrt = NO_SEG;
  553.         result->oprs[operand].segment = NO_SEG;
  554.         }
  555.  
  556.         if (e->type != 0) {    /* there'd better be nothing left! */
  557.         error (ERR_NONFATAL, "invalid effective address");
  558.         result->opcode = -1;
  559.         return result;
  560.         }
  561.  
  562.         result->oprs[operand].type |= MEMORY;
  563.         if (b==-1 && (i==-1 || s==0))
  564.         result->oprs[operand].type |= MEM_OFFS;
  565.         result->oprs[operand].basereg = b;
  566.         result->oprs[operand].indexreg = i;
  567.         result->oprs[operand].scale = s;
  568.         result->oprs[operand].offset = o;
  569.     } else {               /* it's not a memory reference */
  570.         if (is_just_unknown(value)) {     /* it's immediate but unknown */
  571.         result->oprs[operand].type |= IMMEDIATE;
  572.         result->oprs[operand].offset = 0;   /* don't care */
  573.         result->oprs[operand].segment = NO_SEG; /* don't care again */
  574.         result->oprs[operand].wrt = NO_SEG;/* still don't care */
  575.         } else if (is_reloc(value)) {     /* it's immediate */
  576.         result->oprs[operand].type |= IMMEDIATE;
  577.         result->oprs[operand].offset = reloc_value(value);
  578.         result->oprs[operand].segment = reloc_seg(value);
  579.         result->oprs[operand].wrt = reloc_wrt(value);
  580.         if (is_simple(value) && reloc_value(value)==1)
  581.             result->oprs[operand].type |= UNITY;
  582.         } else {           /* it's a register */
  583.         if (value->type>=EXPR_SIMPLE || value->value!=1) {
  584.             error (ERR_NONFATAL, "invalid operand type");
  585.             result->opcode = -1;
  586.             return result;
  587.         }
  588.         /* clear overrides, except TO which applies to FPU regs */
  589.         result->oprs[operand].type &= TO;
  590.         result->oprs[operand].type |= REGISTER;
  591.         result->oprs[operand].type |= reg_flags[value->type];
  592.         result->oprs[operand].basereg = value->type;
  593.         }
  594.     }
  595.     }
  596.  
  597.     result->operands = operand;       /* set operand count */
  598.  
  599.     while (operand<3)               /* clear remaining operands */
  600.     result->oprs[operand++].type = 0;
  601.  
  602.     /*
  603.      * Transform RESW, RESD, RESQ, REST into RESB.
  604.      */
  605.     switch (result->opcode) {
  606.       case I_RESW: result->opcode=I_RESB; result->oprs[0].offset*=2; break;
  607.       case I_RESD: result->opcode=I_RESB; result->oprs[0].offset*=4; break;
  608.       case I_RESQ: result->opcode=I_RESB; result->oprs[0].offset*=8; break;
  609.       case I_REST: result->opcode=I_RESB; result->oprs[0].offset*=10; break;
  610.     }
  611.  
  612.     return result;
  613. }
  614.  
  615. static int is_comma_next (void) {
  616.     char *p;
  617.     int i;
  618.     struct tokenval tv;
  619.  
  620.     p = stdscan_bufptr;
  621.     i = stdscan (NULL, &tv);
  622.     stdscan_bufptr = p;
  623.     return (i == ',' || i == ';' || !i);
  624. }
  625.  
  626. void cleanup_insn (insn *i) {
  627.     extop *e;
  628.  
  629.     while (i->eops) {
  630.     e = i->eops;
  631.     i->eops = i->eops->next;
  632.     nasm_free (e);
  633.     }
  634. }
  635.