nasm.c

来自「开源的nasm编译器源码,研究编译器原理很有帮且」· C语言 代码 · 共 1,683 行 · 第 1/4 页

C
1,683
字号
                        if (l != -1) {                           offs += l;                           SET_CURR_OFFS (offs);                        }                        /*                        * else l == -1 => invalid instruction, which will be                        * flagged as an error on pass 2                        */                     } else { /* pass == 2 */                        offs += assemble (location.segment, offs, sb, cpu,                                       &output_ins, ofmt, report_error, &nasmlist);                        SET_CURR_OFFS (offs);                     }               } /* not an EQU */               cleanup_insn (&output_ins);         }         nasm_free (line);         location.offset = offs = GET_CURR_OFFS;      } /* end while (line = preproc->getline... */      if (pass1==2 && global_offset_changed)         report_error(ERR_NONFATAL, "phase error detected at end of assembly.");      if (pass1 == 1) preproc->cleanup(1);      if (pass1==1 && terminate_after_phase) {         fclose(ofile);         remove(outname);         if (want_usage)               usage();         exit (1);      }      pass_cnt++;      if (pass>1 && !global_offset_changed) {   	 pass0++;   	 if (pass0==2) pass = pass_max - 1;      }	else if (!(optimizing>0)) pass0++;   } /* for (pass=1; pass<=2; pass++) */   preproc->cleanup(0);   nasmlist.cleanup();#if 1   if (optimizing>0 && opt_verbose_info)	/*  -On and -Ov switches */      fprintf(stdout,                "info:: assembly required 1+%d+1 passes\n", pass_cnt-2);#endif} /* exit from assemble_file (...) */static int getkw (char **directive, char **value){    char *p, *q, *buf;        buf = *directive;    /*  allow leading spaces or tabs */    while (*buf==' ' || *buf=='\t')       buf++;    if (*buf!='[')    	return 0;    p = buf;    while (*p && *p != ']') p++;    if (!*p)	return 0;    q = p++;    while (*p && *p != ';') {	if (!isspace(*p))	    return 0;	p++;    }    q[1] = '\0';    *directive = p = buf+1;    while (*buf && *buf!=' ' && *buf!=']' && *buf!='\t')    	buf++;    if (*buf==']') {	*buf = '\0';	*value = buf;    } else {	*buf++ = '\0';        while (isspace(*buf)) buf++;   /* beppu - skip leading whitespace */	*value = buf;	while (*buf!=']') buf++;	*buf++ = '\0';    }#if 0    for (q=p; *q; q++)	*q = tolower(*q);#endif	    if (!nasm_stricmp(p, "segment") || !nasm_stricmp(p, "section"))    	return 1;    if (!nasm_stricmp(p, "extern"))    	return 2;    if (!nasm_stricmp(p, "bits"))    	return 3;    if (!nasm_stricmp(p, "global"))    	return 4;    if (!nasm_stricmp(p, "common"))    	return 5;    if (!nasm_stricmp(p, "absolute"))    	return 6;    if (!nasm_stricmp(p, "debug"))	return 7;    if (!nasm_stricmp(p, "warning"))    	return 8;    if (!nasm_stricmp(p, "cpu"))	return 9;    if (!nasm_stricmp(p, "list"))    /* fbk 9/2/00 */        return 10;    return -1;}/** * gnu style error reporting * This function prints an error message to error_file in the * style used by GNU. An example would be: * file.asm:50: error: blah blah blah * where file.asm is the name of the file, 50 is the line number on  * which the error occurs (or is detected) and "error:" is one of * the possible optional diagnostics -- it can be "error" or "warning" * or something else.  Finally the line terminates with the actual  * error message. *  * @param severity the severity of the warning or error  * @param fmt the printf style format string */static void report_error_gnu (int severity, const char *fmt, ...){    va_list ap;    if (is_suppressed_warning(severity))	return;    if (severity & ERR_NOFILE)	fputs ("nasm: ", error_file);    else {	char * currentfile = NULL;	long lineno = 0;	src_get (&lineno, &currentfile);	fprintf (error_file, "%s:%ld: ", currentfile, lineno);	nasm_free (currentfile);    }    va_start (ap, fmt);    report_error_common (severity, fmt, ap);    va_end (ap);}/** * MS style error reporting * This function prints an error message to error_file in the * style used by Visual C and some other Microsoft tools. An example  * would be: * file.asm(50) : error: blah blah blah * where file.asm is the name of the file, 50 is the line number on  * which the error occurs (or is detected) and "error:" is one of * the possible optional diagnostics -- it can be "error" or "warning" * or something else.  Finally the line terminates with the actual  * error message. *  * @param severity the severity of the warning or error  * @param fmt the printf style format string */static void report_error_vc (int severity, const char *fmt, ...){    va_list ap;    if (is_suppressed_warning (severity))	return;    if (severity & ERR_NOFILE)	fputs ("nasm: ", error_file);    else {	char * currentfile = NULL;	long lineno = 0;	src_get (&lineno, &currentfile);	fprintf (error_file, "%s(%ld) : ", currentfile, lineno);	nasm_free (currentfile);    }    va_start (ap, fmt);    report_error_common (severity, fmt, ap);    va_end (ap);}/** * check for supressed warning * checks for suppressed warning or pass one only warning and we're  * not in pass 1 * * @param severity the severity of the warning or error * @return true if we should abort error/warning printing */static int is_suppressed_warning (int severity){    /*     * See if it's a suppressed warning.     */    return ((severity & ERR_MASK) == ERR_WARNING &&	(severity & ERR_WARN_MASK) != 0 &&	suppressed[ (severity & ERR_WARN_MASK) >> ERR_WARN_SHR ]) ||    /*     * See if it's a pass-one only warning and we're not in pass one.     */	((severity & ERR_PASS1) && pass0 == 2);}/** * common error reporting * This is the common back end of the error reporting schemes currently * implemented.  It prints the nature of the warning and then the  * specific error message to error_file and may or may not return.  It * doesn't return if the error severity is a "panic" or "debug" type. *  * @param severity the severity of the warning or error  * @param fmt the printf style format string */static void report_error_common (int severity, const char *fmt, va_list args){    switch (severity & ERR_MASK) {      case ERR_WARNING:	fputs ("warning: ", error_file); break;      case ERR_NONFATAL:	fputs ("error: ", error_file); break;      case ERR_FATAL:	fputs ("fatal: ", error_file); break;      case ERR_PANIC:	fputs ("panic: ", error_file); break;      case ERR_DEBUG:        fputs("debug: ", error_file); break;    }    vfprintf (error_file, fmt, args);    fputc ('\n', error_file);    if (severity & ERR_USAGE)	want_usage = TRUE;    switch (severity & ERR_MASK) {      case ERR_WARNING: case ERR_DEBUG:	/* no further action, by definition */	break;      case ERR_NONFATAL:	/* hack enables listing(!) on errors */        terminate_after_phase = TRUE;	break;      case ERR_FATAL:	if (ofile) {	    fclose(ofile);	    remove(outname);	}	if (want_usage)	    usage();	exit(1);		       /* instantly die */	break;			       /* placate silly compilers */      case ERR_PANIC:	fflush(NULL);/*	abort();	*/	       /* halt, catch fire, and dump core */	exit(3);	break;    }}static void usage(void){    fputs("type `nasm -h' for help\n", error_file);}static void register_output_formats(void){    ofmt = ofmt_register (report_error);}#define BUF_DELTA 512static FILE *no_pp_fp;static efunc no_pp_err;static ListGen *no_pp_list;static long no_pp_lineinc;static void no_pp_reset (char *file, int pass, efunc error, evalfunc eval,			 ListGen *listgen){    src_set_fname(nasm_strdup(file));    src_set_linnum(0);    no_pp_lineinc = 1;    no_pp_err = error;    no_pp_fp = fopen(file, "r");    if (!no_pp_fp)	no_pp_err (ERR_FATAL | ERR_NOFILE,		   "unable to open input file `%s'", file);    no_pp_list = listgen;    (void) pass;		       /* placate compilers */    (void) eval;		       /* placate compilers */}static char *no_pp_getline (void){    char *buffer, *p, *q;    int bufsize;    bufsize = BUF_DELTA;    buffer = nasm_malloc(BUF_DELTA);    src_set_linnum(src_get_linnum() + no_pp_lineinc);    while (1) {   /* Loop to handle %line */	p = buffer;	while (1) {  /* Loop to handle long lines */	    q = fgets(p, bufsize-(p-buffer), no_pp_fp);	    if (!q)		break;	    p += strlen(p);	    if (p > buffer && p[-1] == '\n')		break;	    if (p-buffer > bufsize-10) {		int offset;		offset = p - buffer;		bufsize += BUF_DELTA;		buffer = nasm_realloc(buffer, bufsize);		p = buffer + offset;	    }	}	if (!q && p == buffer) {	    nasm_free (buffer);	    return NULL;	}	/*	 * Play safe: remove CRs, LFs and any spurious ^Zs, if any of	 * them are present at the end of the line.	 */	buffer[strcspn(buffer, "\r\n\032")] = '\0';	if (!strncmp(buffer, "%line", 5)) {	    long ln;	    int  li;	    char *nm = nasm_malloc(strlen(buffer));	    if (sscanf(buffer+5, "%ld+%d %s", &ln, &li, nm) == 3) {		nasm_free( src_set_fname(nm) );		src_set_linnum(ln);		no_pp_lineinc = li;		continue;	    }	    nasm_free(nm);	}	break;    }    no_pp_list->line (LIST_READ, buffer);    return buffer;}static void no_pp_cleanup (int pass){    fclose(no_pp_fp);}static unsigned long get_cpu (char *value){    if (!strcmp(value, "8086")) return IF_8086;    if (!strcmp(value, "186")) return IF_186;    if (!strcmp(value, "286")) return IF_286;    if (!strcmp(value, "386")) return IF_386;    if (!strcmp(value, "486")) return IF_486;    if (!strcmp(value, "586")    ||    	!nasm_stricmp(value, "pentium") ) 	return IF_PENT;    if (!strcmp(value, "686")  ||    	!nasm_stricmp(value, "ppro") ||    	!nasm_stricmp(value, "pentiumpro") ||    	!nasm_stricmp(value, "p2")    ) 	return IF_P6;    if (!nasm_stricmp(value, "p3")    ||    	!nasm_stricmp(value, "katmai") ) 	return IF_KATMAI;    if (!nasm_stricmp(value, "p4")    ||	/* is this right? -- jrc */    	!nasm_stricmp(value, "willamette") ) 	return IF_WILLAMETTE;    if (!nasm_stricmp(value, "prescott") )      return IF_PRESCOTT;    if (!nasm_stricmp(value, "ia64") ||	!nasm_stricmp(value, "ia-64") ||	!nasm_stricmp(value, "itanium") ||	!nasm_stricmp(value, "itanic") ||	!nasm_stricmp(value, "merced") )	return IF_IA64;    report_error (pass0<2 ? ERR_NONFATAL : ERR_FATAL, "unknown 'cpu' type");    return IF_PLEVEL;	/* the maximum level */}static int get_bits (char *value){    int i;    if ((i = atoi(value)) == 16)  return i;   /* set for a 16-bit segment */    else if (i == 32) {	if (cpu < IF_386) {	    report_error(ERR_NONFATAL,	    	"cannot specify 32-bit segment on processor below a 386");	    i = 16;	}    } else {	report_error(pass0<2 ? ERR_NONFATAL : ERR_FATAL,	   "`%s' is not a valid segment size; must be 16 or 32",	   value);	i = 16;    }    return i;}/* end of nasm.c */

⌨️ 快捷键说明

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