blob: 416cee843f102a0f38b88fc461fae898ba4c3993 [file] [log] [blame]
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001/* The Netwide Assembler main program module
2 *
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
Beroset095e6a22007-12-29 09:44:23 -05005 * redistributable under the license given in the file "LICENSE"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00006 * distributed in the NASM archive.
7 */
8
H. Peter Anvinfe501952007-10-02 21:53:51 -07009#include "compiler.h"
10
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000011#include <stdio.h>
12#include <stdarg.h>
13#include <stdlib.h>
14#include <string.h>
15#include <ctype.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000016#include <inttypes.h>
H. Peter Anvinfd7dd112007-10-10 14:06:59 -070017#include <limits.h>
H. Peter Anvin6b18bcc2008-02-16 14:54:10 -080018#include <time.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000019
20#include "nasm.h"
21#include "nasmlib.h"
H. Peter Anvin1803ded2008-06-09 17:32:43 -070022#include "saa.h"
H. Peter Anvinfcb89092008-06-09 17:40:16 -070023#include "raa.h"
H. Peter Anvinf6c9e652007-10-16 14:40:27 -070024#include "float.h"
H. Peter Anvin74cc5e52007-08-30 22:35:34 +000025#include "stdscan.h"
H. Peter Anvinaf535c12002-04-30 20:59:21 +000026#include "insns.h"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000027#include "preproc.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000028#include "parser.h"
H. Peter Anvin76690a12002-04-30 20:52:49 +000029#include "eval.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000030#include "assemble.h"
31#include "labels.h"
32#include "outform.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000033#include "listing.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000034
H. Peter Anvine2c80182005-01-15 22:15:51 +000035struct forwrefinfo { /* info held on forward refs. */
H. Peter Anvineba20a72002-04-30 20:53:55 +000036 int lineno;
37 int operand;
38};
39
Keith Kaniosa6dfa782007-04-13 16:47:53 +000040static int get_bits(char *value);
41static uint32_t get_cpu(char *cpu_str);
42static void parse_cmdline(int, char **);
H. Peter Anvin9e1f5282008-05-29 21:38:00 -070043static void assemble_file(char *, StrList **);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000044static void register_output_formats(void);
Keith Kaniosa6dfa782007-04-13 16:47:53 +000045static void report_error_gnu(int severity, const char *fmt, ...);
46static void report_error_vc(int severity, const char *fmt, ...);
47static void report_error_common(int severity, const char *fmt,
H. Peter Anvine2c80182005-01-15 22:15:51 +000048 va_list args);
H. Peter Anvin2b046cf2008-01-22 14:08:36 -080049static bool is_suppressed_warning(int severity);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000050static void usage(void);
Ed Berosetfa771012002-06-09 20:56:40 +000051static efunc report_error;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000052
John Coffman0efaec92002-05-26 19:20:08 +000053static int using_debug_info, opt_verbose_info;
H. Peter Anvin6867acc2007-10-10 14:58:45 -070054bool tasm_compatible_mode = false;
H. Peter Anvin00835fe2008-01-08 23:03:57 -080055int pass0, passn;
Keith Kaniosb7a89542007-04-12 02:40:54 +000056int maxbits = 0;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +000057int globalrel = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +000058
H. Peter Anvin6b18bcc2008-02-16 14:54:10 -080059time_t official_compile_time;
60
Keith Kaniosa6dfa782007-04-13 16:47:53 +000061static char inname[FILENAME_MAX];
62static char outname[FILENAME_MAX];
63static char listname[FILENAME_MAX];
Charles Craynefcce07f2007-09-30 22:15:36 -070064static char errname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +000065static int globallineno; /* for forward-reference tracking */
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +000066/* static int pass = 0; */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000067static struct ofmt *ofmt = NULL;
68
H. Peter Anvine2c80182005-01-15 22:15:51 +000069static FILE *error_file; /* Where to write error messages */
H. Peter Anvin620515a2002-04-30 20:57:38 +000070
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000071static FILE *ofile = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +000072int optimizing = -1; /* number of optimization passes to take */
73static int sb, cmd_sb = 16; /* by default */
Keith Kaniosb7a89542007-04-12 02:40:54 +000074static uint32_t cmd_cpu = IF_PLEVEL; /* highest level by default */
75static uint32_t cpu = IF_PLEVEL; /* passed to insn_size & assemble.c */
H. Peter Anvin70055962007-10-11 00:05:31 -070076bool global_offset_changed; /* referenced in labels.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000077
H. Peter Anvin12e46512007-10-03 21:30:57 -070078static struct location location;
H. Peter Anvine2c80182005-01-15 22:15:51 +000079int in_abs_seg; /* Flag we are in ABSOLUTE seg */
Keith Kaniosb7a89542007-04-12 02:40:54 +000080int32_t abs_seg; /* ABSOLUTE segment basis */
81int32_t abs_offset; /* ABSOLUTE offset */
H. Peter Anvin6768eb72002-04-30 20:52:26 +000082
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000083static struct RAA *offsets;
H. Peter Anvinea838272002-04-30 20:51:53 +000084
H. Peter Anvine2c80182005-01-15 22:15:51 +000085static struct SAA *forwrefs; /* keep track of forward references */
H. Peter Anvin9d637df2007-10-04 13:42:56 -070086static const struct forwrefinfo *forwref;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000087
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000088static Preproc *preproc;
H. Peter Anvin620515a2002-04-30 20:57:38 +000089enum op_type {
H. Peter Anvine2c80182005-01-15 22:15:51 +000090 op_normal, /* Preprocess and assemble */
91 op_preprocess, /* Preprocess only */
H. Peter Anvin37a321f2007-09-24 13:41:58 -070092 op_depend, /* Generate dependencies */
H. Peter Anvin620515a2002-04-30 20:57:38 +000093};
94static enum op_type operating_mode;
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -070095/* Dependency flags */
H. Peter Anvin9e1f5282008-05-29 21:38:00 -070096static bool depend_emit_phony = false;
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -070097static bool depend_missing_ok = false;
98static const char *depend_target = NULL;
99static const char *depend_file = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000100
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000101/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000102 * Which of the suppressible warnings are suppressed. Entry zero
H. Peter Anvinb030c922007-11-13 11:31:15 -0800103 * isn't an actual warning, but it used for -w+error/-Werror.
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000104 */
H. Peter Anvinb030c922007-11-13 11:31:15 -0800105static bool suppressed[ERR_WARN_MAX+1] = {
H. Peter Anvinc68ec012007-11-13 11:34:34 -0800106 true, false, true, false, false, true, false, true, true, false
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000107};
108
109/*
110 * The option names for the suppressible warnings. As before, entry
111 * zero does nothing.
112 */
H. Peter Anvinb030c922007-11-13 11:31:15 -0800113static const char *suppressed_names[ERR_WARN_MAX+1] = {
114 "error", "macro-params", "macro-selfref", "orphan-labels",
H. Peter Anvin125c8782007-10-16 11:32:58 -0700115 "number-overflow", "gnu-elf-extensions", "float-overflow",
116 "float-denorm", "float-underflow", "float-toolong"
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000117};
118
119/*
120 * The explanations for the suppressible warnings. As before, entry
121 * zero does nothing.
122 */
H. Peter Anvinb030c922007-11-13 11:31:15 -0800123static const char *suppressed_what[ERR_WARN_MAX+1] = {
124 "treat warnings as errors",
H. Peter Anvinc68ec012007-11-13 11:34:34 -0800125 "macro calls with wrong parameter count",
126 "cyclic macro references",
H. Peter Anvin76690a12002-04-30 20:52:49 +0000127 "labels alone on lines without trailing `:'",
H. Peter Anvinc68ec012007-11-13 11:34:34 -0800128 "numeric constants does not fit in 64 bits",
H. Peter Anvinfab3a6c2007-10-16 11:48:07 -0700129 "using 8- or 16-bit relocation in ELF32, a GNU extension",
H. Peter Anvin125c8782007-10-16 11:32:58 -0700130 "floating point overflow",
131 "floating point denormal",
132 "floating point underflow",
H. Peter Anvinfab3a6c2007-10-16 11:48:07 -0700133 "too many digits in floating-point number"
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000134};
135
136/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000137 * This is a null preprocessor which just copies lines from input
138 * to output. It's used when someone explicitly requests that NASM
139 * not preprocess their source file.
140 */
141
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700142static void no_pp_reset(char *, int, efunc, evalfunc, ListGen *, StrList **);
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000143static char *no_pp_getline(void);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000144static void no_pp_cleanup(int);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000145static Preproc no_pp = {
146 no_pp_reset,
147 no_pp_getline,
148 no_pp_cleanup
149};
150
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000151/*
152 * get/set current offset...
153 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000154#define GET_CURR_OFFS (in_abs_seg?abs_offset:\
H. Peter Anvineba20a72002-04-30 20:53:55 +0000155 raa_read(offsets,location.segment))
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000156#define SET_CURR_OFFS(x) (in_abs_seg?(void)(abs_offset=(x)):\
H. Peter Anvineba20a72002-04-30 20:53:55 +0000157 (void)(offsets=raa_write(offsets,location.segment,(x))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000158
159static int want_usage;
160static int terminate_after_phase;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000161int user_nolist = 0; /* fbk 9/2/00 */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000162
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000163static void nasm_fputs(const char *line, FILE * outfile)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000164{
H. Peter Anvin310b3e12002-05-14 22:38:55 +0000165 if (outfile) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000166 fputs(line, outfile);
H. Peter Anvind1fb15c2007-11-13 09:37:59 -0800167 putc('\n', outfile);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000168 } else
H. Peter Anvine2c80182005-01-15 22:15:51 +0000169 puts(line);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000170}
171
H. Peter Anvin6b18bcc2008-02-16 14:54:10 -0800172/* Convert a struct tm to a POSIX-style time constant */
173static int64_t posix_mktime(struct tm *tm)
174{
175 int64_t t;
176 int64_t y = tm->tm_year;
177
178 /* See IEEE 1003.1:2004, section 4.14 */
179
180 t = (y-70)*365 + (y-69)/4 - (y-1)/100 + (y+299)/400;
181 t += tm->tm_yday;
182 t *= 24;
183 t += tm->tm_hour;
184 t *= 60;
185 t += tm->tm_min;
186 t *= 60;
187 t += tm->tm_sec;
188
189 return t;
190}
191
192static void define_macros_early(void)
193{
194 char temp[128];
195 struct tm lt, *lt_p, gm, *gm_p;
196 int64_t posix_time;
197
198 lt_p = localtime(&official_compile_time);
199 if (lt_p) {
200 lt = *lt_p;
201
202 strftime(temp, sizeof temp, "__DATE__=\"%Y-%m-%d\"", &lt);
203 pp_pre_define(temp);
204 strftime(temp, sizeof temp, "__DATE_NUM__=%Y%m%d", &lt);
205 pp_pre_define(temp);
206 strftime(temp, sizeof temp, "__TIME__=\"%H:%M:%S\"", &lt);
207 pp_pre_define(temp);
208 strftime(temp, sizeof temp, "__TIME_NUM__=%H%M%S", &lt);
209 pp_pre_define(temp);
210 }
211
212 gm_p = gmtime(&official_compile_time);
213 if (gm_p) {
214 gm = *gm_p;
215
216 strftime(temp, sizeof temp, "__UTC_DATE__=\"%Y-%m-%d\"", &gm);
217 pp_pre_define(temp);
218 strftime(temp, sizeof temp, "__UTC_DATE_NUM__=%Y%m%d", &gm);
219 pp_pre_define(temp);
220 strftime(temp, sizeof temp, "__UTC_TIME__=\"%H:%M:%S\"", &gm);
221 pp_pre_define(temp);
222 strftime(temp, sizeof temp, "__UTC_TIME_NUM__=%H%M%S", &gm);
223 pp_pre_define(temp);
224 }
H. Peter Anvind85d2502008-05-04 17:53:31 -0700225
H. Peter Anvin6b18bcc2008-02-16 14:54:10 -0800226 if (gm_p)
227 posix_time = posix_mktime(&gm);
228 else if (lt_p)
229 posix_time = posix_mktime(&lt);
230 else
231 posix_time = 0;
232
233 if (posix_time) {
234 snprintf(temp, sizeof temp, "__POSIX_TIME__=%"PRId64, posix_time);
235 pp_pre_define(temp);
236 }
237}
238
239static void define_macros_late(void)
240{
241 char temp[128];
242
243 snprintf(temp, sizeof(temp), "__OUTPUT_FORMAT__=%s\n",
244 ofmt->shortname);
245 pp_pre_define(temp);
246}
247
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700248static void emit_dependencies(StrList *list)
249{
250 FILE *deps;
251 int linepos, len;
252 StrList *l, *nl;
253
254 if (depend_file && strcmp(depend_file, "-")) {
255 deps = fopen(depend_file, "w");
256 if (!deps) {
257 report_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
258 "unable to write dependency file `%s'", depend_file);
259 return;
260 }
261 } else {
262 deps = stdout;
263 }
264
265 linepos = fprintf(deps, "%s:", depend_target);
266 for (l = list; l; l = l->next) {
267 len = strlen(l->str);
268 if (linepos + len > 62) {
269 fprintf(deps, " \\\n ");
270 linepos = 1;
271 }
272 fprintf(deps, " %s", l->str);
273 linepos += len+1;
274 }
275 fprintf(deps, "\n\n");
276
277 for (l = list; l; l = nl) {
278 if (depend_emit_phony)
279 fprintf(deps, "%s:\n\n", l->str);
280
281 nl = l->next;
282 nasm_free(l);
283 }
284
285 if (deps != stdout)
286 fclose(deps);
287}
288
H. Peter Anvin038d8612007-04-12 16:54:50 +0000289int main(int argc, char **argv)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000290{
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700291 StrList *depend_list = NULL, **depend_ptr;
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700292
H. Peter Anvin6b18bcc2008-02-16 14:54:10 -0800293 time(&official_compile_time);
294
Ed Berosetfa771012002-06-09 20:56:40 +0000295 pass0 = 1;
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700296 want_usage = terminate_after_phase = false;
Ed Berosetfa771012002-06-09 20:56:40 +0000297 report_error = report_error_gnu;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000298
H. Peter Anvin97e15752007-09-25 08:47:47 -0700299 error_file = stderr;
300
H. Peter Anvinac8f8fc2008-06-11 15:49:41 -0700301 tolower_init();
302
H. Peter Anvine2c80182005-01-15 22:15:51 +0000303 nasm_set_malloc_error(report_error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000304 offsets = raa_init();
Keith Kaniosb7a89542007-04-12 02:40:54 +0000305 forwrefs = saa_init((int32_t)sizeof(struct forwrefinfo));
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000306
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000307 preproc = &nasmpp;
H. Peter Anvin620515a2002-04-30 20:57:38 +0000308 operating_mode = op_normal;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000309
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000310 seg_init();
311
312 register_output_formats();
313
H. Peter Anvin6b18bcc2008-02-16 14:54:10 -0800314 /* Define some macros dependent on the runtime, but not
315 on the command line. */
316 define_macros_early();
317
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000318 parse_cmdline(argc, argv);
319
H. Peter Anvine2c80182005-01-15 22:15:51 +0000320 if (terminate_after_phase) {
321 if (want_usage)
322 usage();
323 return 1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000324 }
325
H. Peter Anvinbb88d012003-09-10 23:34:23 +0000326 /* If debugging info is disabled, suppress any debug calls */
327 if (!using_debug_info)
328 ofmt->current_dfmt = &null_debug_form;
329
H. Peter Anvin76690a12002-04-30 20:52:49 +0000330 if (ofmt->stdmac)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000331 pp_extra_stdmac(ofmt->stdmac);
332 parser_global_info(ofmt, &location);
333 eval_global_info(ofmt, lookup_label, &location);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000334
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000335 /* define some macros dependent of command-line */
H. Peter Anvin6b18bcc2008-02-16 14:54:10 -0800336 define_macros_late();
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000337
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700338 depend_ptr = (depend_file || (operating_mode == op_depend))
339 ? &depend_list : NULL;
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700340 if (!depend_target)
341 depend_target = outname;
342
H. Peter Anvine2c80182005-01-15 22:15:51 +0000343 switch (operating_mode) {
H. Peter Anvin620515a2002-04-30 20:57:38 +0000344 case op_depend:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000345 {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000346 char *line;
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700347
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700348 if (depend_missing_ok)
349 pp_include_path(NULL); /* "assume generated" */
350
351 preproc->reset(inname, 0, report_error, evaluate, &nasmlist,
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700352 depend_ptr);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000353 if (outname[0] == '\0')
354 ofmt->filename(inname, outname, report_error);
355 ofile = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000356 while ((line = preproc->getline()))
357 nasm_free(line);
358 preproc->cleanup(0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000359 }
360 break;
H. Peter Anvin620515a2002-04-30 20:57:38 +0000361
362 case op_preprocess:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000363 {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000364 char *line;
365 char *file_name = NULL;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000366 int32_t prior_linnum = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000367 int lineinc = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000368
H. Peter Anvine2c80182005-01-15 22:15:51 +0000369 if (*outname) {
370 ofile = fopen(outname, "w");
371 if (!ofile)
372 report_error(ERR_FATAL | ERR_NOFILE,
373 "unable to open output file `%s'",
374 outname);
375 } else
376 ofile = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000377
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700378 location.known = false;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000379
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700380 /* pass = 1; */
381 preproc->reset(inname, 2, report_error, evaluate, &nasmlist,
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700382 depend_ptr);
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700383
H. Peter Anvine2c80182005-01-15 22:15:51 +0000384 while ((line = preproc->getline())) {
385 /*
386 * We generate %line directives if needed for later programs
387 */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000388 int32_t linnum = prior_linnum += lineinc;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000389 int altline = src_get(&linnum, &file_name);
390 if (altline) {
391 if (altline == 1 && lineinc == 1)
392 nasm_fputs("", ofile);
393 else {
394 lineinc = (altline != -1 || lineinc != 1);
395 fprintf(ofile ? ofile : stdout,
Keith Kanios93f2e9a2007-04-14 00:10:59 +0000396 "%%line %"PRId32"+%d %s\n", linnum, lineinc,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000397 file_name);
398 }
399 prior_linnum = linnum;
400 }
401 nasm_fputs(line, ofile);
402 nasm_free(line);
403 }
404 nasm_free(file_name);
405 preproc->cleanup(0);
406 if (ofile)
407 fclose(ofile);
408 if (ofile && terminate_after_phase)
409 remove(outname);
410 }
411 break;
H. Peter Anvin620515a2002-04-30 20:57:38 +0000412
413 case op_normal:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000414 {
415 /*
416 * We must call ofmt->filename _anyway_, even if the user
417 * has specified their own output file, because some
418 * formats (eg OBJ and COFF) use ofmt->filename to find out
419 * the name of the input file and then put that inside the
420 * file.
421 */
422 ofmt->filename(inname, outname, report_error);
423
424 ofile = fopen(outname, "wb");
425 if (!ofile) {
426 report_error(ERR_FATAL | ERR_NOFILE,
427 "unable to open output file `%s'", outname);
428 }
429
430 /*
431 * We must call init_labels() before ofmt->init() since
432 * some object formats will want to define labels in their
433 * init routines. (eg OS/2 defines the FLAT group)
434 */
435 init_labels();
436
437 ofmt->init(ofile, report_error, define_label, evaluate);
438
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700439 assemble_file(inname, depend_ptr);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000440
441 if (!terminate_after_phase) {
442 ofmt->cleanup(using_debug_info);
443 cleanup_labels();
444 } else {
445 /*
446 * We had an fclose on the output file here, but we
447 * actually do that in all the object file drivers as well,
448 * so we're leaving out the one here.
449 * fclose (ofile);
450 */
451 remove(outname);
452 if (listname[0])
453 remove(listname);
454 }
455 }
456 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000457 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000458
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700459 if (depend_list)
460 emit_dependencies(depend_list);
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700461
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000462 if (want_usage)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000463 usage();
H. Peter Anvin734b1882002-04-30 21:01:08 +0000464
H. Peter Anvine2c80182005-01-15 22:15:51 +0000465 raa_free(offsets);
466 saa_free(forwrefs);
467 eval_cleanup();
H. Peter Anvin74cc5e52007-08-30 22:35:34 +0000468 stdscan_cleanup();
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000469
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000470 if (terminate_after_phase)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000471 return 1;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000472 else
H. Peter Anvine2c80182005-01-15 22:15:51 +0000473 return 0;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000474}
475
H. Peter Anvineba20a72002-04-30 20:53:55 +0000476/*
477 * Get a parameter for a command line option.
478 * First arg must be in the form of e.g. -f...
479 */
H. Peter Anvin423e3812007-11-15 17:12:29 -0800480static char *get_param(char *p, char *q, bool *advance)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000481{
H. Peter Anvin423e3812007-11-15 17:12:29 -0800482 *advance = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000483 if (p[2]) { /* the parameter's in the option */
484 p += 2;
485 while (isspace(*p))
486 p++;
487 return p;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000488 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000489 if (q && q[0]) {
H. Peter Anvin423e3812007-11-15 17:12:29 -0800490 *advance = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000491 return q;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000492 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000493 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
494 "option `-%c' requires an argument", p[1]);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000495 return NULL;
496}
497
H. Peter Anvindc242712007-11-18 11:55:10 -0800498/*
499 * Copy a filename
500 */
501static void copy_filename(char *dst, const char *src)
502{
503 size_t len = strlen(src);
504
505 if (len >= (size_t)FILENAME_MAX) {
506 report_error(ERR_FATAL | ERR_NOFILE, "file name too long");
507 return;
508 }
509 strncpy(dst, src, FILENAME_MAX);
510}
511
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700512/*
513 * Convert a string to Make-safe form
514 */
515static char *quote_for_make(const char *str)
516{
517 const char *p;
518 char *os, *q;
519
520 size_t n = 1; /* Terminating zero */
521 size_t nbs = 0;
522
523 if (!str)
524 return NULL;
525
526 for (p = str; *p; p++) {
527 switch (*p) {
528 case ' ':
529 case '\t':
530 /* Convert N backslashes + ws -> 2N+1 backslashes + ws */
531 n += nbs + 2;
532 nbs = 0;
533 break;
534 case '$':
535 case '#':
536 nbs = 0;
537 n += 2;
538 break;
539 case '\\':
540 nbs++;
541 n++;
542 break;
543 default:
544 nbs = 0;
545 n++;
546 break;
547 }
548 }
549
550 /* Convert N backslashes at the end of filename to 2N backslashes */
551 if (nbs)
552 n += nbs;
553
554 os = q = nasm_malloc(n);
555
556 nbs = 0;
557 for (p = str; *p; p++) {
558 switch (*p) {
559 case ' ':
560 case '\t':
561 while (nbs--)
562 *q++ = '\\';
563 *q++ = '\\';
564 *q++ = *p;
565 break;
566 case '$':
567 *q++ = *p;
568 *q++ = *p;
569 nbs = 0;
570 break;
571 case '#':
572 *q++ = '\\';
573 *q++ = *p;
574 nbs = 0;
575 break;
576 case '\\':
577 *q++ = *p;
578 nbs++;
579 break;
580 default:
581 *q++ = *p;
582 nbs = 0;
583 break;
584 }
585 }
586 while (nbs--)
587 *q++ = '\\';
588
589 *q = '\0';
590
591 return os;
592}
593
H. Peter Anvine2c80182005-01-15 22:15:51 +0000594struct textargs {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000595 const char *label;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000596 int value;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000597};
598
599#define OPT_PREFIX 0
600#define OPT_POSTFIX 1
H. Peter Anvine2c80182005-01-15 22:15:51 +0000601struct textargs textopts[] = {
602 {"prefix", OPT_PREFIX},
603 {"postfix", OPT_POSTFIX},
604 {NULL, 0}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000605};
606
H. Peter Anvin423e3812007-11-15 17:12:29 -0800607static bool stopoptions = false;
608static bool process_arg(char *p, char *q)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000609{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000610 char *param;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800611 int i;
612 bool advance = false;
H. Peter Anvinb030c922007-11-13 11:31:15 -0800613 bool suppress;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000614
615 if (!p || !p[0])
H. Peter Anvin423e3812007-11-15 17:12:29 -0800616 return false;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000617
H. Peter Anvine2c80182005-01-15 22:15:51 +0000618 if (p[0] == '-' && !stopoptions) {
H. Peter Anvin423e3812007-11-15 17:12:29 -0800619 if (strchr("oOfpPdDiIlFXuUZwW", p[1])) {
620 /* These parameters take values */
621 if (!(param = get_param(p, q, &advance)))
622 return advance;
623 }
624
H. Peter Anvine2c80182005-01-15 22:15:51 +0000625 switch (p[1]) {
626 case 's':
627 error_file = stdout;
628 break;
H. Peter Anvin70653092007-10-19 14:42:29 -0700629
H. Peter Anvin423e3812007-11-15 17:12:29 -0800630 case 'o': /* output file */
H. Peter Anvindc242712007-11-18 11:55:10 -0800631 copy_filename(outname, param);
H. Peter Anvin423e3812007-11-15 17:12:29 -0800632 break;
H. Peter Anvinfd7dd112007-10-10 14:06:59 -0700633
H. Peter Anvin423e3812007-11-15 17:12:29 -0800634 case 'f': /* output format */
635 ofmt = ofmt_find(param);
636 if (!ofmt) {
637 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
638 "unrecognised output format `%s' - "
639 "use -hf for a list", param);
640 } else {
641 ofmt->current_dfmt = ofmt->debug_formats[0];
642 }
643 break;
H. Peter Anvin70653092007-10-19 14:42:29 -0700644
H. Peter Anvin423e3812007-11-15 17:12:29 -0800645 case 'O': /* Optimization level */
646 {
647 int opt;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700648
H. Peter Anvin423e3812007-11-15 17:12:29 -0800649 if (!*param) {
650 /* Naked -O == -Ox */
651 optimizing = INT_MAX >> 1; /* Almost unlimited */
652 } else {
653 while (*param) {
654 switch (*param) {
655 case '0': case '1': case '2': case '3': case '4':
656 case '5': case '6': case '7': case '8': case '9':
657 opt = strtoul(param, &param, 10);
H. Peter Anvind85d2502008-05-04 17:53:31 -0700658
H. Peter Anvin423e3812007-11-15 17:12:29 -0800659 /* -O0 -> optimizing == -1, 0.98 behaviour */
660 /* -O1 -> optimizing == 0, 0.98.09 behaviour */
661 if (opt < 2)
662 optimizing = opt - 1;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800663 else
H. Peter Anvin34ec3002008-01-08 22:31:20 -0800664 optimizing = opt;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800665 break;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700666
H. Peter Anvin423e3812007-11-15 17:12:29 -0800667 case 'v':
668 case '+':
669 param++;
670 opt_verbose_info = true;
671 break;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700672
H. Peter Anvin423e3812007-11-15 17:12:29 -0800673 case 'x':
674 param++;
675 optimizing = INT_MAX >> 1; /* Almost unlimited */
676 break;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700677
H. Peter Anvin423e3812007-11-15 17:12:29 -0800678 default:
679 report_error(ERR_FATAL,
680 "unknown optimization option -O%c\n",
681 *param);
682 break;
H. Peter Anvinfd7dd112007-10-10 14:06:59 -0700683 }
684 }
H. Peter Anvin423e3812007-11-15 17:12:29 -0800685 }
686 break;
687 }
688
689 case 'p': /* pre-include */
690 case 'P':
691 pp_pre_include(param);
692 break;
693
694 case 'd': /* pre-define */
695 case 'D':
696 pp_pre_define(param);
697 break;
698
699 case 'u': /* un-define */
700 case 'U':
701 pp_pre_undefine(param);
702 break;
703
704 case 'i': /* include search path */
705 case 'I':
706 pp_include_path(param);
707 break;
708
709 case 'l': /* listing file */
H. Peter Anvindc242712007-11-18 11:55:10 -0800710 copy_filename(listname, param);
H. Peter Anvin423e3812007-11-15 17:12:29 -0800711 break;
712
713 case 'Z': /* error messages file */
714 strcpy(errname, param);
715 break;
716
717 case 'F': /* specify debug format */
718 ofmt->current_dfmt = dfmt_find(ofmt, param);
719 if (!ofmt->current_dfmt) {
720 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
721 "unrecognized debug format `%s' for"
722 " output format `%s'",
723 param, ofmt->shortname);
724 }
725 break;
726
727 case 'X': /* specify error reporting format */
728 if (nasm_stricmp("vc", param) == 0)
729 report_error = report_error_vc;
730 else if (nasm_stricmp("gnu", param) == 0)
731 report_error = report_error_gnu;
732 else
733 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
734 "unrecognized error reporting format `%s'",
735 param);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000736 break;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800737
H. Peter Anvine2c80182005-01-15 22:15:51 +0000738 case 'g':
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700739 using_debug_info = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000740 break;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800741
H. Peter Anvine2c80182005-01-15 22:15:51 +0000742 case 'h':
743 printf
744 ("usage: nasm [-@ response file] [-o outfile] [-f format] "
745 "[-l listfile]\n"
746 " [options...] [--] filename\n"
H. Peter Anvin413fb902007-09-26 15:19:28 -0700747 " or nasm -v for version info\n\n"
H. Peter Anvine2c80182005-01-15 22:15:51 +0000748 " -t assemble in SciTech TASM compatible mode\n"
749 " -g generate debug information in selected format.\n");
750 printf
H. Peter Anvin413fb902007-09-26 15:19:28 -0700751 (" -E (or -e) preprocess only (writes output to stdout by default)\n"
H. Peter Anvine2c80182005-01-15 22:15:51 +0000752 " -a don't preprocess (assemble only)\n"
H. Peter Anvin37a321f2007-09-24 13:41:58 -0700753 " -M generate Makefile dependencies on stdout\n"
754 " -MG d:o, missing files assumed generated\n\n"
H. Peter Anvin413fb902007-09-26 15:19:28 -0700755 " -Z<file> redirect error messages to file\n"
H. Peter Anvine2c80182005-01-15 22:15:51 +0000756 " -s redirect error messages to stdout\n\n"
757 " -F format select a debugging format\n\n"
758 " -I<path> adds a pathname to the include file path\n");
759 printf
760 (" -O<digit> optimize branch offsets (-O0 disables, default)\n"
761 " -P<file> pre-includes a file\n"
762 " -D<macro>[=<value>] pre-defines a macro\n"
763 " -U<macro> undefines a macro\n"
764 " -X<format> specifies error reporting format (gnu or vc)\n"
H. Peter Anvinb030c922007-11-13 11:31:15 -0800765 " -w+foo enables warning foo (equiv. -Wfoo)\n"
766 " -w-foo disable warning foo (equiv. -Wno-foo)\n"
767 "Warnings:\n");
768 for (i = 0; i <= ERR_WARN_MAX; i++)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000769 printf(" %-23s %s (default %s)\n",
770 suppressed_names[i], suppressed_what[i],
771 suppressed[i] ? "off" : "on");
772 printf
773 ("\nresponse files should contain command line parameters"
774 ", one per line.\n");
775 if (p[2] == 'f') {
776 printf("\nvalid output formats for -f are"
777 " (`*' denotes default):\n");
778 ofmt_list(ofmt, stdout);
779 } else {
780 printf("\nFor a list of valid output formats, use -hf.\n");
781 printf("For a list of debug formats, use -f <form> -y.\n");
782 }
783 exit(0); /* never need usage message here */
784 break;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800785
H. Peter Anvine2c80182005-01-15 22:15:51 +0000786 case 'y':
787 printf("\nvalid debug formats for '%s' output format are"
788 " ('*' denotes default):\n", ofmt->shortname);
789 dfmt_list(ofmt, stdout);
790 exit(0);
791 break;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800792
H. Peter Anvine2c80182005-01-15 22:15:51 +0000793 case 't':
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700794 tasm_compatible_mode = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000795 break;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800796
H. Peter Anvine2c80182005-01-15 22:15:51 +0000797 case 'v':
798 {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000799 const char *nasm_version_string =
H. Peter Anvine2c80182005-01-15 22:15:51 +0000800 "NASM version " NASM_VER " compiled on " __DATE__
H. Peter Anvineba20a72002-04-30 20:53:55 +0000801#ifdef DEBUG
H. Peter Anvine2c80182005-01-15 22:15:51 +0000802 " with -DDEBUG"
H. Peter Anvineba20a72002-04-30 20:53:55 +0000803#endif
H. Peter Anvine2c80182005-01-15 22:15:51 +0000804 ;
805 puts(nasm_version_string);
806 exit(0); /* never need usage message here */
807 }
808 break;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800809
H. Peter Anvine2c80182005-01-15 22:15:51 +0000810 case 'e': /* preprocess only */
H. Peter Anvin413fb902007-09-26 15:19:28 -0700811 case 'E':
H. Peter Anvine2c80182005-01-15 22:15:51 +0000812 operating_mode = op_preprocess;
813 break;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800814
H. Peter Anvine2c80182005-01-15 22:15:51 +0000815 case 'a': /* assemble only - don't preprocess */
816 preproc = &no_pp;
817 break;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800818
H. Peter Anvinb030c922007-11-13 11:31:15 -0800819 case 'W':
H. Peter Anvin423e3812007-11-15 17:12:29 -0800820 if (param[0] == 'n' && param[1] == 'o' && param[2] == '-') {
H. Peter Anvinb030c922007-11-13 11:31:15 -0800821 suppress = true;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800822 param += 3;
H. Peter Anvinb030c922007-11-13 11:31:15 -0800823 } else {
824 suppress = false;
H. Peter Anvinb030c922007-11-13 11:31:15 -0800825 }
826 goto set_warning;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800827
H. Peter Anvine2c80182005-01-15 22:15:51 +0000828 case 'w':
H. Peter Anvin423e3812007-11-15 17:12:29 -0800829 if (param[0] != '+' && param[0] != '-') {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000830 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
831 "invalid option to `-w'");
H. Peter Anvinb030c922007-11-13 11:31:15 -0800832 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000833 }
H. Peter Anvin423e3812007-11-15 17:12:29 -0800834 suppress = (param[0] == '-');
835 param++;
H. Peter Anvinb030c922007-11-13 11:31:15 -0800836 goto set_warning;
837 set_warning:
838 for (i = 0; i <= ERR_WARN_MAX; i++)
H. Peter Anvin423e3812007-11-15 17:12:29 -0800839 if (!nasm_stricmp(param, suppressed_names[i]))
H. Peter Anvinb030c922007-11-13 11:31:15 -0800840 break;
841 if (i <= ERR_WARN_MAX)
842 suppressed[i] = suppress;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800843 else if (!nasm_stricmp(param, "all"))
H. Peter Anvinb030c922007-11-13 11:31:15 -0800844 for (i = 1; i <= ERR_WARN_MAX; i++)
845 suppressed[i] = suppress;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800846 else if (!nasm_stricmp(param, "none"))
847 for (i = 1; i <= ERR_WARN_MAX; i++)
848 suppressed[i] = !suppress;
H. Peter Anvinb030c922007-11-13 11:31:15 -0800849 else
850 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
H. Peter Anvin423e3812007-11-15 17:12:29 -0800851 "invalid warning `%s'", param);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000852 break;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800853
H. Peter Anvine2c80182005-01-15 22:15:51 +0000854 case 'M':
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700855 switch (p[2]) {
856 case 0:
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700857 operating_mode = op_depend;
858 break;
859 case 'G':
860 operating_mode = op_depend;
861 depend_missing_ok = true;
862 break;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700863 case 'P':
864 depend_emit_phony = true;
865 break;
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700866 case 'D':
867 depend_file = q;
868 advance = true;
869 break;
870 case 'T':
871 depend_target = q;
872 advance = true;
873 break;
874 case 'Q':
875 depend_target = quote_for_make(q);
876 advance = true;
877 break;
878 default:
879 report_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
880 "unknown dependency option `-M%c'", p[2]);
881 break;
882 }
883 if (advance && (!q || !q[0])) {
884 report_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
885 "option `-M%c' requires a parameter", p[2]);
886 break;
887 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000888 break;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000889
H. Peter Anvine2c80182005-01-15 22:15:51 +0000890 case '-':
891 {
892 int s;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000893
H. Peter Anvine2c80182005-01-15 22:15:51 +0000894 if (p[2] == 0) { /* -- => stop processing options */
895 stopoptions = 1;
896 break;
897 }
898 for (s = 0; textopts[s].label; s++) {
899 if (!nasm_stricmp(p + 2, textopts[s].label)) {
900 break;
901 }
902 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000903
H. Peter Anvine2c80182005-01-15 22:15:51 +0000904 switch (s) {
905
906 case OPT_PREFIX:
907 case OPT_POSTFIX:
908 {
909 if (!q) {
910 report_error(ERR_NONFATAL | ERR_NOFILE |
911 ERR_USAGE,
912 "option `--%s' requires an argument",
913 p + 2);
914 break;
915 } else {
916 advance = 1, param = q;
917 }
918
919 if (s == OPT_PREFIX) {
920 strncpy(lprefix, param, PREFIX_MAX - 1);
921 lprefix[PREFIX_MAX - 1] = 0;
922 break;
923 }
924 if (s == OPT_POSTFIX) {
925 strncpy(lpostfix, param, POSTFIX_MAX - 1);
926 lpostfix[POSTFIX_MAX - 1] = 0;
927 break;
928 }
929 break;
930 }
931 default:
932 {
933 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
934 "unrecognised option `--%s'", p + 2);
935 break;
936 }
937 }
938 break;
939 }
940
941 default:
942 if (!ofmt->setinfo(GI_SWITCH, &p))
943 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
944 "unrecognised option `-%c'", p[1]);
945 break;
946 }
947 } else {
948 if (*inname) {
949 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
950 "more than one input file specified");
H. Peter Anvindc242712007-11-18 11:55:10 -0800951 } else {
952 copy_filename(inname, p);
953 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000954 }
955
956 return advance;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000957}
958
H. Peter Anvineba20a72002-04-30 20:53:55 +0000959#define ARG_BUF_DELTA 128
960
H. Peter Anvine2c80182005-01-15 22:15:51 +0000961static void process_respfile(FILE * rfile)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000962{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000963 char *buffer, *p, *q, *prevarg;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000964 int bufsize, prevargsize;
965
966 bufsize = prevargsize = ARG_BUF_DELTA;
967 buffer = nasm_malloc(ARG_BUF_DELTA);
968 prevarg = nasm_malloc(ARG_BUF_DELTA);
969 prevarg[0] = '\0';
970
H. Peter Anvine2c80182005-01-15 22:15:51 +0000971 while (1) { /* Loop to handle all lines in file */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000972 p = buffer;
973 while (1) { /* Loop to handle long lines */
974 q = fgets(p, bufsize - (p - buffer), rfile);
975 if (!q)
976 break;
977 p += strlen(p);
978 if (p > buffer && p[-1] == '\n')
979 break;
980 if (p - buffer > bufsize - 10) {
981 int offset;
982 offset = p - buffer;
983 bufsize += ARG_BUF_DELTA;
984 buffer = nasm_realloc(buffer, bufsize);
985 p = buffer + offset;
986 }
987 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000988
H. Peter Anvine2c80182005-01-15 22:15:51 +0000989 if (!q && p == buffer) {
990 if (prevarg[0])
991 process_arg(prevarg, NULL);
992 nasm_free(buffer);
993 nasm_free(prevarg);
994 return;
995 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000996
H. Peter Anvine2c80182005-01-15 22:15:51 +0000997 /*
998 * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
999 * them are present at the end of the line.
1000 */
1001 *(p = &buffer[strcspn(buffer, "\r\n\032")]) = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +00001002
H. Peter Anvine2c80182005-01-15 22:15:51 +00001003 while (p > buffer && isspace(p[-1]))
1004 *--p = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +00001005
H. Peter Anvine2c80182005-01-15 22:15:51 +00001006 p = buffer;
1007 while (isspace(*p))
1008 p++;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001009
H. Peter Anvine2c80182005-01-15 22:15:51 +00001010 if (process_arg(prevarg, p))
1011 *p = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +00001012
Charles Crayne192d5b52007-10-18 19:02:42 -07001013 if ((int) strlen(p) > prevargsize - 10) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001014 prevargsize += ARG_BUF_DELTA;
1015 prevarg = nasm_realloc(prevarg, prevargsize);
1016 }
H. Peter Anvindc242712007-11-18 11:55:10 -08001017 strncpy(prevarg, p, prevargsize);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001018 }
1019}
1020
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001021/* Function to process args from a string of args, rather than the
1022 * argv array. Used by the environment variable and response file
1023 * processing.
1024 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001025static void process_args(char *args)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001026{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001027 char *p, *q, *arg, *prevarg;
1028 char separator = ' ';
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001029
1030 p = args;
1031 if (*p && *p != '-')
H. Peter Anvine2c80182005-01-15 22:15:51 +00001032 separator = *p++;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001033 arg = NULL;
1034 while (*p) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001035 q = p;
1036 while (*p && *p != separator)
1037 p++;
1038 while (*p == separator)
1039 *p++ = '\0';
1040 prevarg = arg;
1041 arg = q;
1042 if (process_arg(prevarg, arg))
1043 arg = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001044 }
1045 if (arg)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001046 process_arg(arg, NULL);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001047}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001048
H. Peter Anvinbe2678c2008-01-21 16:23:59 -08001049static void process_response_file(const char *file)
1050{
1051 char str[2048];
1052 FILE *f = fopen(file, "r");
1053 if (!f) {
1054 perror(file);
1055 exit(-1);
1056 }
1057 while (fgets(str, sizeof str, f)) {
1058 process_args(str);
1059 }
1060 fclose(f);
1061}
1062
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001063static void parse_cmdline(int argc, char **argv)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001064{
1065 FILE *rfile;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001066 char *envreal, *envcopy = NULL, *p, *arg;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001067
Charles Craynefcce07f2007-09-30 22:15:36 -07001068 *inname = *outname = *listname = *errname = '\0';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001069
1070 /*
H. Peter Anvinff7ccc02002-05-06 19:41:57 +00001071 * First, process the NASMENV environment variable.
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001072 */
H. Peter Anvinff7ccc02002-05-06 19:41:57 +00001073 envreal = getenv("NASMENV");
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001074 arg = NULL;
1075 if (envreal) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001076 envcopy = nasm_strdup(envreal);
1077 process_args(envcopy);
1078 nasm_free(envcopy);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001079 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001080
1081 /*
1082 * Now process the actual command line.
1083 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001084 while (--argc) {
H. Peter Anvin423e3812007-11-15 17:12:29 -08001085 bool advance;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001086 argv++;
1087 if (argv[0][0] == '@') {
1088 /* We have a response file, so process this as a set of
1089 * arguments like the environment variable. This allows us
1090 * to have multiple arguments on a single line, which is
1091 * different to the -@resp file processing below for regular
1092 * NASM.
1093 */
H. Peter Anvinbe2678c2008-01-21 16:23:59 -08001094 process_response_file(argv[0]+1);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001095 argc--;
1096 argv++;
1097 }
1098 if (!stopoptions && argv[0][0] == '-' && argv[0][1] == '@') {
H. Peter Anvin423e3812007-11-15 17:12:29 -08001099 p = get_param(argv[0], argc > 1 ? argv[1] : NULL, &advance);
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001100 if (p) {
1101 rfile = fopen(p, "r");
1102 if (rfile) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001103 process_respfile(rfile);
1104 fclose(rfile);
1105 } else
1106 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
1107 "unable to open response file `%s'", p);
1108 }
1109 } else
H. Peter Anvin423e3812007-11-15 17:12:29 -08001110 advance = process_arg(argv[0], argc > 1 ? argv[1] : NULL);
1111 argv += advance, argc -= advance;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001112 }
1113
H. Peter Anvin70c0bf22007-11-19 11:45:40 -08001114 /* Look for basic command line typos. This definitely doesn't
1115 catch all errors, but it might help cases of fumbled fingers. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001116 if (!*inname)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001117 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
1118 "no input file specified");
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001119 else if (!strcmp(inname, errname) ||
1120 !strcmp(inname, outname) ||
1121 !strcmp(inname, listname) ||
1122 (depend_file && !strcmp(inname, depend_file)))
H. Peter Anvin59ddd262007-10-01 11:26:31 -07001123 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
1124 "file `%s' is both input and output file",
1125 inname);
H. Peter Anvin59ddd262007-10-01 11:26:31 -07001126
H. Peter Anvin70653092007-10-19 14:42:29 -07001127 if (*errname) {
H. Peter Anvin59ddd262007-10-01 11:26:31 -07001128 error_file = fopen(errname, "w");
1129 if (!error_file) {
1130 error_file = stderr; /* Revert to default! */
1131 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
1132 "cannot open file `%s' for error messages",
1133 errname);
1134 }
Charles Craynefcce07f2007-09-30 22:15:36 -07001135 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001136}
1137
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001138/* List of directives */
H. Peter Anvin70055962007-10-11 00:05:31 -07001139enum directives {
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001140 D_NONE, D_ABSOLUTE, D_BITS, D_COMMON, D_CPU, D_DEBUG, D_DEFAULT,
H. Peter Anvinf6c9e652007-10-16 14:40:27 -07001141 D_EXTERN, D_FLOAT, D_GLOBAL, D_LIST, D_SECTION, D_SEGMENT, D_WARNING
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001142};
1143static const char *directives[] = {
1144 "", "absolute", "bits", "common", "cpu", "debug", "default",
H. Peter Anvinf6c9e652007-10-16 14:40:27 -07001145 "extern", "float", "global", "list", "section", "segment", "warning"
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001146};
H. Peter Anvin70055962007-10-11 00:05:31 -07001147static enum directives getkw(char **directive, char **value);
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001148
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001149static void assemble_file(char *fname, StrList **depend_ptr)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001150{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001151 char *directive, *value, *p, *q, *special, *line, debugid[80];
H. Peter Anvine2c80182005-01-15 22:15:51 +00001152 insn output_ins;
H. Peter Anvin70055962007-10-11 00:05:31 -07001153 int i, validid;
1154 bool rn_error;
Charles Crayne5fbbc8c2007-11-07 19:03:46 -08001155 int32_t seg;
1156 int64_t offs;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001157 struct tokenval tokval;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001158 expr *e;
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001159 int pass_max;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001160
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001161 if (cmd_sb == 32 && cmd_cpu < IF_386)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001162 report_error(ERR_FATAL, "command line: "
1163 "32-bit segment size requires a higher cpu");
H. Peter Anvineba20a72002-04-30 20:53:55 +00001164
H. Peter Anvine2c80182005-01-15 22:15:51 +00001165 pass_max = (optimizing > 0 ? optimizing : 0) + 2; /* passes 1, optimizing, then 2 */
1166 pass0 = !(optimizing > 0); /* start at 1 if not optimizing */
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001167 for (passn = 1; pass0 <= 2; passn++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001168 int pass1, pass2;
1169 ldfunc def_label;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001170
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001171 pass1 = pass0 == 2 ? 2 : 1; /* 1, 1, 1, ..., 1, 2 */
1172 pass2 = passn > 1 ? 2 : 1; /* 1, 2, 2, ..., 2, 2 */
1173 /* pass0 0, 0, 0, ..., 1, 2 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001174
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001175 def_label = passn > 1 ? redefine_label : define_label;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001176
Keith Kaniosb7a89542007-04-12 02:40:54 +00001177 globalbits = sb = cmd_sb; /* set 'bits' to command line default */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001178 cpu = cmd_cpu;
1179 if (pass0 == 2) {
1180 if (*listname)
1181 nasmlist.init(listname, report_error);
1182 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001183 in_abs_seg = false;
1184 global_offset_changed = false; /* set by redefine_label */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001185 location.segment = ofmt->section(NULL, pass2, &sb);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001186 globalbits = sb;
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001187 if (passn > 1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001188 saa_rewind(forwrefs);
1189 forwref = saa_rstruct(forwrefs);
1190 raa_free(offsets);
1191 offsets = raa_init();
1192 }
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -07001193 preproc->reset(fname, pass1, report_error, evaluate, &nasmlist,
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001194 pass1 == 2 ? depend_ptr : NULL);
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -07001195
H. Peter Anvine2c80182005-01-15 22:15:51 +00001196 globallineno = 0;
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001197 if (passn == 1)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001198 location.known = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001199 location.offset = offs = GET_CURR_OFFS;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001200
H. Peter Anvine2c80182005-01-15 22:15:51 +00001201 while ((line = preproc->getline())) {
H. Peter Anvin70055962007-10-11 00:05:31 -07001202 enum directives d;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001203 globallineno++;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001204
H. Peter Anvine2c80182005-01-15 22:15:51 +00001205 /* here we parse our directives; this is not handled by the 'real'
1206 * parser. */
1207 directive = line;
H. Peter Anvin70055962007-10-11 00:05:31 -07001208 d = getkw(&directive, &value);
1209 if (d) {
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001210 int err = 0;
1211
H. Peter Anvin70055962007-10-11 00:05:31 -07001212 switch (d) {
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001213 case D_SEGMENT: /* [SEGMENT n] */
1214 case D_SECTION:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001215 seg = ofmt->section(value, pass2, &sb);
1216 if (seg == NO_SEG) {
1217 report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
Keith Kaniosb7a89542007-04-12 02:40:54 +00001218 "segment name `%s' not recognized",
H. Peter Anvine2c80182005-01-15 22:15:51 +00001219 value);
1220 } else {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001221 in_abs_seg = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001222 location.segment = seg;
1223 }
1224 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001225 case D_EXTERN: /* [EXTERN label:special] */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001226 if (*value == '$')
1227 value++; /* skip initial $ if present */
1228 if (pass0 == 2) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001229 q = value;
1230 while (*q && *q != ':')
H. Peter Anvine2c80182005-01-15 22:15:51 +00001231 q++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001232 if (*q == ':') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001233 *q++ = '\0';
1234 ofmt->symdef(value, 0L, 0L, 3, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001235 }
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001236 } else if (passn == 1) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001237 q = value;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001238 validid = true;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001239 if (!isidstart(*q))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001240 validid = false;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001241 while (*q && *q != ':') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001242 if (!isidchar(*q))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001243 validid = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001244 q++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001245 }
1246 if (!validid) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001247 report_error(ERR_NONFATAL,
1248 "identifier expected after EXTERN");
1249 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001250 }
1251 if (*q == ':') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001252 *q++ = '\0';
1253 special = q;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001254 } else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001255 special = NULL;
1256 if (!is_extern(value)) { /* allow re-EXTERN to be ignored */
1257 int temp = pass0;
1258 pass0 = 1; /* fake pass 1 in labels.c */
1259 declare_as_global(value, special,
1260 report_error);
1261 define_label(value, seg_alloc(), 0L, NULL,
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001262 false, true, ofmt, report_error);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001263 pass0 = temp;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001264 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001265 } /* else pass0 == 1 */
1266 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001267 case D_BITS: /* [BITS bits] */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001268 globalbits = sb = get_bits(value);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001269 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001270 case D_GLOBAL: /* [GLOBAL symbol:special] */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001271 if (*value == '$')
1272 value++; /* skip initial $ if present */
1273 if (pass0 == 2) { /* pass 2 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001274 q = value;
1275 while (*q && *q != ':')
H. Peter Anvine2c80182005-01-15 22:15:51 +00001276 q++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001277 if (*q == ':') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001278 *q++ = '\0';
1279 ofmt->symdef(value, 0L, 0L, 3, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001280 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001281 } else if (pass2 == 1) { /* pass == 1 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001282 q = value;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001283 validid = true;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001284 if (!isidstart(*q))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001285 validid = false;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001286 while (*q && *q != ':') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001287 if (!isidchar(*q))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001288 validid = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001289 q++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001290 }
1291 if (!validid) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001292 report_error(ERR_NONFATAL,
1293 "identifier expected after GLOBAL");
1294 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001295 }
1296 if (*q == ':') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001297 *q++ = '\0';
1298 special = q;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001299 } else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001300 special = NULL;
1301 declare_as_global(value, special, report_error);
1302 } /* pass == 1 */
1303 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001304 case D_COMMON: /* [COMMON symbol size:special] */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001305 if (*value == '$')
1306 value++; /* skip initial $ if present */
1307 if (pass0 == 1) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001308 p = value;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001309 validid = true;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001310 if (!isidstart(*p))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001311 validid = false;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001312 while (*p && !isspace(*p)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001313 if (!isidchar(*p))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001314 validid = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001315 p++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001316 }
1317 if (!validid) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001318 report_error(ERR_NONFATAL,
1319 "identifier expected after COMMON");
1320 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001321 }
1322 if (*p) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001323 int64_t size;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001324
H. Peter Anvine2c80182005-01-15 22:15:51 +00001325 while (*p && isspace(*p))
1326 *p++ = '\0';
1327 q = p;
1328 while (*q && *q != ':')
1329 q++;
1330 if (*q == ':') {
1331 *q++ = '\0';
1332 special = q;
1333 } else
1334 special = NULL;
1335 size = readnum(p, &rn_error);
1336 if (rn_error)
1337 report_error(ERR_NONFATAL,
1338 "invalid size specified"
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001339 " in COMMON declaration");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001340 else
1341 define_common(value, seg_alloc(), size,
1342 special, ofmt, report_error);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001343 } else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001344 report_error(ERR_NONFATAL,
1345 "no size specified in"
1346 " COMMON declaration");
1347 } else if (pass0 == 2) { /* pass == 2 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001348 q = value;
1349 while (*q && *q != ':') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001350 if (isspace(*q))
1351 *q = '\0';
1352 q++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001353 }
1354 if (*q == ':') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001355 *q++ = '\0';
1356 ofmt->symdef(value, 0L, 0L, 3, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001357 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001358 }
1359 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001360 case D_ABSOLUTE: /* [ABSOLUTE address] */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001361 stdscan_reset();
1362 stdscan_bufptr = value;
1363 tokval.t_type = TOKEN_INVALID;
1364 e = evaluate(stdscan, NULL, &tokval, NULL, pass2,
1365 report_error, NULL);
1366 if (e) {
1367 if (!is_reloc(e))
1368 report_error(pass0 ==
1369 1 ? ERR_NONFATAL : ERR_PANIC,
1370 "cannot use non-relocatable expression as "
1371 "ABSOLUTE address");
1372 else {
1373 abs_seg = reloc_seg(e);
1374 abs_offset = reloc_value(e);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001375 }
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001376 } else if (passn == 1)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001377 abs_offset = 0x100; /* don't go near zero in case of / */
1378 else
1379 report_error(ERR_PANIC, "invalid ABSOLUTE address "
1380 "in pass two");
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001381 in_abs_seg = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001382 location.segment = NO_SEG;
1383 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001384 case D_DEBUG: /* [DEBUG] */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001385 p = value;
1386 q = debugid;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001387 validid = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001388 if (!isidstart(*p))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001389 validid = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001390 while (*p && !isspace(*p)) {
1391 if (!isidchar(*p))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001392 validid = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001393 *q++ = *p++;
1394 }
1395 *q++ = 0;
1396 if (!validid) {
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001397 report_error(passn == 1 ? ERR_NONFATAL : ERR_PANIC,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001398 "identifier expected after DEBUG");
1399 break;
1400 }
1401 while (*p && isspace(*p))
1402 p++;
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001403 if (pass0 == 2)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001404 ofmt->current_dfmt->debug_directive(debugid, p);
1405 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001406 case D_WARNING: /* [WARNING {+|-}warn-name] */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001407 if (pass1 == 1) {
1408 while (*value && isspace(*value))
1409 value++;
1410
1411 if (*value == '+' || *value == '-') {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001412 validid = (*value == '-') ? true : false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001413 value++;
1414 } else
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001415 validid = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001416
1417 for (i = 1; i <= ERR_WARN_MAX; i++)
1418 if (!nasm_stricmp(value, suppressed_names[i]))
1419 break;
1420 if (i <= ERR_WARN_MAX)
1421 suppressed[i] = validid;
1422 else
1423 report_error(ERR_NONFATAL,
1424 "invalid warning id in WARNING directive");
1425 }
1426 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001427 case D_CPU: /* [CPU] */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001428 cpu = get_cpu(value);
1429 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001430 case D_LIST: /* [LIST {+|-}] */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001431 while (*value && isspace(*value))
1432 value++;
1433
1434 if (*value == '+') {
1435 user_nolist = 0;
1436 } else {
1437 if (*value == '-') {
1438 user_nolist = 1;
1439 } else {
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001440 err = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001441 }
1442 }
1443 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001444 case D_DEFAULT: /* [DEFAULT] */
1445 stdscan_reset();
1446 stdscan_bufptr = value;
1447 tokval.t_type = TOKEN_INVALID;
1448 if (stdscan(NULL, &tokval) == TOKEN_SPECIAL) {
1449 switch ((int)tokval.t_integer) {
1450 case S_REL:
1451 globalrel = 1;
1452 break;
1453 case S_ABS:
1454 globalrel = 0;
1455 break;
1456 default:
1457 err = 1;
1458 break;
1459 }
1460 } else {
1461 err = 1;
1462 }
1463 break;
H. Peter Anvinf6c9e652007-10-16 14:40:27 -07001464 case D_FLOAT:
1465 if (float_option(value)) {
1466 report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
1467 "unknown 'float' directive: %s",
1468 value);
1469 }
1470 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001471 default:
1472 if (!ofmt->directive(directive, value, pass2))
1473 report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
1474 "unrecognised directive [%s]",
1475 directive);
1476 }
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001477 if (err) {
1478 report_error(ERR_NONFATAL,
1479 "invalid parameter to [%s] directive",
1480 directive);
1481 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001482 } else { /* it isn't a directive */
1483
1484 parse_line(pass1, line, &output_ins,
1485 report_error, evaluate, def_label);
1486
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001487 if (!(optimizing > 0) && pass0 == 2) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001488 if (forwref != NULL && globallineno == forwref->lineno) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001489 output_ins.forw_ref = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001490 do {
1491 output_ins.oprs[forwref->operand].opflags |=
1492 OPFLAG_FORWARD;
1493 forwref = saa_rstruct(forwrefs);
1494 } while (forwref != NULL
1495 && forwref->lineno == globallineno);
1496 } else
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001497 output_ins.forw_ref = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001498 }
1499
1500 if (!(optimizing > 0) && output_ins.forw_ref) {
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001501 if (passn == 1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001502 for (i = 0; i < output_ins.operands; i++) {
1503 if (output_ins.oprs[i].
1504 opflags & OPFLAG_FORWARD) {
1505 struct forwrefinfo *fwinf =
1506 (struct forwrefinfo *)
1507 saa_wstruct(forwrefs);
1508 fwinf->lineno = globallineno;
1509 fwinf->operand = i;
1510 }
1511 }
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001512 } else { /* passn > 1 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001513 /*
H. Peter Anvine2c80182005-01-15 22:15:51 +00001514 * Hack to prevent phase error in the code
1515 * rol ax,x
1516 * x equ 1
1517 *
1518 * If the second operand is a forward reference,
1519 * the UNITY property of the number 1 in that
1520 * operand is cancelled. Otherwise the above
1521 * sequence will cause a phase error.
1522 *
1523 * This hack means that the above code will
1524 * generate 286+ code.
1525 *
1526 * The forward reference will mean that the
1527 * operand will not have the UNITY property on
1528 * the first pass, so the pass behaviours will
1529 * be consistent.
1530 */
H. Peter Anvineba20a72002-04-30 20:53:55 +00001531
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001532 if (output_ins.operands >= 2 &&
H. Peter Anvin5a640e12007-05-29 23:57:12 +00001533 (output_ins.oprs[1].opflags & OPFLAG_FORWARD) &&
1534 !(IMMEDIATE & ~output_ins.oprs[1].type))
1535 {
1536 /* Remove special properties bits */
1537 output_ins.oprs[1].type &= ~REG_SMASK;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001538 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001539
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001540 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001541
H. Peter Anvine2c80182005-01-15 22:15:51 +00001542 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001543
H. Peter Anvine2c80182005-01-15 22:15:51 +00001544 /* forw_ref */
1545 if (output_ins.opcode == I_EQU) {
1546 if (pass1 == 1) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001547 /*
H. Peter Anvine2c80182005-01-15 22:15:51 +00001548 * Special `..' EQUs get processed in pass two,
1549 * except `..@' macro-processor EQUs which are done
1550 * in the normal place.
1551 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001552 if (!output_ins.label)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001553 report_error(ERR_NONFATAL,
1554 "EQU not preceded by label");
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001555
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001556 else if (output_ins.label[0] != '.' ||
1557 output_ins.label[1] != '.' ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001558 output_ins.label[2] == '@') {
1559 if (output_ins.operands == 1 &&
1560 (output_ins.oprs[0].type & IMMEDIATE) &&
1561 output_ins.oprs[0].wrt == NO_SEG) {
1562 int isext =
1563 output_ins.oprs[0].
1564 opflags & OPFLAG_EXTERN;
1565 def_label(output_ins.label,
1566 output_ins.oprs[0].segment,
1567 output_ins.oprs[0].offset, NULL,
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001568 false, isext, ofmt,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001569 report_error);
1570 } else if (output_ins.operands == 2
1571 && (output_ins.oprs[0].
1572 type & IMMEDIATE)
1573 && (output_ins.oprs[0].type & COLON)
1574 && output_ins.oprs[0].segment ==
1575 NO_SEG
1576 && output_ins.oprs[0].wrt == NO_SEG
1577 && (output_ins.oprs[1].
1578 type & IMMEDIATE)
1579 && output_ins.oprs[1].segment ==
1580 NO_SEG
1581 && output_ins.oprs[1].wrt ==
1582 NO_SEG) {
1583 def_label(output_ins.label,
1584 output_ins.oprs[0].
1585 offset | SEG_ABS,
1586 output_ins.oprs[1].offset, NULL,
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001587 false, false, ofmt,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001588 report_error);
1589 } else
1590 report_error(ERR_NONFATAL,
1591 "bad syntax for EQU");
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001592 }
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001593 } else {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001594 /*
H. Peter Anvine2c80182005-01-15 22:15:51 +00001595 * Special `..' EQUs get processed here, except
1596 * `..@' macro processor EQUs which are done above.
1597 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001598 if (output_ins.label[0] == '.' &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001599 output_ins.label[1] == '.' &&
1600 output_ins.label[2] != '@') {
1601 if (output_ins.operands == 1 &&
1602 (output_ins.oprs[0].type & IMMEDIATE)) {
1603 define_label(output_ins.label,
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001604 output_ins.oprs[0].segment,
1605 output_ins.oprs[0].offset,
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001606 NULL, false, false, ofmt,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001607 report_error);
1608 } else if (output_ins.operands == 2
1609 && (output_ins.oprs[0].
1610 type & IMMEDIATE)
1611 && (output_ins.oprs[0].type & COLON)
1612 && output_ins.oprs[0].segment ==
1613 NO_SEG
1614 && (output_ins.oprs[1].
1615 type & IMMEDIATE)
1616 && output_ins.oprs[1].segment ==
1617 NO_SEG) {
1618 define_label(output_ins.label,
1619 output_ins.oprs[0].
1620 offset | SEG_ABS,
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001621 output_ins.oprs[1].offset,
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001622 NULL, false, false, ofmt,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001623 report_error);
1624 } else
1625 report_error(ERR_NONFATAL,
1626 "bad syntax for EQU");
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001627 }
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001628 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001629 } else { /* instruction isn't an EQU */
H. Peter Anvineba20a72002-04-30 20:53:55 +00001630
H. Peter Anvine2c80182005-01-15 22:15:51 +00001631 if (pass1 == 1) {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001632
Charles Crayne5fbbc8c2007-11-07 19:03:46 -08001633 int64_t l = insn_size(location.segment, offs, sb, cpu,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001634 &output_ins, report_error);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001635
H. Peter Anvine2c80182005-01-15 22:15:51 +00001636 /* if (using_debug_info) && output_ins.opcode != -1) */
1637 if (using_debug_info)
1638 { /* fbk 03/25/01 */
1639 /* this is done here so we can do debug type info */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001640 int32_t typeinfo =
H. Peter Anvine2c80182005-01-15 22:15:51 +00001641 TYS_ELEMENTS(output_ins.operands);
1642 switch (output_ins.opcode) {
1643 case I_RESB:
1644 typeinfo =
1645 TYS_ELEMENTS(output_ins.oprs[0].
1646 offset) | TY_BYTE;
1647 break;
1648 case I_RESW:
1649 typeinfo =
1650 TYS_ELEMENTS(output_ins.oprs[0].
1651 offset) | TY_WORD;
1652 break;
1653 case I_RESD:
1654 typeinfo =
1655 TYS_ELEMENTS(output_ins.oprs[0].
1656 offset) | TY_DWORD;
1657 break;
1658 case I_RESQ:
1659 typeinfo =
1660 TYS_ELEMENTS(output_ins.oprs[0].
1661 offset) | TY_QWORD;
1662 break;
1663 case I_REST:
1664 typeinfo =
1665 TYS_ELEMENTS(output_ins.oprs[0].
1666 offset) | TY_TBYTE;
1667 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -07001668 case I_RESO:
1669 typeinfo =
1670 TYS_ELEMENTS(output_ins.oprs[0].
1671 offset) | TY_OWORD;
1672 break;
1673 case I_RESY:
1674 typeinfo =
1675 TYS_ELEMENTS(output_ins.oprs[0].
1676 offset) | TY_YWORD;
1677 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001678 case I_DB:
1679 typeinfo |= TY_BYTE;
1680 break;
1681 case I_DW:
1682 typeinfo |= TY_WORD;
1683 break;
1684 case I_DD:
1685 if (output_ins.eops_float)
1686 typeinfo |= TY_FLOAT;
1687 else
1688 typeinfo |= TY_DWORD;
1689 break;
1690 case I_DQ:
1691 typeinfo |= TY_QWORD;
1692 break;
1693 case I_DT:
1694 typeinfo |= TY_TBYTE;
1695 break;
H. Peter Anvin4408b622007-09-22 21:29:41 -07001696 case I_DO:
1697 typeinfo |= TY_OWORD;
1698 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -07001699 case I_DY:
1700 typeinfo |= TY_YWORD;
1701 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001702 default:
1703 typeinfo = TY_LABEL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001704
H. Peter Anvine2c80182005-01-15 22:15:51 +00001705 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001706
H. Peter Anvine2c80182005-01-15 22:15:51 +00001707 ofmt->current_dfmt->debug_typevalue(typeinfo);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001708
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001709 }
1710 if (l != -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001711 offs += l;
1712 SET_CURR_OFFS(offs);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001713 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001714 /*
H. Peter Anvine2c80182005-01-15 22:15:51 +00001715 * else l == -1 => invalid instruction, which will be
1716 * flagged as an error on pass 2
1717 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001718
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001719 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001720 offs += assemble(location.segment, offs, sb, cpu,
1721 &output_ins, ofmt, report_error,
1722 &nasmlist);
1723 SET_CURR_OFFS(offs);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001724
H. Peter Anvine2c80182005-01-15 22:15:51 +00001725 }
1726 } /* not an EQU */
1727 cleanup_insn(&output_ins);
1728 }
1729 nasm_free(line);
1730 location.offset = offs = GET_CURR_OFFS;
1731 } /* end while (line = preproc->getline... */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001732
H. Peter Anvine2c80182005-01-15 22:15:51 +00001733 if (pass1 == 2 && global_offset_changed)
1734 report_error(ERR_NONFATAL,
1735 "phase error detected at end of assembly.");
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001736
H. Peter Anvine2c80182005-01-15 22:15:51 +00001737 if (pass1 == 1)
1738 preproc->cleanup(1);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001739
H. Peter Anvine2c80182005-01-15 22:15:51 +00001740 if (pass1 == 1 && terminate_after_phase) {
1741 fclose(ofile);
1742 remove(outname);
1743 if (want_usage)
1744 usage();
1745 exit(1);
1746 }
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001747 if (passn >= pass_max - 2 ||
1748 (passn > 1 && !global_offset_changed))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001749 pass0++;
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001750 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001751
H. Peter Anvine2c80182005-01-15 22:15:51 +00001752 preproc->cleanup(0);
1753 nasmlist.cleanup();
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001754#if 1
H. Peter Anvine2c80182005-01-15 22:15:51 +00001755 if (optimizing > 0 && opt_verbose_info) /* -On and -Ov switches */
1756 fprintf(stdout,
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001757 "info:: assembly required 1+%d+1 passes\n", passn-3);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001758#endif
H. Peter Anvine2c80182005-01-15 22:15:51 +00001759} /* exit from assemble_file (...) */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001760
H. Peter Anvin70055962007-10-11 00:05:31 -07001761static enum directives getkw(char **directive, char **value)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001762{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001763 char *p, *q, *buf;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001764
Michael K. Ter Louw1d392362003-08-15 22:25:53 +00001765 buf = *directive;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001766
H. Peter Anvincaa82a12002-04-30 21:03:11 +00001767 /* allow leading spaces or tabs */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001768 while (*buf == ' ' || *buf == '\t')
1769 buf++;
H. Peter Anvincaa82a12002-04-30 21:03:11 +00001770
H. Peter Anvine2c80182005-01-15 22:15:51 +00001771 if (*buf != '[')
1772 return 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001773
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001774 p = buf;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001775
H. Peter Anvine2c80182005-01-15 22:15:51 +00001776 while (*p && *p != ']')
1777 p++;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001778
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001779 if (!*p)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001780 return 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001781
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001782 q = p++;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001783
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001784 while (*p && *p != ';') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001785 if (!isspace(*p))
1786 return 0;
1787 p++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001788 }
1789 q[1] = '\0';
1790
H. Peter Anvine2c80182005-01-15 22:15:51 +00001791 *directive = p = buf + 1;
1792 while (*buf && *buf != ' ' && *buf != ']' && *buf != '\t')
1793 buf++;
1794 if (*buf == ']') {
1795 *buf = '\0';
1796 *value = buf;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001797 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001798 *buf++ = '\0';
1799 while (isspace(*buf))
1800 buf++; /* beppu - skip leading whitespace */
1801 *value = buf;
1802 while (*buf != ']')
1803 buf++;
1804 *buf++ = '\0';
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001805 }
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001806
1807 return bsii(*directive, directives, elements(directives));
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001808}
1809
Ed Berosetfa771012002-06-09 20:56:40 +00001810/**
1811 * gnu style error reporting
1812 * This function prints an error message to error_file in the
1813 * style used by GNU. An example would be:
1814 * file.asm:50: error: blah blah blah
H. Peter Anvin70653092007-10-19 14:42:29 -07001815 * where file.asm is the name of the file, 50 is the line number on
Ed Berosetfa771012002-06-09 20:56:40 +00001816 * which the error occurs (or is detected) and "error:" is one of
1817 * the possible optional diagnostics -- it can be "error" or "warning"
H. Peter Anvin70653092007-10-19 14:42:29 -07001818 * or something else. Finally the line terminates with the actual
Ed Berosetfa771012002-06-09 20:56:40 +00001819 * error message.
H. Peter Anvin70653092007-10-19 14:42:29 -07001820 *
1821 * @param severity the severity of the warning or error
Ed Berosetfa771012002-06-09 20:56:40 +00001822 * @param fmt the printf style format string
1823 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001824static void report_error_gnu(int severity, const char *fmt, ...)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001825{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001826 va_list ap;
1827
Ed Berosetfa771012002-06-09 20:56:40 +00001828 if (is_suppressed_warning(severity))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001829 return;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001830
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001831 if (severity & ERR_NOFILE)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001832 fputs("nasm: ", error_file);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001833 else {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001834 char *currentfile = NULL;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001835 int32_t lineno = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001836 src_get(&lineno, &currentfile);
Keith Kanios93f2e9a2007-04-14 00:10:59 +00001837 fprintf(error_file, "%s:%"PRId32": ", currentfile, lineno);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001838 nasm_free(currentfile);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001839 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001840 va_start(ap, fmt);
1841 report_error_common(severity, fmt, ap);
1842 va_end(ap);
Ed Berosetfa771012002-06-09 20:56:40 +00001843}
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001844
Ed Berosetfa771012002-06-09 20:56:40 +00001845/**
1846 * MS style error reporting
1847 * This function prints an error message to error_file in the
H. Peter Anvin70653092007-10-19 14:42:29 -07001848 * style used by Visual C and some other Microsoft tools. An example
Ed Berosetfa771012002-06-09 20:56:40 +00001849 * would be:
Ed Beroset6e61d0d2002-06-11 03:29:36 +00001850 * file.asm(50) : error: blah blah blah
H. Peter Anvin70653092007-10-19 14:42:29 -07001851 * where file.asm is the name of the file, 50 is the line number on
Ed Beroset6e61d0d2002-06-11 03:29:36 +00001852 * which the error occurs (or is detected) and "error:" is one of
1853 * the possible optional diagnostics -- it can be "error" or "warning"
H. Peter Anvin70653092007-10-19 14:42:29 -07001854 * or something else. Finally the line terminates with the actual
Ed Beroset6e61d0d2002-06-11 03:29:36 +00001855 * error message.
H. Peter Anvin70653092007-10-19 14:42:29 -07001856 *
1857 * @param severity the severity of the warning or error
Ed Berosetfa771012002-06-09 20:56:40 +00001858 * @param fmt the printf style format string
1859 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001860static void report_error_vc(int severity, const char *fmt, ...)
Ed Berosetfa771012002-06-09 20:56:40 +00001861{
1862 va_list ap;
1863
H. Peter Anvine2c80182005-01-15 22:15:51 +00001864 if (is_suppressed_warning(severity))
1865 return;
Ed Berosetfa771012002-06-09 20:56:40 +00001866
1867 if (severity & ERR_NOFILE)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001868 fputs("nasm: ", error_file);
Ed Berosetfa771012002-06-09 20:56:40 +00001869 else {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001870 char *currentfile = NULL;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001871 int32_t lineno = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001872 src_get(&lineno, &currentfile);
Keith Kanios93f2e9a2007-04-14 00:10:59 +00001873 fprintf(error_file, "%s(%"PRId32") : ", currentfile, lineno);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001874 nasm_free(currentfile);
Ed Berosetfa771012002-06-09 20:56:40 +00001875 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001876 va_start(ap, fmt);
1877 report_error_common(severity, fmt, ap);
1878 va_end(ap);
Ed Berosetfa771012002-06-09 20:56:40 +00001879}
1880
1881/**
1882 * check for supressed warning
H. Peter Anvin70653092007-10-19 14:42:29 -07001883 * checks for suppressed warning or pass one only warning and we're
Ed Berosetfa771012002-06-09 20:56:40 +00001884 * not in pass 1
1885 *
1886 * @param severity the severity of the warning or error
1887 * @return true if we should abort error/warning printing
1888 */
H. Peter Anvin2b046cf2008-01-22 14:08:36 -08001889static bool is_suppressed_warning(int severity)
Ed Berosetfa771012002-06-09 20:56:40 +00001890{
1891 /*
1892 * See if it's a suppressed warning.
1893 */
H. Peter Anvin2b046cf2008-01-22 14:08:36 -08001894 return (severity & ERR_MASK) == ERR_WARNING &&
1895 (((severity & ERR_WARN_MASK) != 0 &&
1896 suppressed[(severity & ERR_WARN_MASK) >> ERR_WARN_SHR]) ||
1897 /* See if it's a pass-one only warning and we're not in pass one. */
1898 ((severity & ERR_PASS1) && pass0 != 1));
Ed Berosetfa771012002-06-09 20:56:40 +00001899}
1900
1901/**
1902 * common error reporting
1903 * This is the common back end of the error reporting schemes currently
H. Peter Anvin70653092007-10-19 14:42:29 -07001904 * implemented. It prints the nature of the warning and then the
Ed Berosetfa771012002-06-09 20:56:40 +00001905 * specific error message to error_file and may or may not return. It
1906 * doesn't return if the error severity is a "panic" or "debug" type.
H. Peter Anvin70653092007-10-19 14:42:29 -07001907 *
1908 * @param severity the severity of the warning or error
Ed Berosetfa771012002-06-09 20:56:40 +00001909 * @param fmt the printf style format string
1910 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001911static void report_error_common(int severity, const char *fmt,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001912 va_list args)
Ed Berosetfa771012002-06-09 20:56:40 +00001913{
H. Peter Anvin7df04172008-06-10 18:27:38 -07001914 switch (severity & (ERR_MASK|ERR_NO_SEVERITY)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001915 case ERR_WARNING:
1916 fputs("warning: ", error_file);
1917 break;
1918 case ERR_NONFATAL:
1919 fputs("error: ", error_file);
1920 break;
1921 case ERR_FATAL:
1922 fputs("fatal: ", error_file);
1923 break;
1924 case ERR_PANIC:
1925 fputs("panic: ", error_file);
1926 break;
1927 case ERR_DEBUG:
1928 fputs("debug: ", error_file);
1929 break;
H. Peter Anvin7df04172008-06-10 18:27:38 -07001930 default:
1931 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001932 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001933
H. Peter Anvine2c80182005-01-15 22:15:51 +00001934 vfprintf(error_file, fmt, args);
H. Peter Anvind1fb15c2007-11-13 09:37:59 -08001935 putc('\n', error_file);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001936
1937 if (severity & ERR_USAGE)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001938 want_usage = true;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001939
1940 switch (severity & ERR_MASK) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001941 case ERR_DEBUG:
1942 /* no further action, by definition */
1943 break;
H. Peter Anvinb030c922007-11-13 11:31:15 -08001944 case ERR_WARNING:
1945 if (!suppressed[0]) /* Treat warnings as errors */
1946 terminate_after_phase = true;
1947 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001948 case ERR_NONFATAL:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001949 terminate_after_phase = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001950 break;
1951 case ERR_FATAL:
1952 if (ofile) {
1953 fclose(ofile);
1954 remove(outname);
1955 }
1956 if (want_usage)
1957 usage();
1958 exit(1); /* instantly die */
1959 break; /* placate silly compilers */
1960 case ERR_PANIC:
1961 fflush(NULL);
1962 /* abort(); *//* halt, catch fire, and dump core */
1963 exit(3);
1964 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001965 }
1966}
1967
H. Peter Anvin734b1882002-04-30 21:01:08 +00001968static void usage(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001969{
H. Peter Anvin620515a2002-04-30 20:57:38 +00001970 fputs("type `nasm -h' for help\n", error_file);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001971}
1972
H. Peter Anvin734b1882002-04-30 21:01:08 +00001973static void register_output_formats(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001974{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001975 ofmt = ofmt_register(report_error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001976}
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001977
1978#define BUF_DELTA 512
1979
1980static FILE *no_pp_fp;
1981static efunc no_pp_err;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001982static ListGen *no_pp_list;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001983static int32_t no_pp_lineinc;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001984
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001985static void no_pp_reset(char *file, int pass, efunc error, evalfunc eval,
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001986 ListGen * listgen, StrList **deplist)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001987{
1988 src_set_fname(nasm_strdup(file));
1989 src_set_linnum(0);
1990 no_pp_lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001991 no_pp_err = error;
1992 no_pp_fp = fopen(file, "r");
1993 if (!no_pp_fp)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001994 no_pp_err(ERR_FATAL | ERR_NOFILE,
1995 "unable to open input file `%s'", file);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001996 no_pp_list = listgen;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001997 (void)pass; /* placate compilers */
1998 (void)eval; /* placate compilers */
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001999
2000 if (deplist) {
2001 StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
2002 sl->next = NULL;
2003 strcpy(sl->str, file);
2004 *deplist = sl;
2005 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002006}
2007
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002008static char *no_pp_getline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002009{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002010 char *buffer, *p, *q;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002011 int bufsize;
2012
2013 bufsize = BUF_DELTA;
2014 buffer = nasm_malloc(BUF_DELTA);
H. Peter Anvineba20a72002-04-30 20:53:55 +00002015 src_set_linnum(src_get_linnum() + no_pp_lineinc);
2016
H. Peter Anvine2c80182005-01-15 22:15:51 +00002017 while (1) { /* Loop to handle %line */
H. Peter Anvineba20a72002-04-30 20:53:55 +00002018
H. Peter Anvine2c80182005-01-15 22:15:51 +00002019 p = buffer;
2020 while (1) { /* Loop to handle long lines */
2021 q = fgets(p, bufsize - (p - buffer), no_pp_fp);
2022 if (!q)
2023 break;
2024 p += strlen(p);
2025 if (p > buffer && p[-1] == '\n')
2026 break;
2027 if (p - buffer > bufsize - 10) {
2028 int offset;
2029 offset = p - buffer;
2030 bufsize += BUF_DELTA;
2031 buffer = nasm_realloc(buffer, bufsize);
2032 p = buffer + offset;
2033 }
2034 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00002035
H. Peter Anvine2c80182005-01-15 22:15:51 +00002036 if (!q && p == buffer) {
2037 nasm_free(buffer);
2038 return NULL;
2039 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00002040
H. Peter Anvine2c80182005-01-15 22:15:51 +00002041 /*
2042 * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
2043 * them are present at the end of the line.
2044 */
2045 buffer[strcspn(buffer, "\r\n\032")] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +00002046
H. Peter Anvin0a98f602007-10-03 21:22:16 -07002047 if (!nasm_strnicmp(buffer, "%line", 5)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002048 int32_t ln;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002049 int li;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002050 char *nm = nasm_malloc(strlen(buffer));
Keith Kanios93f2e9a2007-04-14 00:10:59 +00002051 if (sscanf(buffer + 5, "%"PRId32"+%d %s", &ln, &li, nm) == 3) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002052 nasm_free(src_set_fname(nm));
2053 src_set_linnum(ln);
2054 no_pp_lineinc = li;
2055 continue;
2056 }
2057 nasm_free(nm);
2058 }
2059 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002060 }
2061
H. Peter Anvine2c80182005-01-15 22:15:51 +00002062 no_pp_list->line(LIST_READ, buffer);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002063
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002064 return buffer;
2065}
2066
H. Peter Anvine2c80182005-01-15 22:15:51 +00002067static void no_pp_cleanup(int pass)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002068{
Keith Kaniosc7ae18d2007-04-14 00:46:25 +00002069 (void)pass; /* placate GCC */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002070 fclose(no_pp_fp);
2071}
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002072
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002073static uint32_t get_cpu(char *value)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002074{
H. Peter Anvine2c80182005-01-15 22:15:51 +00002075 if (!strcmp(value, "8086"))
2076 return IF_8086;
2077 if (!strcmp(value, "186"))
2078 return IF_186;
2079 if (!strcmp(value, "286"))
2080 return IF_286;
2081 if (!strcmp(value, "386"))
2082 return IF_386;
2083 if (!strcmp(value, "486"))
2084 return IF_486;
2085 if (!strcmp(value, "586") || !nasm_stricmp(value, "pentium"))
2086 return IF_PENT;
2087 if (!strcmp(value, "686") ||
2088 !nasm_stricmp(value, "ppro") ||
2089 !nasm_stricmp(value, "pentiumpro") || !nasm_stricmp(value, "p2"))
2090 return IF_P6;
2091 if (!nasm_stricmp(value, "p3") || !nasm_stricmp(value, "katmai"))
2092 return IF_KATMAI;
2093 if (!nasm_stricmp(value, "p4") || /* is this right? -- jrc */
2094 !nasm_stricmp(value, "willamette"))
2095 return IF_WILLAMETTE;
2096 if (!nasm_stricmp(value, "prescott"))
2097 return IF_PRESCOTT;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002098 if (!nasm_stricmp(value, "x64") ||
2099 !nasm_stricmp(value, "x86-64"))
H. Peter Anvin0db11e22007-04-17 20:23:11 +00002100 return IF_X86_64;
H. Peter Anvin3ab8de62002-05-28 01:25:06 +00002101 if (!nasm_stricmp(value, "ia64") ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00002102 !nasm_stricmp(value, "ia-64") ||
2103 !nasm_stricmp(value, "itanium") ||
2104 !nasm_stricmp(value, "itanic") || !nasm_stricmp(value, "merced"))
2105 return IF_IA64;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002106
H. Peter Anvine2c80182005-01-15 22:15:51 +00002107 report_error(pass0 < 2 ? ERR_NONFATAL : ERR_FATAL,
2108 "unknown 'cpu' type");
H. Peter Anvin734b1882002-04-30 21:01:08 +00002109
H. Peter Anvine2c80182005-01-15 22:15:51 +00002110 return IF_PLEVEL; /* the maximum level */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002111}
2112
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002113static int get_bits(char *value)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002114{
2115 int i;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002116
H. Peter Anvine2c80182005-01-15 22:15:51 +00002117 if ((i = atoi(value)) == 16)
2118 return i; /* set for a 16-bit segment */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002119 else if (i == 32) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002120 if (cpu < IF_386) {
2121 report_error(ERR_NONFATAL,
2122 "cannot specify 32-bit segment on processor below a 386");
2123 i = 16;
2124 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00002125 } else if (i == 64) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +00002126 if (cpu < IF_X86_64) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002127 report_error(ERR_NONFATAL,
2128 "cannot specify 64-bit segment on processor below an x86-64");
2129 i = 16;
2130 }
2131 if (i != maxbits) {
2132 report_error(ERR_NONFATAL,
2133 "%s output format does not support 64-bit code",
2134 ofmt->shortname);
2135 i = 16;
2136 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002137 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002138 report_error(pass0 < 2 ? ERR_NONFATAL : ERR_FATAL,
Keith Kaniosb7a89542007-04-12 02:40:54 +00002139 "`%s' is not a valid segment size; must be 16, 32 or 64",
H. Peter Anvine2c80182005-01-15 22:15:51 +00002140 value);
2141 i = 16;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002142 }
2143 return i;
2144}
2145
2146/* end of nasm.c */