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 + -
显示快捷键?