Set __PASS__ to 3 for preprocess only
[nasm/avx512.git] / nasm.c
bloba92db929e4d8b9dfcecd6e220caa88df4aad63a5
1 /* The Netwide Assembler main program module
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the license given in the file "LICENSE"
6 * distributed in the NASM archive.
7 */
9 #include "compiler.h"
11 #include <stdio.h>
12 #include <stdarg.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <inttypes.h>
17 #include <limits.h>
18 #include <time.h>
20 #include "nasm.h"
21 #include "nasmlib.h"
22 #include "saa.h"
23 #include "raa.h"
24 #include "float.h"
25 #include "stdscan.h"
26 #include "insns.h"
27 #include "preproc.h"
28 #include "parser.h"
29 #include "eval.h"
30 #include "assemble.h"
31 #include "labels.h"
32 #include "outform.h"
33 #include "listing.h"
35 struct forwrefinfo { /* info held on forward refs. */
36 int lineno;
37 int operand;
40 static int get_bits(char *value);
41 static uint32_t get_cpu(char *cpu_str);
42 static void parse_cmdline(int, char **);
43 static void assemble_file(char *, StrList **);
44 static void register_output_formats(void);
45 static void report_error_gnu(int severity, const char *fmt, ...);
46 static void report_error_vc(int severity, const char *fmt, ...);
47 static void report_error_common(int severity, const char *fmt,
48 va_list args);
49 static bool is_suppressed_warning(int severity);
50 static void usage(void);
51 static efunc report_error;
53 static int using_debug_info, opt_verbose_info;
54 bool tasm_compatible_mode = false;
55 int pass0, passn;
56 int maxbits = 0;
57 int globalrel = 0;
59 time_t official_compile_time;
61 static char inname[FILENAME_MAX];
62 static char outname[FILENAME_MAX];
63 static char listname[FILENAME_MAX];
64 static char errname[FILENAME_MAX];
65 static int globallineno; /* for forward-reference tracking */
66 /* static int pass = 0; */
67 static struct ofmt *ofmt = NULL;
69 static FILE *error_file; /* Where to write error messages */
71 static FILE *ofile = NULL;
72 int optimizing = -1; /* number of optimization passes to take */
73 static int sb, cmd_sb = 16; /* by default */
74 static uint32_t cmd_cpu = IF_PLEVEL; /* highest level by default */
75 static uint32_t cpu = IF_PLEVEL; /* passed to insn_size & assemble.c */
76 int64_t global_offset_changed; /* referenced in labels.c */
77 int64_t prev_offset_changed;
78 int32_t stall_count;
80 static struct location location;
81 int in_abs_seg; /* Flag we are in ABSOLUTE seg */
82 int32_t abs_seg; /* ABSOLUTE segment basis */
83 int32_t abs_offset; /* ABSOLUTE offset */
85 static struct RAA *offsets;
87 static struct SAA *forwrefs; /* keep track of forward references */
88 static const struct forwrefinfo *forwref;
90 static Preproc *preproc;
91 enum op_type {
92 op_normal, /* Preprocess and assemble */
93 op_preprocess, /* Preprocess only */
94 op_depend, /* Generate dependencies */
96 static enum op_type operating_mode;
97 /* Dependency flags */
98 static bool depend_emit_phony = false;
99 static bool depend_missing_ok = false;
100 static const char *depend_target = NULL;
101 static const char *depend_file = NULL;
104 * Which of the suppressible warnings are suppressed. Entry zero
105 * isn't an actual warning, but it used for -w+error/-Werror.
107 static bool suppressed[ERR_WARN_MAX+1];
109 static bool suppressed_global[ERR_WARN_MAX+1] = {
110 true, false, true, false, false, false, true, false, true, true, false
113 * The option names for the suppressible warnings. As before, entry
114 * zero does nothing.
116 static const char *suppressed_names[ERR_WARN_MAX+1] = {
117 "error", "macro-params", "macro-selfref", "macro-defaults",
118 "orphan-labels", "number-overflow", "gnu-elf-extensions",
119 "float-overflow", "float-denorm", "float-underflow", "float-toolong"
123 * The explanations for the suppressible warnings. As before, entry
124 * zero does nothing.
126 static const char *suppressed_what[ERR_WARN_MAX+1] = {
127 "treat warnings as errors",
128 "macro calls with wrong parameter count",
129 "cyclic macro references",
130 "macros with more default than optional parameters",
131 "labels alone on lines without trailing `:'",
132 "numeric constants does not fit in 64 bits",
133 "using 8- or 16-bit relocation in ELF32, a GNU extension",
134 "floating point overflow",
135 "floating point denormal",
136 "floating point underflow",
137 "too many digits in floating-point number"
141 * This is a null preprocessor which just copies lines from input
142 * to output. It's used when someone explicitly requests that NASM
143 * not preprocess their source file.
146 static void no_pp_reset(char *, int, efunc, evalfunc, ListGen *, StrList **);
147 static char *no_pp_getline(void);
148 static void no_pp_cleanup(int);
149 static Preproc no_pp = {
150 no_pp_reset,
151 no_pp_getline,
152 no_pp_cleanup
156 * get/set current offset...
158 #define GET_CURR_OFFS (in_abs_seg?abs_offset:\
159 raa_read(offsets,location.segment))
160 #define SET_CURR_OFFS(x) (in_abs_seg?(void)(abs_offset=(x)):\
161 (void)(offsets=raa_write(offsets,location.segment,(x))))
163 static int want_usage;
164 static int terminate_after_phase;
165 int user_nolist = 0; /* fbk 9/2/00 */
167 static void nasm_fputs(const char *line, FILE * outfile)
169 if (outfile) {
170 fputs(line, outfile);
171 putc('\n', outfile);
172 } else
173 puts(line);
176 /* Convert a struct tm to a POSIX-style time constant */
177 static int64_t posix_mktime(struct tm *tm)
179 int64_t t;
180 int64_t y = tm->tm_year;
182 /* See IEEE 1003.1:2004, section 4.14 */
184 t = (y-70)*365 + (y-69)/4 - (y-1)/100 + (y+299)/400;
185 t += tm->tm_yday;
186 t *= 24;
187 t += tm->tm_hour;
188 t *= 60;
189 t += tm->tm_min;
190 t *= 60;
191 t += tm->tm_sec;
193 return t;
196 static void define_macros_early(void)
198 char temp[128];
199 struct tm lt, *lt_p, gm, *gm_p;
200 int64_t posix_time;
202 lt_p = localtime(&official_compile_time);
203 if (lt_p) {
204 lt = *lt_p;
206 strftime(temp, sizeof temp, "__DATE__=\"%Y-%m-%d\"", &lt);
207 pp_pre_define(temp);
208 strftime(temp, sizeof temp, "__DATE_NUM__=%Y%m%d", &lt);
209 pp_pre_define(temp);
210 strftime(temp, sizeof temp, "__TIME__=\"%H:%M:%S\"", &lt);
211 pp_pre_define(temp);
212 strftime(temp, sizeof temp, "__TIME_NUM__=%H%M%S", &lt);
213 pp_pre_define(temp);
216 gm_p = gmtime(&official_compile_time);
217 if (gm_p) {
218 gm = *gm_p;
220 strftime(temp, sizeof temp, "__UTC_DATE__=\"%Y-%m-%d\"", &gm);
221 pp_pre_define(temp);
222 strftime(temp, sizeof temp, "__UTC_DATE_NUM__=%Y%m%d", &gm);
223 pp_pre_define(temp);
224 strftime(temp, sizeof temp, "__UTC_TIME__=\"%H:%M:%S\"", &gm);
225 pp_pre_define(temp);
226 strftime(temp, sizeof temp, "__UTC_TIME_NUM__=%H%M%S", &gm);
227 pp_pre_define(temp);
230 if (gm_p)
231 posix_time = posix_mktime(&gm);
232 else if (lt_p)
233 posix_time = posix_mktime(&lt);
234 else
235 posix_time = 0;
237 if (posix_time) {
238 snprintf(temp, sizeof temp, "__POSIX_TIME__=%"PRId64, posix_time);
239 pp_pre_define(temp);
243 static void define_macros_late(void)
245 char temp[128];
247 snprintf(temp, sizeof(temp), "__OUTPUT_FORMAT__=%s\n",
248 ofmt->shortname);
249 pp_pre_define(temp);
252 static void emit_dependencies(StrList *list)
254 FILE *deps;
255 int linepos, len;
256 StrList *l, *nl;
258 if (depend_file && strcmp(depend_file, "-")) {
259 deps = fopen(depend_file, "w");
260 if (!deps) {
261 report_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
262 "unable to write dependency file `%s'", depend_file);
263 return;
265 } else {
266 deps = stdout;
269 linepos = fprintf(deps, "%s:", depend_target);
270 for (l = list; l; l = l->next) {
271 len = strlen(l->str);
272 if (linepos + len > 62) {
273 fprintf(deps, " \\\n ");
274 linepos = 1;
276 fprintf(deps, " %s", l->str);
277 linepos += len+1;
279 fprintf(deps, "\n\n");
281 for (l = list; l; l = nl) {
282 if (depend_emit_phony)
283 fprintf(deps, "%s:\n\n", l->str);
285 nl = l->next;
286 nasm_free(l);
289 if (deps != stdout)
290 fclose(deps);
293 int main(int argc, char **argv)
295 StrList *depend_list = NULL, **depend_ptr;
297 time(&official_compile_time);
299 pass0 = 0;
300 want_usage = terminate_after_phase = false;
301 report_error = report_error_gnu;
303 error_file = stderr;
305 tolower_init();
307 nasm_set_malloc_error(report_error);
308 offsets = raa_init();
309 forwrefs = saa_init((int32_t)sizeof(struct forwrefinfo));
311 preproc = &nasmpp;
312 operating_mode = op_normal;
314 seg_init();
316 register_output_formats();
318 /* Define some macros dependent on the runtime, but not
319 on the command line. */
320 define_macros_early();
322 parse_cmdline(argc, argv);
324 if (terminate_after_phase) {
325 if (want_usage)
326 usage();
327 return 1;
330 /* If debugging info is disabled, suppress any debug calls */
331 if (!using_debug_info)
332 ofmt->current_dfmt = &null_debug_form;
334 if (ofmt->stdmac)
335 pp_extra_stdmac(ofmt->stdmac);
336 parser_global_info(ofmt, &location);
337 eval_global_info(ofmt, lookup_label, &location);
339 /* define some macros dependent of command-line */
340 define_macros_late();
342 depend_ptr = (depend_file || (operating_mode == op_depend))
343 ? &depend_list : NULL;
344 if (!depend_target)
345 depend_target = outname;
347 switch (operating_mode) {
348 case op_depend:
350 char *line;
352 if (depend_missing_ok)
353 pp_include_path(NULL); /* "assume generated" */
355 preproc->reset(inname, 0, report_error, evaluate, &nasmlist,
356 depend_ptr);
357 if (outname[0] == '\0')
358 ofmt->filename(inname, outname, report_error);
359 ofile = NULL;
360 while ((line = preproc->getline()))
361 nasm_free(line);
362 preproc->cleanup(0);
364 break;
366 case op_preprocess:
368 char *line;
369 char *file_name = NULL;
370 int32_t prior_linnum = 0;
371 int lineinc = 0;
373 if (*outname) {
374 ofile = fopen(outname, "w");
375 if (!ofile)
376 report_error(ERR_FATAL | ERR_NOFILE,
377 "unable to open output file `%s'",
378 outname);
379 } else
380 ofile = NULL;
382 location.known = false;
384 /* pass = 1; */
385 preproc->reset(inname, 3, report_error, evaluate, &nasmlist,
386 depend_ptr);
388 while ((line = preproc->getline())) {
390 * We generate %line directives if needed for later programs
392 int32_t linnum = prior_linnum += lineinc;
393 int altline = src_get(&linnum, &file_name);
394 if (altline) {
395 if (altline == 1 && lineinc == 1)
396 nasm_fputs("", ofile);
397 else {
398 lineinc = (altline != -1 || lineinc != 1);
399 fprintf(ofile ? ofile : stdout,
400 "%%line %"PRId32"+%d %s\n", linnum, lineinc,
401 file_name);
403 prior_linnum = linnum;
405 nasm_fputs(line, ofile);
406 nasm_free(line);
408 nasm_free(file_name);
409 preproc->cleanup(0);
410 if (ofile)
411 fclose(ofile);
412 if (ofile && terminate_after_phase)
413 remove(outname);
415 break;
417 case op_normal:
420 * We must call ofmt->filename _anyway_, even if the user
421 * has specified their own output file, because some
422 * formats (eg OBJ and COFF) use ofmt->filename to find out
423 * the name of the input file and then put that inside the
424 * file.
426 ofmt->filename(inname, outname, report_error);
428 ofile = fopen(outname, "wb");
429 if (!ofile) {
430 report_error(ERR_FATAL | ERR_NOFILE,
431 "unable to open output file `%s'", outname);
435 * We must call init_labels() before ofmt->init() since
436 * some object formats will want to define labels in their
437 * init routines. (eg OS/2 defines the FLAT group)
439 init_labels();
441 ofmt->init(ofile, report_error, define_label, evaluate);
443 assemble_file(inname, depend_ptr);
445 if (!terminate_after_phase) {
446 ofmt->cleanup(using_debug_info);
447 cleanup_labels();
448 } else {
450 * Despite earlier comments, we need this fclose.
451 * The object output drivers only fclose on cleanup,
452 * and we just skipped that.
454 fclose (ofile);
456 remove(outname);
457 if (listname[0])
458 remove(listname);
461 break;
464 if (depend_list)
465 emit_dependencies(depend_list);
467 if (want_usage)
468 usage();
470 raa_free(offsets);
471 saa_free(forwrefs);
472 eval_cleanup();
473 stdscan_cleanup();
475 if (terminate_after_phase)
476 return 1;
477 else
478 return 0;
482 * Get a parameter for a command line option.
483 * First arg must be in the form of e.g. -f...
485 static char *get_param(char *p, char *q, bool *advance)
487 *advance = false;
488 if (p[2]) { /* the parameter's in the option */
489 p += 2;
490 while (nasm_isspace(*p))
491 p++;
492 return p;
494 if (q && q[0]) {
495 *advance = true;
496 return q;
498 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
499 "option `-%c' requires an argument", p[1]);
500 return NULL;
504 * Copy a filename
506 static void copy_filename(char *dst, const char *src)
508 size_t len = strlen(src);
510 if (len >= (size_t)FILENAME_MAX) {
511 report_error(ERR_FATAL | ERR_NOFILE, "file name too long");
512 return;
514 strncpy(dst, src, FILENAME_MAX);
518 * Convert a string to Make-safe form
520 static char *quote_for_make(const char *str)
522 const char *p;
523 char *os, *q;
525 size_t n = 1; /* Terminating zero */
526 size_t nbs = 0;
528 if (!str)
529 return NULL;
531 for (p = str; *p; p++) {
532 switch (*p) {
533 case ' ':
534 case '\t':
535 /* Convert N backslashes + ws -> 2N+1 backslashes + ws */
536 n += nbs + 2;
537 nbs = 0;
538 break;
539 case '$':
540 case '#':
541 nbs = 0;
542 n += 2;
543 break;
544 case '\\':
545 nbs++;
546 n++;
547 break;
548 default:
549 nbs = 0;
550 n++;
551 break;
555 /* Convert N backslashes at the end of filename to 2N backslashes */
556 if (nbs)
557 n += nbs;
559 os = q = nasm_malloc(n);
561 nbs = 0;
562 for (p = str; *p; p++) {
563 switch (*p) {
564 case ' ':
565 case '\t':
566 while (nbs--)
567 *q++ = '\\';
568 *q++ = '\\';
569 *q++ = *p;
570 break;
571 case '$':
572 *q++ = *p;
573 *q++ = *p;
574 nbs = 0;
575 break;
576 case '#':
577 *q++ = '\\';
578 *q++ = *p;
579 nbs = 0;
580 break;
581 case '\\':
582 *q++ = *p;
583 nbs++;
584 break;
585 default:
586 *q++ = *p;
587 nbs = 0;
588 break;
591 while (nbs--)
592 *q++ = '\\';
594 *q = '\0';
596 return os;
599 struct textargs {
600 const char *label;
601 int value;
604 #define OPT_PREFIX 0
605 #define OPT_POSTFIX 1
606 struct textargs textopts[] = {
607 {"prefix", OPT_PREFIX},
608 {"postfix", OPT_POSTFIX},
609 {NULL, 0}
612 static bool stopoptions = false;
613 static bool process_arg(char *p, char *q)
615 char *param;
616 int i;
617 bool advance = false;
618 bool suppress;
620 if (!p || !p[0])
621 return false;
623 if (p[0] == '-' && !stopoptions) {
624 if (strchr("oOfpPdDiIlFXuUZwW", p[1])) {
625 /* These parameters take values */
626 if (!(param = get_param(p, q, &advance)))
627 return advance;
630 switch (p[1]) {
631 case 's':
632 error_file = stdout;
633 break;
635 case 'o': /* output file */
636 copy_filename(outname, param);
637 break;
639 case 'f': /* output format */
640 ofmt = ofmt_find(param);
641 if (!ofmt) {
642 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
643 "unrecognised output format `%s' - "
644 "use -hf for a list", param);
645 } else {
646 ofmt->current_dfmt = ofmt->debug_formats[0];
648 break;
650 case 'O': /* Optimization level */
652 int opt;
654 if (!*param) {
655 /* Naked -O == -Ox */
656 optimizing = INT_MAX >> 1; /* Almost unlimited */
657 } else {
658 while (*param) {
659 switch (*param) {
660 case '0': case '1': case '2': case '3': case '4':
661 case '5': case '6': case '7': case '8': case '9':
662 opt = strtoul(param, &param, 10);
664 /* -O0 -> optimizing == -1, 0.98 behaviour */
665 /* -O1 -> optimizing == 0, 0.98.09 behaviour */
666 if (opt < 2)
667 optimizing = opt - 1;
668 else
669 optimizing = opt;
670 break;
672 case 'v':
673 case '+':
674 param++;
675 opt_verbose_info = true;
676 break;
678 case 'x':
679 param++;
680 optimizing = INT_MAX >> 1; /* Almost unlimited */
681 break;
683 default:
684 report_error(ERR_FATAL,
685 "unknown optimization option -O%c\n",
686 *param);
687 break;
691 break;
694 case 'p': /* pre-include */
695 case 'P':
696 pp_pre_include(param);
697 break;
699 case 'd': /* pre-define */
700 case 'D':
701 pp_pre_define(param);
702 break;
704 case 'u': /* un-define */
705 case 'U':
706 pp_pre_undefine(param);
707 break;
709 case 'i': /* include search path */
710 case 'I':
711 pp_include_path(param);
712 break;
714 case 'l': /* listing file */
715 copy_filename(listname, param);
716 break;
718 case 'Z': /* error messages file */
719 strcpy(errname, param);
720 break;
722 case 'F': /* specify debug format */
723 ofmt->current_dfmt = dfmt_find(ofmt, param);
724 if (!ofmt->current_dfmt) {
725 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
726 "unrecognized debug format `%s' for"
727 " output format `%s'",
728 param, ofmt->shortname);
730 using_debug_info = true;
731 break;
733 case 'X': /* specify error reporting format */
734 if (nasm_stricmp("vc", param) == 0)
735 report_error = report_error_vc;
736 else if (nasm_stricmp("gnu", param) == 0)
737 report_error = report_error_gnu;
738 else
739 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
740 "unrecognized error reporting format `%s'",
741 param);
742 break;
744 case 'g':
745 using_debug_info = true;
746 break;
748 case 'h':
749 printf
750 ("usage: nasm [-@ response file] [-o outfile] [-f format] "
751 "[-l listfile]\n"
752 " [options...] [--] filename\n"
753 " or nasm -v for version info\n\n"
754 " -t assemble in SciTech TASM compatible mode\n"
755 " -g generate debug information in selected format.\n");
756 printf
757 (" -E (or -e) preprocess only (writes output to stdout by default)\n"
758 " -a don't preprocess (assemble only)\n"
759 " -M generate Makefile dependencies on stdout\n"
760 " -MG d:o, missing files assumed generated\n\n"
761 " -Z<file> redirect error messages to file\n"
762 " -s redirect error messages to stdout\n\n"
763 " -F format select a debugging format\n\n"
764 " -I<path> adds a pathname to the include file path\n");
765 printf
766 (" -O<digit> optimize branch offsets (-O0 disables, default)\n"
767 " -P<file> pre-includes a file\n"
768 " -D<macro>[=<value>] pre-defines a macro\n"
769 " -U<macro> undefines a macro\n"
770 " -X<format> specifies error reporting format (gnu or vc)\n"
771 " -w+foo enables warning foo (equiv. -Wfoo)\n"
772 " -w-foo disable warning foo (equiv. -Wno-foo)\n"
773 "Warnings:\n");
774 for (i = 0; i <= ERR_WARN_MAX; i++)
775 printf(" %-23s %s (default %s)\n",
776 suppressed_names[i], suppressed_what[i],
777 suppressed_global[i] ? "off" : "on");
778 printf
779 ("\nresponse files should contain command line parameters"
780 ", one per line.\n");
781 if (p[2] == 'f') {
782 printf("\nvalid output formats for -f are"
783 " (`*' denotes default):\n");
784 ofmt_list(ofmt, stdout);
785 } else {
786 printf("\nFor a list of valid output formats, use -hf.\n");
787 printf("For a list of debug formats, use -f <form> -y.\n");
789 exit(0); /* never need usage message here */
790 break;
792 case 'y':
793 printf("\nvalid debug formats for '%s' output format are"
794 " ('*' denotes default):\n", ofmt->shortname);
795 dfmt_list(ofmt, stdout);
796 exit(0);
797 break;
799 case 't':
800 tasm_compatible_mode = true;
801 break;
803 case 'v':
805 const char *nasm_version_string =
806 "NASM version " NASM_VER " compiled on " __DATE__
807 #ifdef DEBUG
808 " with -DDEBUG"
809 #endif
811 puts(nasm_version_string);
812 exit(0); /* never need usage message here */
814 break;
816 case 'e': /* preprocess only */
817 case 'E':
818 operating_mode = op_preprocess;
819 break;
821 case 'a': /* assemble only - don't preprocess */
822 preproc = &no_pp;
823 break;
825 case 'W':
826 if (param[0] == 'n' && param[1] == 'o' && param[2] == '-') {
827 suppress = true;
828 param += 3;
829 } else {
830 suppress = false;
832 goto set_warning;
834 case 'w':
835 if (param[0] != '+' && param[0] != '-') {
836 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
837 "invalid option to `-w'");
838 break;
840 suppress = (param[0] == '-');
841 param++;
842 goto set_warning;
843 set_warning:
844 for (i = 0; i <= ERR_WARN_MAX; i++)
845 if (!nasm_stricmp(param, suppressed_names[i]))
846 break;
847 if (i <= ERR_WARN_MAX)
848 suppressed_global[i] = suppress;
849 else if (!nasm_stricmp(param, "all"))
850 for (i = 1; i <= ERR_WARN_MAX; i++)
851 suppressed_global[i] = suppress;
852 else if (!nasm_stricmp(param, "none"))
853 for (i = 1; i <= ERR_WARN_MAX; i++)
854 suppressed_global[i] = !suppress;
855 else
856 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
857 "invalid warning `%s'", param);
858 break;
860 case 'M':
861 switch (p[2]) {
862 case 0:
863 operating_mode = op_depend;
864 break;
865 case 'G':
866 operating_mode = op_depend;
867 depend_missing_ok = true;
868 break;
869 case 'P':
870 depend_emit_phony = true;
871 break;
872 case 'D':
873 depend_file = q;
874 advance = true;
875 break;
876 case 'T':
877 depend_target = q;
878 advance = true;
879 break;
880 case 'Q':
881 depend_target = quote_for_make(q);
882 advance = true;
883 break;
884 default:
885 report_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
886 "unknown dependency option `-M%c'", p[2]);
887 break;
889 if (advance && (!q || !q[0])) {
890 report_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
891 "option `-M%c' requires a parameter", p[2]);
892 break;
894 break;
896 case '-':
898 int s;
900 if (p[2] == 0) { /* -- => stop processing options */
901 stopoptions = 1;
902 break;
904 for (s = 0; textopts[s].label; s++) {
905 if (!nasm_stricmp(p + 2, textopts[s].label)) {
906 break;
910 switch (s) {
912 case OPT_PREFIX:
913 case OPT_POSTFIX:
915 if (!q) {
916 report_error(ERR_NONFATAL | ERR_NOFILE |
917 ERR_USAGE,
918 "option `--%s' requires an argument",
919 p + 2);
920 break;
921 } else {
922 advance = 1, param = q;
925 if (s == OPT_PREFIX) {
926 strncpy(lprefix, param, PREFIX_MAX - 1);
927 lprefix[PREFIX_MAX - 1] = 0;
928 break;
930 if (s == OPT_POSTFIX) {
931 strncpy(lpostfix, param, POSTFIX_MAX - 1);
932 lpostfix[POSTFIX_MAX - 1] = 0;
933 break;
935 break;
937 default:
939 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
940 "unrecognised option `--%s'", p + 2);
941 break;
944 break;
947 default:
948 if (!ofmt->setinfo(GI_SWITCH, &p))
949 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
950 "unrecognised option `-%c'", p[1]);
951 break;
953 } else {
954 if (*inname) {
955 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
956 "more than one input file specified");
957 } else {
958 copy_filename(inname, p);
962 return advance;
965 #define ARG_BUF_DELTA 128
967 static void process_respfile(FILE * rfile)
969 char *buffer, *p, *q, *prevarg;
970 int bufsize, prevargsize;
972 bufsize = prevargsize = ARG_BUF_DELTA;
973 buffer = nasm_malloc(ARG_BUF_DELTA);
974 prevarg = nasm_malloc(ARG_BUF_DELTA);
975 prevarg[0] = '\0';
977 while (1) { /* Loop to handle all lines in file */
978 p = buffer;
979 while (1) { /* Loop to handle long lines */
980 q = fgets(p, bufsize - (p - buffer), rfile);
981 if (!q)
982 break;
983 p += strlen(p);
984 if (p > buffer && p[-1] == '\n')
985 break;
986 if (p - buffer > bufsize - 10) {
987 int offset;
988 offset = p - buffer;
989 bufsize += ARG_BUF_DELTA;
990 buffer = nasm_realloc(buffer, bufsize);
991 p = buffer + offset;
995 if (!q && p == buffer) {
996 if (prevarg[0])
997 process_arg(prevarg, NULL);
998 nasm_free(buffer);
999 nasm_free(prevarg);
1000 return;
1004 * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
1005 * them are present at the end of the line.
1007 *(p = &buffer[strcspn(buffer, "\r\n\032")]) = '\0';
1009 while (p > buffer && nasm_isspace(p[-1]))
1010 *--p = '\0';
1012 p = buffer;
1013 while (nasm_isspace(*p))
1014 p++;
1016 if (process_arg(prevarg, p))
1017 *p = '\0';
1019 if ((int) strlen(p) > prevargsize - 10) {
1020 prevargsize += ARG_BUF_DELTA;
1021 prevarg = nasm_realloc(prevarg, prevargsize);
1023 strncpy(prevarg, p, prevargsize);
1027 /* Function to process args from a string of args, rather than the
1028 * argv array. Used by the environment variable and response file
1029 * processing.
1031 static void process_args(char *args)
1033 char *p, *q, *arg, *prevarg;
1034 char separator = ' ';
1036 p = args;
1037 if (*p && *p != '-')
1038 separator = *p++;
1039 arg = NULL;
1040 while (*p) {
1041 q = p;
1042 while (*p && *p != separator)
1043 p++;
1044 while (*p == separator)
1045 *p++ = '\0';
1046 prevarg = arg;
1047 arg = q;
1048 if (process_arg(prevarg, arg))
1049 arg = NULL;
1051 if (arg)
1052 process_arg(arg, NULL);
1055 static void process_response_file(const char *file)
1057 char str[2048];
1058 FILE *f = fopen(file, "r");
1059 if (!f) {
1060 perror(file);
1061 exit(-1);
1063 while (fgets(str, sizeof str, f)) {
1064 process_args(str);
1066 fclose(f);
1069 static void parse_cmdline(int argc, char **argv)
1071 FILE *rfile;
1072 char *envreal, *envcopy = NULL, *p, *arg;
1074 *inname = *outname = *listname = *errname = '\0';
1077 * First, process the NASMENV environment variable.
1079 envreal = getenv("NASMENV");
1080 arg = NULL;
1081 if (envreal) {
1082 envcopy = nasm_strdup(envreal);
1083 process_args(envcopy);
1084 nasm_free(envcopy);
1088 * Now process the actual command line.
1090 while (--argc) {
1091 bool advance;
1092 argv++;
1093 if (argv[0][0] == '@') {
1094 /* We have a response file, so process this as a set of
1095 * arguments like the environment variable. This allows us
1096 * to have multiple arguments on a single line, which is
1097 * different to the -@resp file processing below for regular
1098 * NASM.
1100 process_response_file(argv[0]+1);
1101 argc--;
1102 argv++;
1104 if (!stopoptions && argv[0][0] == '-' && argv[0][1] == '@') {
1105 p = get_param(argv[0], argc > 1 ? argv[1] : NULL, &advance);
1106 if (p) {
1107 rfile = fopen(p, "r");
1108 if (rfile) {
1109 process_respfile(rfile);
1110 fclose(rfile);
1111 } else
1112 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
1113 "unable to open response file `%s'", p);
1115 } else
1116 advance = process_arg(argv[0], argc > 1 ? argv[1] : NULL);
1117 argv += advance, argc -= advance;
1120 /* Look for basic command line typos. This definitely doesn't
1121 catch all errors, but it might help cases of fumbled fingers. */
1122 if (!*inname)
1123 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
1124 "no input file specified");
1125 else if (!strcmp(inname, errname) ||
1126 !strcmp(inname, outname) ||
1127 !strcmp(inname, listname) ||
1128 (depend_file && !strcmp(inname, depend_file)))
1129 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
1130 "file `%s' is both input and output file",
1131 inname);
1133 if (*errname) {
1134 error_file = fopen(errname, "w");
1135 if (!error_file) {
1136 error_file = stderr; /* Revert to default! */
1137 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
1138 "cannot open file `%s' for error messages",
1139 errname);
1144 /* List of directives */
1145 enum directives {
1146 D_NONE, D_ABSOLUTE, D_BITS, D_COMMON, D_CPU, D_DEBUG, D_DEFAULT,
1147 D_EXTERN, D_FLOAT, D_GLOBAL, D_LIST, D_SECTION, D_SEGMENT, D_WARNING
1149 static const char *directives[] = {
1150 "", "absolute", "bits", "common", "cpu", "debug", "default",
1151 "extern", "float", "global", "list", "section", "segment", "warning"
1153 static enum directives getkw(char **directive, char **value);
1155 static void assemble_file(char *fname, StrList **depend_ptr)
1157 char *directive, *value, *p, *q, *special, *line, debugid[80];
1158 insn output_ins;
1159 int i, validid;
1160 bool rn_error;
1161 int32_t seg;
1162 int64_t offs;
1163 struct tokenval tokval;
1164 expr *e;
1165 int pass_max;
1167 if (cmd_sb == 32 && cmd_cpu < IF_386)
1168 report_error(ERR_FATAL, "command line: "
1169 "32-bit segment size requires a higher cpu");
1171 pass_max = prev_offset_changed = (INT_MAX >> 1) + 2; /* Almost unlimited */
1172 for (passn = 1; pass0 <= 2; passn++) {
1173 int pass1, pass2;
1174 ldfunc def_label;
1176 pass1 = pass0 == 2 ? 2 : 1; /* 1, 1, 1, ..., 1, 2 */
1177 pass2 = passn > 1 ? 2 : 1; /* 1, 2, 2, ..., 2, 2 */
1178 /* pass0 0, 0, 0, ..., 1, 2 */
1180 def_label = passn > 1 ? redefine_label : define_label;
1182 globalbits = sb = cmd_sb; /* set 'bits' to command line default */
1183 cpu = cmd_cpu;
1184 if (pass0 == 2) {
1185 if (*listname)
1186 nasmlist.init(listname, report_error);
1188 in_abs_seg = false;
1189 global_offset_changed = 0; /* set by redefine_label */
1190 location.segment = ofmt->section(NULL, pass2, &sb);
1191 globalbits = sb;
1192 if (passn > 1) {
1193 saa_rewind(forwrefs);
1194 forwref = saa_rstruct(forwrefs);
1195 raa_free(offsets);
1196 offsets = raa_init();
1198 preproc->reset(fname, pass1, report_error, evaluate, &nasmlist,
1199 pass1 == 2 ? depend_ptr : NULL);
1200 memcpy(suppressed, suppressed_global, (ERR_WARN_MAX+1) * sizeof(bool));
1202 globallineno = 0;
1203 if (passn == 1)
1204 location.known = true;
1205 location.offset = offs = GET_CURR_OFFS;
1207 while ((line = preproc->getline())) {
1208 enum directives d;
1209 globallineno++;
1211 /* here we parse our directives; this is not handled by the 'real'
1212 * parser. */
1213 directive = line;
1214 d = getkw(&directive, &value);
1215 if (d) {
1216 int err = 0;
1218 switch (d) {
1219 case D_SEGMENT: /* [SEGMENT n] */
1220 case D_SECTION:
1221 seg = ofmt->section(value, pass2, &sb);
1222 if (seg == NO_SEG) {
1223 report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
1224 "segment name `%s' not recognized",
1225 value);
1226 } else {
1227 in_abs_seg = false;
1228 location.segment = seg;
1230 break;
1231 case D_EXTERN: /* [EXTERN label:special] */
1232 if (*value == '$')
1233 value++; /* skip initial $ if present */
1234 if (pass0 == 2) {
1235 q = value;
1236 while (*q && *q != ':')
1237 q++;
1238 if (*q == ':') {
1239 *q++ = '\0';
1240 ofmt->symdef(value, 0L, 0L, 3, q);
1242 } else if (passn == 1) {
1243 q = value;
1244 validid = true;
1245 if (!isidstart(*q))
1246 validid = false;
1247 while (*q && *q != ':') {
1248 if (!isidchar(*q))
1249 validid = false;
1250 q++;
1252 if (!validid) {
1253 report_error(ERR_NONFATAL,
1254 "identifier expected after EXTERN");
1255 break;
1257 if (*q == ':') {
1258 *q++ = '\0';
1259 special = q;
1260 } else
1261 special = NULL;
1262 if (!is_extern(value)) { /* allow re-EXTERN to be ignored */
1263 int temp = pass0;
1264 pass0 = 1; /* fake pass 1 in labels.c */
1265 declare_as_global(value, special,
1266 report_error);
1267 define_label(value, seg_alloc(), 0L, NULL,
1268 false, true, ofmt, report_error);
1269 pass0 = temp;
1271 } /* else pass0 == 1 */
1272 break;
1273 case D_BITS: /* [BITS bits] */
1274 globalbits = sb = get_bits(value);
1275 break;
1276 case D_GLOBAL: /* [GLOBAL symbol:special] */
1277 if (*value == '$')
1278 value++; /* skip initial $ if present */
1279 if (pass0 == 2) { /* pass 2 */
1280 q = value;
1281 while (*q && *q != ':')
1282 q++;
1283 if (*q == ':') {
1284 *q++ = '\0';
1285 ofmt->symdef(value, 0L, 0L, 3, q);
1287 } else if (pass2 == 1) { /* pass == 1 */
1288 q = value;
1289 validid = true;
1290 if (!isidstart(*q))
1291 validid = false;
1292 while (*q && *q != ':') {
1293 if (!isidchar(*q))
1294 validid = false;
1295 q++;
1297 if (!validid) {
1298 report_error(ERR_NONFATAL,
1299 "identifier expected after GLOBAL");
1300 break;
1302 if (*q == ':') {
1303 *q++ = '\0';
1304 special = q;
1305 } else
1306 special = NULL;
1307 declare_as_global(value, special, report_error);
1308 } /* pass == 1 */
1309 break;
1310 case D_COMMON: /* [COMMON symbol size:special] */
1311 if (*value == '$')
1312 value++; /* skip initial $ if present */
1313 if (pass0 == 1) {
1314 p = value;
1315 validid = true;
1316 if (!isidstart(*p))
1317 validid = false;
1318 while (*p && !nasm_isspace(*p)) {
1319 if (!isidchar(*p))
1320 validid = false;
1321 p++;
1323 if (!validid) {
1324 report_error(ERR_NONFATAL,
1325 "identifier expected after COMMON");
1326 break;
1328 if (*p) {
1329 int64_t size;
1331 while (*p && nasm_isspace(*p))
1332 *p++ = '\0';
1333 q = p;
1334 while (*q && *q != ':')
1335 q++;
1336 if (*q == ':') {
1337 *q++ = '\0';
1338 special = q;
1339 } else
1340 special = NULL;
1341 size = readnum(p, &rn_error);
1342 if (rn_error)
1343 report_error(ERR_NONFATAL,
1344 "invalid size specified"
1345 " in COMMON declaration");
1346 else
1347 define_common(value, seg_alloc(), size,
1348 special, ofmt, report_error);
1349 } else
1350 report_error(ERR_NONFATAL,
1351 "no size specified in"
1352 " COMMON declaration");
1353 } else if (pass0 == 2) { /* pass == 2 */
1354 q = value;
1355 while (*q && *q != ':') {
1356 if (nasm_isspace(*q))
1357 *q = '\0';
1358 q++;
1360 if (*q == ':') {
1361 *q++ = '\0';
1362 ofmt->symdef(value, 0L, 0L, 3, q);
1365 break;
1366 case D_ABSOLUTE: /* [ABSOLUTE address] */
1367 stdscan_reset();
1368 stdscan_bufptr = value;
1369 tokval.t_type = TOKEN_INVALID;
1370 e = evaluate(stdscan, NULL, &tokval, NULL, pass2,
1371 report_error, NULL);
1372 if (e) {
1373 if (!is_reloc(e))
1374 report_error(pass0 ==
1375 1 ? ERR_NONFATAL : ERR_PANIC,
1376 "cannot use non-relocatable expression as "
1377 "ABSOLUTE address");
1378 else {
1379 abs_seg = reloc_seg(e);
1380 abs_offset = reloc_value(e);
1382 } else if (passn == 1)
1383 abs_offset = 0x100; /* don't go near zero in case of / */
1384 else
1385 report_error(ERR_PANIC, "invalid ABSOLUTE address "
1386 "in pass two");
1387 in_abs_seg = true;
1388 location.segment = NO_SEG;
1389 break;
1390 case D_DEBUG: /* [DEBUG] */
1391 p = value;
1392 q = debugid;
1393 validid = true;
1394 if (!isidstart(*p))
1395 validid = false;
1396 while (*p && !nasm_isspace(*p)) {
1397 if (!isidchar(*p))
1398 validid = false;
1399 *q++ = *p++;
1401 *q++ = 0;
1402 if (!validid) {
1403 report_error(passn == 1 ? ERR_NONFATAL : ERR_PANIC,
1404 "identifier expected after DEBUG");
1405 break;
1407 while (*p && nasm_isspace(*p))
1408 p++;
1409 if (pass0 == 2)
1410 ofmt->current_dfmt->debug_directive(debugid, p);
1411 break;
1412 case D_WARNING: /* [WARNING {+|-|*}warn-name] */
1413 if (pass1 == 1) {
1414 while (*value && nasm_isspace(*value))
1415 value++;
1417 switch(*value) {
1418 case '-': validid = 0; value++; break;
1419 case '+': validid = 1; value++; break;
1420 case '*': validid = 2; value++; break;
1421 default: /*
1422 * Should this error out?
1423 * I'll keep it so nothing breaks.
1425 validid = 1; break;
1428 for (i = 1; i <= ERR_WARN_MAX; i++)
1429 if (!nasm_stricmp(value, suppressed_names[i]))
1430 break;
1431 if (i <= ERR_WARN_MAX) {
1432 switch(validid) {
1433 case 0: suppressed[i] = true; break;
1434 case 1: suppressed[i] = false; break;
1435 case 2: suppressed[i] = suppressed_global[i];
1436 break;
1439 else
1440 report_error(ERR_NONFATAL,
1441 "invalid warning id in WARNING directive");
1443 break;
1444 case D_CPU: /* [CPU] */
1445 cpu = get_cpu(value);
1446 break;
1447 case D_LIST: /* [LIST {+|-}] */
1448 while (*value && nasm_isspace(*value))
1449 value++;
1451 if (*value == '+') {
1452 user_nolist = 0;
1453 } else {
1454 if (*value == '-') {
1455 user_nolist = 1;
1456 } else {
1457 err = 1;
1460 break;
1461 case D_DEFAULT: /* [DEFAULT] */
1462 stdscan_reset();
1463 stdscan_bufptr = value;
1464 tokval.t_type = TOKEN_INVALID;
1465 if (stdscan(NULL, &tokval) == TOKEN_SPECIAL) {
1466 switch ((int)tokval.t_integer) {
1467 case S_REL:
1468 globalrel = 1;
1469 break;
1470 case S_ABS:
1471 globalrel = 0;
1472 break;
1473 default:
1474 err = 1;
1475 break;
1477 } else {
1478 err = 1;
1480 break;
1481 case D_FLOAT:
1482 if (float_option(value)) {
1483 report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
1484 "unknown 'float' directive: %s",
1485 value);
1487 break;
1488 default:
1489 if (!ofmt->directive(directive, value, pass2))
1490 report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
1491 "unrecognised directive [%s]",
1492 directive);
1494 if (err) {
1495 report_error(ERR_NONFATAL,
1496 "invalid parameter to [%s] directive",
1497 directive);
1499 } else { /* it isn't a directive */
1501 parse_line(pass1, line, &output_ins,
1502 report_error, evaluate, def_label);
1504 if (optimizing > 0) {
1505 if (forwref != NULL && globallineno == forwref->lineno) {
1506 output_ins.forw_ref = true;
1507 do {
1508 output_ins.oprs[forwref->operand].opflags |=
1509 OPFLAG_FORWARD;
1510 forwref = saa_rstruct(forwrefs);
1511 } while (forwref != NULL
1512 && forwref->lineno == globallineno);
1513 } else
1514 output_ins.forw_ref = false;
1517 if (optimizing > 0) {
1518 if (passn == 1) {
1519 for (i = 0; i < output_ins.operands; i++) {
1520 if (output_ins.oprs[i].
1521 opflags & OPFLAG_FORWARD) {
1522 struct forwrefinfo *fwinf =
1523 (struct forwrefinfo *)
1524 saa_wstruct(forwrefs);
1525 fwinf->lineno = globallineno;
1526 fwinf->operand = i;
1532 /* forw_ref */
1533 if (output_ins.opcode == I_EQU) {
1534 if (pass1 == 1) {
1536 * Special `..' EQUs get processed in pass two,
1537 * except `..@' macro-processor EQUs which are done
1538 * in the normal place.
1540 if (!output_ins.label)
1541 report_error(ERR_NONFATAL,
1542 "EQU not preceded by label");
1544 else if (output_ins.label[0] != '.' ||
1545 output_ins.label[1] != '.' ||
1546 output_ins.label[2] == '@') {
1547 if (output_ins.operands == 1 &&
1548 (output_ins.oprs[0].type & IMMEDIATE) &&
1549 output_ins.oprs[0].wrt == NO_SEG) {
1550 int isext =
1551 output_ins.oprs[0].
1552 opflags & OPFLAG_EXTERN;
1553 def_label(output_ins.label,
1554 output_ins.oprs[0].segment,
1555 output_ins.oprs[0].offset, NULL,
1556 false, isext, ofmt,
1557 report_error);
1558 } else if (output_ins.operands == 2
1559 && (output_ins.oprs[0].
1560 type & IMMEDIATE)
1561 && (output_ins.oprs[0].type & COLON)
1562 && output_ins.oprs[0].segment ==
1563 NO_SEG
1564 && output_ins.oprs[0].wrt == NO_SEG
1565 && (output_ins.oprs[1].
1566 type & IMMEDIATE)
1567 && output_ins.oprs[1].segment ==
1568 NO_SEG
1569 && output_ins.oprs[1].wrt ==
1570 NO_SEG) {
1571 def_label(output_ins.label,
1572 output_ins.oprs[0].
1573 offset | SEG_ABS,
1574 output_ins.oprs[1].offset, NULL,
1575 false, false, ofmt,
1576 report_error);
1577 } else
1578 report_error(ERR_NONFATAL,
1579 "bad syntax for EQU");
1581 } else {
1583 * Special `..' EQUs get processed here, except
1584 * `..@' macro processor EQUs which are done above.
1586 if (output_ins.label[0] == '.' &&
1587 output_ins.label[1] == '.' &&
1588 output_ins.label[2] != '@') {
1589 if (output_ins.operands == 1 &&
1590 (output_ins.oprs[0].type & IMMEDIATE)) {
1591 define_label(output_ins.label,
1592 output_ins.oprs[0].segment,
1593 output_ins.oprs[0].offset,
1594 NULL, false, false, ofmt,
1595 report_error);
1596 } else if (output_ins.operands == 2
1597 && (output_ins.oprs[0].
1598 type & IMMEDIATE)
1599 && (output_ins.oprs[0].type & COLON)
1600 && output_ins.oprs[0].segment ==
1601 NO_SEG
1602 && (output_ins.oprs[1].
1603 type & IMMEDIATE)
1604 && output_ins.oprs[1].segment ==
1605 NO_SEG) {
1606 define_label(output_ins.label,
1607 output_ins.oprs[0].
1608 offset | SEG_ABS,
1609 output_ins.oprs[1].offset,
1610 NULL, false, false, ofmt,
1611 report_error);
1612 } else
1613 report_error(ERR_NONFATAL,
1614 "bad syntax for EQU");
1617 } else { /* instruction isn't an EQU */
1619 if (pass1 == 1) {
1621 int64_t l = insn_size(location.segment, offs, sb, cpu,
1622 &output_ins, report_error);
1624 /* if (using_debug_info) && output_ins.opcode != -1) */
1625 if (using_debug_info)
1626 { /* fbk 03/25/01 */
1627 /* this is done here so we can do debug type info */
1628 int32_t typeinfo =
1629 TYS_ELEMENTS(output_ins.operands);
1630 switch (output_ins.opcode) {
1631 case I_RESB:
1632 typeinfo =
1633 TYS_ELEMENTS(output_ins.oprs[0].
1634 offset) | TY_BYTE;
1635 break;
1636 case I_RESW:
1637 typeinfo =
1638 TYS_ELEMENTS(output_ins.oprs[0].
1639 offset) | TY_WORD;
1640 break;
1641 case I_RESD:
1642 typeinfo =
1643 TYS_ELEMENTS(output_ins.oprs[0].
1644 offset) | TY_DWORD;
1645 break;
1646 case I_RESQ:
1647 typeinfo =
1648 TYS_ELEMENTS(output_ins.oprs[0].
1649 offset) | TY_QWORD;
1650 break;
1651 case I_REST:
1652 typeinfo =
1653 TYS_ELEMENTS(output_ins.oprs[0].
1654 offset) | TY_TBYTE;
1655 break;
1656 case I_RESO:
1657 typeinfo =
1658 TYS_ELEMENTS(output_ins.oprs[0].
1659 offset) | TY_OWORD;
1660 break;
1661 case I_RESY:
1662 typeinfo =
1663 TYS_ELEMENTS(output_ins.oprs[0].
1664 offset) | TY_YWORD;
1665 break;
1666 case I_DB:
1667 typeinfo |= TY_BYTE;
1668 break;
1669 case I_DW:
1670 typeinfo |= TY_WORD;
1671 break;
1672 case I_DD:
1673 if (output_ins.eops_float)
1674 typeinfo |= TY_FLOAT;
1675 else
1676 typeinfo |= TY_DWORD;
1677 break;
1678 case I_DQ:
1679 typeinfo |= TY_QWORD;
1680 break;
1681 case I_DT:
1682 typeinfo |= TY_TBYTE;
1683 break;
1684 case I_DO:
1685 typeinfo |= TY_OWORD;
1686 break;
1687 case I_DY:
1688 typeinfo |= TY_YWORD;
1689 break;
1690 default:
1691 typeinfo = TY_LABEL;
1695 ofmt->current_dfmt->debug_typevalue(typeinfo);
1698 if (l != -1) {
1699 offs += l;
1700 SET_CURR_OFFS(offs);
1703 * else l == -1 => invalid instruction, which will be
1704 * flagged as an error on pass 2
1707 } else {
1708 offs += assemble(location.segment, offs, sb, cpu,
1709 &output_ins, ofmt, report_error,
1710 &nasmlist);
1711 SET_CURR_OFFS(offs);
1714 } /* not an EQU */
1715 cleanup_insn(&output_ins);
1717 nasm_free(line);
1718 location.offset = offs = GET_CURR_OFFS;
1719 } /* end while (line = preproc->getline... */
1720 if (pass1 == 2 && global_offset_changed)
1721 report_error(ERR_NONFATAL,
1722 "phase error detected at end of assembly.");
1724 if (pass1 == 1)
1725 preproc->cleanup(1);
1727 if (pass1 == 1 && terminate_after_phase) {
1728 fclose(ofile);
1729 remove(outname);
1730 if (want_usage)
1731 usage();
1732 exit(1);
1735 if (passn > 1 && !global_offset_changed)
1736 pass0++;
1737 else if (global_offset_changed && global_offset_changed < prev_offset_changed) {
1738 prev_offset_changed = global_offset_changed;
1739 stall_count = 0;
1741 else stall_count++;
1743 if((stall_count > 997) || (passn >= pass_max))
1744 /* We get here if the labels don't converge
1745 * Example: FOO equ FOO + 1
1747 report_error(ERR_NONFATAL,
1748 "Can't find valid values for all labels "
1749 "after %d passes, giving up.\n"
1750 " Possible cause: recursive equ's.", passn);
1753 preproc->cleanup(0);
1754 nasmlist.cleanup();
1755 if (opt_verbose_info) /* -On and -Ov switches */
1756 fprintf(stdout,
1757 "info:: assembly required 1+%d+1 passes\n", passn-3);
1758 } /* exit from assemble_file (...) */
1760 static enum directives getkw(char **directive, char **value)
1762 char *p, *q, *buf;
1764 buf = *directive;
1766 /* allow leading spaces or tabs */
1767 while (*buf == ' ' || *buf == '\t')
1768 buf++;
1770 if (*buf != '[')
1771 return 0;
1773 p = buf;
1775 while (*p && *p != ']')
1776 p++;
1778 if (!*p)
1779 return 0;
1781 q = p++;
1783 while (*p && *p != ';') {
1784 if (!nasm_isspace(*p))
1785 return 0;
1786 p++;
1788 q[1] = '\0';
1790 *directive = p = buf + 1;
1791 while (*buf && *buf != ' ' && *buf != ']' && *buf != '\t')
1792 buf++;
1793 if (*buf == ']') {
1794 *buf = '\0';
1795 *value = buf;
1796 } else {
1797 *buf++ = '\0';
1798 while (nasm_isspace(*buf))
1799 buf++; /* beppu - skip leading whitespace */
1800 *value = buf;
1801 while (*buf != ']')
1802 buf++;
1803 *buf++ = '\0';
1806 return bsii(*directive, directives, elements(directives));
1810 * gnu style error reporting
1811 * This function prints an error message to error_file in the
1812 * style used by GNU. An example would be:
1813 * file.asm:50: error: blah blah blah
1814 * where file.asm is the name of the file, 50 is the line number on
1815 * which the error occurs (or is detected) and "error:" is one of
1816 * the possible optional diagnostics -- it can be "error" or "warning"
1817 * or something else. Finally the line terminates with the actual
1818 * error message.
1820 * @param severity the severity of the warning or error
1821 * @param fmt the printf style format string
1823 static void report_error_gnu(int severity, const char *fmt, ...)
1825 va_list ap;
1827 if (is_suppressed_warning(severity))
1828 return;
1830 if (severity & ERR_NOFILE)
1831 fputs("nasm: ", error_file);
1832 else {
1833 char *currentfile = NULL;
1834 int32_t lineno = 0;
1835 src_get(&lineno, &currentfile);
1836 fprintf(error_file, "%s:%"PRId32": ", currentfile, lineno);
1837 nasm_free(currentfile);
1839 va_start(ap, fmt);
1840 report_error_common(severity, fmt, ap);
1841 va_end(ap);
1845 * MS style error reporting
1846 * This function prints an error message to error_file in the
1847 * style used by Visual C and some other Microsoft tools. An example
1848 * would be:
1849 * file.asm(50) : error: blah blah blah
1850 * where file.asm is the name of the file, 50 is the line number on
1851 * which the error occurs (or is detected) and "error:" is one of
1852 * the possible optional diagnostics -- it can be "error" or "warning"
1853 * or something else. Finally the line terminates with the actual
1854 * error message.
1856 * @param severity the severity of the warning or error
1857 * @param fmt the printf style format string
1859 static void report_error_vc(int severity, const char *fmt, ...)
1861 va_list ap;
1863 if (is_suppressed_warning(severity))
1864 return;
1866 if (severity & ERR_NOFILE)
1867 fputs("nasm: ", error_file);
1868 else {
1869 char *currentfile = NULL;
1870 int32_t lineno = 0;
1871 src_get(&lineno, &currentfile);
1872 fprintf(error_file, "%s(%"PRId32") : ", currentfile, lineno);
1873 nasm_free(currentfile);
1875 va_start(ap, fmt);
1876 report_error_common(severity, fmt, ap);
1877 va_end(ap);
1881 * check for supressed warning
1882 * checks for suppressed warning or pass one only warning and we're
1883 * not in pass 1
1885 * @param severity the severity of the warning or error
1886 * @return true if we should abort error/warning printing
1888 static bool is_suppressed_warning(int severity)
1891 * See if it's a suppressed warning.
1893 return (severity & ERR_MASK) == ERR_WARNING &&
1894 (((severity & ERR_WARN_MASK) != 0 &&
1895 suppressed[(severity & ERR_WARN_MASK) >> ERR_WARN_SHR]) ||
1896 /* See if it's a pass-one only warning and we're not in pass one. */
1897 ((severity & ERR_PASS1) && pass0 != 1));
1901 * common error reporting
1902 * This is the common back end of the error reporting schemes currently
1903 * implemented. It prints the nature of the warning and then the
1904 * specific error message to error_file and may or may not return. It
1905 * doesn't return if the error severity is a "panic" or "debug" type.
1907 * @param severity the severity of the warning or error
1908 * @param fmt the printf style format string
1910 static void report_error_common(int severity, const char *fmt,
1911 va_list args)
1913 switch (severity & (ERR_MASK|ERR_NO_SEVERITY)) {
1914 case ERR_WARNING:
1915 fputs("warning: ", error_file);
1916 break;
1917 case ERR_NONFATAL:
1918 fputs("error: ", error_file);
1919 break;
1920 case ERR_FATAL:
1921 fputs("fatal: ", error_file);
1922 break;
1923 case ERR_PANIC:
1924 fputs("panic: ", error_file);
1925 break;
1926 case ERR_DEBUG:
1927 fputs("debug: ", error_file);
1928 break;
1929 default:
1930 break;
1933 vfprintf(error_file, fmt, args);
1934 putc('\n', error_file);
1936 if (severity & ERR_USAGE)
1937 want_usage = true;
1939 switch (severity & ERR_MASK) {
1940 case ERR_DEBUG:
1941 /* no further action, by definition */
1942 break;
1943 case ERR_WARNING:
1944 if (!suppressed[0]) /* Treat warnings as errors */
1945 terminate_after_phase = true;
1946 break;
1947 case ERR_NONFATAL:
1948 terminate_after_phase = true;
1949 break;
1950 case ERR_FATAL:
1951 if (ofile) {
1952 fclose(ofile);
1953 remove(outname);
1955 if (want_usage)
1956 usage();
1957 exit(1); /* instantly die */
1958 break; /* placate silly compilers */
1959 case ERR_PANIC:
1960 fflush(NULL);
1961 /* abort(); *//* halt, catch fire, and dump core */
1962 exit(3);
1963 break;
1967 static void usage(void)
1969 fputs("type `nasm -h' for help\n", error_file);
1972 static void register_output_formats(void)
1974 ofmt = ofmt_register(report_error);
1977 #define BUF_DELTA 512
1979 static FILE *no_pp_fp;
1980 static efunc no_pp_err;
1981 static ListGen *no_pp_list;
1982 static int32_t no_pp_lineinc;
1984 static void no_pp_reset(char *file, int pass, efunc error, evalfunc eval,
1985 ListGen * listgen, StrList **deplist)
1987 src_set_fname(nasm_strdup(file));
1988 src_set_linnum(0);
1989 no_pp_lineinc = 1;
1990 no_pp_err = error;
1991 no_pp_fp = fopen(file, "r");
1992 if (!no_pp_fp)
1993 no_pp_err(ERR_FATAL | ERR_NOFILE,
1994 "unable to open input file `%s'", file);
1995 no_pp_list = listgen;
1996 (void)pass; /* placate compilers */
1997 (void)eval; /* placate compilers */
1999 if (deplist) {
2000 StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
2001 sl->next = NULL;
2002 strcpy(sl->str, file);
2003 *deplist = sl;
2007 static char *no_pp_getline(void)
2009 char *buffer, *p, *q;
2010 int bufsize;
2012 bufsize = BUF_DELTA;
2013 buffer = nasm_malloc(BUF_DELTA);
2014 src_set_linnum(src_get_linnum() + no_pp_lineinc);
2016 while (1) { /* Loop to handle %line */
2018 p = buffer;
2019 while (1) { /* Loop to handle long lines */
2020 q = fgets(p, bufsize - (p - buffer), no_pp_fp);
2021 if (!q)
2022 break;
2023 p += strlen(p);
2024 if (p > buffer && p[-1] == '\n')
2025 break;
2026 if (p - buffer > bufsize - 10) {
2027 int offset;
2028 offset = p - buffer;
2029 bufsize += BUF_DELTA;
2030 buffer = nasm_realloc(buffer, bufsize);
2031 p = buffer + offset;
2035 if (!q && p == buffer) {
2036 nasm_free(buffer);
2037 return NULL;
2041 * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
2042 * them are present at the end of the line.
2044 buffer[strcspn(buffer, "\r\n\032")] = '\0';
2046 if (!nasm_strnicmp(buffer, "%line", 5)) {
2047 int32_t ln;
2048 int li;
2049 char *nm = nasm_malloc(strlen(buffer));
2050 if (sscanf(buffer + 5, "%"PRId32"+%d %s", &ln, &li, nm) == 3) {
2051 nasm_free(src_set_fname(nm));
2052 src_set_linnum(ln);
2053 no_pp_lineinc = li;
2054 continue;
2056 nasm_free(nm);
2058 break;
2061 no_pp_list->line(LIST_READ, buffer);
2063 return buffer;
2066 static void no_pp_cleanup(int pass)
2068 (void)pass; /* placate GCC */
2069 fclose(no_pp_fp);
2072 static uint32_t get_cpu(char *value)
2074 if (!strcmp(value, "8086"))
2075 return IF_8086;
2076 if (!strcmp(value, "186"))
2077 return IF_186;
2078 if (!strcmp(value, "286"))
2079 return IF_286;
2080 if (!strcmp(value, "386"))
2081 return IF_386;
2082 if (!strcmp(value, "486"))
2083 return IF_486;
2084 if (!strcmp(value, "586") || !nasm_stricmp(value, "pentium"))
2085 return IF_PENT;
2086 if (!strcmp(value, "686") ||
2087 !nasm_stricmp(value, "ppro") ||
2088 !nasm_stricmp(value, "pentiumpro") || !nasm_stricmp(value, "p2"))
2089 return IF_P6;
2090 if (!nasm_stricmp(value, "p3") || !nasm_stricmp(value, "katmai"))
2091 return IF_KATMAI;
2092 if (!nasm_stricmp(value, "p4") || /* is this right? -- jrc */
2093 !nasm_stricmp(value, "willamette"))
2094 return IF_WILLAMETTE;
2095 if (!nasm_stricmp(value, "prescott"))
2096 return IF_PRESCOTT;
2097 if (!nasm_stricmp(value, "x64") ||
2098 !nasm_stricmp(value, "x86-64"))
2099 return IF_X86_64;
2100 if (!nasm_stricmp(value, "ia64") ||
2101 !nasm_stricmp(value, "ia-64") ||
2102 !nasm_stricmp(value, "itanium") ||
2103 !nasm_stricmp(value, "itanic") || !nasm_stricmp(value, "merced"))
2104 return IF_IA64;
2106 report_error(pass0 < 2 ? ERR_NONFATAL : ERR_FATAL,
2107 "unknown 'cpu' type");
2109 return IF_PLEVEL; /* the maximum level */
2112 static int get_bits(char *value)
2114 int i;
2116 if ((i = atoi(value)) == 16)
2117 return i; /* set for a 16-bit segment */
2118 else if (i == 32) {
2119 if (cpu < IF_386) {
2120 report_error(ERR_NONFATAL,
2121 "cannot specify 32-bit segment on processor below a 386");
2122 i = 16;
2124 } else if (i == 64) {
2125 if (cpu < IF_X86_64) {
2126 report_error(ERR_NONFATAL,
2127 "cannot specify 64-bit segment on processor below an x86-64");
2128 i = 16;
2130 if (i != maxbits) {
2131 report_error(ERR_NONFATAL,
2132 "%s output format does not support 64-bit code",
2133 ofmt->shortname);
2134 i = 16;
2136 } else {
2137 report_error(pass0 < 2 ? ERR_NONFATAL : ERR_FATAL,
2138 "`%s' is not a valid segment size; must be 16, 32 or 64",
2139 value);
2140 i = 16;
2142 return i;
2145 /* end of nasm.c */