Allow %warning output to be suppressed
[nasm/sigaren-mirror.git] / nasm.c
blob3aedfb0c51870a2d906355669794e49ef883f752
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,
111 true
114 * The option names for the suppressible warnings. As before, entry
115 * zero does nothing.
117 static const char *suppressed_names[ERR_WARN_MAX+1] = {
118 "error", "macro-params", "macro-selfref", "macro-defaults",
119 "orphan-labels", "number-overflow", "gnu-elf-extensions",
120 "float-overflow", "float-denorm", "float-underflow", "float-toolong",
121 "user"
125 * The explanations for the suppressible warnings. As before, entry
126 * zero does nothing.
128 static const char *suppressed_what[ERR_WARN_MAX+1] = {
129 "treat warnings as errors",
130 "macro calls with wrong parameter count",
131 "cyclic macro references",
132 "macros with more default than optional parameters",
133 "labels alone on lines without trailing `:'",
134 "numeric constants does not fit in 64 bits",
135 "using 8- or 16-bit relocation in ELF32, a GNU extension",
136 "floating point overflow",
137 "floating point denormal",
138 "floating point underflow",
139 "too many digits in floating-point number",
140 "%warning directives"
144 * This is a null preprocessor which just copies lines from input
145 * to output. It's used when someone explicitly requests that NASM
146 * not preprocess their source file.
149 static void no_pp_reset(char *, int, efunc, evalfunc, ListGen *, StrList **);
150 static char *no_pp_getline(void);
151 static void no_pp_cleanup(int);
152 static Preproc no_pp = {
153 no_pp_reset,
154 no_pp_getline,
155 no_pp_cleanup
159 * get/set current offset...
161 #define GET_CURR_OFFS (in_abs_seg?abs_offset:\
162 raa_read(offsets,location.segment))
163 #define SET_CURR_OFFS(x) (in_abs_seg?(void)(abs_offset=(x)):\
164 (void)(offsets=raa_write(offsets,location.segment,(x))))
166 static int want_usage;
167 static int terminate_after_phase;
168 int user_nolist = 0; /* fbk 9/2/00 */
170 static void nasm_fputs(const char *line, FILE * outfile)
172 if (outfile) {
173 fputs(line, outfile);
174 putc('\n', outfile);
175 } else
176 puts(line);
179 /* Convert a struct tm to a POSIX-style time constant */
180 static int64_t posix_mktime(struct tm *tm)
182 int64_t t;
183 int64_t y = tm->tm_year;
185 /* See IEEE 1003.1:2004, section 4.14 */
187 t = (y-70)*365 + (y-69)/4 - (y-1)/100 + (y+299)/400;
188 t += tm->tm_yday;
189 t *= 24;
190 t += tm->tm_hour;
191 t *= 60;
192 t += tm->tm_min;
193 t *= 60;
194 t += tm->tm_sec;
196 return t;
199 static void define_macros_early(void)
201 char temp[128];
202 struct tm lt, *lt_p, gm, *gm_p;
203 int64_t posix_time;
205 lt_p = localtime(&official_compile_time);
206 if (lt_p) {
207 lt = *lt_p;
209 strftime(temp, sizeof temp, "__DATE__=\"%Y-%m-%d\"", &lt);
210 pp_pre_define(temp);
211 strftime(temp, sizeof temp, "__DATE_NUM__=%Y%m%d", &lt);
212 pp_pre_define(temp);
213 strftime(temp, sizeof temp, "__TIME__=\"%H:%M:%S\"", &lt);
214 pp_pre_define(temp);
215 strftime(temp, sizeof temp, "__TIME_NUM__=%H%M%S", &lt);
216 pp_pre_define(temp);
219 gm_p = gmtime(&official_compile_time);
220 if (gm_p) {
221 gm = *gm_p;
223 strftime(temp, sizeof temp, "__UTC_DATE__=\"%Y-%m-%d\"", &gm);
224 pp_pre_define(temp);
225 strftime(temp, sizeof temp, "__UTC_DATE_NUM__=%Y%m%d", &gm);
226 pp_pre_define(temp);
227 strftime(temp, sizeof temp, "__UTC_TIME__=\"%H:%M:%S\"", &gm);
228 pp_pre_define(temp);
229 strftime(temp, sizeof temp, "__UTC_TIME_NUM__=%H%M%S", &gm);
230 pp_pre_define(temp);
233 if (gm_p)
234 posix_time = posix_mktime(&gm);
235 else if (lt_p)
236 posix_time = posix_mktime(&lt);
237 else
238 posix_time = 0;
240 if (posix_time) {
241 snprintf(temp, sizeof temp, "__POSIX_TIME__=%"PRId64, posix_time);
242 pp_pre_define(temp);
246 static void define_macros_late(void)
248 char temp[128];
250 snprintf(temp, sizeof(temp), "__OUTPUT_FORMAT__=%s\n",
251 ofmt->shortname);
252 pp_pre_define(temp);
255 static void emit_dependencies(StrList *list)
257 FILE *deps;
258 int linepos, len;
259 StrList *l, *nl;
261 if (depend_file && strcmp(depend_file, "-")) {
262 deps = fopen(depend_file, "w");
263 if (!deps) {
264 report_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
265 "unable to write dependency file `%s'", depend_file);
266 return;
268 } else {
269 deps = stdout;
272 linepos = fprintf(deps, "%s:", depend_target);
273 for (l = list; l; l = l->next) {
274 len = strlen(l->str);
275 if (linepos + len > 62) {
276 fprintf(deps, " \\\n ");
277 linepos = 1;
279 fprintf(deps, " %s", l->str);
280 linepos += len+1;
282 fprintf(deps, "\n\n");
284 for (l = list; l; l = nl) {
285 if (depend_emit_phony)
286 fprintf(deps, "%s:\n\n", l->str);
288 nl = l->next;
289 nasm_free(l);
292 if (deps != stdout)
293 fclose(deps);
296 int main(int argc, char **argv)
298 StrList *depend_list = NULL, **depend_ptr;
300 time(&official_compile_time);
302 pass0 = 0;
303 want_usage = terminate_after_phase = false;
304 report_error = report_error_gnu;
306 error_file = stderr;
308 tolower_init();
310 nasm_set_malloc_error(report_error);
311 offsets = raa_init();
312 forwrefs = saa_init((int32_t)sizeof(struct forwrefinfo));
314 preproc = &nasmpp;
315 operating_mode = op_normal;
317 seg_init();
319 register_output_formats();
321 /* Define some macros dependent on the runtime, but not
322 on the command line. */
323 define_macros_early();
325 parse_cmdline(argc, argv);
327 if (terminate_after_phase) {
328 if (want_usage)
329 usage();
330 return 1;
333 /* If debugging info is disabled, suppress any debug calls */
334 if (!using_debug_info)
335 ofmt->current_dfmt = &null_debug_form;
337 if (ofmt->stdmac)
338 pp_extra_stdmac(ofmt->stdmac);
339 parser_global_info(ofmt, &location);
340 eval_global_info(ofmt, lookup_label, &location);
342 /* define some macros dependent of command-line */
343 define_macros_late();
345 depend_ptr = (depend_file || (operating_mode == op_depend))
346 ? &depend_list : NULL;
347 if (!depend_target)
348 depend_target = outname;
350 switch (operating_mode) {
351 case op_depend:
353 char *line;
355 if (depend_missing_ok)
356 pp_include_path(NULL); /* "assume generated" */
358 preproc->reset(inname, 0, report_error, evaluate, &nasmlist,
359 depend_ptr);
360 if (outname[0] == '\0')
361 ofmt->filename(inname, outname, report_error);
362 ofile = NULL;
363 while ((line = preproc->getline()))
364 nasm_free(line);
365 preproc->cleanup(0);
367 break;
369 case op_preprocess:
371 char *line;
372 char *file_name = NULL;
373 int32_t prior_linnum = 0;
374 int lineinc = 0;
376 if (*outname) {
377 ofile = fopen(outname, "w");
378 if (!ofile)
379 report_error(ERR_FATAL | ERR_NOFILE,
380 "unable to open output file `%s'",
381 outname);
382 } else
383 ofile = NULL;
385 location.known = false;
387 /* pass = 1; */
388 preproc->reset(inname, 3, report_error, evaluate, &nasmlist,
389 depend_ptr);
391 while ((line = preproc->getline())) {
393 * We generate %line directives if needed for later programs
395 int32_t linnum = prior_linnum += lineinc;
396 int altline = src_get(&linnum, &file_name);
397 if (altline) {
398 if (altline == 1 && lineinc == 1)
399 nasm_fputs("", ofile);
400 else {
401 lineinc = (altline != -1 || lineinc != 1);
402 fprintf(ofile ? ofile : stdout,
403 "%%line %"PRId32"+%d %s\n", linnum, lineinc,
404 file_name);
406 prior_linnum = linnum;
408 nasm_fputs(line, ofile);
409 nasm_free(line);
411 nasm_free(file_name);
412 preproc->cleanup(0);
413 if (ofile)
414 fclose(ofile);
415 if (ofile && terminate_after_phase)
416 remove(outname);
418 break;
420 case op_normal:
423 * We must call ofmt->filename _anyway_, even if the user
424 * has specified their own output file, because some
425 * formats (eg OBJ and COFF) use ofmt->filename to find out
426 * the name of the input file and then put that inside the
427 * file.
429 ofmt->filename(inname, outname, report_error);
431 ofile = fopen(outname, "wb");
432 if (!ofile) {
433 report_error(ERR_FATAL | ERR_NOFILE,
434 "unable to open output file `%s'", outname);
438 * We must call init_labels() before ofmt->init() since
439 * some object formats will want to define labels in their
440 * init routines. (eg OS/2 defines the FLAT group)
442 init_labels();
444 ofmt->init(ofile, report_error, define_label, evaluate);
446 assemble_file(inname, depend_ptr);
448 if (!terminate_after_phase) {
449 ofmt->cleanup(using_debug_info);
450 cleanup_labels();
451 } else {
453 * Despite earlier comments, we need this fclose.
454 * The object output drivers only fclose on cleanup,
455 * and we just skipped that.
457 fclose (ofile);
459 remove(outname);
460 if (listname[0])
461 remove(listname);
464 break;
467 if (depend_list)
468 emit_dependencies(depend_list);
470 if (want_usage)
471 usage();
473 raa_free(offsets);
474 saa_free(forwrefs);
475 eval_cleanup();
476 stdscan_cleanup();
478 if (terminate_after_phase)
479 return 1;
480 else
481 return 0;
485 * Get a parameter for a command line option.
486 * First arg must be in the form of e.g. -f...
488 static char *get_param(char *p, char *q, bool *advance)
490 *advance = false;
491 if (p[2]) { /* the parameter's in the option */
492 p += 2;
493 while (nasm_isspace(*p))
494 p++;
495 return p;
497 if (q && q[0]) {
498 *advance = true;
499 return q;
501 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
502 "option `-%c' requires an argument", p[1]);
503 return NULL;
507 * Copy a filename
509 static void copy_filename(char *dst, const char *src)
511 size_t len = strlen(src);
513 if (len >= (size_t)FILENAME_MAX) {
514 report_error(ERR_FATAL | ERR_NOFILE, "file name too long");
515 return;
517 strncpy(dst, src, FILENAME_MAX);
521 * Convert a string to Make-safe form
523 static char *quote_for_make(const char *str)
525 const char *p;
526 char *os, *q;
528 size_t n = 1; /* Terminating zero */
529 size_t nbs = 0;
531 if (!str)
532 return NULL;
534 for (p = str; *p; p++) {
535 switch (*p) {
536 case ' ':
537 case '\t':
538 /* Convert N backslashes + ws -> 2N+1 backslashes + ws */
539 n += nbs + 2;
540 nbs = 0;
541 break;
542 case '$':
543 case '#':
544 nbs = 0;
545 n += 2;
546 break;
547 case '\\':
548 nbs++;
549 n++;
550 break;
551 default:
552 nbs = 0;
553 n++;
554 break;
558 /* Convert N backslashes at the end of filename to 2N backslashes */
559 if (nbs)
560 n += nbs;
562 os = q = nasm_malloc(n);
564 nbs = 0;
565 for (p = str; *p; p++) {
566 switch (*p) {
567 case ' ':
568 case '\t':
569 while (nbs--)
570 *q++ = '\\';
571 *q++ = '\\';
572 *q++ = *p;
573 break;
574 case '$':
575 *q++ = *p;
576 *q++ = *p;
577 nbs = 0;
578 break;
579 case '#':
580 *q++ = '\\';
581 *q++ = *p;
582 nbs = 0;
583 break;
584 case '\\':
585 *q++ = *p;
586 nbs++;
587 break;
588 default:
589 *q++ = *p;
590 nbs = 0;
591 break;
594 while (nbs--)
595 *q++ = '\\';
597 *q = '\0';
599 return os;
602 struct textargs {
603 const char *label;
604 int value;
607 #define OPT_PREFIX 0
608 #define OPT_POSTFIX 1
609 struct textargs textopts[] = {
610 {"prefix", OPT_PREFIX},
611 {"postfix", OPT_POSTFIX},
612 {NULL, 0}
615 static bool stopoptions = false;
616 static bool process_arg(char *p, char *q)
618 char *param;
619 int i;
620 bool advance = false;
621 bool suppress;
623 if (!p || !p[0])
624 return false;
626 if (p[0] == '-' && !stopoptions) {
627 if (strchr("oOfpPdDiIlFXuUZwW", p[1])) {
628 /* These parameters take values */
629 if (!(param = get_param(p, q, &advance)))
630 return advance;
633 switch (p[1]) {
634 case 's':
635 error_file = stdout;
636 break;
638 case 'o': /* output file */
639 copy_filename(outname, param);
640 break;
642 case 'f': /* output format */
643 ofmt = ofmt_find(param);
644 if (!ofmt) {
645 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
646 "unrecognised output format `%s' - "
647 "use -hf for a list", param);
648 } else {
649 ofmt->current_dfmt = ofmt->debug_formats[0];
651 break;
653 case 'O': /* Optimization level */
655 int opt;
657 if (!*param) {
658 /* Naked -O == -Ox */
659 optimizing = INT_MAX >> 1; /* Almost unlimited */
660 } else {
661 while (*param) {
662 switch (*param) {
663 case '0': case '1': case '2': case '3': case '4':
664 case '5': case '6': case '7': case '8': case '9':
665 opt = strtoul(param, &param, 10);
667 /* -O0 -> optimizing == -1, 0.98 behaviour */
668 /* -O1 -> optimizing == 0, 0.98.09 behaviour */
669 if (opt < 2)
670 optimizing = opt - 1;
671 else
672 optimizing = opt;
673 break;
675 case 'v':
676 case '+':
677 param++;
678 opt_verbose_info = true;
679 break;
681 case 'x':
682 param++;
683 optimizing = INT_MAX >> 1; /* Almost unlimited */
684 break;
686 default:
687 report_error(ERR_FATAL,
688 "unknown optimization option -O%c\n",
689 *param);
690 break;
694 break;
697 case 'p': /* pre-include */
698 case 'P':
699 pp_pre_include(param);
700 break;
702 case 'd': /* pre-define */
703 case 'D':
704 pp_pre_define(param);
705 break;
707 case 'u': /* un-define */
708 case 'U':
709 pp_pre_undefine(param);
710 break;
712 case 'i': /* include search path */
713 case 'I':
714 pp_include_path(param);
715 break;
717 case 'l': /* listing file */
718 copy_filename(listname, param);
719 break;
721 case 'Z': /* error messages file */
722 strcpy(errname, param);
723 break;
725 case 'F': /* specify debug format */
726 ofmt->current_dfmt = dfmt_find(ofmt, param);
727 if (!ofmt->current_dfmt) {
728 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
729 "unrecognized debug format `%s' for"
730 " output format `%s'",
731 param, ofmt->shortname);
733 using_debug_info = true;
734 break;
736 case 'X': /* specify error reporting format */
737 if (nasm_stricmp("vc", param) == 0)
738 report_error = report_error_vc;
739 else if (nasm_stricmp("gnu", param) == 0)
740 report_error = report_error_gnu;
741 else
742 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
743 "unrecognized error reporting format `%s'",
744 param);
745 break;
747 case 'g':
748 using_debug_info = true;
749 break;
751 case 'h':
752 printf
753 ("usage: nasm [-@ response file] [-o outfile] [-f format] "
754 "[-l listfile]\n"
755 " [options...] [--] filename\n"
756 " or nasm -v for version info\n\n"
757 " -t assemble in SciTech TASM compatible mode\n"
758 " -g generate debug information in selected format.\n");
759 printf
760 (" -E (or -e) preprocess only (writes output to stdout by default)\n"
761 " -a don't preprocess (assemble only)\n"
762 " -M generate Makefile dependencies on stdout\n"
763 " -MG d:o, missing files assumed generated\n\n"
764 " -Z<file> redirect error messages to file\n"
765 " -s redirect error messages to stdout\n\n"
766 " -F format select a debugging format\n\n"
767 " -I<path> adds a pathname to the include file path\n");
768 printf
769 (" -O<digit> optimize branch offsets (-O0 disables, default)\n"
770 " -P<file> pre-includes a file\n"
771 " -D<macro>[=<value>] pre-defines a macro\n"
772 " -U<macro> undefines a macro\n"
773 " -X<format> specifies error reporting format (gnu or vc)\n"
774 " -w+foo enables warning foo (equiv. -Wfoo)\n"
775 " -w-foo disable warning foo (equiv. -Wno-foo)\n"
776 "Warnings:\n");
777 for (i = 0; i <= ERR_WARN_MAX; i++)
778 printf(" %-23s %s (default %s)\n",
779 suppressed_names[i], suppressed_what[i],
780 suppressed_global[i] ? "off" : "on");
781 printf
782 ("\nresponse files should contain command line parameters"
783 ", one per line.\n");
784 if (p[2] == 'f') {
785 printf("\nvalid output formats for -f are"
786 " (`*' denotes default):\n");
787 ofmt_list(ofmt, stdout);
788 } else {
789 printf("\nFor a list of valid output formats, use -hf.\n");
790 printf("For a list of debug formats, use -f <form> -y.\n");
792 exit(0); /* never need usage message here */
793 break;
795 case 'y':
796 printf("\nvalid debug formats for '%s' output format are"
797 " ('*' denotes default):\n", ofmt->shortname);
798 dfmt_list(ofmt, stdout);
799 exit(0);
800 break;
802 case 't':
803 tasm_compatible_mode = true;
804 break;
806 case 'v':
808 const char *nasm_version_string =
809 "NASM version " NASM_VER " compiled on " __DATE__
810 #ifdef DEBUG
811 " with -DDEBUG"
812 #endif
814 puts(nasm_version_string);
815 exit(0); /* never need usage message here */
817 break;
819 case 'e': /* preprocess only */
820 case 'E':
821 operating_mode = op_preprocess;
822 break;
824 case 'a': /* assemble only - don't preprocess */
825 preproc = &no_pp;
826 break;
828 case 'W':
829 if (param[0] == 'n' && param[1] == 'o' && param[2] == '-') {
830 suppress = true;
831 param += 3;
832 } else {
833 suppress = false;
835 goto set_warning;
837 case 'w':
838 if (param[0] != '+' && param[0] != '-') {
839 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
840 "invalid option to `-w'");
841 break;
843 suppress = (param[0] == '-');
844 param++;
845 goto set_warning;
846 set_warning:
847 for (i = 0; i <= ERR_WARN_MAX; i++)
848 if (!nasm_stricmp(param, suppressed_names[i]))
849 break;
850 if (i <= ERR_WARN_MAX)
851 suppressed_global[i] = suppress;
852 else if (!nasm_stricmp(param, "all"))
853 for (i = 1; i <= ERR_WARN_MAX; i++)
854 suppressed_global[i] = suppress;
855 else if (!nasm_stricmp(param, "none"))
856 for (i = 1; i <= ERR_WARN_MAX; i++)
857 suppressed_global[i] = !suppress;
858 else
859 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
860 "invalid warning `%s'", param);
861 break;
863 case 'M':
864 switch (p[2]) {
865 case 0:
866 operating_mode = op_depend;
867 break;
868 case 'G':
869 operating_mode = op_depend;
870 depend_missing_ok = true;
871 break;
872 case 'P':
873 depend_emit_phony = true;
874 break;
875 case 'D':
876 depend_file = q;
877 advance = true;
878 break;
879 case 'T':
880 depend_target = q;
881 advance = true;
882 break;
883 case 'Q':
884 depend_target = quote_for_make(q);
885 advance = true;
886 break;
887 default:
888 report_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
889 "unknown dependency option `-M%c'", p[2]);
890 break;
892 if (advance && (!q || !q[0])) {
893 report_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
894 "option `-M%c' requires a parameter", p[2]);
895 break;
897 break;
899 case '-':
901 int s;
903 if (p[2] == 0) { /* -- => stop processing options */
904 stopoptions = 1;
905 break;
907 for (s = 0; textopts[s].label; s++) {
908 if (!nasm_stricmp(p + 2, textopts[s].label)) {
909 break;
913 switch (s) {
915 case OPT_PREFIX:
916 case OPT_POSTFIX:
918 if (!q) {
919 report_error(ERR_NONFATAL | ERR_NOFILE |
920 ERR_USAGE,
921 "option `--%s' requires an argument",
922 p + 2);
923 break;
924 } else {
925 advance = 1, param = q;
928 if (s == OPT_PREFIX) {
929 strncpy(lprefix, param, PREFIX_MAX - 1);
930 lprefix[PREFIX_MAX - 1] = 0;
931 break;
933 if (s == OPT_POSTFIX) {
934 strncpy(lpostfix, param, POSTFIX_MAX - 1);
935 lpostfix[POSTFIX_MAX - 1] = 0;
936 break;
938 break;
940 default:
942 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
943 "unrecognised option `--%s'", p + 2);
944 break;
947 break;
950 default:
951 if (!ofmt->setinfo(GI_SWITCH, &p))
952 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
953 "unrecognised option `-%c'", p[1]);
954 break;
956 } else {
957 if (*inname) {
958 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
959 "more than one input file specified");
960 } else {
961 copy_filename(inname, p);
965 return advance;
968 #define ARG_BUF_DELTA 128
970 static void process_respfile(FILE * rfile)
972 char *buffer, *p, *q, *prevarg;
973 int bufsize, prevargsize;
975 bufsize = prevargsize = ARG_BUF_DELTA;
976 buffer = nasm_malloc(ARG_BUF_DELTA);
977 prevarg = nasm_malloc(ARG_BUF_DELTA);
978 prevarg[0] = '\0';
980 while (1) { /* Loop to handle all lines in file */
981 p = buffer;
982 while (1) { /* Loop to handle long lines */
983 q = fgets(p, bufsize - (p - buffer), rfile);
984 if (!q)
985 break;
986 p += strlen(p);
987 if (p > buffer && p[-1] == '\n')
988 break;
989 if (p - buffer > bufsize - 10) {
990 int offset;
991 offset = p - buffer;
992 bufsize += ARG_BUF_DELTA;
993 buffer = nasm_realloc(buffer, bufsize);
994 p = buffer + offset;
998 if (!q && p == buffer) {
999 if (prevarg[0])
1000 process_arg(prevarg, NULL);
1001 nasm_free(buffer);
1002 nasm_free(prevarg);
1003 return;
1007 * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
1008 * them are present at the end of the line.
1010 *(p = &buffer[strcspn(buffer, "\r\n\032")]) = '\0';
1012 while (p > buffer && nasm_isspace(p[-1]))
1013 *--p = '\0';
1015 p = buffer;
1016 while (nasm_isspace(*p))
1017 p++;
1019 if (process_arg(prevarg, p))
1020 *p = '\0';
1022 if ((int) strlen(p) > prevargsize - 10) {
1023 prevargsize += ARG_BUF_DELTA;
1024 prevarg = nasm_realloc(prevarg, prevargsize);
1026 strncpy(prevarg, p, prevargsize);
1030 /* Function to process args from a string of args, rather than the
1031 * argv array. Used by the environment variable and response file
1032 * processing.
1034 static void process_args(char *args)
1036 char *p, *q, *arg, *prevarg;
1037 char separator = ' ';
1039 p = args;
1040 if (*p && *p != '-')
1041 separator = *p++;
1042 arg = NULL;
1043 while (*p) {
1044 q = p;
1045 while (*p && *p != separator)
1046 p++;
1047 while (*p == separator)
1048 *p++ = '\0';
1049 prevarg = arg;
1050 arg = q;
1051 if (process_arg(prevarg, arg))
1052 arg = NULL;
1054 if (arg)
1055 process_arg(arg, NULL);
1058 static void process_response_file(const char *file)
1060 char str[2048];
1061 FILE *f = fopen(file, "r");
1062 if (!f) {
1063 perror(file);
1064 exit(-1);
1066 while (fgets(str, sizeof str, f)) {
1067 process_args(str);
1069 fclose(f);
1072 static void parse_cmdline(int argc, char **argv)
1074 FILE *rfile;
1075 char *envreal, *envcopy = NULL, *p, *arg;
1077 *inname = *outname = *listname = *errname = '\0';
1080 * First, process the NASMENV environment variable.
1082 envreal = getenv("NASMENV");
1083 arg = NULL;
1084 if (envreal) {
1085 envcopy = nasm_strdup(envreal);
1086 process_args(envcopy);
1087 nasm_free(envcopy);
1091 * Now process the actual command line.
1093 while (--argc) {
1094 bool advance;
1095 argv++;
1096 if (argv[0][0] == '@') {
1097 /* We have a response file, so process this as a set of
1098 * arguments like the environment variable. This allows us
1099 * to have multiple arguments on a single line, which is
1100 * different to the -@resp file processing below for regular
1101 * NASM.
1103 process_response_file(argv[0]+1);
1104 argc--;
1105 argv++;
1107 if (!stopoptions && argv[0][0] == '-' && argv[0][1] == '@') {
1108 p = get_param(argv[0], argc > 1 ? argv[1] : NULL, &advance);
1109 if (p) {
1110 rfile = fopen(p, "r");
1111 if (rfile) {
1112 process_respfile(rfile);
1113 fclose(rfile);
1114 } else
1115 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
1116 "unable to open response file `%s'", p);
1118 } else
1119 advance = process_arg(argv[0], argc > 1 ? argv[1] : NULL);
1120 argv += advance, argc -= advance;
1123 /* Look for basic command line typos. This definitely doesn't
1124 catch all errors, but it might help cases of fumbled fingers. */
1125 if (!*inname)
1126 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
1127 "no input file specified");
1128 else if (!strcmp(inname, errname) ||
1129 !strcmp(inname, outname) ||
1130 !strcmp(inname, listname) ||
1131 (depend_file && !strcmp(inname, depend_file)))
1132 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
1133 "file `%s' is both input and output file",
1134 inname);
1136 if (*errname) {
1137 error_file = fopen(errname, "w");
1138 if (!error_file) {
1139 error_file = stderr; /* Revert to default! */
1140 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
1141 "cannot open file `%s' for error messages",
1142 errname);
1147 /* List of directives */
1148 enum directives {
1149 D_NONE, D_ABSOLUTE, D_BITS, D_COMMON, D_CPU, D_DEBUG, D_DEFAULT,
1150 D_EXTERN, D_FLOAT, D_GLOBAL, D_LIST, D_SECTION, D_SEGMENT, D_WARNING
1152 static const char *directives[] = {
1153 "", "absolute", "bits", "common", "cpu", "debug", "default",
1154 "extern", "float", "global", "list", "section", "segment", "warning"
1156 static enum directives getkw(char **directive, char **value);
1158 static void assemble_file(char *fname, StrList **depend_ptr)
1160 char *directive, *value, *p, *q, *special, *line, debugid[80];
1161 insn output_ins;
1162 int i, validid;
1163 bool rn_error;
1164 int32_t seg;
1165 int64_t offs;
1166 struct tokenval tokval;
1167 expr *e;
1168 int pass_max;
1170 if (cmd_sb == 32 && cmd_cpu < IF_386)
1171 report_error(ERR_FATAL, "command line: "
1172 "32-bit segment size requires a higher cpu");
1174 pass_max = prev_offset_changed = (INT_MAX >> 1) + 2; /* Almost unlimited */
1175 for (passn = 1; pass0 <= 2; passn++) {
1176 int pass1, pass2;
1177 ldfunc def_label;
1179 pass1 = pass0 == 2 ? 2 : 1; /* 1, 1, 1, ..., 1, 2 */
1180 pass2 = passn > 1 ? 2 : 1; /* 1, 2, 2, ..., 2, 2 */
1181 /* pass0 0, 0, 0, ..., 1, 2 */
1183 def_label = passn > 1 ? redefine_label : define_label;
1185 globalbits = sb = cmd_sb; /* set 'bits' to command line default */
1186 cpu = cmd_cpu;
1187 if (pass0 == 2) {
1188 if (*listname)
1189 nasmlist.init(listname, report_error);
1191 in_abs_seg = false;
1192 global_offset_changed = 0; /* set by redefine_label */
1193 location.segment = ofmt->section(NULL, pass2, &sb);
1194 globalbits = sb;
1195 if (passn > 1) {
1196 saa_rewind(forwrefs);
1197 forwref = saa_rstruct(forwrefs);
1198 raa_free(offsets);
1199 offsets = raa_init();
1201 preproc->reset(fname, pass1, report_error, evaluate, &nasmlist,
1202 pass1 == 2 ? depend_ptr : NULL);
1203 memcpy(suppressed, suppressed_global, (ERR_WARN_MAX+1) * sizeof(bool));
1205 globallineno = 0;
1206 if (passn == 1)
1207 location.known = true;
1208 location.offset = offs = GET_CURR_OFFS;
1210 while ((line = preproc->getline())) {
1211 enum directives d;
1212 globallineno++;
1214 /* here we parse our directives; this is not handled by the 'real'
1215 * parser. */
1216 directive = line;
1217 d = getkw(&directive, &value);
1218 if (d) {
1219 int err = 0;
1221 switch (d) {
1222 case D_SEGMENT: /* [SEGMENT n] */
1223 case D_SECTION:
1224 seg = ofmt->section(value, pass2, &sb);
1225 if (seg == NO_SEG) {
1226 report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
1227 "segment name `%s' not recognized",
1228 value);
1229 } else {
1230 in_abs_seg = false;
1231 location.segment = seg;
1233 break;
1234 case D_EXTERN: /* [EXTERN label:special] */
1235 if (*value == '$')
1236 value++; /* skip initial $ if present */
1237 if (pass0 == 2) {
1238 q = value;
1239 while (*q && *q != ':')
1240 q++;
1241 if (*q == ':') {
1242 *q++ = '\0';
1243 ofmt->symdef(value, 0L, 0L, 3, q);
1245 } else if (passn == 1) {
1246 q = value;
1247 validid = true;
1248 if (!isidstart(*q))
1249 validid = false;
1250 while (*q && *q != ':') {
1251 if (!isidchar(*q))
1252 validid = false;
1253 q++;
1255 if (!validid) {
1256 report_error(ERR_NONFATAL,
1257 "identifier expected after EXTERN");
1258 break;
1260 if (*q == ':') {
1261 *q++ = '\0';
1262 special = q;
1263 } else
1264 special = NULL;
1265 if (!is_extern(value)) { /* allow re-EXTERN to be ignored */
1266 int temp = pass0;
1267 pass0 = 1; /* fake pass 1 in labels.c */
1268 declare_as_global(value, special,
1269 report_error);
1270 define_label(value, seg_alloc(), 0L, NULL,
1271 false, true, ofmt, report_error);
1272 pass0 = temp;
1274 } /* else pass0 == 1 */
1275 break;
1276 case D_BITS: /* [BITS bits] */
1277 globalbits = sb = get_bits(value);
1278 break;
1279 case D_GLOBAL: /* [GLOBAL symbol:special] */
1280 if (*value == '$')
1281 value++; /* skip initial $ if present */
1282 if (pass0 == 2) { /* pass 2 */
1283 q = value;
1284 while (*q && *q != ':')
1285 q++;
1286 if (*q == ':') {
1287 *q++ = '\0';
1288 ofmt->symdef(value, 0L, 0L, 3, q);
1290 } else if (pass2 == 1) { /* pass == 1 */
1291 q = value;
1292 validid = true;
1293 if (!isidstart(*q))
1294 validid = false;
1295 while (*q && *q != ':') {
1296 if (!isidchar(*q))
1297 validid = false;
1298 q++;
1300 if (!validid) {
1301 report_error(ERR_NONFATAL,
1302 "identifier expected after GLOBAL");
1303 break;
1305 if (*q == ':') {
1306 *q++ = '\0';
1307 special = q;
1308 } else
1309 special = NULL;
1310 declare_as_global(value, special, report_error);
1311 } /* pass == 1 */
1312 break;
1313 case D_COMMON: /* [COMMON symbol size:special] */
1314 if (*value == '$')
1315 value++; /* skip initial $ if present */
1316 if (pass0 == 1) {
1317 p = value;
1318 validid = true;
1319 if (!isidstart(*p))
1320 validid = false;
1321 while (*p && !nasm_isspace(*p)) {
1322 if (!isidchar(*p))
1323 validid = false;
1324 p++;
1326 if (!validid) {
1327 report_error(ERR_NONFATAL,
1328 "identifier expected after COMMON");
1329 break;
1331 if (*p) {
1332 int64_t size;
1334 while (*p && nasm_isspace(*p))
1335 *p++ = '\0';
1336 q = p;
1337 while (*q && *q != ':')
1338 q++;
1339 if (*q == ':') {
1340 *q++ = '\0';
1341 special = q;
1342 } else
1343 special = NULL;
1344 size = readnum(p, &rn_error);
1345 if (rn_error)
1346 report_error(ERR_NONFATAL,
1347 "invalid size specified"
1348 " in COMMON declaration");
1349 else
1350 define_common(value, seg_alloc(), size,
1351 special, ofmt, report_error);
1352 } else
1353 report_error(ERR_NONFATAL,
1354 "no size specified in"
1355 " COMMON declaration");
1356 } else if (pass0 == 2) { /* pass == 2 */
1357 q = value;
1358 while (*q && *q != ':') {
1359 if (nasm_isspace(*q))
1360 *q = '\0';
1361 q++;
1363 if (*q == ':') {
1364 *q++ = '\0';
1365 ofmt->symdef(value, 0L, 0L, 3, q);
1368 break;
1369 case D_ABSOLUTE: /* [ABSOLUTE address] */
1370 stdscan_reset();
1371 stdscan_bufptr = value;
1372 tokval.t_type = TOKEN_INVALID;
1373 e = evaluate(stdscan, NULL, &tokval, NULL, pass2,
1374 report_error, NULL);
1375 if (e) {
1376 if (!is_reloc(e))
1377 report_error(pass0 ==
1378 1 ? ERR_NONFATAL : ERR_PANIC,
1379 "cannot use non-relocatable expression as "
1380 "ABSOLUTE address");
1381 else {
1382 abs_seg = reloc_seg(e);
1383 abs_offset = reloc_value(e);
1385 } else if (passn == 1)
1386 abs_offset = 0x100; /* don't go near zero in case of / */
1387 else
1388 report_error(ERR_PANIC, "invalid ABSOLUTE address "
1389 "in pass two");
1390 in_abs_seg = true;
1391 location.segment = NO_SEG;
1392 break;
1393 case D_DEBUG: /* [DEBUG] */
1394 p = value;
1395 q = debugid;
1396 validid = true;
1397 if (!isidstart(*p))
1398 validid = false;
1399 while (*p && !nasm_isspace(*p)) {
1400 if (!isidchar(*p))
1401 validid = false;
1402 *q++ = *p++;
1404 *q++ = 0;
1405 if (!validid) {
1406 report_error(passn == 1 ? ERR_NONFATAL : ERR_PANIC,
1407 "identifier expected after DEBUG");
1408 break;
1410 while (*p && nasm_isspace(*p))
1411 p++;
1412 if (pass0 == 2)
1413 ofmt->current_dfmt->debug_directive(debugid, p);
1414 break;
1415 case D_WARNING: /* [WARNING {+|-|*}warn-name] */
1416 if (pass1 == 1) {
1417 while (*value && nasm_isspace(*value))
1418 value++;
1420 switch(*value) {
1421 case '-': validid = 0; value++; break;
1422 case '+': validid = 1; value++; break;
1423 case '*': validid = 2; value++; break;
1424 default: /*
1425 * Should this error out?
1426 * I'll keep it so nothing breaks.
1428 validid = 1; break;
1431 for (i = 1; i <= ERR_WARN_MAX; i++)
1432 if (!nasm_stricmp(value, suppressed_names[i]))
1433 break;
1434 if (i <= ERR_WARN_MAX) {
1435 switch(validid) {
1436 case 0: suppressed[i] = true; break;
1437 case 1: suppressed[i] = false; break;
1438 case 2: suppressed[i] = suppressed_global[i];
1439 break;
1442 else
1443 report_error(ERR_NONFATAL,
1444 "invalid warning id in WARNING directive");
1446 break;
1447 case D_CPU: /* [CPU] */
1448 cpu = get_cpu(value);
1449 break;
1450 case D_LIST: /* [LIST {+|-}] */
1451 while (*value && nasm_isspace(*value))
1452 value++;
1454 if (*value == '+') {
1455 user_nolist = 0;
1456 } else {
1457 if (*value == '-') {
1458 user_nolist = 1;
1459 } else {
1460 err = 1;
1463 break;
1464 case D_DEFAULT: /* [DEFAULT] */
1465 stdscan_reset();
1466 stdscan_bufptr = value;
1467 tokval.t_type = TOKEN_INVALID;
1468 if (stdscan(NULL, &tokval) == TOKEN_SPECIAL) {
1469 switch ((int)tokval.t_integer) {
1470 case S_REL:
1471 globalrel = 1;
1472 break;
1473 case S_ABS:
1474 globalrel = 0;
1475 break;
1476 default:
1477 err = 1;
1478 break;
1480 } else {
1481 err = 1;
1483 break;
1484 case D_FLOAT:
1485 if (float_option(value)) {
1486 report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
1487 "unknown 'float' directive: %s",
1488 value);
1490 break;
1491 default:
1492 if (!ofmt->directive(directive, value, pass2))
1493 report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
1494 "unrecognised directive [%s]",
1495 directive);
1497 if (err) {
1498 report_error(ERR_NONFATAL,
1499 "invalid parameter to [%s] directive",
1500 directive);
1502 } else { /* it isn't a directive */
1504 parse_line(pass1, line, &output_ins,
1505 report_error, evaluate, def_label);
1507 if (optimizing > 0) {
1508 if (forwref != NULL && globallineno == forwref->lineno) {
1509 output_ins.forw_ref = true;
1510 do {
1511 output_ins.oprs[forwref->operand].opflags |=
1512 OPFLAG_FORWARD;
1513 forwref = saa_rstruct(forwrefs);
1514 } while (forwref != NULL
1515 && forwref->lineno == globallineno);
1516 } else
1517 output_ins.forw_ref = false;
1520 if (optimizing > 0) {
1521 if (passn == 1) {
1522 for (i = 0; i < output_ins.operands; i++) {
1523 if (output_ins.oprs[i].
1524 opflags & OPFLAG_FORWARD) {
1525 struct forwrefinfo *fwinf =
1526 (struct forwrefinfo *)
1527 saa_wstruct(forwrefs);
1528 fwinf->lineno = globallineno;
1529 fwinf->operand = i;
1535 /* forw_ref */
1536 if (output_ins.opcode == I_EQU) {
1537 if (pass1 == 1) {
1539 * Special `..' EQUs get processed in pass two,
1540 * except `..@' macro-processor EQUs which are done
1541 * in the normal place.
1543 if (!output_ins.label)
1544 report_error(ERR_NONFATAL,
1545 "EQU not preceded by label");
1547 else if (output_ins.label[0] != '.' ||
1548 output_ins.label[1] != '.' ||
1549 output_ins.label[2] == '@') {
1550 if (output_ins.operands == 1 &&
1551 (output_ins.oprs[0].type & IMMEDIATE) &&
1552 output_ins.oprs[0].wrt == NO_SEG) {
1553 int isext =
1554 output_ins.oprs[0].
1555 opflags & OPFLAG_EXTERN;
1556 def_label(output_ins.label,
1557 output_ins.oprs[0].segment,
1558 output_ins.oprs[0].offset, NULL,
1559 false, isext, ofmt,
1560 report_error);
1561 } else if (output_ins.operands == 2
1562 && (output_ins.oprs[0].
1563 type & IMMEDIATE)
1564 && (output_ins.oprs[0].type & COLON)
1565 && output_ins.oprs[0].segment ==
1566 NO_SEG
1567 && output_ins.oprs[0].wrt == NO_SEG
1568 && (output_ins.oprs[1].
1569 type & IMMEDIATE)
1570 && output_ins.oprs[1].segment ==
1571 NO_SEG
1572 && output_ins.oprs[1].wrt ==
1573 NO_SEG) {
1574 def_label(output_ins.label,
1575 output_ins.oprs[0].
1576 offset | SEG_ABS,
1577 output_ins.oprs[1].offset, NULL,
1578 false, false, ofmt,
1579 report_error);
1580 } else
1581 report_error(ERR_NONFATAL,
1582 "bad syntax for EQU");
1584 } else {
1586 * Special `..' EQUs get processed here, except
1587 * `..@' macro processor EQUs which are done above.
1589 if (output_ins.label[0] == '.' &&
1590 output_ins.label[1] == '.' &&
1591 output_ins.label[2] != '@') {
1592 if (output_ins.operands == 1 &&
1593 (output_ins.oprs[0].type & IMMEDIATE)) {
1594 define_label(output_ins.label,
1595 output_ins.oprs[0].segment,
1596 output_ins.oprs[0].offset,
1597 NULL, false, false, ofmt,
1598 report_error);
1599 } else if (output_ins.operands == 2
1600 && (output_ins.oprs[0].
1601 type & IMMEDIATE)
1602 && (output_ins.oprs[0].type & COLON)
1603 && output_ins.oprs[0].segment ==
1604 NO_SEG
1605 && (output_ins.oprs[1].
1606 type & IMMEDIATE)
1607 && output_ins.oprs[1].segment ==
1608 NO_SEG) {
1609 define_label(output_ins.label,
1610 output_ins.oprs[0].
1611 offset | SEG_ABS,
1612 output_ins.oprs[1].offset,
1613 NULL, false, false, ofmt,
1614 report_error);
1615 } else
1616 report_error(ERR_NONFATAL,
1617 "bad syntax for EQU");
1620 } else { /* instruction isn't an EQU */
1622 if (pass1 == 1) {
1624 int64_t l = insn_size(location.segment, offs, sb, cpu,
1625 &output_ins, report_error);
1627 /* if (using_debug_info) && output_ins.opcode != -1) */
1628 if (using_debug_info)
1629 { /* fbk 03/25/01 */
1630 /* this is done here so we can do debug type info */
1631 int32_t typeinfo =
1632 TYS_ELEMENTS(output_ins.operands);
1633 switch (output_ins.opcode) {
1634 case I_RESB:
1635 typeinfo =
1636 TYS_ELEMENTS(output_ins.oprs[0].
1637 offset) | TY_BYTE;
1638 break;
1639 case I_RESW:
1640 typeinfo =
1641 TYS_ELEMENTS(output_ins.oprs[0].
1642 offset) | TY_WORD;
1643 break;
1644 case I_RESD:
1645 typeinfo =
1646 TYS_ELEMENTS(output_ins.oprs[0].
1647 offset) | TY_DWORD;
1648 break;
1649 case I_RESQ:
1650 typeinfo =
1651 TYS_ELEMENTS(output_ins.oprs[0].
1652 offset) | TY_QWORD;
1653 break;
1654 case I_REST:
1655 typeinfo =
1656 TYS_ELEMENTS(output_ins.oprs[0].
1657 offset) | TY_TBYTE;
1658 break;
1659 case I_RESO:
1660 typeinfo =
1661 TYS_ELEMENTS(output_ins.oprs[0].
1662 offset) | TY_OWORD;
1663 break;
1664 case I_RESY:
1665 typeinfo =
1666 TYS_ELEMENTS(output_ins.oprs[0].
1667 offset) | TY_YWORD;
1668 break;
1669 case I_DB:
1670 typeinfo |= TY_BYTE;
1671 break;
1672 case I_DW:
1673 typeinfo |= TY_WORD;
1674 break;
1675 case I_DD:
1676 if (output_ins.eops_float)
1677 typeinfo |= TY_FLOAT;
1678 else
1679 typeinfo |= TY_DWORD;
1680 break;
1681 case I_DQ:
1682 typeinfo |= TY_QWORD;
1683 break;
1684 case I_DT:
1685 typeinfo |= TY_TBYTE;
1686 break;
1687 case I_DO:
1688 typeinfo |= TY_OWORD;
1689 break;
1690 case I_DY:
1691 typeinfo |= TY_YWORD;
1692 break;
1693 default:
1694 typeinfo = TY_LABEL;
1698 ofmt->current_dfmt->debug_typevalue(typeinfo);
1701 if (l != -1) {
1702 offs += l;
1703 SET_CURR_OFFS(offs);
1706 * else l == -1 => invalid instruction, which will be
1707 * flagged as an error on pass 2
1710 } else {
1711 offs += assemble(location.segment, offs, sb, cpu,
1712 &output_ins, ofmt, report_error,
1713 &nasmlist);
1714 SET_CURR_OFFS(offs);
1717 } /* not an EQU */
1718 cleanup_insn(&output_ins);
1720 nasm_free(line);
1721 location.offset = offs = GET_CURR_OFFS;
1722 } /* end while (line = preproc->getline... */
1723 if (pass1 == 2 && global_offset_changed)
1724 report_error(ERR_NONFATAL,
1725 "phase error detected at end of assembly.");
1727 if (pass1 == 1)
1728 preproc->cleanup(1);
1730 if (pass1 == 1 && terminate_after_phase) {
1731 fclose(ofile);
1732 remove(outname);
1733 if (want_usage)
1734 usage();
1735 exit(1);
1738 if (passn > 1 && !global_offset_changed)
1739 pass0++;
1740 else if (global_offset_changed && global_offset_changed < prev_offset_changed) {
1741 prev_offset_changed = global_offset_changed;
1742 stall_count = 0;
1744 else stall_count++;
1746 if((stall_count > 997) || (passn >= pass_max))
1747 /* We get here if the labels don't converge
1748 * Example: FOO equ FOO + 1
1750 report_error(ERR_NONFATAL,
1751 "Can't find valid values for all labels "
1752 "after %d passes, giving up.\n"
1753 " Possible cause: recursive equ's.", passn);
1756 preproc->cleanup(0);
1757 nasmlist.cleanup();
1758 if (opt_verbose_info) /* -On and -Ov switches */
1759 fprintf(stdout,
1760 "info:: assembly required 1+%d+1 passes\n", passn-3);
1761 } /* exit from assemble_file (...) */
1763 static enum directives getkw(char **directive, char **value)
1765 char *p, *q, *buf;
1767 buf = *directive;
1769 /* allow leading spaces or tabs */
1770 while (*buf == ' ' || *buf == '\t')
1771 buf++;
1773 if (*buf != '[')
1774 return 0;
1776 p = buf;
1778 while (*p && *p != ']')
1779 p++;
1781 if (!*p)
1782 return 0;
1784 q = p++;
1786 while (*p && *p != ';') {
1787 if (!nasm_isspace(*p))
1788 return 0;
1789 p++;
1791 q[1] = '\0';
1793 *directive = p = buf + 1;
1794 while (*buf && *buf != ' ' && *buf != ']' && *buf != '\t')
1795 buf++;
1796 if (*buf == ']') {
1797 *buf = '\0';
1798 *value = buf;
1799 } else {
1800 *buf++ = '\0';
1801 while (nasm_isspace(*buf))
1802 buf++; /* beppu - skip leading whitespace */
1803 *value = buf;
1804 while (*buf != ']')
1805 buf++;
1806 *buf++ = '\0';
1809 return bsii(*directive, directives, elements(directives));
1813 * gnu style error reporting
1814 * This function prints an error message to error_file in the
1815 * style used by GNU. An example would be:
1816 * file.asm:50: error: blah blah blah
1817 * where file.asm is the name of the file, 50 is the line number on
1818 * which the error occurs (or is detected) and "error:" is one of
1819 * the possible optional diagnostics -- it can be "error" or "warning"
1820 * or something else. Finally the line terminates with the actual
1821 * error message.
1823 * @param severity the severity of the warning or error
1824 * @param fmt the printf style format string
1826 static void report_error_gnu(int severity, const char *fmt, ...)
1828 va_list ap;
1830 if (is_suppressed_warning(severity))
1831 return;
1833 if (severity & ERR_NOFILE)
1834 fputs("nasm: ", error_file);
1835 else {
1836 char *currentfile = NULL;
1837 int32_t lineno = 0;
1838 src_get(&lineno, &currentfile);
1839 fprintf(error_file, "%s:%"PRId32": ", currentfile, lineno);
1840 nasm_free(currentfile);
1842 va_start(ap, fmt);
1843 report_error_common(severity, fmt, ap);
1844 va_end(ap);
1848 * MS style error reporting
1849 * This function prints an error message to error_file in the
1850 * style used by Visual C and some other Microsoft tools. An example
1851 * would be:
1852 * file.asm(50) : error: blah blah blah
1853 * where file.asm is the name of the file, 50 is the line number on
1854 * which the error occurs (or is detected) and "error:" is one of
1855 * the possible optional diagnostics -- it can be "error" or "warning"
1856 * or something else. Finally the line terminates with the actual
1857 * error message.
1859 * @param severity the severity of the warning or error
1860 * @param fmt the printf style format string
1862 static void report_error_vc(int severity, const char *fmt, ...)
1864 va_list ap;
1866 if (is_suppressed_warning(severity))
1867 return;
1869 if (severity & ERR_NOFILE)
1870 fputs("nasm: ", error_file);
1871 else {
1872 char *currentfile = NULL;
1873 int32_t lineno = 0;
1874 src_get(&lineno, &currentfile);
1875 fprintf(error_file, "%s(%"PRId32") : ", currentfile, lineno);
1876 nasm_free(currentfile);
1878 va_start(ap, fmt);
1879 report_error_common(severity, fmt, ap);
1880 va_end(ap);
1884 * check for supressed warning
1885 * checks for suppressed warning or pass one only warning and we're
1886 * not in pass 1
1888 * @param severity the severity of the warning or error
1889 * @return true if we should abort error/warning printing
1891 static bool is_suppressed_warning(int severity)
1894 * See if it's a suppressed warning.
1896 return (severity & ERR_MASK) == ERR_WARNING &&
1897 (((severity & ERR_WARN_MASK) != 0 &&
1898 suppressed[(severity & ERR_WARN_MASK) >> ERR_WARN_SHR]) ||
1899 /* See if it's a pass-one only warning and we're not in pass one. */
1900 ((severity & ERR_PASS1) && pass0 != 1));
1904 * common error reporting
1905 * This is the common back end of the error reporting schemes currently
1906 * implemented. It prints the nature of the warning and then the
1907 * specific error message to error_file and may or may not return. It
1908 * doesn't return if the error severity is a "panic" or "debug" type.
1910 * @param severity the severity of the warning or error
1911 * @param fmt the printf style format string
1913 static void report_error_common(int severity, const char *fmt,
1914 va_list args)
1916 switch (severity & (ERR_MASK|ERR_NO_SEVERITY)) {
1917 case ERR_WARNING:
1918 fputs("warning: ", error_file);
1919 break;
1920 case ERR_NONFATAL:
1921 fputs("error: ", error_file);
1922 break;
1923 case ERR_FATAL:
1924 fputs("fatal: ", error_file);
1925 break;
1926 case ERR_PANIC:
1927 fputs("panic: ", error_file);
1928 break;
1929 case ERR_DEBUG:
1930 fputs("debug: ", error_file);
1931 break;
1932 default:
1933 break;
1936 vfprintf(error_file, fmt, args);
1937 putc('\n', error_file);
1939 if (severity & ERR_USAGE)
1940 want_usage = true;
1942 switch (severity & ERR_MASK) {
1943 case ERR_DEBUG:
1944 /* no further action, by definition */
1945 break;
1946 case ERR_WARNING:
1947 if (!suppressed[0]) /* Treat warnings as errors */
1948 terminate_after_phase = true;
1949 break;
1950 case ERR_NONFATAL:
1951 terminate_after_phase = true;
1952 break;
1953 case ERR_FATAL:
1954 if (ofile) {
1955 fclose(ofile);
1956 remove(outname);
1958 if (want_usage)
1959 usage();
1960 exit(1); /* instantly die */
1961 break; /* placate silly compilers */
1962 case ERR_PANIC:
1963 fflush(NULL);
1964 /* abort(); *//* halt, catch fire, and dump core */
1965 exit(3);
1966 break;
1970 static void usage(void)
1972 fputs("type `nasm -h' for help\n", error_file);
1975 static void register_output_formats(void)
1977 ofmt = ofmt_register(report_error);
1980 #define BUF_DELTA 512
1982 static FILE *no_pp_fp;
1983 static efunc no_pp_err;
1984 static ListGen *no_pp_list;
1985 static int32_t no_pp_lineinc;
1987 static void no_pp_reset(char *file, int pass, efunc error, evalfunc eval,
1988 ListGen * listgen, StrList **deplist)
1990 src_set_fname(nasm_strdup(file));
1991 src_set_linnum(0);
1992 no_pp_lineinc = 1;
1993 no_pp_err = error;
1994 no_pp_fp = fopen(file, "r");
1995 if (!no_pp_fp)
1996 no_pp_err(ERR_FATAL | ERR_NOFILE,
1997 "unable to open input file `%s'", file);
1998 no_pp_list = listgen;
1999 (void)pass; /* placate compilers */
2000 (void)eval; /* placate compilers */
2002 if (deplist) {
2003 StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
2004 sl->next = NULL;
2005 strcpy(sl->str, file);
2006 *deplist = sl;
2010 static char *no_pp_getline(void)
2012 char *buffer, *p, *q;
2013 int bufsize;
2015 bufsize = BUF_DELTA;
2016 buffer = nasm_malloc(BUF_DELTA);
2017 src_set_linnum(src_get_linnum() + no_pp_lineinc);
2019 while (1) { /* Loop to handle %line */
2021 p = buffer;
2022 while (1) { /* Loop to handle long lines */
2023 q = fgets(p, bufsize - (p - buffer), no_pp_fp);
2024 if (!q)
2025 break;
2026 p += strlen(p);
2027 if (p > buffer && p[-1] == '\n')
2028 break;
2029 if (p - buffer > bufsize - 10) {
2030 int offset;
2031 offset = p - buffer;
2032 bufsize += BUF_DELTA;
2033 buffer = nasm_realloc(buffer, bufsize);
2034 p = buffer + offset;
2038 if (!q && p == buffer) {
2039 nasm_free(buffer);
2040 return NULL;
2044 * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
2045 * them are present at the end of the line.
2047 buffer[strcspn(buffer, "\r\n\032")] = '\0';
2049 if (!nasm_strnicmp(buffer, "%line", 5)) {
2050 int32_t ln;
2051 int li;
2052 char *nm = nasm_malloc(strlen(buffer));
2053 if (sscanf(buffer + 5, "%"PRId32"+%d %s", &ln, &li, nm) == 3) {
2054 nasm_free(src_set_fname(nm));
2055 src_set_linnum(ln);
2056 no_pp_lineinc = li;
2057 continue;
2059 nasm_free(nm);
2061 break;
2064 no_pp_list->line(LIST_READ, buffer);
2066 return buffer;
2069 static void no_pp_cleanup(int pass)
2071 (void)pass; /* placate GCC */
2072 fclose(no_pp_fp);
2075 static uint32_t get_cpu(char *value)
2077 if (!strcmp(value, "8086"))
2078 return IF_8086;
2079 if (!strcmp(value, "186"))
2080 return IF_186;
2081 if (!strcmp(value, "286"))
2082 return IF_286;
2083 if (!strcmp(value, "386"))
2084 return IF_386;
2085 if (!strcmp(value, "486"))
2086 return IF_486;
2087 if (!strcmp(value, "586") || !nasm_stricmp(value, "pentium"))
2088 return IF_PENT;
2089 if (!strcmp(value, "686") ||
2090 !nasm_stricmp(value, "ppro") ||
2091 !nasm_stricmp(value, "pentiumpro") || !nasm_stricmp(value, "p2"))
2092 return IF_P6;
2093 if (!nasm_stricmp(value, "p3") || !nasm_stricmp(value, "katmai"))
2094 return IF_KATMAI;
2095 if (!nasm_stricmp(value, "p4") || /* is this right? -- jrc */
2096 !nasm_stricmp(value, "willamette"))
2097 return IF_WILLAMETTE;
2098 if (!nasm_stricmp(value, "prescott"))
2099 return IF_PRESCOTT;
2100 if (!nasm_stricmp(value, "x64") ||
2101 !nasm_stricmp(value, "x86-64"))
2102 return IF_X86_64;
2103 if (!nasm_stricmp(value, "ia64") ||
2104 !nasm_stricmp(value, "ia-64") ||
2105 !nasm_stricmp(value, "itanium") ||
2106 !nasm_stricmp(value, "itanic") || !nasm_stricmp(value, "merced"))
2107 return IF_IA64;
2109 report_error(pass0 < 2 ? ERR_NONFATAL : ERR_FATAL,
2110 "unknown 'cpu' type");
2112 return IF_PLEVEL; /* the maximum level */
2115 static int get_bits(char *value)
2117 int i;
2119 if ((i = atoi(value)) == 16)
2120 return i; /* set for a 16-bit segment */
2121 else if (i == 32) {
2122 if (cpu < IF_386) {
2123 report_error(ERR_NONFATAL,
2124 "cannot specify 32-bit segment on processor below a 386");
2125 i = 16;
2127 } else if (i == 64) {
2128 if (cpu < IF_X86_64) {
2129 report_error(ERR_NONFATAL,
2130 "cannot specify 64-bit segment on processor below an x86-64");
2131 i = 16;
2133 if (i != maxbits) {
2134 report_error(ERR_NONFATAL,
2135 "%s output format does not support 64-bit code",
2136 ofmt->shortname);
2137 i = 16;
2139 } else {
2140 report_error(pass0 < 2 ? ERR_NONFATAL : ERR_FATAL,
2141 "`%s' is not a valid segment size; must be 16, 32 or 64",
2142 value);
2143 i = 16;
2145 return i;
2148 /* end of nasm.c */