Merge tag 'nasm-2.14.03rc1'
[nasm.git] / asm / nasm.c
blob644712c4eb70904c2d21c0bf85aa479220d9e459
1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2018 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
35 * The Netwide Assembler main program module
38 #include "compiler.h"
40 #include <stdio.h>
41 #include <stdarg.h>
42 #include <stdlib.h>
43 #include <limits.h>
45 #include "nasm.h"
46 #include "nasmlib.h"
47 #include "nctype.h"
48 #include "error.h"
49 #include "saa.h"
50 #include "raa.h"
51 #include "float.h"
52 #include "stdscan.h"
53 #include "insns.h"
54 #include "preproc.h"
55 #include "parser.h"
56 #include "eval.h"
57 #include "assemble.h"
58 #include "labels.h"
59 #include "outform.h"
60 #include "listing.h"
61 #include "iflag.h"
62 #include "ver.h"
65 * This is the maximum number of optimization passes to do. If we ever
66 * find a case where the optimizer doesn't naturally converge, we might
67 * have to drop this value so the assembler doesn't appear to just hang.
69 #define MAX_OPTIMIZE (INT_MAX >> 1)
71 struct forwrefinfo { /* info held on forward refs. */
72 int lineno;
73 int operand;
76 static void parse_cmdline(int, char **, int);
77 static void assemble_file(const char *, struct strlist *);
78 static bool skip_this_pass(errflags severity);
79 static void nasm_verror_asm(errflags severity, const char *fmt, va_list args);
80 static void usage(void);
81 static void help(char xopt);
83 struct error_format {
84 const char *beforeline; /* Before line number, if present */
85 const char *afterline; /* After line number, if present */
86 const char *beforemsg; /* Before actual message */
89 static const struct error_format errfmt_gnu = { ":", "", ": " };
90 static const struct error_format errfmt_msvc = { "(", ")", " : " };
91 static const struct error_format *errfmt = &errfmt_gnu;
92 static struct strlist *warn_list;
94 static bool using_debug_info, opt_verbose_info;
95 static const char *debug_format;
97 #ifndef ABORT_ON_PANIC
98 # define ABORT_ON_PANIC 0
99 #endif
100 static bool abort_on_panic = ABORT_ON_PANIC;
101 static bool keep_all;
103 bool tasm_compatible_mode = false;
104 enum pass_type _pass_type;
105 const char * const _pass_types[] =
107 "init", "first", "optimize", "stabilize", "final"
109 int64_t _passn;
110 int globalrel = 0;
111 int globalbnd = 0;
113 struct compile_time official_compile_time;
115 const char *inname;
116 const char *outname;
117 static const char *listname;
118 static const char *errname;
120 static int64_t globallineno; /* for forward-reference tracking */
122 const struct ofmt *ofmt = &OF_DEFAULT;
123 const struct ofmt_alias *ofmt_alias = NULL;
124 const struct dfmt *dfmt;
126 FILE *error_file; /* Where to write error messages */
128 FILE *ofile = NULL;
129 struct optimization optimizing =
130 { MAX_OPTIMIZE, OPTIM_ALL_ENABLED }; /* number of optimization passes to take */
131 static int cmd_sb = 16; /* by default */
133 iflag_t cpu;
134 static iflag_t cmd_cpu;
136 struct location location;
137 bool in_absolute; /* Flag we are in ABSOLUTE seg */
138 struct location absolute; /* Segment/offset inside ABSOLUTE */
140 static struct RAA *offsets;
142 static struct SAA *forwrefs; /* keep track of forward references */
143 static const struct forwrefinfo *forwref;
145 static const struct preproc_ops *preproc;
146 static struct strlist *include_path;
147 bool pp_noline; /* Ignore %line directives */
149 #define OP_NORMAL (1U << 0)
150 #define OP_PREPROCESS (1U << 1)
151 #define OP_DEPEND (1U << 2)
153 static unsigned int operating_mode;
155 /* Dependency flags */
156 static bool depend_emit_phony = false;
157 static bool depend_missing_ok = false;
158 static const char *depend_target = NULL;
159 static const char *depend_file = NULL;
160 struct strlist *depend_list;
162 static bool want_usage;
163 static bool terminate_after_phase;
164 bool user_nolist = false;
166 static char *quote_for_pmake(const char *str);
167 static char *quote_for_wmake(const char *str);
168 static char *(*quote_for_make)(const char *) = quote_for_pmake;
171 * Execution limits that can be set via a command-line option or %pragma
174 #define LIMIT_MAX_VAL (INT64_MAX >> 1) /* Effectively unlimited */
176 int64_t nasm_limit[LIMIT_MAX+1] =
177 { LIMIT_MAX_VAL, 1000, 1000000, 1000000, 1000000, 2000000000 };
179 struct limit_info {
180 const char *name;
181 const char *help;
183 static const struct limit_info limit_info[LIMIT_MAX+1] = {
184 { "passes", "total number of passes" },
185 { "stalled-passes", "number of passes without forward progress" },
186 { "macro-levels", "levels of macro expansion"},
187 { "rep", "%rep count" },
188 { "eval", "expression evaluation descent"},
189 { "lines", "total source lines processed"}
192 enum directive_result
193 nasm_set_limit(const char *limit, const char *valstr)
195 int i;
196 int64_t val;
197 bool rn_error;
198 int errlevel;
200 for (i = 0; i <= LIMIT_MAX; i++) {
201 if (!nasm_stricmp(limit, limit_info[i].name))
202 break;
204 if (i > LIMIT_MAX) {
205 if (not_started())
206 errlevel = ERR_WARNING|WARN_OTHER|ERR_USAGE;
207 else
208 errlevel = ERR_WARNING|WARN_UNKNOWN_PRAGMA;
209 nasm_error(errlevel, "unknown limit: `%s'", limit);
210 return DIRR_ERROR;
213 if (!nasm_stricmp(valstr, "unlimited")) {
214 val = LIMIT_MAX_VAL;
215 } else {
216 val = readnum(valstr, &rn_error);
217 if (rn_error || val < 0) {
218 if (not_started())
219 errlevel = ERR_WARNING|WARN_OTHER|ERR_USAGE;
220 else
221 errlevel = ERR_WARNING|WARN_BAD_PRAGMA;
222 nasm_error(errlevel, "invalid limit value: `%s'", limit);
223 return DIRR_ERROR;
225 if (val > LIMIT_MAX_VAL)
226 val = LIMIT_MAX_VAL;
229 nasm_limit[i] = val;
230 return DIRR_OK;
233 int64_t switch_segment(int32_t segment)
235 location.segment = segment;
236 if (segment == NO_SEG) {
237 location.offset = absolute.offset;
238 in_absolute = true;
239 } else {
240 location.offset = raa_read(offsets, segment);
241 in_absolute = false;
243 return location.offset;
246 static void set_curr_offs(int64_t l_off)
248 if (in_absolute)
249 absolute.offset = l_off;
250 else
251 offsets = raa_write(offsets, location.segment, l_off);
254 static void increment_offset(int64_t delta)
256 if (unlikely(delta == 0))
257 return;
259 location.offset += delta;
260 set_curr_offs(location.offset);
263 static void nasm_fputs(const char *line, FILE * outfile)
265 if (outfile) {
266 fputs(line, outfile);
267 putc('\n', outfile);
268 } else
269 puts(line);
273 * Define system-defined macros that are not part of
274 * macros/standard.mac.
276 static void define_macros(void)
278 const struct compile_time * const oct = &official_compile_time;
279 char temp[128];
281 if (oct->have_local) {
282 strftime(temp, sizeof temp, "__DATE__=\"%Y-%m-%d\"", &oct->local);
283 preproc->pre_define(temp);
284 strftime(temp, sizeof temp, "__DATE_NUM__=%Y%m%d", &oct->local);
285 preproc->pre_define(temp);
286 strftime(temp, sizeof temp, "__TIME__=\"%H:%M:%S\"", &oct->local);
287 preproc->pre_define(temp);
288 strftime(temp, sizeof temp, "__TIME_NUM__=%H%M%S", &oct->local);
289 preproc->pre_define(temp);
292 if (oct->have_gm) {
293 strftime(temp, sizeof temp, "__UTC_DATE__=\"%Y-%m-%d\"", &oct->gm);
294 preproc->pre_define(temp);
295 strftime(temp, sizeof temp, "__UTC_DATE_NUM__=%Y%m%d", &oct->gm);
296 preproc->pre_define(temp);
297 strftime(temp, sizeof temp, "__UTC_TIME__=\"%H:%M:%S\"", &oct->gm);
298 preproc->pre_define(temp);
299 strftime(temp, sizeof temp, "__UTC_TIME_NUM__=%H%M%S", &oct->gm);
300 preproc->pre_define(temp);
303 if (oct->have_posix) {
304 snprintf(temp, sizeof temp, "__POSIX_TIME__=%"PRId64, oct->posix);
305 preproc->pre_define(temp);
309 * In case if output format is defined by alias
310 * we have to put shortname of the alias itself here
311 * otherwise ABI backward compatibility gets broken.
313 snprintf(temp, sizeof(temp), "__OUTPUT_FORMAT__=%s",
314 ofmt_alias ? ofmt_alias->shortname : ofmt->shortname);
315 preproc->pre_define(temp);
318 * Output-format specific macros.
320 if (ofmt->stdmac)
321 preproc->extra_stdmac(ofmt->stdmac);
324 * Debug format, if any
326 if (dfmt != &null_debug_form) {
327 snprintf(temp, sizeof(temp), "__DEBUG_FORMAT__=%s", dfmt->shortname);
328 preproc->pre_define(temp);
333 * Initialize the preprocessor, set up the include path, and define
334 * the system-included macros. This is called between passes 1 and 2
335 * of parsing the command options; ofmt and dfmt are defined at this
336 * point.
338 * Command-line specified preprocessor directives (-p, -d, -u,
339 * --pragma, --before) are processed after this function.
341 static void preproc_init(struct strlist *ipath)
343 preproc->init();
344 define_macros();
345 preproc->include_path(ipath);
348 static void emit_dependencies(struct strlist *list)
350 FILE *deps;
351 int linepos, len;
352 bool wmake = (quote_for_make == quote_for_wmake);
353 const char *wrapstr, *nulltarget;
354 const struct strlist_entry *l;
356 if (!list)
357 return;
359 wrapstr = wmake ? " &\n " : " \\\n ";
360 nulltarget = wmake ? "\t%null\n" : "";
362 if (depend_file && strcmp(depend_file, "-")) {
363 deps = nasm_open_write(depend_file, NF_TEXT);
364 if (!deps) {
365 nasm_nonfatal("unable to write dependency file `%s'", depend_file);
366 return;
368 } else {
369 deps = stdout;
372 linepos = fprintf(deps, "%s :", depend_target);
373 strlist_for_each(l, list) {
374 char *file = quote_for_make(l->str);
375 len = strlen(file);
376 if (linepos + len > 62 && linepos > 1) {
377 fputs(wrapstr, deps);
378 linepos = 1;
380 fprintf(deps, " %s", file);
381 linepos += len+1;
382 nasm_free(file);
384 fprintf(deps, "\n\n");
386 strlist_for_each(l, list) {
387 if (depend_emit_phony) {
388 char *file = quote_for_make(l->str);
389 fprintf(deps, "%s :\n%s\n", file, nulltarget);
390 nasm_free(file);
394 strlist_free(&list);
396 if (deps != stdout)
397 fclose(deps);
400 /* Convert a struct tm to a POSIX-style time constant */
401 static int64_t make_posix_time(const struct tm *tm)
403 int64_t t;
404 int64_t y = tm->tm_year;
406 /* See IEEE 1003.1:2004, section 4.14 */
408 t = (y-70)*365 + (y-69)/4 - (y-1)/100 + (y+299)/400;
409 t += tm->tm_yday;
410 t *= 24;
411 t += tm->tm_hour;
412 t *= 60;
413 t += tm->tm_min;
414 t *= 60;
415 t += tm->tm_sec;
417 return t;
420 static void timestamp(void)
422 struct compile_time * const oct = &official_compile_time;
423 const struct tm *tp, *best_gm;
425 time(&oct->t);
427 best_gm = NULL;
429 tp = localtime(&oct->t);
430 if (tp) {
431 oct->local = *tp;
432 best_gm = &oct->local;
433 oct->have_local = true;
436 tp = gmtime(&oct->t);
437 if (tp) {
438 oct->gm = *tp;
439 best_gm = &oct->gm;
440 oct->have_gm = true;
441 if (!oct->have_local)
442 oct->local = oct->gm;
443 } else {
444 oct->gm = oct->local;
447 if (best_gm) {
448 oct->posix = make_posix_time(best_gm);
449 oct->have_posix = true;
453 int main(int argc, char **argv)
455 timestamp();
457 error_file = stderr;
459 iflag_set_default_cpu(&cpu);
460 iflag_set_default_cpu(&cmd_cpu);
462 include_path = strlist_alloc(true);
464 _pass_type = PASS_INIT;
465 _passn = 0;
467 want_usage = terminate_after_phase = false;
468 nasm_set_verror(nasm_verror_asm);
470 nasm_ctype_init();
471 src_init();
474 * We must call init_labels() before the command line parsing,
475 * because we may be setting prefixes/suffixes from the command
476 * line.
478 init_labels();
480 offsets = raa_init();
481 forwrefs = saa_init((int32_t)sizeof(struct forwrefinfo));
483 preproc = &nasmpp;
484 operating_mode = OP_NORMAL;
486 parse_cmdline(argc, argv, 1);
487 if (terminate_after_phase) {
488 if (want_usage)
489 usage();
490 return 1;
493 /* At this point we have ofmt and the name of the desired debug format */
494 if (!using_debug_info) {
495 /* No debug info, redirect to the null backend (empty stubs) */
496 dfmt = &null_debug_form;
497 } else if (!debug_format) {
498 /* Default debug format for this backend */
499 dfmt = ofmt->default_dfmt;
500 } else {
501 dfmt = dfmt_find(ofmt, debug_format);
502 if (!dfmt) {
503 nasm_fatalf(ERR_USAGE, "unrecognized debug format `%s' for output format `%s'",
504 debug_format, ofmt->shortname);
508 preproc_init(include_path);
510 parse_cmdline(argc, argv, 2);
511 if (terminate_after_phase) {
512 if (want_usage)
513 usage();
514 return 1;
517 /* Save away the default state of warnings */
518 memcpy(warning_state_init, warning_state, sizeof warning_state_init);
520 /* Dependency filename if we are also doing other things */
521 if (!depend_file && (operating_mode & ~OP_DEPEND)) {
522 if (outname)
523 depend_file = nasm_strcat(outname, ".d");
524 else
525 depend_file = filename_set_extension(inname, ".d");
529 * If no output file name provided and this
530 * is preprocess mode, we're perfectly
531 * fine to output into stdout.
533 if (!outname && !(operating_mode & OP_PREPROCESS)) {
534 outname = filename_set_extension(inname, ofmt->extension);
535 if (!strcmp(outname, inname)) {
536 outname = "nasm.out";
537 nasm_warn(WARN_OTHER, "default output file same as input, using `%s' for output\n", outname);
541 depend_list = (operating_mode & OP_DEPEND) ? strlist_alloc(true) : NULL;
543 if (!depend_target)
544 depend_target = quote_for_make(outname);
546 if (!(operating_mode & (OP_PREPROCESS|OP_NORMAL))) {
547 char *line;
549 if (depend_missing_ok)
550 preproc->include_path(NULL); /* "assume generated" */
552 preproc->reset(inname, PP_DEPS, depend_list);
553 ofile = NULL;
554 while ((line = preproc->getline()))
555 nasm_free(line);
556 preproc->cleanup_pass();
557 } else if (operating_mode & OP_PREPROCESS) {
558 char *line;
559 const char *file_name = NULL;
560 int32_t prior_linnum = 0;
561 int lineinc = 0;
563 if (outname) {
564 ofile = nasm_open_write(outname, NF_TEXT);
565 if (!ofile)
566 nasm_fatal("unable to open output file `%s'", outname);
567 } else
568 ofile = NULL;
570 location.known = false;
572 _pass_type = PASS_FIRST; /* We emulate this assembly pass */
573 preproc->reset(inname, PP_PREPROC, depend_list);
575 /* Revert all warnings to the default state */
576 memcpy(warning_state, warning_state_init, sizeof warning_state);
578 while ((line = preproc->getline())) {
580 * We generate %line directives if needed for later programs
582 int32_t linnum = prior_linnum += lineinc;
583 int altline = src_get(&linnum, &file_name);
584 if (altline) {
585 if (altline == 1 && lineinc == 1)
586 nasm_fputs("", ofile);
587 else {
588 lineinc = (altline != -1 || lineinc != 1);
589 fprintf(ofile ? ofile : stdout,
590 "%%line %"PRId32"+%d %s\n", linnum, lineinc,
591 file_name);
593 prior_linnum = linnum;
595 nasm_fputs(line, ofile);
596 nasm_free(line);
598 preproc->cleanup_pass();
599 if (ofile)
600 fclose(ofile);
601 if (ofile && terminate_after_phase && !keep_all)
602 remove(outname);
603 ofile = NULL;
606 if (operating_mode & OP_NORMAL) {
607 ofile = nasm_open_write(outname, (ofmt->flags & OFMT_TEXT) ? NF_TEXT : NF_BINARY);
608 if (!ofile)
609 nasm_fatal("unable to open output file `%s'", outname);
611 ofmt->init();
612 dfmt->init();
614 assemble_file(inname, depend_list);
616 if (!terminate_after_phase) {
617 ofmt->cleanup();
618 cleanup_labels();
619 fflush(ofile);
620 if (ferror(ofile))
621 nasm_nonfatal("write error on output file `%s'", outname);
624 if (ofile) {
625 fclose(ofile);
626 if (terminate_after_phase && !keep_all)
627 remove(outname);
628 ofile = NULL;
632 preproc->cleanup_session();
634 if (depend_list && !terminate_after_phase)
635 emit_dependencies(depend_list);
637 if (want_usage)
638 usage();
640 raa_free(offsets);
641 saa_free(forwrefs);
642 eval_cleanup();
643 stdscan_cleanup();
644 src_free();
645 strlist_free(&include_path);
647 return terminate_after_phase;
651 * Get a parameter for a command line option.
652 * First arg must be in the form of e.g. -f...
654 static char *get_param(char *p, char *q, bool *advance)
656 *advance = false;
657 if (p[2]) /* the parameter's in the option */
658 return nasm_skip_spaces(p + 2);
659 if (q && q[0]) {
660 *advance = true;
661 return q;
663 nasm_nonfatalf(ERR_USAGE, "option `-%c' requires an argument", p[1]);
664 return NULL;
668 * Copy a filename
670 static void copy_filename(const char **dst, const char *src, const char *what)
672 if (*dst)
673 nasm_fatal("more than one %s file specified: %s\n", what, src);
675 *dst = nasm_strdup(src);
679 * Convert a string to a POSIX make-safe form
681 static char *quote_for_pmake(const char *str)
683 const char *p;
684 char *os, *q;
686 size_t n = 1; /* Terminating zero */
687 size_t nbs = 0;
689 if (!str)
690 return NULL;
692 for (p = str; *p; p++) {
693 switch (*p) {
694 case ' ':
695 case '\t':
696 /* Convert N backslashes + ws -> 2N+1 backslashes + ws */
697 n += nbs + 2;
698 nbs = 0;
699 break;
700 case '$':
701 case '#':
702 nbs = 0;
703 n += 2;
704 break;
705 case '\\':
706 nbs++;
707 n++;
708 break;
709 default:
710 nbs = 0;
711 n++;
712 break;
716 /* Convert N backslashes at the end of filename to 2N backslashes */
717 if (nbs)
718 n += nbs;
720 os = q = nasm_malloc(n);
722 nbs = 0;
723 for (p = str; *p; p++) {
724 switch (*p) {
725 case ' ':
726 case '\t':
727 while (nbs--)
728 *q++ = '\\';
729 *q++ = '\\';
730 *q++ = *p;
731 break;
732 case '$':
733 *q++ = *p;
734 *q++ = *p;
735 nbs = 0;
736 break;
737 case '#':
738 *q++ = '\\';
739 *q++ = *p;
740 nbs = 0;
741 break;
742 case '\\':
743 *q++ = *p;
744 nbs++;
745 break;
746 default:
747 *q++ = *p;
748 nbs = 0;
749 break;
752 while (nbs--)
753 *q++ = '\\';
755 *q = '\0';
757 return os;
761 * Convert a string to a Watcom make-safe form
763 static char *quote_for_wmake(const char *str)
765 const char *p;
766 char *os, *q;
767 bool quote = false;
769 size_t n = 1; /* Terminating zero */
771 if (!str)
772 return NULL;
774 for (p = str; *p; p++) {
775 switch (*p) {
776 case ' ':
777 case '\t':
778 case '&':
779 quote = true;
780 n++;
781 break;
782 case '\"':
783 quote = true;
784 n += 2;
785 break;
786 case '$':
787 case '#':
788 n += 2;
789 break;
790 default:
791 n++;
792 break;
796 if (quote)
797 n += 2;
799 os = q = nasm_malloc(n);
801 if (quote)
802 *q++ = '\"';
804 for (p = str; *p; p++) {
805 switch (*p) {
806 case '$':
807 case '#':
808 *q++ = '$';
809 *q++ = *p;
810 break;
811 case '\"':
812 *q++ = *p;
813 *q++ = *p;
814 break;
815 default:
816 *q++ = *p;
817 break;
821 if (quote)
822 *q++ = '\"';
824 *q = '\0';
826 return os;
829 enum text_options {
830 OPT_BOGUS,
831 OPT_VERSION,
832 OPT_HELP,
833 OPT_ABORT_ON_PANIC,
834 OPT_MANGLE,
835 OPT_INCLUDE,
836 OPT_PRAGMA,
837 OPT_BEFORE,
838 OPT_LIMIT,
839 OPT_KEEP_ALL,
840 OPT_NO_LINE
842 struct textargs {
843 const char *label;
844 enum text_options opt;
845 bool need_arg;
846 int pvt;
848 static const struct textargs textopts[] = {
849 {"v", OPT_VERSION, false, 0},
850 {"version", OPT_VERSION, false, 0},
851 {"help", OPT_HELP, false, 0},
852 {"abort-on-panic", OPT_ABORT_ON_PANIC, false, 0},
853 {"prefix", OPT_MANGLE, true, LM_GPREFIX},
854 {"postfix", OPT_MANGLE, true, LM_GSUFFIX},
855 {"gprefix", OPT_MANGLE, true, LM_GPREFIX},
856 {"gpostfix", OPT_MANGLE, true, LM_GSUFFIX},
857 {"lprefix", OPT_MANGLE, true, LM_LPREFIX},
858 {"lpostfix", OPT_MANGLE, true, LM_LSUFFIX},
859 {"include", OPT_INCLUDE, true, 0},
860 {"pragma", OPT_PRAGMA, true, 0},
861 {"before", OPT_BEFORE, true, 0},
862 {"limit-", OPT_LIMIT, true, 0},
863 {"keep-all", OPT_KEEP_ALL, false, 0},
864 {"no-line", OPT_NO_LINE, false, 0},
865 {NULL, OPT_BOGUS, false, 0}
868 static void show_version(void)
870 printf("NASM version %s compiled on %s%s\n",
871 nasm_version, nasm_date, nasm_compile_options);
872 exit(0);
875 static bool stopoptions = false;
876 static bool process_arg(char *p, char *q, int pass)
878 char *param;
879 bool advance = false;
881 if (!p || !p[0])
882 return false;
884 if (p[0] == '-' && !stopoptions) {
885 if (strchr("oOfpPdDiIlFXuUZwW", p[1])) {
886 /* These parameters take values */
887 if (!(param = get_param(p, q, &advance)))
888 return advance;
891 switch (p[1]) {
892 case 's':
893 if (pass == 1)
894 error_file = stdout;
895 break;
897 case 'o': /* output file */
898 if (pass == 2)
899 copy_filename(&outname, param, "output");
900 break;
902 case 'f': /* output format */
903 if (pass == 1) {
904 ofmt = ofmt_find(param, &ofmt_alias);
905 if (!ofmt) {
906 nasm_fatalf(ERR_USAGE, "unrecognised output format `%s' - use -hf for a list", param);
909 break;
911 case 'O': /* Optimization level */
912 if (pass == 1) {
913 int opt;
915 if (!*param) {
916 /* Naked -O == -Ox */
917 optimizing.level = MAX_OPTIMIZE;
918 } else {
919 while (*param) {
920 switch (*param) {
921 case '0': case '1': case '2': case '3': case '4':
922 case '5': case '6': case '7': case '8': case '9':
923 opt = strtoul(param, &param, 10);
925 /* -O0 -> optimizing.level == -1, 0.98 behaviour */
926 /* -O1 -> optimizing.level == 0, 0.98.09 behaviour */
927 if (opt < 2)
928 optimizing.level = opt - 1;
929 else
930 optimizing.level = opt;
931 break;
933 case 'v':
934 case '+':
935 param++;
936 opt_verbose_info = true;
937 break;
939 case 'x':
940 param++;
941 optimizing.level = MAX_OPTIMIZE;
942 break;
944 default:
945 nasm_fatal("unknown optimization option -O%c\n",
946 *param);
947 break;
950 if (optimizing.level > MAX_OPTIMIZE)
951 optimizing.level = MAX_OPTIMIZE;
954 break;
956 case 'p': /* pre-include */
957 case 'P':
958 if (pass == 2)
959 preproc->pre_include(param);
960 break;
962 case 'd': /* pre-define */
963 case 'D':
964 if (pass == 2)
965 preproc->pre_define(param);
966 break;
968 case 'u': /* un-define */
969 case 'U':
970 if (pass == 2)
971 preproc->pre_undefine(param);
972 break;
974 case 'i': /* include search path */
975 case 'I':
976 if (pass == 1)
977 strlist_add(include_path, param);
978 break;
980 case 'l': /* listing file */
981 if (pass == 2)
982 copy_filename(&listname, param, "listing");
983 break;
985 case 'Z': /* error messages file */
986 if (pass == 1)
987 copy_filename(&errname, param, "error");
988 break;
990 case 'F': /* specify debug format */
991 if (pass == 1) {
992 using_debug_info = true;
993 debug_format = param;
995 break;
997 case 'X': /* specify error reporting format */
998 if (pass == 1) {
999 if (!nasm_stricmp("vc", param) || !nasm_stricmp("msvc", param) || !nasm_stricmp("ms", param))
1000 errfmt = &errfmt_msvc;
1001 else if (!nasm_stricmp("gnu", param) || !nasm_stricmp("gcc", param))
1002 errfmt = &errfmt_gnu;
1003 else
1004 nasm_fatalf(ERR_USAGE, "unrecognized error reporting format `%s'", param);
1006 break;
1008 case 'g':
1009 if (pass == 1) {
1010 using_debug_info = true;
1011 if (p[2])
1012 debug_format = nasm_skip_spaces(p + 2);
1014 break;
1016 case 'h':
1017 help(p[2]);
1018 exit(0); /* never need usage message here */
1019 break;
1021 case 'y':
1022 printf("\nvalid debug formats for '%s' output format are"
1023 " ('*' denotes default):\n", ofmt->shortname);
1024 dfmt_list(ofmt, stdout);
1025 exit(0);
1026 break;
1028 case 't':
1029 if (pass == 2) {
1030 tasm_compatible_mode = true;
1031 nasm_ctype_tasm_mode();
1033 break;
1035 case 'v':
1036 show_version();
1037 break;
1039 case 'e': /* preprocess only */
1040 case 'E':
1041 if (pass == 1)
1042 operating_mode = OP_PREPROCESS;
1043 break;
1045 case 'a': /* assemble only - don't preprocess */
1046 if (pass == 1)
1047 preproc = &preproc_nop;
1048 break;
1050 case 'w':
1051 case 'W':
1052 if (pass == 2)
1053 set_warning_status(param);
1054 break;
1056 case 'M':
1057 if (pass == 1) {
1058 switch (p[2]) {
1059 case 'W':
1060 quote_for_make = quote_for_wmake;
1061 break;
1062 case 'D':
1063 case 'F':
1064 case 'T':
1065 case 'Q':
1066 advance = true;
1067 break;
1068 default:
1069 break;
1071 } else {
1072 switch (p[2]) {
1073 case 0:
1074 operating_mode = OP_DEPEND;
1075 break;
1076 case 'G':
1077 operating_mode = OP_DEPEND;
1078 depend_missing_ok = true;
1079 break;
1080 case 'P':
1081 depend_emit_phony = true;
1082 break;
1083 case 'D':
1084 operating_mode |= OP_DEPEND;
1085 if (q && (q[0] != '-' || q[1] == '\0')) {
1086 depend_file = q;
1087 advance = true;
1089 break;
1090 case 'F':
1091 depend_file = q;
1092 advance = true;
1093 break;
1094 case 'T':
1095 depend_target = q;
1096 advance = true;
1097 break;
1098 case 'Q':
1099 depend_target = quote_for_make(q);
1100 advance = true;
1101 break;
1102 case 'W':
1103 /* handled in pass 1 */
1104 break;
1105 default:
1106 nasm_nonfatalf(ERR_USAGE, "unknown dependency option `-M%c'", p[2]);
1107 break;
1110 if (advance && (!q || !q[0])) {
1111 nasm_nonfatalf(ERR_USAGE, "option `-M%c' requires a parameter", p[2]);
1112 break;
1114 break;
1116 case '-':
1118 const struct textargs *tx;
1119 size_t olen, plen;
1120 char *eqsave;
1122 p += 2;
1124 if (!*p) { /* -- => stop processing options */
1125 stopoptions = true;
1126 break;
1129 olen = 0; /* Placate gcc at lower optimization levels */
1130 plen = strlen(p);
1131 for (tx = textopts; tx->label; tx++) {
1132 olen = strlen(tx->label);
1134 if (olen > plen)
1135 continue;
1137 if (nasm_memicmp(p, tx->label, olen))
1138 continue;
1140 if (tx->label[olen-1] == '-')
1141 break; /* Incomplete option */
1143 if (!p[olen] || p[olen] == '=')
1144 break; /* Complete option */
1147 if (!tx->label) {
1148 nasm_nonfatalf(ERR_USAGE, "unrecognized option `--%s'", p);
1151 eqsave = param = strchr(p+olen, '=');
1152 if (param)
1153 *param++ = '\0';
1155 if (tx->need_arg) {
1156 if (!param) {
1157 param = q;
1158 advance = true;
1161 /* Note: a null string is a valid parameter */
1162 if (!param) {
1163 nasm_nonfatalf(ERR_USAGE, "option `--%s' requires an argument", p);
1164 break;
1166 } else {
1167 if (param) {
1168 nasm_nonfatalf(ERR_USAGE, "option `--%s' does not take an argument", p);
1172 switch (tx->opt) {
1173 case OPT_VERSION:
1174 show_version();
1175 break;
1176 case OPT_ABORT_ON_PANIC:
1177 abort_on_panic = true;
1178 break;
1179 case OPT_MANGLE:
1180 if (pass == 2)
1181 set_label_mangle(tx->pvt, param);
1182 break;
1183 case OPT_INCLUDE:
1184 if (pass == 2)
1185 preproc->pre_include(q);
1186 break;
1187 case OPT_PRAGMA:
1188 if (pass == 2)
1189 preproc->pre_command("pragma", param);
1190 break;
1191 case OPT_BEFORE:
1192 if (pass == 2)
1193 preproc->pre_command(NULL, param);
1194 break;
1195 case OPT_LIMIT:
1196 if (pass == 1)
1197 nasm_set_limit(p+olen, param);
1198 break;
1199 case OPT_KEEP_ALL:
1200 keep_all = true;
1201 break;
1202 case OPT_NO_LINE:
1203 pp_noline = true;
1204 break;
1205 case OPT_HELP:
1206 help(0);
1207 exit(0);
1208 default:
1209 panic();
1212 if (eqsave)
1213 *eqsave = '='; /* Restore = argument separator */
1215 break;
1218 default:
1219 nasm_nonfatalf(ERR_USAGE, "unrecognised option `-%c'", p[1]);
1220 break;
1222 } else if (pass == 2) {
1223 /* In theory we could allow multiple input files... */
1224 copy_filename(&inname, p, "input");
1227 return advance;
1230 #define ARG_BUF_DELTA 128
1232 static void process_respfile(FILE * rfile, int pass)
1234 char *buffer, *p, *q, *prevarg;
1235 int bufsize, prevargsize;
1237 bufsize = prevargsize = ARG_BUF_DELTA;
1238 buffer = nasm_malloc(ARG_BUF_DELTA);
1239 prevarg = nasm_malloc(ARG_BUF_DELTA);
1240 prevarg[0] = '\0';
1242 while (1) { /* Loop to handle all lines in file */
1243 p = buffer;
1244 while (1) { /* Loop to handle long lines */
1245 q = fgets(p, bufsize - (p - buffer), rfile);
1246 if (!q)
1247 break;
1248 p += strlen(p);
1249 if (p > buffer && p[-1] == '\n')
1250 break;
1251 if (p - buffer > bufsize - 10) {
1252 int offset;
1253 offset = p - buffer;
1254 bufsize += ARG_BUF_DELTA;
1255 buffer = nasm_realloc(buffer, bufsize);
1256 p = buffer + offset;
1260 if (!q && p == buffer) {
1261 if (prevarg[0])
1262 process_arg(prevarg, NULL, pass);
1263 nasm_free(buffer);
1264 nasm_free(prevarg);
1265 return;
1269 * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
1270 * them are present at the end of the line.
1272 *(p = &buffer[strcspn(buffer, "\r\n\032")]) = '\0';
1274 while (p > buffer && nasm_isspace(p[-1]))
1275 *--p = '\0';
1277 p = nasm_skip_spaces(buffer);
1279 if (process_arg(prevarg, p, pass))
1280 *p = '\0';
1282 if ((int) strlen(p) > prevargsize - 10) {
1283 prevargsize += ARG_BUF_DELTA;
1284 prevarg = nasm_realloc(prevarg, prevargsize);
1286 strncpy(prevarg, p, prevargsize);
1290 /* Function to process args from a string of args, rather than the
1291 * argv array. Used by the environment variable and response file
1292 * processing.
1294 static void process_args(char *args, int pass)
1296 char *p, *q, *arg, *prevarg;
1297 char separator = ' ';
1299 p = args;
1300 if (*p && *p != '-')
1301 separator = *p++;
1302 arg = NULL;
1303 while (*p) {
1304 q = p;
1305 while (*p && *p != separator)
1306 p++;
1307 while (*p == separator)
1308 *p++ = '\0';
1309 prevarg = arg;
1310 arg = q;
1311 if (process_arg(prevarg, arg, pass))
1312 arg = NULL;
1314 if (arg)
1315 process_arg(arg, NULL, pass);
1318 static void process_response_file(const char *file, int pass)
1320 char str[2048];
1321 FILE *f = nasm_open_read(file, NF_TEXT);
1322 if (!f) {
1323 perror(file);
1324 exit(-1);
1326 while (fgets(str, sizeof str, f)) {
1327 process_args(str, pass);
1329 fclose(f);
1332 static void parse_cmdline(int argc, char **argv, int pass)
1334 FILE *rfile;
1335 char *envreal, *envcopy = NULL, *p;
1338 * Initialize all the warnings to their default state, including
1339 * warning index 0 used for "always on".
1341 memcpy(warning_state, warning_default, sizeof warning_state);
1342 memcpy(warning_state_init, warning_default, sizeof warning_state_init);
1345 * First, process the NASMENV environment variable.
1347 envreal = getenv("NASMENV");
1348 if (envreal) {
1349 envcopy = nasm_strdup(envreal);
1350 process_args(envcopy, pass);
1351 nasm_free(envcopy);
1355 * Now process the actual command line.
1357 while (--argc) {
1358 bool advance;
1359 argv++;
1360 if (argv[0][0] == '@') {
1362 * We have a response file, so process this as a set of
1363 * arguments like the environment variable. This allows us
1364 * to have multiple arguments on a single line, which is
1365 * different to the -@resp file processing below for regular
1366 * NASM.
1368 process_response_file(argv[0]+1, pass);
1369 argc--;
1370 argv++;
1372 if (!stopoptions && argv[0][0] == '-' && argv[0][1] == '@') {
1373 p = get_param(argv[0], argc > 1 ? argv[1] : NULL, &advance);
1374 if (p) {
1375 rfile = nasm_open_read(p, NF_TEXT);
1376 if (rfile) {
1377 process_respfile(rfile, pass);
1378 fclose(rfile);
1379 } else {
1380 nasm_nonfatalf(ERR_USAGE, "unable to open response file `%s'", p);
1383 } else
1384 advance = process_arg(argv[0], argc > 1 ? argv[1] : NULL, pass);
1385 argv += advance, argc -= advance;
1389 * Look for basic command line typos. This definitely doesn't
1390 * catch all errors, but it might help cases of fumbled fingers.
1392 if (pass != 2)
1393 return;
1395 if (!inname)
1396 nasm_fatalf(ERR_USAGE, "no input file specified");
1397 else if ((errname && !strcmp(inname, errname)) ||
1398 (outname && !strcmp(inname, outname)) ||
1399 (listname && !strcmp(inname, listname)) ||
1400 (depend_file && !strcmp(inname, depend_file)))
1401 nasm_fatalf(ERR_USAGE, "will not overwrite input file");
1403 if (errname) {
1404 error_file = nasm_open_write(errname, NF_TEXT);
1405 if (!error_file) {
1406 error_file = stderr; /* Revert to default! */
1407 nasm_fatalf(ERR_USAGE, "cannot open file `%s' for error messages", errname);
1412 static void forward_refs(insn *instruction)
1414 int i;
1415 struct forwrefinfo *fwinf;
1417 instruction->forw_ref = false;
1419 if (!optimizing.level)
1420 return; /* For -O0 don't bother */
1422 if (!forwref)
1423 return;
1425 if (forwref->lineno != globallineno)
1426 return;
1428 instruction->forw_ref = true;
1429 do {
1430 instruction->oprs[forwref->operand].opflags |= OPFLAG_FORWARD;
1431 forwref = saa_rstruct(forwrefs);
1432 } while (forwref && forwref->lineno == globallineno);
1434 if (!pass_first())
1435 return;
1437 for (i = 0; i < instruction->operands; i++) {
1438 if (instruction->oprs[i].opflags & OPFLAG_FORWARD) {
1439 fwinf = saa_wstruct(forwrefs);
1440 fwinf->lineno = globallineno;
1441 fwinf->operand = i;
1446 static void process_insn(insn *instruction)
1448 int32_t n;
1449 int64_t l;
1451 if (!instruction->times)
1452 return; /* Nothing to do... */
1454 nasm_assert(instruction->times > 0);
1457 * NOTE: insn_size() can change instruction->times
1458 * (usually to 1) when called.
1460 if (!pass_final()) {
1461 for (n = 1; n <= instruction->times; n++) {
1462 l = insn_size(location.segment, location.offset,
1463 globalbits, instruction);
1464 if (l != -1) /* l == -1 -> invalid instruction */
1465 increment_offset(l);
1467 } else {
1468 l = assemble(location.segment, location.offset,
1469 globalbits, instruction);
1470 /* We can't get an invalid instruction here */
1471 increment_offset(l);
1473 if (instruction->times > 1) {
1474 lfmt->uplevel(LIST_TIMES);
1475 for (n = 2; n <= instruction->times; n++) {
1476 l = assemble(location.segment, location.offset,
1477 globalbits, instruction);
1478 increment_offset(l);
1480 lfmt->downlevel(LIST_TIMES);
1485 static void assemble_file(const char *fname, struct strlist *depend_list)
1487 char *line;
1488 insn output_ins;
1489 uint64_t prev_offset_changed;
1490 int64_t stall_count = 0; /* Make sure we make forward progress... */
1492 switch (cmd_sb) {
1493 case 16:
1494 break;
1495 case 32:
1496 if (!iflag_cpu_level_ok(&cmd_cpu, IF_386))
1497 nasm_fatal("command line: 32-bit segment size requires a higher cpu");
1498 break;
1499 case 64:
1500 if (!iflag_cpu_level_ok(&cmd_cpu, IF_X86_64))
1501 nasm_fatal("command line: 64-bit segment size requires a higher cpu");
1502 break;
1503 default:
1504 panic();
1505 break;
1508 prev_offset_changed = INT64_MAX;
1510 if (listname && !keep_all) {
1511 /* Remove the list file in case we die before the output pass */
1512 remove(listname);
1515 while (!terminate_after_phase && !pass_final()) {
1516 _passn++;
1517 if (pass_type() != PASS_OPT || !global_offset_changed)
1518 _pass_type++;
1519 global_offset_changed = 0;
1522 * Create a warning buffer list unless we are in
1523 * pass 2 (everything will be emitted immediately in pass 2.)
1525 if (warn_list) {
1526 if (warn_list->nstr || pass_final())
1527 strlist_free(&warn_list);
1530 if (!pass_final() && !warn_list)
1531 warn_list = strlist_alloc(false);
1533 globalbits = cmd_sb; /* set 'bits' to command line default */
1534 cpu = cmd_cpu;
1535 if (pass_final())
1536 lfmt->init(listname);
1538 in_absolute = false;
1539 if (!pass_first()) {
1540 saa_rewind(forwrefs);
1541 forwref = saa_rstruct(forwrefs);
1542 raa_free(offsets);
1543 offsets = raa_init();
1545 location.segment = NO_SEG;
1546 location.offset = 0;
1547 if (pass_first())
1548 location.known = true;
1549 ofmt->reset();
1550 switch_segment(ofmt->section(NULL, &globalbits));
1551 preproc->reset(fname, PP_NORMAL, pass_final() ? depend_list : NULL);
1553 /* Revert all warnings to the default state */
1554 memcpy(warning_state, warning_state_init, sizeof warning_state);
1556 globallineno = 0;
1558 while ((line = preproc->getline())) {
1559 if (++globallineno > nasm_limit[LIMIT_LINES])
1560 nasm_fatal("overall line count exceeds the maximum %"PRId64"\n",
1561 nasm_limit[LIMIT_LINES]);
1564 * Here we parse our directives; this is not handled by the
1565 * main parser.
1567 if (process_directives(line))
1568 goto end_of_line; /* Just do final cleanup */
1570 /* Not a directive, or even something that starts with [ */
1571 parse_line(line, &output_ins);
1572 forward_refs(&output_ins);
1573 process_insn(&output_ins);
1574 cleanup_insn(&output_ins);
1576 end_of_line:
1577 nasm_free(line);
1578 } /* end while (line = preproc->getline... */
1580 preproc->cleanup_pass();
1582 /* Don't output further messages if we are dead anyway */
1583 if (terminate_after_phase)
1584 break;
1586 if (global_offset_changed) {
1587 switch (pass_type()) {
1588 case PASS_OPT:
1590 * This is the only pass type that can be executed more
1591 * than once, and therefore has the ability to stall.
1593 if (global_offset_changed < prev_offset_changed) {
1594 prev_offset_changed = global_offset_changed;
1595 stall_count = 0;
1596 } else {
1597 stall_count++;
1600 if (stall_count > nasm_limit[LIMIT_STALLED] ||
1601 pass_count() >= nasm_limit[LIMIT_PASSES]) {
1602 /* No convergence, almost certainly dead */
1603 nasm_nonfatal("unable to find valid values for all labels "
1604 "after %"PRId64" passes; "
1605 "stalled for %"PRId64", giving up.",
1606 pass_count(), stall_count);
1607 nasm_note("Possible causes: recursive EQUs, macro abuse.");
1609 break;
1611 case PASS_STAB:
1613 *!phase [off] phase error during stabilization
1614 *! warns about symbols having changed values during
1615 *! the second-to-last assembly pass. This is not
1616 *! inherently fatal, but may be a source of bugs.
1618 nasm_warn(WARN_PHASE, "phase error during stabilization "
1619 "pass, hoping for the best");
1620 break;
1622 case PASS_FINAL:
1623 nasm_nonfatal("phase error during code generation pass");
1624 break;
1626 default:
1627 /* This is normal, we'll keep going... */
1628 break;
1633 if (opt_verbose_info && pass_final()) {
1634 /* -On and -Ov switches */
1635 nasm_note("info: assembly required 1+%"PRId64"+2 passes\n",
1636 pass_count()-3);
1639 strlist_free(&warn_list);
1640 lfmt->cleanup();
1644 * get warning index; 0 if this is non-suppressible.
1646 static size_t warn_index(errflags severity)
1648 size_t index;
1650 if ((severity & ERR_MASK) >= ERR_FATAL)
1651 return 0; /* Fatal errors are never suppressible */
1653 /* Warnings MUST HAVE a warning category specifier! */
1654 nasm_assert((severity & (ERR_MASK|WARN_MASK)) != ERR_WARNING);
1656 index = WARN_IDX(severity);
1657 nasm_assert(index < WARN_IDX_ALL);
1659 return index;
1662 static bool skip_this_pass(errflags severity)
1665 * See if it's a pass-specific error or warning which should be skipped.
1666 * We can never skip fatal errors as by definition they cannot be
1667 * resumed from.
1669 if ((severity & ERR_MASK) >= ERR_FATAL)
1670 return false;
1672 /* This message not applicable unless pass_final */
1673 return (severity & ERR_PASS2) && !pass_final();
1677 * check for suppressed message (usually warnings or notes)
1679 * @param severity the severity of the warning or error
1680 * @return true if we should abort error/warning printing
1682 static bool is_suppressed(errflags severity)
1684 /* Fatal errors must never be suppressed */
1685 if ((severity & ERR_MASK) >= ERR_FATAL)
1686 return false;
1688 /* This error/warning is pointless if we are dead anyway */
1689 if ((severity & ERR_UNDEAD) && terminate_after_phase)
1690 return true;
1692 return !(warning_state[warn_index(severity)] & WARN_ST_ENABLED);
1696 * Return the true error type (the ERR_MASK part) of the given
1697 * severity, accounting for warnings that may need to be promoted to
1698 * error.
1700 * @param severity the severity of the warning or error
1701 * @return true if we should error out
1703 static errflags true_error_type(errflags severity)
1705 const uint8_t warn_is_err = WARN_ST_ENABLED|WARN_ST_ERROR;
1706 int type;
1708 type = severity & ERR_MASK;
1710 /* Promote warning to error? */
1711 if (type == ERR_WARNING) {
1712 uint8_t state = warning_state[warn_index(severity)];
1713 if ((state & warn_is_err) == warn_is_err)
1714 type = ERR_NONFATAL;
1717 return type;
1721 * common error reporting
1722 * This is the common back end of the error reporting schemes currently
1723 * implemented. It prints the nature of the warning and then the
1724 * specific error message to error_file and may or may not return. It
1725 * doesn't return if the error severity is a "panic" or "debug" type.
1727 * @param severity the severity of the warning or error
1728 * @param fmt the printf style format string
1730 static void nasm_verror_asm(errflags severity, const char *fmt, va_list args)
1732 char msg[1024];
1733 char warnsuf[64];
1734 char linestr[64];
1735 const char *pfx;
1736 errflags spec_type = severity & ERR_MASK; /* type originally specified */
1737 errflags true_type = true_error_type(severity);
1738 const char *currentfile = NULL;
1739 int32_t lineno = 0;
1740 static const char * const pfx_table[ERR_MASK+1] = {
1741 "debug: ", "note: ", "warning: ", "error: ",
1742 "", "", "fatal: ", "panic: "
1745 if (is_suppressed(severity))
1746 return;
1748 if (!(severity & ERR_NOFILE)) {
1749 src_get(&lineno, &currentfile);
1750 if (!currentfile) {
1751 currentfile = currentfile ? currentfile :
1752 inname && inname[0] ? inname :
1753 outname && outname[0] ? outname :
1754 NULL;
1755 lineno = 0;
1760 * For a debug/warning/note event, if ERR_HERE is set don't
1761 * output anything if there is no current filename available
1763 if (!currentfile && (severity & ERR_HERE) && true_type <= ERR_WARNING)
1764 return;
1766 if (severity & ERR_NO_SEVERITY)
1767 pfx = "";
1768 else
1769 pfx = pfx_table[true_type];
1771 vsnprintf(msg, sizeof msg, fmt, args);
1772 *warnsuf = 0;
1773 if (spec_type == ERR_WARNING) {
1774 snprintf(warnsuf, sizeof warnsuf, " [-w+%s%s]",
1775 (true_type >= ERR_NONFATAL) ? "error=" : "",
1776 warning_name[warn_index(severity)]);
1779 *linestr = 0;
1780 if (lineno) {
1781 snprintf(linestr, sizeof linestr, "%s%"PRId32"%s",
1782 errfmt->beforeline, lineno, errfmt->afterline);
1785 if (!skip_this_pass(severity)) {
1786 const char *file = currentfile ? currentfile : "nasm";
1787 const char *here = (severity & ERR_HERE) ? " here" : "";
1789 if (warn_list && true_type < ERR_NONFATAL &&
1790 !(pass_first() && (severity & ERR_PASS1)))
1793 * Buffer up warnings until we either get an error
1794 * or we are on the code-generation pass.
1796 strlist_printf(warn_list, "%s%s%s%s%s%s%s",
1797 file, linestr, errfmt->beforemsg,
1798 pfx, msg, here, warnsuf);
1799 } else {
1801 * If we have buffered warnings, and this is a non-warning,
1802 * output them now.
1804 if (true_type >= ERR_NONFATAL && warn_list) {
1805 strlist_write(warn_list, "\n", error_file);
1806 strlist_free(&warn_list);
1809 fprintf(error_file, "%s%s%s%s%s%s%s\n",
1810 file, linestr, errfmt->beforemsg,
1811 pfx, msg, here, warnsuf);
1816 /* Are we recursing from error_list_macros? */
1817 if (severity & ERR_PP_LISTMACRO)
1818 return;
1821 * Don't suppress this with skip_this_pass(), or we don't get
1822 * pass1 or preprocessor warnings in the list file
1824 if (severity & ERR_HERE) {
1825 if (lineno)
1826 lfmt->error(severity, "%s%s at %s:%"PRId32"%s",
1827 pfx, msg, currentfile, lineno, warnsuf);
1828 else if (currentfile)
1829 lfmt->error(severity, "%s%s in file %s%s",
1830 pfx, msg, currentfile, warnsuf);
1831 else
1832 lfmt->error(severity, "%s%s in unknown location%s",
1833 pfx, msg, warnsuf);
1834 } else {
1835 lfmt->error(severity, "%s%s%s", pfx, msg, warnsuf);
1838 if (skip_this_pass(severity))
1839 return;
1841 if (severity & ERR_USAGE)
1842 want_usage = true;
1844 preproc->error_list_macros(severity);
1846 switch (true_type) {
1847 case ERR_NOTE:
1848 case ERR_DEBUG:
1849 case ERR_WARNING:
1850 /* no further action, by definition */
1851 break;
1852 case ERR_NONFATAL:
1853 terminate_after_phase = true;
1854 break;
1855 case ERR_FATAL:
1856 if (ofile) {
1857 fclose(ofile);
1858 if (!keep_all)
1859 remove(outname);
1860 ofile = NULL;
1862 if (want_usage)
1863 usage();
1864 exit(1); /* instantly die */
1865 break; /* placate silly compilers */
1866 case ERR_PANIC:
1867 fflush(NULL);
1869 if (abort_on_panic)
1870 abort(); /* halt, catch fire, dump core/stop debugger */
1872 if (ofile) {
1873 fclose(ofile);
1874 if (!keep_all)
1875 remove(outname);
1876 ofile = NULL;
1878 exit(3);
1879 break;
1880 default:
1881 break; /* ??? */
1885 static void usage(void)
1887 fputs("type `nasm -h' for help\n", error_file);
1890 static void help(const char xopt)
1892 int i;
1894 printf
1895 ("usage: nasm [-@ response file] [-o outfile] [-f format] "
1896 "[-l listfile]\n"
1897 " [options...] [--] filename\n"
1898 " or nasm -v (or --v) for version info\n\n"
1899 "\n"
1900 "Response files should contain command line parameters,\n"
1901 "one per line.\n"
1902 "\n"
1903 " -t assemble in SciTech TASM compatible mode\n");
1904 printf
1905 (" -E (or -e) preprocess only (writes output to stdout by default)\n"
1906 " -a don't preprocess (assemble only)\n"
1907 " -M generate Makefile dependencies on stdout\n"
1908 " -MG d:o, missing files assumed generated\n"
1909 " -MF file set Makefile dependency file\n"
1910 " -MD file assemble and generate dependencies\n"
1911 " -MT file dependency target name\n"
1912 " -MQ file dependency target name (quoted)\n"
1913 " -MP emit phony target\n\n"
1914 " -Zfile redirect error messages to file\n"
1915 " -s redirect error messages to stdout\n\n"
1916 " -g generate debugging information\n\n"
1917 " -F format select a debugging format\n\n"
1918 " -gformat same as -g -F format\n\n"
1919 " -o outfile write output to an outfile\n\n"
1920 " -f format select an output format\n\n"
1921 " -l listfile write listing to a listfile\n\n"
1922 " -Ipath add a pathname to the include file path\n");
1923 printf
1924 (" -Oflags... optimize opcodes, immediates and branch offsets\n"
1925 " -O0 no optimization\n"
1926 " -O1 minimal optimization\n"
1927 " -Ox multipass optimization (default)\n"
1928 " -Ov display the number of passes executed at the end\n"
1929 " -Pfile pre-include a file (also --include)\n"
1930 " -Dmacro[=str] pre-define a macro\n"
1931 " -Umacro undefine a macro\n"
1932 " -Xformat specifiy error reporting format (gnu or vc)\n"
1933 " -w+foo enable warning foo (equiv. -Wfoo)\n"
1934 " -w-foo disable warning foo (equiv. -Wno-foo)\n"
1935 " -w[+-]error[=foo]\n"
1936 " promote [specific] warnings to errors\n"
1937 " -h show invocation summary and exit (also --help)\n\n"
1938 " --pragma str pre-executes a specific %%pragma\n"
1939 " --before str add line (usually a preprocessor statement) before the input\n"
1940 " --prefix str prepend the given string to all the given string\n"
1941 " to all extern, common and global symbols (also --gprefix)\n"
1942 " --postfix str append the given string to all the given string\n"
1943 " to all extern, common and global symbols (also --gpostfix)\n"
1944 " --lprefix str prepend the given string to all other symbols\n"
1945 " --lpostfix str append the given string to all other symbols\n"
1946 " --keep-all output files will not be removed even if an error happens\n"
1947 " --no-line ignore %%line directives in input\n"
1948 " --limit-X val set execution limit X\n");
1950 for (i = 0; i <= LIMIT_MAX; i++) {
1951 printf(" %-15s %s (default ",
1952 limit_info[i].name, limit_info[i].help);
1953 if (nasm_limit[i] < LIMIT_MAX_VAL) {
1954 printf("%"PRId64")\n", nasm_limit[i]);
1955 } else {
1956 printf("unlimited)\n");
1960 printf("\nWarnings for the -W/-w options: (defaults in brackets)\n");
1962 for (i = 1; i <= WARN_IDX_ALL; i++) {
1963 printf(" %-23s %s%s\n",
1964 warning_name[i], warning_help[i],
1965 i == WARN_IDX_ALL ? "\n" :
1966 (warning_default[i] & WARN_ST_ERROR) ? " [error]" :
1967 (warning_default[i] & WARN_ST_ENABLED) ? " [on]" : " [off]");
1970 if (xopt == 'f') {
1971 printf("valid output formats for -f are"
1972 " (`*' denotes default):\n");
1973 ofmt_list(ofmt, stdout);
1974 } else {
1975 printf("For a list of valid output formats, use -hf.\n");
1976 printf("For a list of debug formats, use -f <format> -y.\n");