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

📄 parser.c

📁 汇编编译器的最新版本的源码.买了自己动手写操作系统这本书的人一定要下
💻 C
📖 第 1 页 / 共 3 页
字号:
        critical = (pass0 < 2 ? 1 : 2);

    } else
        critical = (pass == 2 ? 2 : 0);

    if (result->opcode == I_DB || result->opcode == I_DW ||
        result->opcode == I_DD || result->opcode == I_DQ ||
        result->opcode == I_DT || result->opcode == I_DO ||
	result->opcode == I_DY || result->opcode == I_INCBIN) {
        extop *eop, **tail = &result->eops, **fixptr;
        int oper_num = 0;
	int32_t sign;

        result->eops_float = false;

        /*
         * Begin to read the DB/DW/DD/DQ/DT/DO/INCBIN operands.
         */
        while (1) {
            i = stdscan(NULL, &tokval);
            if (i == 0)
                break;
	    else if (first && i == ':') {
		insn_is_label = true;
		goto restart_parse;
	    }
	    first = false;
            fixptr = tail;
            eop = *tail = nasm_malloc(sizeof(extop));
            tail = &eop->next;
            eop->next = NULL;
            eop->type = EOT_NOTHING;
            oper_num++;
	    sign = +1;

	    /* is_comma_next() here is to distinguish this from
	       a string used as part of an expression... */
            if (i == TOKEN_STR && is_comma_next()) {
                eop->type = EOT_DB_STRING;
                eop->stringval = tokval.t_charptr;
                eop->stringlen = tokval.t_inttwo;
                i = stdscan(NULL, &tokval);     /* eat the comma */
	    } else if (i == TOKEN_STRFUNC) {
		bool parens = false;
		const char *funcname = tokval.t_charptr;
		enum strfunc func = tokval.t_integer;
		i = stdscan(NULL, &tokval);
		if (i == '(') {
		    parens = true;
		    i = stdscan(NULL, &tokval);
		}
		if (i != TOKEN_STR) {
		    error(ERR_NONFATAL,
			  "%s must be followed by a string constant",
			  funcname);
			eop->type = EOT_NOTHING;
		} else {
		    eop->type = EOT_DB_STRING_FREE;
		    eop->stringlen =
			string_transform(tokval.t_charptr, tokval.t_inttwo,
					 &eop->stringval, func);
		    if (eop->stringlen == (size_t)-1) {
			error(ERR_NONFATAL, "invalid string for transform");
			eop->type = EOT_NOTHING;
		    }
		}
		if (parens && i && i != ')') {
		    i = stdscan(NULL, &tokval);
		    if (i != ')') {
			error(ERR_NONFATAL, "unterminated %s function",
			      funcname);
		    }
		}
		if (i && i != ',')
		    i = stdscan(NULL, &tokval);
	    } else if (i == '-' || i == '+') {
		char *save = stdscan_bufptr;
		int token = i;
		sign = (i == '-') ? -1 : 1;
		i = stdscan(NULL, &tokval);
		if (i != TOKEN_FLOAT) {
		    stdscan_bufptr = save;
		    i = tokval.t_type = token;
		    goto is_expression;
		} else {
		    goto is_float;
		}
            } else if (i == TOKEN_FLOAT) {
	    is_float:
		eop->type = EOT_DB_STRING;
		result->eops_float = true;
		switch (result->opcode) {
		case I_DB:
		    eop->stringlen = 1;
		    break;
		case I_DW:
		    eop->stringlen = 2;
		    break;
		case I_DD:
		    eop->stringlen = 4;
		    break;
		case I_DQ:
		    eop->stringlen = 8;
		    break;
		case I_DT:
		    eop->stringlen = 10;
		    break;
		case I_DO:
		    eop->stringlen = 16;
		    break;
		case I_DY:
		    error(ERR_NONFATAL, "floating-point constant"
			  " encountered in DY instruction");
		    eop->stringlen = 0;
		    break;
		default:
		    error(ERR_NONFATAL, "floating-point constant"
			  " encountered in unknown instruction");
		    /*
		     * fix suggested by Pedro Gimeno... original line
		     * was:
		     * eop->type = EOT_NOTHING;
		     */
		    eop->stringlen = 0;
		    break;
		}
		eop = nasm_realloc(eop, sizeof(extop) + eop->stringlen);
		tail = &eop->next;
		*fixptr = eop;
		eop->stringval = (char *)eop + sizeof(extop);
		if (!eop->stringlen ||
		    !float_const(tokval.t_charptr, sign,
				 (uint8_t *)eop->stringval,
				 eop->stringlen, error))
		    eop->type = EOT_NOTHING;
		i = stdscan(NULL, &tokval); /* eat the comma */
	    } else {
		/* anything else, assume it is an expression */
                expr *value;

	    is_expression:
                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 four
     * of these, separated by commas, and terminated by a zero token. */

    for (operand = 0; operand < MAX_OPERANDS; 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].disp_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 */
	else if (first && i == ':') {
	    insn_is_label = true;
	    goto restart_parse;
	}
	first = false;
        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_OWORD:
                if (!setsize)
                    result->oprs[operand].type |= BITS128;
                setsize = 1;
                break;
            case S_YWORD:
                if (!setsize)
                    result->oprs[operand].type |= BITS256;
                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); /* then skip the colon */
            while (i == TOKEN_SPECIAL || i == TOKEN_PREFIX) {
		process_size_override(result, operand);
                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,

⌨️ 快捷键说明

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