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

📄 nasm.c

📁 一个汇编语言编译器源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		    suppressed[i] = (p[2] == '-');
		else
		    report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
				  "invalid option to `-w'");
	    }
	    break;
          case 'M':
	    operating_mode = op_depend;
	    break; 
	  default:
	    if (!ofmt->setinfo(GI_SWITCH,&p))
	    	report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
			  "unrecognised option `-%c'",
			  p[1]);
	    break;
	}
    } 
    else 
    {
	if (*inname) {
	    report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
			  "more than one input file specified");
	} else
	    strcpy(inname, p);
    }

    return advance;
}

#define ARG_BUF_DELTA 128

static void process_respfile (FILE *rfile)
{
    char *buffer, *p, *q, *prevarg;
    int bufsize, prevargsize;

    bufsize = prevargsize = ARG_BUF_DELTA;
    buffer = nasm_malloc(ARG_BUF_DELTA);
    prevarg = nasm_malloc(ARG_BUF_DELTA);
    prevarg[0] = '\0';

    while (1) {   /* Loop to handle all lines in file */

	p = buffer;
	while (1) {  /* Loop to handle long lines */
	    q = fgets(p, bufsize-(p-buffer), rfile);
	    if (!q)
		break;
	    p += strlen(p);
	    if (p > buffer && p[-1] == '\n')
		break;
	    if (p-buffer > bufsize-10) {
		int offset;
		offset = p - buffer;
		bufsize += ARG_BUF_DELTA;
		buffer = nasm_realloc(buffer, bufsize);
		p = buffer + offset;
	    }
	}

	if (!q && p == buffer) {
	    if (prevarg[0])
		process_arg (prevarg, NULL);
	    nasm_free (buffer);
	    nasm_free (prevarg);
	    return;
	}

	/*
	 * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
	 * them are present at the end of the line.
	 */
	*(p = &buffer[strcspn(buffer, "\r\n\032")]) = '\0';

	while (p > buffer && isspace(p[-1]))
	    *--p = '\0';

	p = buffer;
	while (isspace(*p))
	    p++;

	if (process_arg (prevarg, p))
	    *p = '\0';

	if (strlen(p) > prevargsize-10) {
	    prevargsize += ARG_BUF_DELTA;
	    prevarg = nasm_realloc(prevarg, prevargsize);
	}
	strcpy (prevarg, p);
    }
}

static void parse_cmdline(int argc, char **argv)
{
    FILE *rfile;
    char *envreal, *envcopy=NULL, *p, *q, *arg, *prevarg;
    char separator = ' ';

    *inname = *outname = *listname = '\0';

    /*
     * First, process the NASM environment variable.
     */
    envreal = getenv("NASM");
    arg = NULL;
    if (envreal) {
	envcopy = nasm_strdup(envreal);
	p = envcopy;
	if (*p && *p != '-')
	    separator = *p++;
	while (*p) {
	    q = p;
	    while (*p && *p != separator) p++;
	    while (*p == separator) *p++ = '\0';
	    prevarg = arg;
	    arg = q;
	    if (process_arg (prevarg, arg))
		arg = NULL;
	}
	if (arg)
	    process_arg (arg, NULL);
	nasm_free (envcopy);
    }

    /*
     * Now process the actual command line.
     */
    while (--argc)
    {
	int i;
	argv++;
	if (!stopoptions && argv[0][0] == '-' && argv[0][1] == '@') {
	    if ((p = get_param (argv[0], argc > 1 ? argv[1] : NULL, &i)))
		if ((rfile = fopen(p, "r"))) {
		    process_respfile (rfile);
		    fclose(rfile);
		} else
		    report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
			    "unable to open response file `%s'", p);
	} else
	    i = process_arg (argv[0], argc > 1 ? argv[1] : NULL);
	argv += i, argc -= i;
    }

    if (!*inname)
	report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
		      "no input file specified");
}

static void assemble_file (char *fname)
{
    char   * value, * p, * q, * special, * line, debugid[80];
    insn   output_ins;
    int    i, rn_error, validid;
    long   seg, offs;
    struct tokenval tokval;
    expr   * e;

    /*
     * pass one 
     */
    pass = 1;
    in_abs_seg = FALSE;
    location.segment = ofmt->section(NULL, pass, &sb);
    preproc->reset(fname, 1, report_error, evaluate, &nasmlist);
    globallineno = 0;
    location.known = TRUE;
    location.offset = offs = get_curr_ofs;

    while ( (line = preproc->getline()) ) 
    {
	globallineno++;

	/* here we parse our directives; this is not handled by the 'real'
	 * parser. */
	if ( (i = getkw (line, &value)) ) 
	{
	    switch (i) {
	      case 1:	       /* [SEGMENT n] */
		seg = ofmt->section (value, pass, &sb);
		if (seg == NO_SEG) {
		    report_error (ERR_NONFATAL,
				  "segment name `%s' not recognised",
				  value);
		} else {
		    in_abs_seg = FALSE;
		    location.segment = seg;
		}
		break;
	      case 2:	       /* [EXTERN label:special] */
		if (*value == '$')
		    value++;	       /* skip initial $ if present */
		q = value;
		validid = TRUE;
		if (!isidstart(*q))
		    validid = FALSE;
		while (*q && *q != ':') {
		    if (!isidchar(*q))
			validid = FALSE;
		    q++;
		}
		if (!validid) {
		    report_error (ERR_NONFATAL,
				  "identifier expected after EXTERN");
		    break;
		}
		if (*q == ':') {
		    *q++ = '\0';
		    special = q;
		} else
		    special = NULL;
		if (!is_extern(value)) {   /* allow re-EXTERN to be ignored */
		    declare_as_global (value, special, report_error);
		    define_label (value, seg_alloc(), 0L, NULL, FALSE, TRUE,
				  ofmt, report_error);
		}
		break;
	      case 3:	       /* [BITS bits] */
		switch (atoi(value)) {
		  case 16:
		  case 32:
		    sb = atoi(value);
		    break;
		  default:
		    report_error(ERR_NONFATAL,
				 "`%s' is not a valid argument to [BITS]",
				 value);
		    break;
		}
		break;
	      case 4:	       /* [GLOBAL symbol:special] */
		if (*value == '$')
		    value++;	       /* skip initial $ if present */
		q = value;
		validid = TRUE;
		if (!isidstart(*q))
		    validid = FALSE;
		while (*q && *q != ':') {
		    if (!isidchar(*q))
			validid = FALSE;
		    q++;
		}
		if (!validid) {
		    report_error (ERR_NONFATAL,
				  "identifier expected after GLOBAL");
		    break;
		}
		if (*q == ':') {
		    *q++ = '\0';
		    special = q;
		} else
		    special = NULL;
		declare_as_global (value, special, report_error);
		break;
	      case 5:	       /* [COMMON symbol size:special] */
		p = value;
		validid = TRUE;
		if (!isidstart(*p))
		    validid = FALSE;
		while (*p && !isspace(*p)) {
		    if (!isidchar(*p))
			validid = FALSE;
		    p++;
		}
		if (!validid) {
		    report_error (ERR_NONFATAL,
				  "identifier expected after COMMON");
		    break;
		}
		if (*p) {
		    long size;

		    while (*p && isspace(*p))
			*p++ = '\0';
		    q = p;
		    while (*q && *q != ':')
			q++;
		    if (*q == ':') {
			*q++ = '\0';
			special = q;
		    } else
			special = NULL;
		    size = readnum (p, &rn_error);
		    if (rn_error)
			report_error (ERR_NONFATAL, "invalid size specified"
				      " in COMMON declaration");
		    else
			define_common (value, seg_alloc(), size,
				       special, ofmt, report_error);
		} else
		    report_error (ERR_NONFATAL, "no size specified in"
				  " COMMON declaration");
		break;
	      case 6:		       /* [ABSOLUTE address] */
		stdscan_reset();
		stdscan_bufptr = value;
		tokval.t_type = TOKEN_INVALID;
		e = evaluate(stdscan, NULL, &tokval, NULL, 1, report_error,
			     NULL);
		if (e) {
		    if (!is_reloc(e))
			report_error (ERR_NONFATAL, "cannot use non-"
				      "relocatable expression as ABSOLUTE"
				      " address");
		    else {
			abs_seg = reloc_seg(e);
			abs_offset = reloc_value(e);
		    }
		} else
		    abs_offset = 0x100;/* don't go near zero in case of / */
		in_abs_seg = TRUE;
		location.segment = abs_seg;
		break;
	      case 7:
		p = value;
		validid = TRUE;
		if (!isidstart(*p))
		    validid = FALSE;
		while (*p && !isspace(*p)) {
		    if (!isidchar(*p))
			validid = FALSE;
                    p++;
		}
		if (!validid) {
		    report_error (ERR_NONFATAL,
				  "identifier expected after DEBUG");
		    break;
		}
                while (*p && isspace(*p)) p++;
		break;
	      default:
		if (!ofmt->directive (line+1, value, 1))
		    report_error (ERR_NONFATAL, "unrecognised directive [%s]",
				  line+1);
		break;
	    }
	}
	else 	/* it isn't a directive */
	{
	    parse_line (1, line, &output_ins,
			report_error, evaluate, define_label);

	    if (output_ins.forw_ref) 
	    {
		for(i = 0; i < output_ins.operands; i++) 
		{
		    if (output_ins.oprs[i].opflags & OPFLAG_FORWARD) 
		    {
		    	struct forwrefinfo *fwinf =
		    	    (struct forwrefinfo *)saa_wstruct(forwrefs);
			fwinf->lineno = globallineno;
			fwinf->operand = i;
		    }
		}
	    }

	    if (output_ins.opcode == I_EQU) 
	    {
		/*
		 * Special `..' EQUs get processed in pass two,
		 * except `..@' macro-processor EQUs which are done
		 * in the normal place.
		 */
		if (!output_ins.label)
		    report_error (ERR_NONFATAL,
				  "EQU not preceded by label");

		else if (output_ins.label[0] != '.' ||
			 output_ins.label[1] != '.' ||
			 output_ins.label[2] == '@') 
		{
		    if (output_ins.operands == 1 &&
			(output_ins.oprs[0].type & IMMEDIATE) &&
			output_ins.oprs[0].wrt == NO_SEG) 
		    {
		      int isext = output_ins.oprs[0].opflags & OPFLAG_EXTERN;
		      define_label (output_ins.label,
				    output_ins.oprs[0].segment,
				    output_ins.oprs[0].offset,
				    NULL, FALSE, isext, ofmt, report_error);
		    } 
		    else if (output_ins.operands == 2 &&
			       (output_ins.oprs[0].type & IMMEDIATE) &&
			       (output_ins.oprs[0].type & COLON) &&
			       output_ins.oprs[0].segment == NO_SEG &&
			       output_ins.oprs[0].wrt == NO_SEG &&
			       (output_ins.oprs[1].type & IMMEDIATE) &&
			       output_ins.oprs[1].segment == NO_SEG &&
			       output_ins.oprs[1].wrt == NO_SEG) 
		    {
			define_label (output_ins.label,
				      output_ins.oprs[0].offset | SEG_ABS,
				      output_ins.oprs[1].offset,
				      NULL, FALSE, FALSE, ofmt, report_error);
		    } 
		    else
			report_error(ERR_NONFATAL, "bad syntax for EQU");
		}
	    } 
	    else  /* instruction isn't an EQU */
	    {
		long l = insn_size (location.segment, offs, sb,
				   &output_ins, report_error);
		if (using_debug_info && output_ins.opcode != -1) {
		    /* this is done here so we can do debug type info */
                    long typeinfo = TYS_ELEMENTS(output_ins.operands);
		    switch (output_ins.opcode) {
		    	case I_RESB:
        		    typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_BYTE;  
			    break;
		    	case I_RESW:
        		    typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_WORD;  
			    break;
		    	case I_RESD:
        		    typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_DWORD;  
			    break;
		    	case I_RESQ:
        		    typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_QWORD;  
			    break;
		    	case I_REST:
        		    typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_TBYTE;  
			    break;
	    	    	case I_DB:
		    	    typeinfo |= TY_BYTE;
		    	    break;
	            	case I_DW:
		    	    typeinfo |= TY_WORD;
		    	    break;
	            	case I_DD:
		    	    if (output_ins.eops_float)
		    	    	typeinfo |= TY_FLOAT;
                    	    else
		    	    	typeinfo |= TY_DWORD;
		    	    break;
	    	        case I_DQ:
		    	    typeinfo |= TY_QWORD;
		    	    break;
	    	    	case I_DT:
		    	    typeinfo |= TY_TBYTE;
		    	    break;
	    	    	default:
		    	    typeinfo = TY_LABEL;
		    }
		    ofmt->current_dfmt->debug_typevalue(typeinfo);
		}
		if (l != -1) {
		    offs += l;
		    set_curr_ofs (offs);
		}

⌨️ 快捷键说明

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