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, ¤tfile); 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, ¤tfile); 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 + -
显示快捷键?