⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parser.c

📁 nasm的全套源代码,有些我做了些修改,以方便您更方便更容易调试成功,方便学习做编译器
💻 C
📖 第 1 页 / 共 3 页
字号:
                    i = stdscan(NULL, &tokval); /* eat the comma */
                    continue;
                }
            }

            /* anything else */
            {
                expr *value;
                value = evaluate(stdscan, NULL, &tokval, NULL,
                                 critical, error, NULL);
                i = tokval.t_type;
                if (!value) {   /* error in evaluator */
                    result->opcode = -1;        /* unrecoverable parse error: */
                    return result;      /* ignore this instruction */
                }
                if (is_unknown(value)) {
                    eop->type = EOT_DB_NUMBER;
                    eop->offset = 0;    /* doesn't matter what we put */
                    eop->segment = eop->wrt = NO_SEG;   /* likewise */
                } else if (is_reloc(value)) {
                    eop->type = EOT_DB_NUMBER;
                    eop->offset = reloc_value(value);
                    eop->segment = reloc_seg(value);
                    eop->wrt = reloc_wrt(value);
                } else {
                    error(ERR_NONFATAL,
                          "operand %d: expression is not simple"
                          " or relocatable", oper_num);
                }
            }

            /*
             * We're about to call stdscan(), which will eat the
             * comma that we're currently sitting on between
             * arguments. However, we'd better check first that it
             * _is_ a comma.
             */
            if (i == 0)         /* also could be EOL */
                break;
            if (i != ',') {
                error(ERR_NONFATAL, "comma expected after operand %d",
                      oper_num);
                result->opcode = -1;    /* unrecoverable parse error: */
                return result;  /* ignore this instruction */
            }
        }

        if (result->opcode == I_INCBIN) {
            /*
             * Correct syntax for INCBIN is that there should be
             * one string operand, followed by one or two numeric
             * operands.
             */
            if (!result->eops || result->eops->type != EOT_DB_STRING)
                error(ERR_NONFATAL, "`incbin' expects a file name");
            else if (result->eops->next &&
                     result->eops->next->type != EOT_DB_NUMBER)
                error(ERR_NONFATAL, "`incbin': second parameter is",
                      " non-numeric");
            else if (result->eops->next && result->eops->next->next &&
                     result->eops->next->next->type != EOT_DB_NUMBER)
                error(ERR_NONFATAL, "`incbin': third parameter is",
                      " non-numeric");
            else if (result->eops->next && result->eops->next->next &&
                     result->eops->next->next->next)
                error(ERR_NONFATAL,
                      "`incbin': more than three parameters");
            else
                return result;
            /*
             * If we reach here, one of the above errors happened.
             * Throw the instruction away.
             */
            result->opcode = -1;
            return result;
        } else /* DB ... */ if (oper_num == 0)
            error(ERR_WARNING | ERR_PASS1,
                  "no operand for data declaration");
        else
            result->operands = oper_num;

        return result;
    }

    /* right. Now we begin to parse the operands. There may be up to three
     * of these, separated by commas, and terminated by a zero token. */

    for (operand = 0; operand < 3; operand++) {
        expr *value;            /* used most of the time */
        int mref;               /* is this going to be a memory ref? */
        int bracket;            /* is it a [] mref, or a & mref? */
        int setsize = 0;

        result->oprs[operand].addr_size = 0;    /* have to zero this whatever */
        result->oprs[operand].eaflags = 0;      /* and this */
        result->oprs[operand].opflags = 0;

        i = stdscan(NULL, &tokval);
        if (i == 0)
            break;              /* end of operands: get out of here */
        result->oprs[operand].type = 0; /* so far, no override */
        while (i == TOKEN_SPECIAL) {    /* size specifiers */
            switch ((int)tokval.t_integer) {
            case S_BYTE:
                if (!setsize)   /* we want to use only the first */
                    result->oprs[operand].type |= BITS8;
                setsize = 1;
                break;
            case S_WORD:
                if (!setsize)
                    result->oprs[operand].type |= BITS16;
                setsize = 1;
                break;
            case S_DWORD:
            case S_LONG:
                if (!setsize)
                    result->oprs[operand].type |= BITS32;
                setsize = 1;
                break;
            case S_QWORD:
                if (!setsize)
                    result->oprs[operand].type |= BITS64;
                setsize = 1;
                break;
            case S_TWORD:
                if (!setsize)
                    result->oprs[operand].type |= BITS80;
                setsize = 1;
                break;
            case S_TO:
                result->oprs[operand].type |= TO;
                break;
            case S_STRICT:
                result->oprs[operand].type |= STRICT;
                break;
            case S_FAR:
                result->oprs[operand].type |= FAR;
                break;
            case S_NEAR:
                result->oprs[operand].type |= NEAR;
                break;
            case S_SHORT:
                result->oprs[operand].type |= SHORT;
                break;
            default:
                error(ERR_NONFATAL, "invalid operand size specification");
            }
            i = stdscan(NULL, &tokval);
        }

        if (i == '[' || i == '&') {     /* memory reference */
            mref = TRUE;
            bracket = (i == '[');
            i = stdscan(NULL, &tokval);
            if (i == TOKEN_SPECIAL) {   /* check for address size override */
                if (tasm_compatible_mode) {
                    switch ((int)tokval.t_integer) {
                        /* For TASM compatibility a size override inside the
                         * brackets changes the size of the operand, not the
                         * address type of the operand as it does in standard
                         * NASM syntax. Hence:
                         *
                         *  mov     eax,[DWORD val]
                         *
                         * is valid syntax in TASM compatibility mode. Note that
                         * you lose the ability to override the default address
                         * type for the instruction, but we never use anything
                         * but 32-bit flat model addressing in our code.
                         */
                    case S_BYTE:
                        result->oprs[operand].type |= BITS8;
                        break;
                    case S_WORD:
                        result->oprs[operand].type |= BITS16;
                        break;
                    case S_DWORD:
                    case S_LONG:
                        result->oprs[operand].type |= BITS32;
                        break;
                    case S_QWORD:
                        result->oprs[operand].type |= BITS64;
                        break;
                    case S_TWORD:
                        result->oprs[operand].type |= BITS80;
                        break;
                    default:
                        error(ERR_NONFATAL,
                              "invalid operand size specification");
                    }
                } else {
                    /* Standard NASM compatible syntax */
                    switch ((int)tokval.t_integer) {
                    case S_NOSPLIT:
                        result->oprs[operand].eaflags |= EAF_TIMESTWO;
                        break;
                    case S_BYTE:
                        result->oprs[operand].eaflags |= EAF_BYTEOFFS;
                        break;
                    case S_WORD:
                        result->oprs[operand].addr_size = 16;
                        result->oprs[operand].eaflags |= EAF_WORDOFFS;
                        break;
                    case S_DWORD:
                    case S_LONG:
                        result->oprs[operand].addr_size = 32;
                        result->oprs[operand].eaflags |= EAF_WORDOFFS;
                        break;
                    default:
                        error(ERR_NONFATAL, "invalid size specification in"
                              " effective address");
                    }
                }
                i = stdscan(NULL, &tokval);
            }
        } else {                /* immediate operand, or register */
            mref = FALSE;
            bracket = FALSE;    /* placate optimisers */
        }

        if ((result->oprs[operand].type & FAR) && !mref &&
            result->opcode != I_JMP && result->opcode != I_CALL) {
            error(ERR_NONFATAL, "invalid use of FAR operand specifier");
        }

        value = evaluate(stdscan, NULL, &tokval,
                         &result->oprs[operand].opflags,
                         critical, error, &hints);
        i = tokval.t_type;
        if (result->oprs[operand].opflags & OPFLAG_FORWARD) {
            result->forw_ref = TRUE;
        }
        if (!value) {           /* error in evaluator */
            result->opcode = -1;        /* unrecoverable parse error: */
            return result;      /* ignore this instruction */
        }
        if (i == ':' && mref) { /* it was seg:offset */
            /*
             * Process the segment override.
             */
            if (value[1].type != 0 || value->value != 1 ||
                REG_SREG & ~reg_flags[value->type])
                error(ERR_NONFATAL, "invalid segment override");
            else if (result->nprefix == MAXPREFIX)
                error(ERR_NONFATAL,
                      "instruction has more than %d prefixes", MAXPREFIX);
            else
                result->prefixes[result->nprefix++] = value->type;

            i = stdscan(NULL, &tokval); /* then skip the colon */
            if (i == TOKEN_SPECIAL) {   /* another check for size override */
                switch ((int)tokval.t_integer) {
                case S_WORD:
                    result->oprs[operand].addr_size = 16;
                    break;
                case S_DWORD:
                case S_LONG:
                    result->oprs[operand].addr_size = 32;
                    break;
                default:
                    error(ERR_NONFATAL, "invalid size specification in"

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -