nasm.c
来自「开源的nasm编译器源码,研究编译器原理很有帮且」· C语言 代码 · 共 1,683 行 · 第 1/4 页
C
1,683 行
if (opt == -99) report_error(ERR_FATAL, "command line optimization level must be 'v', 0..3 or <nn>"); } else if (p[1]=='P' || p[1]=='p') { /* pre-include */ pp_pre_include (param); } else if (p[1]=='D' || p[1]=='d') { /* pre-define */ pp_pre_define (param); } else if (p[1]=='U' || p[1]=='u') { /* un-define */ pp_pre_undefine (param); } else if (p[1]=='I' || p[1]=='i') { /* include search path */ pp_include_path (param); } else if (p[1]=='l') { /* listing file */ strcpy (listname, param); } else if (p[1]=='E') { /* error messages file */ error_file = fopen(param, "w"); if ( !error_file ) { error_file = stderr; /* Revert to default! */ report_error (ERR_FATAL | ERR_NOFILE | ERR_USAGE, "cannot open file `%s' for error messages", param); } } else if (p[1] == 'F') { /* specify debug format */ ofmt->current_dfmt = dfmt_find(ofmt, param); if (!ofmt->current_dfmt) { report_error (ERR_FATAL | ERR_NOFILE | ERR_USAGE, "unrecognized debug format `%s' for" " output format `%s'", param, ofmt->shortname); } } else if (p[1] == 'X') { /* specify error reporting format */ if (nasm_stricmp("vc", param) == 0) report_error = report_error_vc; else if (nasm_stricmp("gnu", param) == 0) report_error = report_error_gnu; else report_error (ERR_FATAL | ERR_NOFILE | ERR_USAGE, "unrecognized error reporting format `%s'", param); } break; case 'g': using_debug_info = TRUE; break; case 'h': printf("usage: nasm [-@ response file] [-o outfile] [-f format] " "[-l listfile]\n" " [options...] [--] filename\n" " or nasm -r for version info (obsolete)\n" " or nasm -v for version info (preferred)\n\n" " -t Assemble in SciTech TASM compatible mode\n" " -g Generate debug information in selected format.\n"); printf(" -e preprocess only (writes output to stdout by default)\n" " -a don't preprocess (assemble only)\n" " -M generate Makefile dependencies on stdout\n\n" " -E<file> redirect error messages to file\n" " -s redirect error messages to stdout\n\n" " -F format select a debugging format\n\n" " -I<path> adds a pathname to the include file path\n"); printf(" -O<digit> optimize branch offsets (-O0 disables, default)\n" " -P<file> pre-includes a file\n" " -D<macro>[=<value>] pre-defines a macro\n" " -U<macro> undefines a macro\n" " -X<format> specifies error reporting format (gnu or vc)\n" " -w+foo enables warnings about foo; -w-foo disables them\n" "where foo can be:\n"); for (i=1; i<=ERR_WARN_MAX; i++) printf(" %-23s %s (default %s)\n", suppressed_names[i], suppressed_what[i], suppressed[i] ? "off" : "on"); printf ("\nresponse files should contain command line parameters" ", one per line.\n"); if (p[2] == 'f') { printf("\nvalid output formats for -f are" " (`*' denotes default):\n"); ofmt_list(ofmt, stdout); } else { printf ("\nFor a list of valid output formats, use -hf.\n"); printf ("For a list of debug formats, use -f <form> -y.\n"); } exit (0); /* never need usage message here */ break; case 'y': printf("\nvalid debug formats for '%s' output format are" " ('*' denotes default):\n", ofmt->shortname); dfmt_list(ofmt, stdout); exit(0); break; case 't': tasm_compatible_mode = TRUE; break; case 'r': case 'v': { const char *nasm_version_string = "NASM version " NASM_VER " compiled on " __DATE__#ifdef DEBUG " with -DDEBUG"#endif ; puts(nasm_version_string); exit (0); /* never need usage message here */ } break; case 'e': /* preprocess only */ operating_mode = op_preprocess; break; case 'a': /* assemble only - don't preprocess */ preproc = &no_pp; break; case 'w': if (p[2] != '+' && p[2] != '-') { report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE, "invalid option to `-w'"); } else { for (i=1; i<=ERR_WARN_MAX; i++) if (!nasm_stricmp(p+3, suppressed_names[i])) break; if (i <= ERR_WARN_MAX) 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; case '-': { int s; if (p[2]==0) { /* -- => stop processing options */ stopoptions = 1; break; } for(s=0; textopts[s].label; s++) { if(!nasm_stricmp(p+2, textopts[s].label)) { break; } } switch(s) { case OPT_PREFIX: case OPT_POSTFIX: { if (!q) { report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE, "option `--%s' requires an argument", p+2); break; } else { advance = 1, param = q; } if(s == OPT_PREFIX) { strncpy(lprefix,param,PREFIX_MAX-1); lprefix[PREFIX_MAX-1]=0; break; } if(s == OPT_POSTFIX) { strncpy(lpostfix,param,POSTFIX_MAX-1); lpostfix[POSTFIX_MAX-1]=0; break; } break; } default: { report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE, "unrecognised option `--%s'", p+2); break; } } 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 128static 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); }}/* Function to process args from a string of args, rather than the * argv array. Used by the environment variable and response file * processing. */static void process_args (char *args) { char *p, *q, *arg, *prevarg; char separator = ' '; p = args; if (*p && *p != '-') separator = *p++; arg = NULL; 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);}static void parse_cmdline(int argc, char **argv){ FILE *rfile; char *envreal, *envcopy=NULL, *p, *arg; *inname = *outname = *listname = '\0'; /* * First, process the NASMENV environment variable. */ envreal = getenv("NASMENV"); arg = NULL; if (envreal) { envcopy = nasm_strdup(envreal); process_args(envcopy); nasm_free (envcopy); } /* * Now process the actual command line. */ while (--argc) { int i; argv++; if (argv[0][0] == '@') { /* We have a response file, so process this as a set of * arguments like the environment variable. This allows us * to have multiple arguments on a single line, which is * different to the -@resp file processing below for regular * NASM. */ char *str = malloc(2048); FILE *f = fopen(&argv[0][1],"r"); if (!str) { printf("out of memory"); exit(-1); } if (f) { while (fgets(str,2048,f)) { process_args(str); } fclose(f); } free(str); argc--; 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 * directive, * value, * p, * q, * special, * line, debugid[80]; insn output_ins; int i, rn_error, validid; long seg, offs; struct tokenval tokval; expr * e; int pass, pass_max; int pass_cnt = 0; /* count actual passes */ if (cmd_sb == 32 && cmd_cpu < IF_386) report_error(ERR_FATAL, "command line: " "32-bit segment size requires a higher cpu"); pass_max = (optimizing>0 ? optimizing : 0) + 2; /* passes 1, optimizing, then 2 */ pass0 = !(optimizing>0); /* start at 1 if not optimizing */ for (pass = 1; pass <= pass_max && pass0 <= 2; pass++) { int pass1, pass2; ldfunc def_label; pass1 = pass < pass_max ? 1 : 2; /* seq is 1, 1, 1,..., 1, 2 */ pass2 = pass > 1 ? 2 : 1; /* seq is 1, 2, 2,..., 2, 2 */ /* pass0 seq is 0, 0, 0,..., 1, 2 */ def_label = pass > 1 ? redefine_label : define_label; sb = cmd_sb; /* set 'bits' to command line default */ cpu = cmd_cpu; if (pass0 == 2) { if (*listname) nasmlist.init(listname, report_error); } in_abs_seg = FALSE; global_offset_changed = FALSE; /* set by redefine_label */ location.segment = ofmt->section(NULL, pass2, &sb); if (pass > 1) { saa_rewind (forwrefs); forwref = saa_rstruct (forwrefs); raa_free (offsets); offsets = raa_init(); } preproc->reset(fname, pass1, report_error, evaluate, &nasmlist); globallineno = 0; if (pass == 1) location.known = TRUE; location.offset = offs = GET_CURR_OFFS; while ( (line = preproc->getline()) ) { globallineno++; /* here we parse our directives; this is not handled by the 'real' * parser. */ directive = line; if ( (i = getkw (&directive, &value)) ) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?