Don't forget to setup warning levels on preprocessor phase
[platform/upstream/nasm.git] / nasm.c
1 /* ----------------------------------------------------------------------- *
2  *
3  *   Copyright 1996-2011 The NASM Authors - All Rights Reserved
4  *   See the file AUTHORS included with the NASM distribution for
5  *   the specific copyright holders.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following
9  *   conditions are met:
10  *
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.
17  *
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.
31  *
32  * ----------------------------------------------------------------------- */
33
34 /*
35  * The Netwide Assembler main program module
36  */
37
38 #include "compiler.h"
39
40 #include <stdio.h>
41 #include <stdarg.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <ctype.h>
45 #include <inttypes.h>
46 #include <limits.h>
47 #include <time.h>
48
49 #include "nasm.h"
50 #include "nasmlib.h"
51 #include "saa.h"
52 #include "raa.h"
53 #include "float.h"
54 #include "stdscan.h"
55 #include "insns.h"
56 #include "preproc.h"
57 #include "parser.h"
58 #include "eval.h"
59 #include "assemble.h"
60 #include "labels.h"
61 #include "output/outform.h"
62 #include "listing.h"
63
64 /*
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.
68  */
69 #define MAX_OPTIMIZE (INT_MAX >> 1)
70
71 struct forwrefinfo {            /* info held on forward refs. */
72     int lineno;
73     int operand;
74 };
75
76 static int get_bits(char *value);
77 static uint32_t get_cpu(char *cpu_str);
78 static void parse_cmdline(int, char **);
79 static void assemble_file(char *, StrList **);
80 static void nasm_verror_gnu(int severity, const char *fmt, va_list args);
81 static void nasm_verror_vc(int severity, const char *fmt, va_list args);
82 static void nasm_verror_common(int severity, const char *fmt, va_list args);
83 static bool is_suppressed_warning(int severity);
84 static void usage(void);
85
86 static int using_debug_info, opt_verbose_info;
87 bool tasm_compatible_mode = false;
88 int pass0, passn;
89 int maxbits = 0;
90 int globalrel = 0;
91
92 static time_t official_compile_time;
93
94 static char inname[FILENAME_MAX];
95 static char outname[FILENAME_MAX];
96 static char listname[FILENAME_MAX];
97 static char errname[FILENAME_MAX];
98 static int globallineno;        /* for forward-reference tracking */
99 /* static int pass = 0; */
100 struct ofmt *ofmt = &OF_DEFAULT;
101 struct ofmt_alias *ofmt_alias = NULL;
102 const struct dfmt *dfmt;
103
104 static FILE *error_file;        /* Where to write error messages */
105
106 FILE *ofile = NULL;
107 int optimizing = MAX_OPTIMIZE; /* number of optimization passes to take */
108 static int sb, cmd_sb = 16;    /* by default */
109 static uint32_t cmd_cpu = IF_PLEVEL;       /* highest level by default */
110 static uint32_t cpu = IF_PLEVEL;   /* passed to insn_size & assemble.c */
111 int64_t global_offset_changed;      /* referenced in labels.c */
112 int64_t prev_offset_changed;
113 int32_t stall_count;
114
115 static struct location location;
116 int in_abs_seg;                 /* Flag we are in ABSOLUTE seg */
117 int32_t abs_seg;                   /* ABSOLUTE segment basis */
118 int32_t abs_offset;                /* ABSOLUTE offset */
119
120 static struct RAA *offsets;
121
122 static struct SAA *forwrefs;    /* keep track of forward references */
123 static const struct forwrefinfo *forwref;
124
125 static struct preproc_ops *preproc;
126
127 enum op_type {
128     op_normal,                  /* Preprocess and assemble */
129     op_preprocess,              /* Preprocess only */
130     op_depend,                  /* Generate dependencies */
131 };
132 static enum op_type operating_mode;
133 /* Dependency flags */
134 static bool depend_emit_phony = false;
135 static bool depend_missing_ok = false;
136 static const char *depend_target = NULL;
137 static const char *depend_file = NULL;
138
139 /*
140  * Which of the suppressible warnings are suppressed. Entry zero
141  * isn't an actual warning, but it used for -w+error/-Werror.
142  */
143
144 static bool warning_on[ERR_WARN_MAX+1]; /* Current state */
145 static bool warning_on_global[ERR_WARN_MAX+1]; /* Command-line state */
146
147 static const struct warning {
148     const char *name;
149     const char *help;
150     bool enabled;
151 } warnings[ERR_WARN_MAX+1] = {
152     {"error", "treat warnings as errors", false},
153     {"macro-params", "macro calls with wrong parameter count", true},
154     {"macro-selfref", "cyclic macro references", false},
155     {"macro-defaults", "macros with more default than optional parameters", true},
156     {"orphan-labels", "labels alone on lines without trailing `:'", true},
157     {"number-overflow", "numeric constant does not fit", true},
158     {"gnu-elf-extensions", "using 8- or 16-bit relocation in ELF32, a GNU extension", false},
159     {"float-overflow", "floating point overflow", true},
160     {"float-denorm", "floating point denormal", false},
161     {"float-underflow", "floating point underflow", false},
162     {"float-toolong", "too many digits in floating-point number", true},
163     {"user", "%warning directives", true},
164 };
165
166 /*
167  * This is a null preprocessor which just copies lines from input
168  * to output. It's used when someone explicitly requests that NASM
169  * not preprocess their source file.
170  */
171
172 static void no_pp_reset(char *file, int pass, ListGen *listgen, StrList **deplist);
173 static char *no_pp_getline(void);
174 static void no_pp_cleanup(int pass);
175
176 static struct preproc_ops no_pp = {
177     no_pp_reset,
178     no_pp_getline,
179     no_pp_cleanup
180 };
181
182 /*
183  * get/set current offset...
184  */
185 #define GET_CURR_OFFS (in_abs_seg?abs_offset:\
186                       raa_read(offsets,location.segment))
187 #define SET_CURR_OFFS(x) (in_abs_seg?(void)(abs_offset=(x)):\
188                          (void)(offsets=raa_write(offsets,location.segment,(x))))
189
190 static bool want_usage;
191 static bool terminate_after_phase;
192 int user_nolist = 0;            /* fbk 9/2/00 */
193
194 static void nasm_fputs(const char *line, FILE * outfile)
195 {
196     if (outfile) {
197         fputs(line, outfile);
198         putc('\n', outfile);
199     } else
200         puts(line);
201 }
202
203 /* Convert a struct tm to a POSIX-style time constant */
204 static int64_t posix_mktime(struct tm *tm)
205 {
206     int64_t t;
207     int64_t y = tm->tm_year;
208
209     /* See IEEE 1003.1:2004, section 4.14 */
210
211     t = (y-70)*365 + (y-69)/4 - (y-1)/100 + (y+299)/400;
212     t += tm->tm_yday;
213     t *= 24;
214     t += tm->tm_hour;
215     t *= 60;
216     t += tm->tm_min;
217     t *= 60;
218     t += tm->tm_sec;
219
220     return t;
221 }
222
223 static void define_macros_early(void)
224 {
225     char temp[128];
226     struct tm lt, *lt_p, gm, *gm_p;
227     int64_t posix_time;
228
229     lt_p = localtime(&official_compile_time);
230     if (lt_p) {
231         lt = *lt_p;
232
233         strftime(temp, sizeof temp, "__DATE__=\"%Y-%m-%d\"", &lt);
234         pp_pre_define(temp);
235         strftime(temp, sizeof temp, "__DATE_NUM__=%Y%m%d", &lt);
236         pp_pre_define(temp);
237         strftime(temp, sizeof temp, "__TIME__=\"%H:%M:%S\"", &lt);
238         pp_pre_define(temp);
239         strftime(temp, sizeof temp, "__TIME_NUM__=%H%M%S", &lt);
240         pp_pre_define(temp);
241     }
242
243     gm_p = gmtime(&official_compile_time);
244     if (gm_p) {
245         gm = *gm_p;
246
247         strftime(temp, sizeof temp, "__UTC_DATE__=\"%Y-%m-%d\"", &gm);
248         pp_pre_define(temp);
249         strftime(temp, sizeof temp, "__UTC_DATE_NUM__=%Y%m%d", &gm);
250         pp_pre_define(temp);
251         strftime(temp, sizeof temp, "__UTC_TIME__=\"%H:%M:%S\"", &gm);
252         pp_pre_define(temp);
253         strftime(temp, sizeof temp, "__UTC_TIME_NUM__=%H%M%S", &gm);
254         pp_pre_define(temp);
255     }
256
257     if (gm_p)
258         posix_time = posix_mktime(&gm);
259     else if (lt_p)
260         posix_time = posix_mktime(&lt);
261     else
262         posix_time = 0;
263
264     if (posix_time) {
265         snprintf(temp, sizeof temp, "__POSIX_TIME__=%"PRId64, posix_time);
266         pp_pre_define(temp);
267     }
268 }
269
270 static void define_macros_late(void)
271 {
272     char temp[128];
273
274     /*
275      * In case if output format is defined by alias
276      * we have to put shortname of the alias itself here
277      * otherwise ABI backward compatibility gets broken.
278      */
279     snprintf(temp, sizeof(temp), "__OUTPUT_FORMAT__=%s",
280              ofmt_alias ? ofmt_alias->shortname : ofmt->shortname);
281     pp_pre_define(temp);
282 }
283
284 static void emit_dependencies(StrList *list)
285 {
286     FILE *deps;
287     int linepos, len;
288     StrList *l, *nl;
289
290     if (depend_file && strcmp(depend_file, "-")) {
291         deps = fopen(depend_file, "w");
292         if (!deps) {
293             nasm_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
294                          "unable to write dependency file `%s'", depend_file);
295             return;
296         }
297     } else {
298         deps = stdout;
299     }
300
301     linepos = fprintf(deps, "%s:", depend_target);
302     list_for_each(l, list) {
303         len = strlen(l->str);
304         if (linepos + len > 62) {
305             fprintf(deps, " \\\n ");
306             linepos = 1;
307         }
308         fprintf(deps, " %s", l->str);
309         linepos += len+1;
310     }
311     fprintf(deps, "\n\n");
312
313     list_for_each_safe(l, nl, list) {
314         if (depend_emit_phony)
315             fprintf(deps, "%s:\n\n", l->str);
316         nasm_free(l);
317     }
318
319     if (deps != stdout)
320         fclose(deps);
321 }
322
323 int main(int argc, char **argv)
324 {
325     StrList *depend_list = NULL, **depend_ptr;
326
327     time(&official_compile_time);
328
329     pass0 = 0;
330     want_usage = terminate_after_phase = false;
331     nasm_set_verror(nasm_verror_gnu);
332
333     error_file = stderr;
334
335     tolower_init();
336
337     nasm_init_malloc_error();
338     offsets = raa_init();
339     forwrefs = saa_init((int32_t)sizeof(struct forwrefinfo));
340
341     preproc = &nasmpp;
342     operating_mode = op_normal;
343
344     seg_init();
345
346     /* Define some macros dependent on the runtime, but not
347        on the command line. */
348     define_macros_early();
349
350     parse_cmdline(argc, argv);
351
352     if (terminate_after_phase) {
353         if (want_usage)
354             usage();
355         return 1;
356     }
357
358     /* If debugging info is disabled, suppress any debug calls */
359     if (!using_debug_info)
360         ofmt->current_dfmt = &null_debug_form;
361
362     if (ofmt->stdmac)
363         pp_extra_stdmac(ofmt->stdmac);
364     parser_global_info(&location);
365     eval_global_info(ofmt, lookup_label, &location);
366
367     /* define some macros dependent of command-line */
368     define_macros_late();
369
370     depend_ptr = (depend_file || (operating_mode == op_depend))
371         ? &depend_list : NULL;
372     if (!depend_target)
373         depend_target = outname;
374
375     switch (operating_mode) {
376     case op_depend:
377         {
378             char *line;
379
380             if (depend_missing_ok)
381                 pp_include_path(NULL);  /* "assume generated" */
382
383             preproc->reset(inname, 0, &nasmlist, depend_ptr);
384             if (outname[0] == '\0')
385                 ofmt->filename(inname, outname);
386             ofile = NULL;
387             while ((line = preproc->getline()))
388                 nasm_free(line);
389             preproc->cleanup(0);
390         }
391         break;
392
393     case op_preprocess:
394         {
395             char *line;
396             char *file_name = NULL;
397             int32_t prior_linnum = 0;
398             int lineinc = 0;
399
400             if (*outname) {
401                 ofile = fopen(outname, "w");
402                 if (!ofile)
403                     nasm_error(ERR_FATAL | ERR_NOFILE,
404                                  "unable to open output file `%s'",
405                                  outname);
406             } else
407                 ofile = NULL;
408
409             location.known = false;
410
411             /* pass = 1; */
412             preproc->reset(inname, 3, &nasmlist, depend_ptr);
413             memcpy(warning_on, warning_on_global, (ERR_WARN_MAX+1) * sizeof(bool));
414
415             while ((line = preproc->getline())) {
416                 /*
417                  * We generate %line directives if needed for later programs
418                  */
419                 int32_t linnum = prior_linnum += lineinc;
420                 int altline = src_get(&linnum, &file_name);
421                 if (altline) {
422                     if (altline == 1 && lineinc == 1)
423                         nasm_fputs("", ofile);
424                     else {
425                         lineinc = (altline != -1 || lineinc != 1);
426                         fprintf(ofile ? ofile : stdout,
427                                 "%%line %"PRId32"+%d %s\n", linnum, lineinc,
428                                 file_name);
429                     }
430                     prior_linnum = linnum;
431                 }
432                 nasm_fputs(line, ofile);
433                 nasm_free(line);
434             }
435             nasm_free(file_name);
436             preproc->cleanup(0);
437             if (ofile)
438                 fclose(ofile);
439             if (ofile && terminate_after_phase)
440                 remove(outname);
441             ofile = NULL;
442         }
443         break;
444
445     case op_normal:
446         {
447             /*
448              * We must call ofmt->filename _anyway_, even if the user
449              * has specified their own output file, because some
450              * formats (eg OBJ and COFF) use ofmt->filename to find out
451              * the name of the input file and then put that inside the
452              * file.
453              */
454             ofmt->filename(inname, outname);
455
456             ofile = fopen(outname, (ofmt->flags & OFMT_TEXT) ? "w" : "wb");
457             if (!ofile) {
458                 nasm_error(ERR_FATAL | ERR_NOFILE,
459                              "unable to open output file `%s'", outname);
460             }
461
462             /*
463              * We must call init_labels() before ofmt->init() since
464              * some object formats will want to define labels in their
465              * init routines. (eg OS/2 defines the FLAT group)
466              */
467             init_labels();
468
469             ofmt->init();
470             dfmt = ofmt->current_dfmt;
471             dfmt->init();
472
473             assemble_file(inname, depend_ptr);
474
475             if (!terminate_after_phase) {
476                 ofmt->cleanup(using_debug_info);
477                 cleanup_labels();
478                 fflush(ofile);
479                 if (ferror(ofile)) {
480                     nasm_error(ERR_NONFATAL|ERR_NOFILE,
481                                  "write error on output file `%s'", outname);
482                 }
483             }
484
485             if (ofile) {
486                 fclose(ofile);
487                 if (terminate_after_phase)
488                     remove(outname);
489                 ofile = NULL;
490             }
491         }
492         break;
493     }
494
495     if (depend_list && !terminate_after_phase)
496         emit_dependencies(depend_list);
497
498     if (want_usage)
499         usage();
500
501     raa_free(offsets);
502     saa_free(forwrefs);
503     eval_cleanup();
504     stdscan_cleanup();
505
506     return terminate_after_phase;
507 }
508
509 /*
510  * Get a parameter for a command line option.
511  * First arg must be in the form of e.g. -f...
512  */
513 static char *get_param(char *p, char *q, bool *advance)
514 {
515     *advance = false;
516     if (p[2]) /* the parameter's in the option */
517         return nasm_skip_spaces(p + 2);
518     if (q && q[0]) {
519         *advance = true;
520         return q;
521     }
522     nasm_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
523                  "option `-%c' requires an argument", p[1]);
524     return NULL;
525 }
526
527 /*
528  * Copy a filename
529  */
530 static void copy_filename(char *dst, const char *src)
531 {
532     size_t len = strlen(src);
533
534     if (len >= (size_t)FILENAME_MAX) {
535         nasm_error(ERR_FATAL | ERR_NOFILE, "file name too long");
536         return;
537     }
538     strncpy(dst, src, FILENAME_MAX);
539 }
540
541 /*
542  * Convert a string to Make-safe form
543  */
544 static char *quote_for_make(const char *str)
545 {
546     const char *p;
547     char *os, *q;
548
549     size_t n = 1;               /* Terminating zero */
550     size_t nbs = 0;
551
552     if (!str)
553         return NULL;
554
555     for (p = str; *p; p++) {
556         switch (*p) {
557         case ' ':
558         case '\t':
559             /* Convert N backslashes + ws -> 2N+1 backslashes + ws */
560             n += nbs + 2;
561             nbs = 0;
562             break;
563         case '$':
564         case '#':
565             nbs = 0;
566             n += 2;
567             break;
568         case '\\':
569             nbs++;
570             n++;
571             break;
572         default:
573             nbs = 0;
574             n++;
575         break;
576         }
577     }
578
579     /* Convert N backslashes at the end of filename to 2N backslashes */
580     if (nbs)
581         n += nbs;
582
583     os = q = nasm_malloc(n);
584
585     nbs = 0;
586     for (p = str; *p; p++) {
587         switch (*p) {
588         case ' ':
589         case '\t':
590             while (nbs--)
591                 *q++ = '\\';
592             *q++ = '\\';
593             *q++ = *p;
594             break;
595         case '$':
596             *q++ = *p;
597             *q++ = *p;
598             nbs = 0;
599             break;
600         case '#':
601             *q++ = '\\';
602             *q++ = *p;
603             nbs = 0;
604             break;
605         case '\\':
606             *q++ = *p;
607             nbs++;
608             break;
609         default:
610             *q++ = *p;
611             nbs = 0;
612         break;
613         }
614     }
615     while (nbs--)
616         *q++ = '\\';
617
618     *q = '\0';
619
620     return os;
621 }
622
623 struct textargs {
624     const char *label;
625     int value;
626 };
627
628 #define OPT_PREFIX 0
629 #define OPT_POSTFIX 1
630 struct textargs textopts[] = {
631     {"prefix", OPT_PREFIX},
632     {"postfix", OPT_POSTFIX},
633     {NULL, 0}
634 };
635
636 static bool stopoptions = false;
637 static bool process_arg(char *p, char *q)
638 {
639     char *param;
640     int i;
641     bool advance = false;
642     bool do_warn;
643
644     if (!p || !p[0])
645         return false;
646
647     if (p[0] == '-' && !stopoptions) {
648         if (strchr("oOfpPdDiIlFXuUZwW", p[1])) {
649             /* These parameters take values */
650             if (!(param = get_param(p, q, &advance)))
651                 return advance;
652         }
653
654         switch (p[1]) {
655         case 's':
656             error_file = stdout;
657             break;
658
659         case 'o':               /* output file */
660             copy_filename(outname, param);
661             break;
662
663         case 'f':               /* output format */
664         ofmt = ofmt_find(param, &ofmt_alias);
665             if (!ofmt) {
666                 nasm_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
667                              "unrecognised output format `%s' - "
668                              "use -hf for a list", param);
669             }
670             break;
671
672         case 'O':               /* Optimization level */
673         {
674             int opt;
675
676             if (!*param) {
677                 /* Naked -O == -Ox */
678                 optimizing = MAX_OPTIMIZE;
679             } else {
680                 while (*param) {
681                     switch (*param) {
682                     case '0': case '1': case '2': case '3': case '4':
683                     case '5': case '6': case '7': case '8': case '9':
684                         opt = strtoul(param, &param, 10);
685
686                         /* -O0 -> optimizing == -1, 0.98 behaviour */
687                         /* -O1 -> optimizing == 0, 0.98.09 behaviour */
688                         if (opt < 2)
689                             optimizing = opt - 1;
690                         else
691                             optimizing = opt;
692                         break;
693
694                     case 'v':
695                     case '+':
696                         param++;
697                         opt_verbose_info = true;
698                         break;
699
700                     case 'x':
701                         param++;
702                         optimizing = MAX_OPTIMIZE;
703                         break;
704
705                     default:
706                         nasm_error(ERR_FATAL,
707                                      "unknown optimization option -O%c\n",
708                                      *param);
709                         break;
710                     }
711                 }
712                 if (optimizing > MAX_OPTIMIZE)
713                     optimizing = MAX_OPTIMIZE;
714             }
715             break;
716         }
717
718         case 'p':                       /* pre-include */
719         case 'P':
720             pp_pre_include(param);
721             break;
722
723         case 'd':                       /* pre-define */
724         case 'D':
725             pp_pre_define(param);
726             break;
727
728         case 'u':                       /* un-define */
729         case 'U':
730             pp_pre_undefine(param);
731             break;
732
733         case 'i':                       /* include search path */
734         case 'I':
735             pp_include_path(param);
736             break;
737
738         case 'l':                       /* listing file */
739             copy_filename(listname, param);
740             break;
741
742         case 'Z':                       /* error messages file */
743             copy_filename(errname, param);
744             break;
745
746         case 'F':                       /* specify debug format */
747             ofmt->current_dfmt = dfmt_find(ofmt, param);
748             if (!ofmt->current_dfmt) {
749                 nasm_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
750                              "unrecognized debug format `%s' for"
751                              " output format `%s'",
752                              param, ofmt->shortname);
753             }
754             using_debug_info = true;
755             break;
756
757         case 'X':               /* specify error reporting format */
758             if (nasm_stricmp("vc", param) == 0)
759                 nasm_set_verror(nasm_verror_vc);
760             else if (nasm_stricmp("gnu", param) == 0)
761                 nasm_set_verror(nasm_verror_gnu);
762             else
763                 nasm_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
764                              "unrecognized error reporting format `%s'",
765                              param);
766             break;
767
768         case 'g':
769             using_debug_info = true;
770             break;
771
772         case 'h':
773             printf
774                 ("usage: nasm [-@ response file] [-o outfile] [-f format] "
775                  "[-l listfile]\n"
776                  "            [options...] [--] filename\n"
777                  "    or nasm -v   for version info\n\n"
778                  "    -t          assemble in SciTech TASM compatible mode\n"
779                  "    -g          generate debug information in selected format\n");
780             printf
781                 ("    -E (or -e)  preprocess only (writes output to stdout by default)\n"
782                  "    -a          don't preprocess (assemble only)\n"
783                  "    -M          generate Makefile dependencies on stdout\n"
784                  "    -MG         d:o, missing files assumed generated\n"
785                  "    -MF <file>  set Makefile dependency file\n"
786                  "    -MD <file>  assemble and generate dependencies\n"
787                  "    -MT <file>  dependency target name\n"
788                  "    -MQ <file>  dependency target name (quoted)\n"
789                  "    -MP         emit phony target\n\n"
790                  "    -Z<file>    redirect error messages to file\n"
791                  "    -s          redirect error messages to stdout\n\n"
792                  "    -F format   select a debugging format\n\n"
793                  "    -I<path>    adds a pathname to the include file path\n");
794             printf
795                 ("    -O<digit>   optimize branch offsets\n"
796                  "                -O0: No optimization (default)\n"
797                  "                -O1: Minimal optimization\n"
798                  "                -Ox: Multipass optimization (recommended)\n\n"
799                  "    -P<file>    pre-includes a file\n"
800                  "    -D<macro>[=<value>] pre-defines a macro\n"
801                  "    -U<macro>   undefines a macro\n"
802                  "    -X<format>  specifies error reporting format (gnu or vc)\n"
803                  "    -w+foo      enables warning foo (equiv. -Wfoo)\n"
804                  "    -w-foo      disable warning foo (equiv. -Wno-foo)\n\n"
805                  "--prefix,--postfix\n"
806                  "  this options prepend or append the given argument to all\n"
807                  "  extern and global variables\n\n"
808                  "Warnings:\n");
809             for (i = 0; i <= ERR_WARN_MAX; i++)
810                 printf("    %-23s %s (default %s)\n",
811                        warnings[i].name, warnings[i].help,
812                        warnings[i].enabled ? "on" : "off");
813             printf
814                 ("\nresponse files should contain command line parameters"
815                  ", one per line.\n");
816             if (p[2] == 'f') {
817                 printf("\nvalid output formats for -f are"
818                        " (`*' denotes default):\n");
819                 ofmt_list(ofmt, stdout);
820             } else {
821                 printf("\nFor a list of valid output formats, use -hf.\n");
822                 printf("For a list of debug formats, use -f <form> -y.\n");
823             }
824             exit(0);            /* never need usage message here */
825             break;
826
827         case 'y':
828             printf("\nvalid debug formats for '%s' output format are"
829                    " ('*' denotes default):\n", ofmt->shortname);
830             dfmt_list(ofmt, stdout);
831             exit(0);
832             break;
833
834         case 't':
835             tasm_compatible_mode = true;
836             break;
837
838         case 'v':
839             printf("NASM version %s compiled on %s%s\n",
840                    nasm_version, nasm_date, nasm_compile_options);
841             exit(0);        /* never need usage message here */
842             break;
843
844         case 'e':              /* preprocess only */
845         case 'E':
846             operating_mode = op_preprocess;
847             break;
848
849         case 'a':              /* assemble only - don't preprocess */
850             preproc = &no_pp;
851             break;
852
853         case 'W':
854             if (param[0] == 'n' && param[1] == 'o' && param[2] == '-') {
855                 do_warn = false;
856                 param += 3;
857             } else {
858                 do_warn = true;
859             }
860             goto set_warning;
861
862         case 'w':
863             if (param[0] != '+' && param[0] != '-') {
864                 nasm_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
865                              "invalid option to `-w'");
866                 break;
867             }
868             do_warn = (param[0] == '+');
869             param++;
870
871 set_warning:
872             for (i = 0; i <= ERR_WARN_MAX; i++) {
873                 if (!nasm_stricmp(param, warnings[i].name))
874                     break;
875             }
876             if (i <= ERR_WARN_MAX) {
877                 warning_on_global[i] = do_warn;
878             } else if (!nasm_stricmp(param, "all")) {
879                 for (i = 1; i <= ERR_WARN_MAX; i++)
880                     warning_on_global[i] = do_warn;
881             } else if (!nasm_stricmp(param, "none")) {
882                 for (i = 1; i <= ERR_WARN_MAX; i++)
883                     warning_on_global[i] = !do_warn;
884             } else {
885                 nasm_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
886                            "invalid warning `%s'", param);
887             }
888             break;
889
890         case 'M':
891             switch (p[2]) {
892             case 0:
893                 operating_mode = op_depend;
894                 break;
895             case 'G':
896                 operating_mode = op_depend;
897                 depend_missing_ok = true;
898                 break;
899             case 'P':
900                 depend_emit_phony = true;
901                 break;
902             case 'D':
903                 depend_file = q;
904                 advance = true;
905                 break;
906             case 'T':
907                 depend_target = q;
908                 advance = true;
909                 break;
910             case 'Q':
911                 depend_target = quote_for_make(q);
912                 advance = true;
913                 break;
914             default:
915                 nasm_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
916                              "unknown dependency option `-M%c'", p[2]);
917                 break;
918             }
919             if (advance && (!q || !q[0])) {
920                 nasm_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
921                              "option `-M%c' requires a parameter", p[2]);
922                 break;
923             }
924             break;
925
926         case '-':
927             {
928                 int s;
929
930                 if (p[2] == 0) {        /* -- => stop processing options */
931                     stopoptions = 1;
932                     break;
933                 }
934                 for (s = 0; textopts[s].label; s++) {
935                     if (!nasm_stricmp(p + 2, textopts[s].label)) {
936                         break;
937                     }
938                 }
939
940                 switch (s) {
941
942                 case OPT_PREFIX:
943                 case OPT_POSTFIX:
944                     {
945                         if (!q) {
946                             nasm_error(ERR_NONFATAL | ERR_NOFILE |
947                                          ERR_USAGE,
948                                          "option `--%s' requires an argument",
949                                          p + 2);
950                             break;
951                         } else {
952                             advance = 1, param = q;
953                         }
954
955                         if (s == OPT_PREFIX) {
956                             strncpy(lprefix, param, PREFIX_MAX - 1);
957                             lprefix[PREFIX_MAX - 1] = 0;
958                             break;
959                         }
960                         if (s == OPT_POSTFIX) {
961                             strncpy(lpostfix, param, POSTFIX_MAX - 1);
962                             lpostfix[POSTFIX_MAX - 1] = 0;
963                             break;
964                         }
965                         break;
966                     }
967                 default:
968                     {
969                         nasm_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
970                                      "unrecognised option `--%s'", p + 2);
971                         break;
972                     }
973                 }
974                 break;
975             }
976
977         default:
978             if (!ofmt->setinfo(GI_SWITCH, &p))
979                 nasm_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
980                              "unrecognised option `-%c'", p[1]);
981             break;
982         }
983     } else {
984         if (*inname) {
985             nasm_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
986                          "more than one input file specified");
987         } else {
988             copy_filename(inname, p);
989         }
990     }
991
992     return advance;
993 }
994
995 #define ARG_BUF_DELTA 128
996
997 static void process_respfile(FILE * rfile)
998 {
999     char *buffer, *p, *q, *prevarg;
1000     int bufsize, prevargsize;
1001
1002     bufsize = prevargsize = ARG_BUF_DELTA;
1003     buffer = nasm_malloc(ARG_BUF_DELTA);
1004     prevarg = nasm_malloc(ARG_BUF_DELTA);
1005     prevarg[0] = '\0';
1006
1007     while (1) {                 /* Loop to handle all lines in file */
1008         p = buffer;
1009         while (1) {             /* Loop to handle long lines */
1010             q = fgets(p, bufsize - (p - buffer), rfile);
1011             if (!q)
1012                 break;
1013             p += strlen(p);
1014             if (p > buffer && p[-1] == '\n')
1015                 break;
1016             if (p - buffer > bufsize - 10) {
1017                 int offset;
1018                 offset = p - buffer;
1019                 bufsize += ARG_BUF_DELTA;
1020                 buffer = nasm_realloc(buffer, bufsize);
1021                 p = buffer + offset;
1022             }
1023         }
1024
1025         if (!q && p == buffer) {
1026             if (prevarg[0])
1027                 process_arg(prevarg, NULL);
1028             nasm_free(buffer);
1029             nasm_free(prevarg);
1030             return;
1031         }
1032
1033         /*
1034          * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
1035          * them are present at the end of the line.
1036          */
1037         *(p = &buffer[strcspn(buffer, "\r\n\032")]) = '\0';
1038
1039         while (p > buffer && nasm_isspace(p[-1]))
1040             *--p = '\0';
1041
1042         p = nasm_skip_spaces(buffer);
1043
1044         if (process_arg(prevarg, p))
1045             *p = '\0';
1046
1047         if ((int) strlen(p) > prevargsize - 10) {
1048             prevargsize += ARG_BUF_DELTA;
1049             prevarg = nasm_realloc(prevarg, prevargsize);
1050         }
1051         strncpy(prevarg, p, prevargsize);
1052     }
1053 }
1054
1055 /* Function to process args from a string of args, rather than the
1056  * argv array. Used by the environment variable and response file
1057  * processing.
1058  */
1059 static void process_args(char *args)
1060 {
1061     char *p, *q, *arg, *prevarg;
1062     char separator = ' ';
1063
1064     p = args;
1065     if (*p && *p != '-')
1066         separator = *p++;
1067     arg = NULL;
1068     while (*p) {
1069         q = p;
1070         while (*p && *p != separator)
1071             p++;
1072         while (*p == separator)
1073             *p++ = '\0';
1074         prevarg = arg;
1075         arg = q;
1076         if (process_arg(prevarg, arg))
1077             arg = NULL;
1078     }
1079     if (arg)
1080         process_arg(arg, NULL);
1081 }
1082
1083 static void process_response_file(const char *file)
1084 {
1085     char str[2048];
1086     FILE *f = fopen(file, "r");
1087     if (!f) {
1088         perror(file);
1089         exit(-1);
1090     }
1091     while (fgets(str, sizeof str, f)) {
1092         process_args(str);
1093     }
1094     fclose(f);
1095 }
1096
1097 static void parse_cmdline(int argc, char **argv)
1098 {
1099     FILE *rfile;
1100     char *envreal, *envcopy = NULL, *p;
1101     int i;
1102
1103     *inname = *outname = *listname = *errname = '\0';
1104
1105     for (i = 0; i <= ERR_WARN_MAX; i++)
1106         warning_on_global[i] = warnings[i].enabled;
1107
1108     /*
1109      * First, process the NASMENV environment variable.
1110      */
1111     envreal = getenv("NASMENV");
1112     if (envreal) {
1113         envcopy = nasm_strdup(envreal);
1114         process_args(envcopy);
1115         nasm_free(envcopy);
1116     }
1117
1118     /*
1119      * Now process the actual command line.
1120      */
1121     while (--argc) {
1122         bool advance;
1123         argv++;
1124         if (argv[0][0] == '@') {
1125             /*
1126              * We have a response file, so process this as a set of
1127              * arguments like the environment variable. This allows us
1128              * to have multiple arguments on a single line, which is
1129              * different to the -@resp file processing below for regular
1130              * NASM.
1131              */
1132             process_response_file(argv[0]+1);
1133             argc--;
1134             argv++;
1135         }
1136         if (!stopoptions && argv[0][0] == '-' && argv[0][1] == '@') {
1137             p = get_param(argv[0], argc > 1 ? argv[1] : NULL, &advance);
1138             if (p) {
1139                 rfile = fopen(p, "r");
1140                 if (rfile) {
1141                     process_respfile(rfile);
1142                     fclose(rfile);
1143                 } else
1144                     nasm_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
1145                                  "unable to open response file `%s'", p);
1146             }
1147         } else
1148             advance = process_arg(argv[0], argc > 1 ? argv[1] : NULL);
1149         argv += advance, argc -= advance;
1150     }
1151
1152     /*
1153      * Look for basic command line typos. This definitely doesn't
1154      * catch all errors, but it might help cases of fumbled fingers.
1155      */
1156     if (!*inname)
1157         nasm_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
1158                    "no input file specified");
1159     else if (!strcmp(inname, errname)   ||
1160              !strcmp(inname, outname)   ||
1161              !strcmp(inname, listname)  ||
1162              (depend_file && !strcmp(inname, depend_file)))
1163         nasm_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
1164                    "file `%s' is both input and output file",
1165                    inname);
1166
1167     if (*errname) {
1168         error_file = fopen(errname, "w");
1169         if (!error_file) {
1170             error_file = stderr;        /* Revert to default! */
1171             nasm_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
1172                        "cannot open file `%s' for error messages",
1173                        errname);
1174         }
1175     }
1176 }
1177
1178 static enum directives getkw(char **directive, char **value);
1179
1180 static void assemble_file(char *fname, StrList **depend_ptr)
1181 {
1182     char *directive, *value, *p, *q, *special, *line;
1183     insn output_ins;
1184     int i, validid;
1185     bool rn_error;
1186     int32_t seg;
1187     int64_t offs;
1188     struct tokenval tokval;
1189     expr *e;
1190     int pass_max;
1191
1192     if (cmd_sb == 32 && cmd_cpu < IF_386)
1193         nasm_error(ERR_FATAL, "command line: "
1194                      "32-bit segment size requires a higher cpu");
1195
1196     pass_max = prev_offset_changed = (INT_MAX >> 1) + 2; /* Almost unlimited */
1197     for (passn = 1; pass0 <= 2; passn++) {
1198         int pass1, pass2;
1199         ldfunc def_label;
1200
1201         pass1 = pass0 == 2 ? 2 : 1;     /* 1, 1, 1, ..., 1, 2 */
1202         pass2 = passn > 1  ? 2 : 1;     /* 1, 2, 2, ..., 2, 2 */
1203         /* pass0                           0, 0, 0, ..., 1, 2 */
1204
1205         def_label = passn > 1 ? redefine_label : define_label;
1206
1207         globalbits = sb = cmd_sb;   /* set 'bits' to command line default */
1208         cpu = cmd_cpu;
1209         if (pass0 == 2) {
1210             if (*listname)
1211                 nasmlist.init(listname, nasm_error);
1212         }
1213         in_abs_seg = false;
1214         global_offset_changed = 0;  /* set by redefine_label */
1215         location.segment = ofmt->section(NULL, pass2, &sb);
1216         globalbits = sb;
1217         if (passn > 1) {
1218             saa_rewind(forwrefs);
1219             forwref = saa_rstruct(forwrefs);
1220             raa_free(offsets);
1221             offsets = raa_init();
1222         }
1223         preproc->reset(fname, pass1, &nasmlist,
1224                        pass1 == 2 ? depend_ptr : NULL);
1225         memcpy(warning_on, warning_on_global, (ERR_WARN_MAX+1) * sizeof(bool));
1226
1227         globallineno = 0;
1228         if (passn == 1)
1229             location.known = true;
1230         location.offset = offs = GET_CURR_OFFS;
1231
1232         while ((line = preproc->getline())) {
1233             enum directives d;
1234             globallineno++;
1235
1236             /*
1237              * Here we parse our directives; this is not handled by the
1238              * 'real' parser.  This really should be a separate function.
1239              */
1240             directive = line;
1241             d = getkw(&directive, &value);
1242             if (d) {
1243                 int err = 0;
1244
1245                 switch (d) {
1246                 case D_SEGMENT:         /* [SEGMENT n] */
1247                 case D_SECTION:
1248                     seg = ofmt->section(value, pass2, &sb);
1249                     if (seg == NO_SEG) {
1250                         nasm_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
1251                                      "segment name `%s' not recognized",
1252                                      value);
1253                     } else {
1254                         in_abs_seg = false;
1255                         location.segment = seg;
1256                     }
1257                     break;
1258                 case D_SECTALIGN:        /* [SECTALIGN n] */
1259                     if (*value) {
1260                         stdscan_reset();
1261                         stdscan_set(value);
1262                         tokval.t_type = TOKEN_INVALID;
1263                         e = evaluate(stdscan, NULL, &tokval, NULL, pass2, nasm_error, NULL);
1264                         if (e) {
1265                             unsigned int align = (unsigned int)e->value;
1266                             if ((uint64_t)e->value > 0x7fffffff) {
1267                                 /*
1268                                  * FIXME: Please make some sane message here
1269                                  * ofmt should have some 'check' method which
1270                                  * would report segment alignment bounds.
1271                                  */
1272                                 nasm_error(ERR_FATAL,
1273                                            "incorrect segment alignment `%s'", value);
1274                             } else if (!is_power2(align)) {
1275                                 nasm_error(ERR_NONFATAL,
1276                                            "segment alignment `%s' is not power of two",
1277                                             value);
1278                             }
1279                             /* callee should be able to handle all details */
1280                             ofmt->sectalign(location.segment, align);
1281                         }
1282                     }
1283                     break;
1284                 case D_EXTERN:              /* [EXTERN label:special] */
1285                     if (*value == '$')
1286                         value++;        /* skip initial $ if present */
1287                     if (pass0 == 2) {
1288                         q = value;
1289                         while (*q && *q != ':')
1290                             q++;
1291                         if (*q == ':') {
1292                             *q++ = '\0';
1293                             ofmt->symdef(value, 0L, 0L, 3, q);
1294                         }
1295                     } else if (passn == 1) {
1296                         q = value;
1297                         validid = true;
1298                         if (!isidstart(*q))
1299                             validid = false;
1300                         while (*q && *q != ':') {
1301                             if (!isidchar(*q))
1302                                 validid = false;
1303                             q++;
1304                         }
1305                         if (!validid) {
1306                             nasm_error(ERR_NONFATAL,
1307                                          "identifier expected after EXTERN");
1308                             break;
1309                         }
1310                         if (*q == ':') {
1311                             *q++ = '\0';
1312                             special = q;
1313                         } else
1314                             special = NULL;
1315                         if (!is_extern(value)) {        /* allow re-EXTERN to be ignored */
1316                             int temp = pass0;
1317                             pass0 = 1;  /* fake pass 1 in labels.c */
1318                             declare_as_global(value, special);
1319                             define_label(value, seg_alloc(), 0L, NULL,
1320                                          false, true);
1321                             pass0 = temp;
1322                         }
1323                     }           /* else  pass0 == 1 */
1324                     break;
1325                 case D_BITS:            /* [BITS bits] */
1326                     globalbits = sb = get_bits(value);
1327                     break;
1328                 case D_GLOBAL:          /* [GLOBAL symbol:special] */
1329                     if (*value == '$')
1330                         value++;        /* skip initial $ if present */
1331                     if (pass0 == 2) {   /* pass 2 */
1332                         q = value;
1333                         while (*q && *q != ':')
1334                             q++;
1335                         if (*q == ':') {
1336                             *q++ = '\0';
1337                             ofmt->symdef(value, 0L, 0L, 3, q);
1338                         }
1339                     } else if (pass2 == 1) {    /* pass == 1 */
1340                         q = value;
1341                         validid = true;
1342                         if (!isidstart(*q))
1343                             validid = false;
1344                         while (*q && *q != ':') {
1345                             if (!isidchar(*q))
1346                                 validid = false;
1347                             q++;
1348                         }
1349                         if (!validid) {
1350                             nasm_error(ERR_NONFATAL,
1351                                          "identifier expected after GLOBAL");
1352                             break;
1353                         }
1354                         if (*q == ':') {
1355                             *q++ = '\0';
1356                             special = q;
1357                         } else
1358                             special = NULL;
1359                         declare_as_global(value, special);
1360                     }           /* pass == 1 */
1361                     break;
1362                 case D_COMMON:          /* [COMMON symbol size:special] */
1363                 {
1364                     int64_t size;
1365
1366                     if (*value == '$')
1367                         value++;        /* skip initial $ if present */
1368                     p = value;
1369                     validid = true;
1370                     if (!isidstart(*p))
1371                         validid = false;
1372                     while (*p && !nasm_isspace(*p)) {
1373                         if (!isidchar(*p))
1374                             validid = false;
1375                         p++;
1376                     }
1377                     if (!validid) {
1378                         nasm_error(ERR_NONFATAL,
1379                                      "identifier expected after COMMON");
1380                         break;
1381                     }
1382                     if (*p) {
1383                         p = nasm_zap_spaces_fwd(p);
1384                         q = p;
1385                         while (*q && *q != ':')
1386                             q++;
1387                         if (*q == ':') {
1388                             *q++ = '\0';
1389                             special = q;
1390                         } else {
1391                             special = NULL;
1392                         }
1393                         size = readnum(p, &rn_error);
1394                         if (rn_error) {
1395                             nasm_error(ERR_NONFATAL,
1396                                          "invalid size specified"
1397                                          " in COMMON declaration");
1398                             break;
1399                         }
1400                     } else {
1401                         nasm_error(ERR_NONFATAL,
1402                                      "no size specified in"
1403                                      " COMMON declaration");
1404                         break;
1405                     }
1406
1407                     if (pass0 < 2) {
1408                         define_common(value, seg_alloc(), size, special);
1409                     } else if (pass0 == 2) {
1410                         if (special)
1411                             ofmt->symdef(value, 0L, 0L, 3, special);
1412                     }
1413                     break;
1414                 }
1415                 case D_ABSOLUTE:                /* [ABSOLUTE address] */
1416                     stdscan_reset();
1417                     stdscan_set(value);
1418                     tokval.t_type = TOKEN_INVALID;
1419                     e = evaluate(stdscan, NULL, &tokval, NULL, pass2,
1420                                  nasm_error, NULL);
1421                     if (e) {
1422                         if (!is_reloc(e))
1423                             nasm_error(pass0 ==
1424                                          1 ? ERR_NONFATAL : ERR_PANIC,
1425                                          "cannot use non-relocatable expression as "
1426                                          "ABSOLUTE address");
1427                         else {
1428                             abs_seg = reloc_seg(e);
1429                             abs_offset = reloc_value(e);
1430                         }
1431                     } else if (passn == 1)
1432                         abs_offset = 0x100;     /* don't go near zero in case of / */
1433                     else
1434                         nasm_error(ERR_PANIC, "invalid ABSOLUTE address "
1435                                      "in pass two");
1436                     in_abs_seg = true;
1437                     location.segment = NO_SEG;
1438                     break;
1439                 case D_DEBUG:           /* [DEBUG] */
1440                 {
1441                     char debugid[128];
1442                     bool badid, overlong;
1443
1444                     p = value;
1445                     q = debugid;
1446                     badid = overlong = false;
1447                     if (!isidstart(*p)) {
1448                         badid = true;
1449                     } else {
1450                         while (*p && !nasm_isspace(*p)) {
1451                             if (q >= debugid + sizeof debugid - 1) {
1452                                 overlong = true;
1453                                 break;
1454                             }
1455                             if (!isidchar(*p))
1456                                 badid = true;
1457                             *q++ = *p++;
1458                         }
1459                         *q = 0;
1460                     }
1461                     if (badid) {
1462                         nasm_error(passn == 1 ? ERR_NONFATAL : ERR_PANIC,
1463                                    "identifier expected after DEBUG");
1464                         break;
1465                     }
1466                     if (overlong) {
1467                         nasm_error(passn == 1 ? ERR_NONFATAL : ERR_PANIC,
1468                                    "DEBUG identifier too long");
1469                         break;
1470                     }
1471                     p = nasm_skip_spaces(p);
1472                     if (pass0 == 2)
1473                         dfmt->debug_directive(debugid, p);
1474                     break;
1475                 }
1476                 case D_WARNING:         /* [WARNING {+|-|*}warn-name] */
1477                     value = nasm_skip_spaces(value);
1478                     switch(*value) {
1479                     case '-': validid = 0; value++; break;
1480                     case '+': validid = 1; value++; break;
1481                     case '*': validid = 2; value++; break;
1482                     default:  validid = 1; break;
1483                     }
1484
1485                     for (i = 1; i <= ERR_WARN_MAX; i++)
1486                         if (!nasm_stricmp(value, warnings[i].name))
1487                             break;
1488                     if (i <= ERR_WARN_MAX) {
1489                         switch(validid) {
1490                         case 0:
1491                             warning_on[i] = false;
1492                             break;
1493                         case 1:
1494                             warning_on[i] = true;
1495                             break;
1496                         case 2:
1497                             warning_on[i] = warning_on_global[i];
1498                             break;
1499                         }
1500                     }
1501                     else
1502                         nasm_error(ERR_NONFATAL,
1503                                      "invalid warning id in WARNING directive");
1504                     break;
1505                 case D_CPU:             /* [CPU] */
1506                     cpu = get_cpu(value);
1507                     break;
1508                 case D_LIST:            /* [LIST {+|-}] */
1509                     value = nasm_skip_spaces(value);
1510                     if (*value == '+') {
1511                         user_nolist = 0;
1512                     } else {
1513                         if (*value == '-') {
1514                             user_nolist = 1;
1515                         } else {
1516                             err = 1;
1517                         }
1518                     }
1519                     break;
1520                 case D_DEFAULT:         /* [DEFAULT] */
1521                     stdscan_reset();
1522                     stdscan_set(value);
1523                     tokval.t_type = TOKEN_INVALID;
1524                     if (stdscan(NULL, &tokval) == TOKEN_SPECIAL) {
1525                         switch ((int)tokval.t_integer) {
1526                         case S_REL:
1527                             globalrel = 1;
1528                             break;
1529                         case S_ABS:
1530                             globalrel = 0;
1531                             break;
1532                         default:
1533                             err = 1;
1534                             break;
1535                         }
1536                     } else {
1537                         err = 1;
1538                     }
1539                     break;
1540                 case D_FLOAT:
1541                     if (float_option(value)) {
1542                         nasm_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
1543                                      "unknown 'float' directive: %s",
1544                                      value);
1545                     }
1546                     break;
1547                 default:
1548                     if (ofmt->directive(d, value, pass2))
1549                         break;
1550                     /* else fall through */
1551                 case D_unknown:
1552                     nasm_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
1553                                "unrecognised directive [%s]",
1554                                directive);
1555                     break;
1556                 }
1557                 if (err) {
1558                     nasm_error(ERR_NONFATAL,
1559                                  "invalid parameter to [%s] directive",
1560                                  directive);
1561                 }
1562             } else {            /* it isn't a directive */
1563                 parse_line(pass1, line, &output_ins, def_label);
1564
1565                 if (optimizing > 0) {
1566                     if (forwref != NULL && globallineno == forwref->lineno) {
1567                         output_ins.forw_ref = true;
1568                         do {
1569                             output_ins.oprs[forwref->operand].opflags |= OPFLAG_FORWARD;
1570                             forwref = saa_rstruct(forwrefs);
1571                         } while (forwref != NULL
1572                                  && forwref->lineno == globallineno);
1573                     } else
1574                         output_ins.forw_ref = false;
1575
1576                     if (output_ins.forw_ref) {
1577                         if (passn == 1) {
1578                             for (i = 0; i < output_ins.operands; i++) {
1579                                 if (output_ins.oprs[i].opflags & OPFLAG_FORWARD) {
1580                                     struct forwrefinfo *fwinf =
1581                                         (struct forwrefinfo *)
1582                                         saa_wstruct(forwrefs);
1583                                     fwinf->lineno = globallineno;
1584                                 fwinf->operand = i;
1585                                 }
1586                             }
1587                         }
1588                     }
1589                 }
1590
1591                 /*  forw_ref */
1592                 if (output_ins.opcode == I_EQU) {
1593                     if (pass1 == 1) {
1594                         /*
1595                          * Special `..' EQUs get processed in pass two,
1596                          * except `..@' macro-processor EQUs which are done
1597                          * in the normal place.
1598                          */
1599                         if (!output_ins.label)
1600                             nasm_error(ERR_NONFATAL,
1601                                          "EQU not preceded by label");
1602
1603                         else if (output_ins.label[0] != '.' ||
1604                                  output_ins.label[1] != '.' ||
1605                                  output_ins.label[2] == '@') {
1606                             if (output_ins.operands == 1 &&
1607                                 (output_ins.oprs[0].type & IMMEDIATE) &&
1608                                 output_ins.oprs[0].wrt == NO_SEG) {
1609                                 bool isext = !!(output_ins.oprs[0].opflags
1610                                                 & OPFLAG_EXTERN);
1611                                 def_label(output_ins.label,
1612                                           output_ins.oprs[0].segment,
1613                                           output_ins.oprs[0].offset, NULL,
1614                                           false, isext);
1615                             } else if (output_ins.operands == 2
1616                                        && (output_ins.oprs[0].type & IMMEDIATE)
1617                                        && (output_ins.oprs[0].type & COLON)
1618                                        && output_ins.oprs[0].segment == NO_SEG
1619                                        && output_ins.oprs[0].wrt == NO_SEG
1620                                        && (output_ins.oprs[1].type & IMMEDIATE)
1621                                        && output_ins.oprs[1].segment == NO_SEG
1622                                        && output_ins.oprs[1].wrt == NO_SEG) {
1623                                 def_label(output_ins.label,
1624                                           output_ins.oprs[0].offset | SEG_ABS,
1625                                           output_ins.oprs[1].offset,
1626                                           NULL, false, false);
1627                             } else
1628                                 nasm_error(ERR_NONFATAL,
1629                                              "bad syntax for EQU");
1630                         }
1631                     } else {
1632                         /*
1633                          * Special `..' EQUs get processed here, except
1634                          * `..@' macro processor EQUs which are done above.
1635                          */
1636                         if (output_ins.label[0] == '.' &&
1637                             output_ins.label[1] == '.' &&
1638                             output_ins.label[2] != '@') {
1639                             if (output_ins.operands == 1 &&
1640                                 (output_ins.oprs[0].type & IMMEDIATE)) {
1641                                 define_label(output_ins.label,
1642                                              output_ins.oprs[0].segment,
1643                                              output_ins.oprs[0].offset,
1644                                              NULL, false, false);
1645                             } else if (output_ins.operands == 2
1646                                        && (output_ins.oprs[0].type & IMMEDIATE)
1647                                        && (output_ins.oprs[0].type & COLON)
1648                                        && output_ins.oprs[0].segment == NO_SEG
1649                                        && (output_ins.oprs[1].type & IMMEDIATE)
1650                                        && output_ins.oprs[1].segment == NO_SEG) {
1651                                 define_label(output_ins.label,
1652                                              output_ins.oprs[0].offset | SEG_ABS,
1653                                              output_ins.oprs[1].offset,
1654                                              NULL, false, false);
1655                             } else
1656                                 nasm_error(ERR_NONFATAL,
1657                                              "bad syntax for EQU");
1658                         }
1659                     }
1660                 } else {        /* instruction isn't an EQU */
1661
1662                     if (pass1 == 1) {
1663
1664                         int64_t l = insn_size(location.segment, offs, sb, cpu,
1665                                            &output_ins, nasm_error);
1666
1667                         /* if (using_debug_info)  && output_ins.opcode != -1) */
1668                         if (using_debug_info)
1669                         {       /* fbk 03/25/01 */
1670                             /* this is done here so we can do debug type info */
1671                             int32_t typeinfo =
1672                                 TYS_ELEMENTS(output_ins.operands);
1673                             switch (output_ins.opcode) {
1674                             case I_RESB:
1675                                 typeinfo =
1676                                     TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_BYTE;
1677                                 break;
1678                             case I_RESW:
1679                                 typeinfo =
1680                                     TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_WORD;
1681                                 break;
1682                             case I_RESD:
1683                                 typeinfo =
1684                                     TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_DWORD;
1685                                 break;
1686                             case I_RESQ:
1687                                 typeinfo =
1688                                     TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_QWORD;
1689                                 break;
1690                             case I_REST:
1691                                 typeinfo =
1692                                     TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_TBYTE;
1693                                 break;
1694                             case I_RESO:
1695                                 typeinfo =
1696                                     TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_OWORD;
1697                                 break;
1698                             case I_RESY:
1699                                 typeinfo =
1700                                     TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_YWORD;
1701                                 break;
1702                             case I_DB:
1703                                 typeinfo |= TY_BYTE;
1704                                 break;
1705                             case I_DW:
1706                                 typeinfo |= TY_WORD;
1707                                 break;
1708                             case I_DD:
1709                                 if (output_ins.eops_float)
1710                                     typeinfo |= TY_FLOAT;
1711                                 else
1712                                     typeinfo |= TY_DWORD;
1713                                 break;
1714                             case I_DQ:
1715                                 typeinfo |= TY_QWORD;
1716                                 break;
1717                             case I_DT:
1718                                 typeinfo |= TY_TBYTE;
1719                                 break;
1720                             case I_DO:
1721                                 typeinfo |= TY_OWORD;
1722                                 break;
1723                             case I_DY:
1724                                 typeinfo |= TY_YWORD;
1725                                 break;
1726                             default:
1727                                 typeinfo = TY_LABEL;
1728
1729                             }
1730
1731                             dfmt->debug_typevalue(typeinfo);
1732                         }
1733                         if (l != -1) {
1734                             offs += l;
1735                             SET_CURR_OFFS(offs);
1736                         }
1737                         /*
1738                          * else l == -1 => invalid instruction, which will be
1739                          * flagged as an error on pass 2
1740                          */
1741
1742                     } else {
1743                         offs += assemble(location.segment, offs, sb, cpu,
1744                                          &output_ins, ofmt, nasm_error,
1745                                          &nasmlist);
1746                         SET_CURR_OFFS(offs);
1747
1748                     }
1749                 }               /* not an EQU */
1750                 cleanup_insn(&output_ins);
1751             }
1752             nasm_free(line);
1753             location.offset = offs = GET_CURR_OFFS;
1754         }                       /* end while (line = preproc->getline... */
1755
1756         if (pass0 == 2 && global_offset_changed && !terminate_after_phase)
1757             nasm_error(ERR_NONFATAL,
1758                          "phase error detected at end of assembly.");
1759
1760         if (pass1 == 1)
1761             preproc->cleanup(1);
1762
1763         if ((passn > 1 && !global_offset_changed) || pass0 == 2) {
1764             pass0++;
1765         } else if (global_offset_changed &&
1766                  global_offset_changed < prev_offset_changed) {
1767             prev_offset_changed = global_offset_changed;
1768             stall_count = 0;
1769         } else {
1770             stall_count++;
1771         }
1772
1773         if (terminate_after_phase)
1774             break;
1775
1776         if ((stall_count > 997) || (passn >= pass_max)) {
1777             /* We get here if the labels don't converge
1778              * Example: FOO equ FOO + 1
1779              */
1780              nasm_error(ERR_NONFATAL,
1781                           "Can't find valid values for all labels "
1782                           "after %d passes, giving up.", passn);
1783              nasm_error(ERR_NONFATAL,
1784                           "Possible causes: recursive EQUs, macro abuse.");
1785              break;
1786         }
1787     }
1788
1789     preproc->cleanup(0);
1790     nasmlist.cleanup();
1791     if (!terminate_after_phase && opt_verbose_info) {
1792         /*  -On and -Ov switches */
1793         fprintf(stdout, "info: assembly required 1+%d+1 passes\n", passn-3);
1794     }
1795 }
1796
1797 static enum directives getkw(char **directive, char **value)
1798 {
1799     char *p, *q, *buf;
1800
1801     buf = nasm_skip_spaces(*directive);
1802
1803     /* it should be enclosed in [ ] */
1804     if (*buf != '[')
1805         return D_none;
1806     q = strchr(buf, ']');
1807     if (!q)
1808         return D_none;
1809
1810     /* stip off the comments */
1811     p = strchr(buf, ';');
1812     if (p) {
1813         if (p < q) /* ouch! somwhere inside */
1814             return D_none;
1815         *p = '\0';
1816     }
1817
1818     /* no brace, no trailing spaces */
1819     *q = '\0';
1820     nasm_zap_spaces_rev(--q);
1821
1822     /* directive */
1823     p = nasm_skip_spaces(++buf);
1824     q = nasm_skip_word(p);
1825     if (!q)
1826         return D_none; /* sigh... no value there */
1827     *q = '\0';
1828     *directive = p;
1829
1830     /* and value finally */
1831     p = nasm_skip_spaces(++q);
1832     *value = p;
1833
1834     return find_directive(*directive);
1835 }
1836
1837 /**
1838  * gnu style error reporting
1839  * This function prints an error message to error_file in the
1840  * style used by GNU. An example would be:
1841  * file.asm:50: error: blah blah blah
1842  * where file.asm is the name of the file, 50 is the line number on
1843  * which the error occurs (or is detected) and "error:" is one of
1844  * the possible optional diagnostics -- it can be "error" or "warning"
1845  * or something else.  Finally the line terminates with the actual
1846  * error message.
1847  *
1848  * @param severity the severity of the warning or error
1849  * @param fmt the printf style format string
1850  */
1851 static void nasm_verror_gnu(int severity, const char *fmt, va_list ap)
1852 {
1853     char *currentfile = NULL;
1854     int32_t lineno = 0;
1855
1856     if (is_suppressed_warning(severity))
1857         return;
1858
1859     if (!(severity & ERR_NOFILE))
1860         src_get(&lineno, &currentfile);
1861
1862     if (currentfile) {
1863         fprintf(error_file, "%s:%"PRId32": ", currentfile, lineno);
1864         nasm_free(currentfile);
1865     } else {
1866         fputs("nasm: ", error_file);
1867     }
1868
1869     nasm_verror_common(severity, fmt, ap);
1870 }
1871
1872 /**
1873  * MS style error reporting
1874  * This function prints an error message to error_file in the
1875  * style used by Visual C and some other Microsoft tools. An example
1876  * would be:
1877  * file.asm(50) : error: blah blah blah
1878  * where file.asm is the name of the file, 50 is the line number on
1879  * which the error occurs (or is detected) and "error:" is one of
1880  * the possible optional diagnostics -- it can be "error" or "warning"
1881  * or something else.  Finally the line terminates with the actual
1882  * error message.
1883  *
1884  * @param severity the severity of the warning or error
1885  * @param fmt the printf style format string
1886  */
1887 static void nasm_verror_vc(int severity, const char *fmt, va_list ap)
1888 {
1889     char *currentfile = NULL;
1890     int32_t lineno = 0;
1891
1892     if (is_suppressed_warning(severity))
1893         return;
1894
1895     if (!(severity & ERR_NOFILE))
1896         src_get(&lineno, &currentfile);
1897
1898     if (currentfile) {
1899         fprintf(error_file, "%s(%"PRId32") : ", currentfile, lineno);
1900         nasm_free(currentfile);
1901     } else {
1902         fputs("nasm: ", error_file);
1903     }
1904
1905     nasm_verror_common(severity, fmt, ap);
1906 }
1907
1908 /**
1909  * check for supressed warning
1910  * checks for suppressed warning or pass one only warning and we're
1911  * not in pass 1
1912  *
1913  * @param severity the severity of the warning or error
1914  * @return true if we should abort error/warning printing
1915  */
1916 static bool is_suppressed_warning(int severity)
1917 {
1918
1919     /* Not a warning at all */
1920     if ((severity & ERR_MASK) != ERR_WARNING)
1921         return false;
1922
1923     /* Might be a warning but suppresed explicitly */
1924     if (severity & ERR_WARN_MASK) {
1925         if (warning_on[WARN_IDX(severity)])
1926             return false;
1927     }
1928
1929     /* See if it's a pass-one only warning and we're not in pass one. */
1930     if (((severity & ERR_PASS1) && pass0 != 1) ||
1931         ((severity & ERR_PASS2) && pass0 != 2))
1932         return true;
1933
1934     return true;
1935 }
1936
1937 /**
1938  * common error reporting
1939  * This is the common back end of the error reporting schemes currently
1940  * implemented.  It prints the nature of the warning and then the
1941  * specific error message to error_file and may or may not return.  It
1942  * doesn't return if the error severity is a "panic" or "debug" type.
1943  *
1944  * @param severity the severity of the warning or error
1945  * @param fmt the printf style format string
1946  */
1947 static void nasm_verror_common(int severity, const char *fmt, va_list args)
1948 {
1949     char msg[1024];
1950     const char *pfx;
1951
1952     switch (severity & (ERR_MASK|ERR_NO_SEVERITY)) {
1953     case ERR_WARNING:
1954         pfx = "warning: ";
1955         break;
1956     case ERR_NONFATAL:
1957         pfx = "error: ";
1958         break;
1959     case ERR_FATAL:
1960         pfx = "fatal: ";
1961         break;
1962     case ERR_PANIC:
1963         pfx = "panic: ";
1964         break;
1965     case ERR_DEBUG:
1966         pfx = "debug: ";
1967         break;
1968     default:
1969         pfx = "";
1970         break;
1971     }
1972
1973     vsnprintf(msg, sizeof msg, fmt, args);
1974
1975     fprintf(error_file, "%s%s\n", pfx, msg);
1976
1977     if (*listname)
1978         nasmlist.error(severity, pfx, msg);
1979
1980     if (severity & ERR_USAGE)
1981         want_usage = true;
1982
1983     switch (severity & ERR_MASK) {
1984     case ERR_DEBUG:
1985         /* no further action, by definition */
1986         break;
1987     case ERR_WARNING:
1988         /* Treat warnings as errors */
1989         if (warning_on[WARN_IDX(ERR_WARN_TERM)])
1990             terminate_after_phase = true;
1991         break;
1992     case ERR_NONFATAL:
1993         terminate_after_phase = true;
1994         break;
1995     case ERR_FATAL:
1996         if (ofile) {
1997             fclose(ofile);
1998             remove(outname);
1999             ofile = NULL;
2000         }
2001         if (want_usage)
2002             usage();
2003         exit(1);                /* instantly die */
2004         break;                  /* placate silly compilers */
2005     case ERR_PANIC:
2006         fflush(NULL);
2007         /*      abort();        *//* halt, catch fire, and dump core */
2008         exit(3);
2009         break;
2010     }
2011 }
2012
2013 static void usage(void)
2014 {
2015     fputs("type `nasm -h' for help\n", error_file);
2016 }
2017
2018 #define BUF_DELTA 512
2019
2020 static FILE *no_pp_fp;
2021 static ListGen *no_pp_list;
2022 static int32_t no_pp_lineinc;
2023
2024 static void no_pp_reset(char *file, int pass, ListGen * listgen,
2025                         StrList **deplist)
2026 {
2027     src_set_fname(nasm_strdup(file));
2028     src_set_linnum(0);
2029     no_pp_lineinc = 1;
2030     no_pp_fp = fopen(file, "r");
2031     if (!no_pp_fp)
2032         nasm_error(ERR_FATAL | ERR_NOFILE,
2033                    "unable to open input file `%s'", file);
2034     no_pp_list = listgen;
2035     (void)pass;                 /* placate compilers */
2036
2037     if (deplist) {
2038         StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
2039         sl->next = NULL;
2040         strcpy(sl->str, file);
2041         *deplist = sl;
2042     }
2043 }
2044
2045 static char *no_pp_getline(void)
2046 {
2047     char *buffer, *p, *q;
2048     int bufsize;
2049
2050     bufsize = BUF_DELTA;
2051     buffer = nasm_malloc(BUF_DELTA);
2052     src_set_linnum(src_get_linnum() + no_pp_lineinc);
2053
2054     while (1) {                 /* Loop to handle %line */
2055
2056         p = buffer;
2057         while (1) {             /* Loop to handle long lines */
2058             q = fgets(p, bufsize - (p - buffer), no_pp_fp);
2059             if (!q)
2060                 break;
2061             p += strlen(p);
2062             if (p > buffer && p[-1] == '\n')
2063                 break;
2064             if (p - buffer > bufsize - 10) {
2065                 int offset;
2066                 offset = p - buffer;
2067                 bufsize += BUF_DELTA;
2068                 buffer = nasm_realloc(buffer, bufsize);
2069                 p = buffer + offset;
2070             }
2071         }
2072
2073         if (!q && p == buffer) {
2074             nasm_free(buffer);
2075             return NULL;
2076         }
2077
2078         /*
2079          * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
2080          * them are present at the end of the line.
2081          */
2082         buffer[strcspn(buffer, "\r\n\032")] = '\0';
2083
2084         if (!nasm_strnicmp(buffer, "%line", 5)) {
2085             int32_t ln;
2086             int li;
2087             char *nm = nasm_malloc(strlen(buffer));
2088             if (sscanf(buffer + 5, "%"PRId32"+%d %s", &ln, &li, nm) == 3) {
2089                 nasm_free(src_set_fname(nm));
2090                 src_set_linnum(ln);
2091                 no_pp_lineinc = li;
2092                 continue;
2093             }
2094             nasm_free(nm);
2095         }
2096         break;
2097     }
2098
2099     no_pp_list->line(LIST_READ, buffer);
2100
2101     return buffer;
2102 }
2103
2104 static void no_pp_cleanup(int pass)
2105 {
2106     (void)pass;                     /* placate GCC */
2107     if (no_pp_fp) {
2108         fclose(no_pp_fp);
2109         no_pp_fp = NULL;
2110     }
2111 }
2112
2113 static uint32_t get_cpu(char *value)
2114 {
2115     if (!strcmp(value, "8086"))
2116         return IF_8086;
2117     if (!strcmp(value, "186"))
2118         return IF_186;
2119     if (!strcmp(value, "286"))
2120         return IF_286;
2121     if (!strcmp(value, "386"))
2122         return IF_386;
2123     if (!strcmp(value, "486"))
2124         return IF_486;
2125     if (!strcmp(value, "586") || !nasm_stricmp(value, "pentium"))
2126         return IF_PENT;
2127     if (!strcmp(value, "686") ||
2128         !nasm_stricmp(value, "ppro") ||
2129         !nasm_stricmp(value, "pentiumpro") || !nasm_stricmp(value, "p2"))
2130         return IF_P6;
2131     if (!nasm_stricmp(value, "p3") || !nasm_stricmp(value, "katmai"))
2132         return IF_KATMAI;
2133     if (!nasm_stricmp(value, "p4") ||   /* is this right? -- jrc */
2134         !nasm_stricmp(value, "willamette"))
2135         return IF_WILLAMETTE;
2136     if (!nasm_stricmp(value, "prescott"))
2137         return IF_PRESCOTT;
2138     if (!nasm_stricmp(value, "x64") ||
2139         !nasm_stricmp(value, "x86-64"))
2140         return IF_X86_64;
2141     if (!nasm_stricmp(value, "ia64") ||
2142         !nasm_stricmp(value, "ia-64") ||
2143         !nasm_stricmp(value, "itanium") ||
2144         !nasm_stricmp(value, "itanic") || !nasm_stricmp(value, "merced"))
2145         return IF_IA64;
2146
2147     nasm_error(pass0 < 2 ? ERR_NONFATAL : ERR_FATAL,
2148                  "unknown 'cpu' type");
2149
2150     return IF_PLEVEL;           /* the maximum level */
2151 }
2152
2153 static int get_bits(char *value)
2154 {
2155     int i;
2156
2157     if ((i = atoi(value)) == 16)
2158         return i;               /* set for a 16-bit segment */
2159     else if (i == 32) {
2160         if (cpu < IF_386) {
2161             nasm_error(ERR_NONFATAL,
2162                          "cannot specify 32-bit segment on processor below a 386");
2163             i = 16;
2164         }
2165     } else if (i == 64) {
2166         if (cpu < IF_X86_64) {
2167             nasm_error(ERR_NONFATAL,
2168                          "cannot specify 64-bit segment on processor below an x86-64");
2169             i = 16;
2170         }
2171         if (i != maxbits) {
2172             nasm_error(ERR_NONFATAL,
2173                          "%s output format does not support 64-bit code",
2174                          ofmt->shortname);
2175             i = 16;
2176         }
2177     } else {
2178         nasm_error(pass0 < 2 ? ERR_NONFATAL : ERR_FATAL,
2179                      "`%s' is not a valid segment size; must be 16, 32 or 64",
2180                      value);
2181         i = 16;
2182     }
2183     return i;
2184 }