blob: 6208a728ee84679200aac008eed79a2f47d95d6e [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 */
Victor van den Elzen819703a2008-07-16 15:20:56 +0200105static bool suppressed[ERR_WARN_MAX+1];
106
107static bool suppressed_global[ERR_WARN_MAX+1] = {
Victor van den Elzen22343c22008-08-06 14:47:54 +0200108 true, false, true, false, false, false, true, false, true, true, false
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000109};
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000110/*
111 * The option names for the suppressible warnings. As before, entry
112 * zero does nothing.
113 */
H. Peter Anvinb030c922007-11-13 11:31:15 -0800114static const char *suppressed_names[ERR_WARN_MAX+1] = {
Victor van den Elzen22343c22008-08-06 14:47:54 +0200115 "error", "macro-params", "macro-selfref", "macro-defaults",
116 "orphan-labels", "number-overflow", "gnu-elf-extensions",
117 "float-overflow", "float-denorm", "float-underflow", "float-toolong"
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000118};
119
120/*
121 * The explanations for the suppressible warnings. As before, entry
122 * zero does nothing.
123 */
H. Peter Anvinb030c922007-11-13 11:31:15 -0800124static const char *suppressed_what[ERR_WARN_MAX+1] = {
125 "treat warnings as errors",
H. Peter Anvinc68ec012007-11-13 11:34:34 -0800126 "macro calls with wrong parameter count",
127 "cyclic macro references",
Victor van den Elzen22343c22008-08-06 14:47:54 +0200128 "macros with more default than optional parameters",
H. Peter Anvin76690a12002-04-30 20:52:49 +0000129 "labels alone on lines without trailing `:'",
H. Peter Anvinc68ec012007-11-13 11:34:34 -0800130 "numeric constants does not fit in 64 bits",
H. Peter Anvinfab3a6c2007-10-16 11:48:07 -0700131 "using 8- or 16-bit relocation in ELF32, a GNU extension",
H. Peter Anvin125c8782007-10-16 11:32:58 -0700132 "floating point overflow",
133 "floating point denormal",
134 "floating point underflow",
H. Peter Anvinfab3a6c2007-10-16 11:48:07 -0700135 "too many digits in floating-point number"
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000136};
137
138/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000139 * This is a null preprocessor which just copies lines from input
140 * to output. It's used when someone explicitly requests that NASM
141 * not preprocess their source file.
142 */
143
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700144static void no_pp_reset(char *, int, efunc, evalfunc, ListGen *, StrList **);
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000145static char *no_pp_getline(void);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000146static void no_pp_cleanup(int);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000147static Preproc no_pp = {
148 no_pp_reset,
149 no_pp_getline,
150 no_pp_cleanup
151};
152
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000153/*
154 * get/set current offset...
155 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000156#define GET_CURR_OFFS (in_abs_seg?abs_offset:\
H. Peter Anvineba20a72002-04-30 20:53:55 +0000157 raa_read(offsets,location.segment))
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000158#define SET_CURR_OFFS(x) (in_abs_seg?(void)(abs_offset=(x)):\
H. Peter Anvineba20a72002-04-30 20:53:55 +0000159 (void)(offsets=raa_write(offsets,location.segment,(x))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000160
161static int want_usage;
162static int terminate_after_phase;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000163int user_nolist = 0; /* fbk 9/2/00 */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000164
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000165static void nasm_fputs(const char *line, FILE * outfile)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000166{
H. Peter Anvin310b3e12002-05-14 22:38:55 +0000167 if (outfile) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000168 fputs(line, outfile);
H. Peter Anvind1fb15c2007-11-13 09:37:59 -0800169 putc('\n', outfile);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000170 } else
H. Peter Anvine2c80182005-01-15 22:15:51 +0000171 puts(line);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000172}
173
H. Peter Anvin6b18bcc2008-02-16 14:54:10 -0800174/* Convert a struct tm to a POSIX-style time constant */
175static int64_t posix_mktime(struct tm *tm)
176{
177 int64_t t;
178 int64_t y = tm->tm_year;
179
180 /* See IEEE 1003.1:2004, section 4.14 */
181
182 t = (y-70)*365 + (y-69)/4 - (y-1)/100 + (y+299)/400;
183 t += tm->tm_yday;
184 t *= 24;
185 t += tm->tm_hour;
186 t *= 60;
187 t += tm->tm_min;
188 t *= 60;
189 t += tm->tm_sec;
190
191 return t;
192}
193
194static void define_macros_early(void)
195{
196 char temp[128];
197 struct tm lt, *lt_p, gm, *gm_p;
198 int64_t posix_time;
199
200 lt_p = localtime(&official_compile_time);
201 if (lt_p) {
202 lt = *lt_p;
203
204 strftime(temp, sizeof temp, "__DATE__=\"%Y-%m-%d\"", &lt);
205 pp_pre_define(temp);
206 strftime(temp, sizeof temp, "__DATE_NUM__=%Y%m%d", &lt);
207 pp_pre_define(temp);
208 strftime(temp, sizeof temp, "__TIME__=\"%H:%M:%S\"", &lt);
209 pp_pre_define(temp);
210 strftime(temp, sizeof temp, "__TIME_NUM__=%H%M%S", &lt);
211 pp_pre_define(temp);
212 }
213
214 gm_p = gmtime(&official_compile_time);
215 if (gm_p) {
216 gm = *gm_p;
217
218 strftime(temp, sizeof temp, "__UTC_DATE__=\"%Y-%m-%d\"", &gm);
219 pp_pre_define(temp);
220 strftime(temp, sizeof temp, "__UTC_DATE_NUM__=%Y%m%d", &gm);
221 pp_pre_define(temp);
222 strftime(temp, sizeof temp, "__UTC_TIME__=\"%H:%M:%S\"", &gm);
223 pp_pre_define(temp);
224 strftime(temp, sizeof temp, "__UTC_TIME_NUM__=%H%M%S", &gm);
225 pp_pre_define(temp);
226 }
H. Peter Anvind85d2502008-05-04 17:53:31 -0700227
H. Peter Anvin6b18bcc2008-02-16 14:54:10 -0800228 if (gm_p)
229 posix_time = posix_mktime(&gm);
230 else if (lt_p)
231 posix_time = posix_mktime(&lt);
232 else
233 posix_time = 0;
234
235 if (posix_time) {
236 snprintf(temp, sizeof temp, "__POSIX_TIME__=%"PRId64, posix_time);
237 pp_pre_define(temp);
238 }
239}
240
241static void define_macros_late(void)
242{
243 char temp[128];
244
245 snprintf(temp, sizeof(temp), "__OUTPUT_FORMAT__=%s\n",
246 ofmt->shortname);
247 pp_pre_define(temp);
248}
249
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700250static void emit_dependencies(StrList *list)
251{
252 FILE *deps;
253 int linepos, len;
254 StrList *l, *nl;
255
256 if (depend_file && strcmp(depend_file, "-")) {
257 deps = fopen(depend_file, "w");
258 if (!deps) {
259 report_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
260 "unable to write dependency file `%s'", depend_file);
261 return;
262 }
263 } else {
264 deps = stdout;
265 }
266
267 linepos = fprintf(deps, "%s:", depend_target);
268 for (l = list; l; l = l->next) {
269 len = strlen(l->str);
270 if (linepos + len > 62) {
271 fprintf(deps, " \\\n ");
272 linepos = 1;
273 }
274 fprintf(deps, " %s", l->str);
275 linepos += len+1;
276 }
277 fprintf(deps, "\n\n");
278
279 for (l = list; l; l = nl) {
280 if (depend_emit_phony)
281 fprintf(deps, "%s:\n\n", l->str);
282
283 nl = l->next;
284 nasm_free(l);
285 }
286
287 if (deps != stdout)
288 fclose(deps);
289}
290
H. Peter Anvin038d8612007-04-12 16:54:50 +0000291int main(int argc, char **argv)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000292{
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700293 StrList *depend_list = NULL, **depend_ptr;
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700294
H. Peter Anvin6b18bcc2008-02-16 14:54:10 -0800295 time(&official_compile_time);
296
Ed Berosetfa771012002-06-09 20:56:40 +0000297 pass0 = 1;
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700298 want_usage = terminate_after_phase = false;
Ed Berosetfa771012002-06-09 20:56:40 +0000299 report_error = report_error_gnu;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000300
H. Peter Anvin97e15752007-09-25 08:47:47 -0700301 error_file = stderr;
302
H. Peter Anvinac8f8fc2008-06-11 15:49:41 -0700303 tolower_init();
304
H. Peter Anvine2c80182005-01-15 22:15:51 +0000305 nasm_set_malloc_error(report_error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000306 offsets = raa_init();
Keith Kaniosb7a89542007-04-12 02:40:54 +0000307 forwrefs = saa_init((int32_t)sizeof(struct forwrefinfo));
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000308
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000309 preproc = &nasmpp;
H. Peter Anvin620515a2002-04-30 20:57:38 +0000310 operating_mode = op_normal;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000311
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000312 seg_init();
313
314 register_output_formats();
315
H. Peter Anvin6b18bcc2008-02-16 14:54:10 -0800316 /* Define some macros dependent on the runtime, but not
317 on the command line. */
318 define_macros_early();
319
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000320 parse_cmdline(argc, argv);
321
H. Peter Anvine2c80182005-01-15 22:15:51 +0000322 if (terminate_after_phase) {
323 if (want_usage)
324 usage();
325 return 1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000326 }
327
H. Peter Anvinbb88d012003-09-10 23:34:23 +0000328 /* If debugging info is disabled, suppress any debug calls */
329 if (!using_debug_info)
330 ofmt->current_dfmt = &null_debug_form;
331
H. Peter Anvin76690a12002-04-30 20:52:49 +0000332 if (ofmt->stdmac)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000333 pp_extra_stdmac(ofmt->stdmac);
334 parser_global_info(ofmt, &location);
335 eval_global_info(ofmt, lookup_label, &location);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000336
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000337 /* define some macros dependent of command-line */
H. Peter Anvin6b18bcc2008-02-16 14:54:10 -0800338 define_macros_late();
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000339
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700340 depend_ptr = (depend_file || (operating_mode == op_depend))
341 ? &depend_list : NULL;
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700342 if (!depend_target)
343 depend_target = outname;
344
H. Peter Anvine2c80182005-01-15 22:15:51 +0000345 switch (operating_mode) {
H. Peter Anvin620515a2002-04-30 20:57:38 +0000346 case op_depend:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000347 {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000348 char *line;
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700349
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700350 if (depend_missing_ok)
351 pp_include_path(NULL); /* "assume generated" */
352
353 preproc->reset(inname, 0, report_error, evaluate, &nasmlist,
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700354 depend_ptr);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000355 if (outname[0] == '\0')
356 ofmt->filename(inname, outname, report_error);
357 ofile = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000358 while ((line = preproc->getline()))
359 nasm_free(line);
360 preproc->cleanup(0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000361 }
362 break;
H. Peter Anvin620515a2002-04-30 20:57:38 +0000363
364 case op_preprocess:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000365 {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000366 char *line;
367 char *file_name = NULL;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000368 int32_t prior_linnum = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000369 int lineinc = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000370
H. Peter Anvine2c80182005-01-15 22:15:51 +0000371 if (*outname) {
372 ofile = fopen(outname, "w");
373 if (!ofile)
374 report_error(ERR_FATAL | ERR_NOFILE,
375 "unable to open output file `%s'",
376 outname);
377 } else
378 ofile = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000379
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700380 location.known = false;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000381
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700382 /* pass = 1; */
383 preproc->reset(inname, 2, report_error, evaluate, &nasmlist,
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700384 depend_ptr);
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700385
H. Peter Anvine2c80182005-01-15 22:15:51 +0000386 while ((line = preproc->getline())) {
387 /*
388 * We generate %line directives if needed for later programs
389 */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000390 int32_t linnum = prior_linnum += lineinc;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000391 int altline = src_get(&linnum, &file_name);
392 if (altline) {
393 if (altline == 1 && lineinc == 1)
394 nasm_fputs("", ofile);
395 else {
396 lineinc = (altline != -1 || lineinc != 1);
397 fprintf(ofile ? ofile : stdout,
Keith Kanios93f2e9a2007-04-14 00:10:59 +0000398 "%%line %"PRId32"+%d %s\n", linnum, lineinc,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000399 file_name);
400 }
401 prior_linnum = linnum;
402 }
403 nasm_fputs(line, ofile);
404 nasm_free(line);
405 }
406 nasm_free(file_name);
407 preproc->cleanup(0);
408 if (ofile)
409 fclose(ofile);
410 if (ofile && terminate_after_phase)
411 remove(outname);
412 }
413 break;
H. Peter Anvin620515a2002-04-30 20:57:38 +0000414
415 case op_normal:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000416 {
417 /*
418 * We must call ofmt->filename _anyway_, even if the user
419 * has specified their own output file, because some
420 * formats (eg OBJ and COFF) use ofmt->filename to find out
421 * the name of the input file and then put that inside the
422 * file.
423 */
424 ofmt->filename(inname, outname, report_error);
425
426 ofile = fopen(outname, "wb");
427 if (!ofile) {
428 report_error(ERR_FATAL | ERR_NOFILE,
429 "unable to open output file `%s'", outname);
430 }
431
432 /*
433 * We must call init_labels() before ofmt->init() since
434 * some object formats will want to define labels in their
435 * init routines. (eg OS/2 defines the FLAT group)
436 */
437 init_labels();
438
439 ofmt->init(ofile, report_error, define_label, evaluate);
440
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700441 assemble_file(inname, depend_ptr);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000442
443 if (!terminate_after_phase) {
444 ofmt->cleanup(using_debug_info);
445 cleanup_labels();
446 } else {
447 /*
Victor van den Elzenc82c3722008-06-04 15:24:20 +0200448 * Despite earlier comments, we need this fclose.
449 * The object output drivers only fclose on cleanup,
450 * and we just skipped that.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000451 */
Victor van den Elzenc82c3722008-06-04 15:24:20 +0200452 fclose (ofile);
453
H. Peter Anvine2c80182005-01-15 22:15:51 +0000454 remove(outname);
455 if (listname[0])
456 remove(listname);
457 }
458 }
459 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000460 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000461
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700462 if (depend_list)
463 emit_dependencies(depend_list);
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700464
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000465 if (want_usage)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000466 usage();
H. Peter Anvin734b1882002-04-30 21:01:08 +0000467
H. Peter Anvine2c80182005-01-15 22:15:51 +0000468 raa_free(offsets);
469 saa_free(forwrefs);
470 eval_cleanup();
H. Peter Anvin74cc5e52007-08-30 22:35:34 +0000471 stdscan_cleanup();
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000472
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000473 if (terminate_after_phase)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000474 return 1;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000475 else
H. Peter Anvine2c80182005-01-15 22:15:51 +0000476 return 0;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000477}
478
H. Peter Anvineba20a72002-04-30 20:53:55 +0000479/*
480 * Get a parameter for a command line option.
481 * First arg must be in the form of e.g. -f...
482 */
H. Peter Anvin423e3812007-11-15 17:12:29 -0800483static char *get_param(char *p, char *q, bool *advance)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000484{
H. Peter Anvin423e3812007-11-15 17:12:29 -0800485 *advance = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000486 if (p[2]) { /* the parameter's in the option */
487 p += 2;
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -0700488 while (nasm_isspace(*p))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000489 p++;
490 return p;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000491 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000492 if (q && q[0]) {
H. Peter Anvin423e3812007-11-15 17:12:29 -0800493 *advance = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000494 return q;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000495 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000496 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
497 "option `-%c' requires an argument", p[1]);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000498 return NULL;
499}
500
H. Peter Anvindc242712007-11-18 11:55:10 -0800501/*
502 * Copy a filename
503 */
504static void copy_filename(char *dst, const char *src)
505{
506 size_t len = strlen(src);
507
508 if (len >= (size_t)FILENAME_MAX) {
509 report_error(ERR_FATAL | ERR_NOFILE, "file name too long");
510 return;
511 }
512 strncpy(dst, src, FILENAME_MAX);
513}
514
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700515/*
516 * Convert a string to Make-safe form
517 */
518static char *quote_for_make(const char *str)
519{
520 const char *p;
521 char *os, *q;
522
523 size_t n = 1; /* Terminating zero */
524 size_t nbs = 0;
525
526 if (!str)
527 return NULL;
528
529 for (p = str; *p; p++) {
530 switch (*p) {
531 case ' ':
532 case '\t':
533 /* Convert N backslashes + ws -> 2N+1 backslashes + ws */
534 n += nbs + 2;
535 nbs = 0;
536 break;
537 case '$':
538 case '#':
539 nbs = 0;
540 n += 2;
541 break;
542 case '\\':
543 nbs++;
544 n++;
545 break;
546 default:
547 nbs = 0;
548 n++;
549 break;
550 }
551 }
552
553 /* Convert N backslashes at the end of filename to 2N backslashes */
554 if (nbs)
555 n += nbs;
556
557 os = q = nasm_malloc(n);
558
559 nbs = 0;
560 for (p = str; *p; p++) {
561 switch (*p) {
562 case ' ':
563 case '\t':
564 while (nbs--)
565 *q++ = '\\';
566 *q++ = '\\';
567 *q++ = *p;
568 break;
569 case '$':
570 *q++ = *p;
571 *q++ = *p;
572 nbs = 0;
573 break;
574 case '#':
575 *q++ = '\\';
576 *q++ = *p;
577 nbs = 0;
578 break;
579 case '\\':
580 *q++ = *p;
581 nbs++;
582 break;
583 default:
584 *q++ = *p;
585 nbs = 0;
586 break;
587 }
588 }
589 while (nbs--)
590 *q++ = '\\';
591
592 *q = '\0';
593
594 return os;
595}
596
H. Peter Anvine2c80182005-01-15 22:15:51 +0000597struct textargs {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000598 const char *label;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000599 int value;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000600};
601
602#define OPT_PREFIX 0
603#define OPT_POSTFIX 1
H. Peter Anvine2c80182005-01-15 22:15:51 +0000604struct textargs textopts[] = {
605 {"prefix", OPT_PREFIX},
606 {"postfix", OPT_POSTFIX},
607 {NULL, 0}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000608};
609
H. Peter Anvin423e3812007-11-15 17:12:29 -0800610static bool stopoptions = false;
611static bool process_arg(char *p, char *q)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000612{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000613 char *param;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800614 int i;
615 bool advance = false;
H. Peter Anvinb030c922007-11-13 11:31:15 -0800616 bool suppress;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000617
618 if (!p || !p[0])
H. Peter Anvin423e3812007-11-15 17:12:29 -0800619 return false;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000620
H. Peter Anvine2c80182005-01-15 22:15:51 +0000621 if (p[0] == '-' && !stopoptions) {
H. Peter Anvin423e3812007-11-15 17:12:29 -0800622 if (strchr("oOfpPdDiIlFXuUZwW", p[1])) {
623 /* These parameters take values */
624 if (!(param = get_param(p, q, &advance)))
625 return advance;
626 }
627
H. Peter Anvine2c80182005-01-15 22:15:51 +0000628 switch (p[1]) {
629 case 's':
630 error_file = stdout;
631 break;
H. Peter Anvin70653092007-10-19 14:42:29 -0700632
H. Peter Anvin423e3812007-11-15 17:12:29 -0800633 case 'o': /* output file */
H. Peter Anvindc242712007-11-18 11:55:10 -0800634 copy_filename(outname, param);
H. Peter Anvin423e3812007-11-15 17:12:29 -0800635 break;
H. Peter Anvinfd7dd112007-10-10 14:06:59 -0700636
H. Peter Anvin423e3812007-11-15 17:12:29 -0800637 case 'f': /* output format */
638 ofmt = ofmt_find(param);
639 if (!ofmt) {
640 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
641 "unrecognised output format `%s' - "
642 "use -hf for a list", param);
643 } else {
644 ofmt->current_dfmt = ofmt->debug_formats[0];
645 }
646 break;
H. Peter Anvin70653092007-10-19 14:42:29 -0700647
H. Peter Anvin423e3812007-11-15 17:12:29 -0800648 case 'O': /* Optimization level */
649 {
650 int opt;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700651
H. Peter Anvin423e3812007-11-15 17:12:29 -0800652 if (!*param) {
653 /* Naked -O == -Ox */
654 optimizing = INT_MAX >> 1; /* Almost unlimited */
655 } else {
656 while (*param) {
657 switch (*param) {
658 case '0': case '1': case '2': case '3': case '4':
659 case '5': case '6': case '7': case '8': case '9':
660 opt = strtoul(param, &param, 10);
H. Peter Anvind85d2502008-05-04 17:53:31 -0700661
H. Peter Anvin423e3812007-11-15 17:12:29 -0800662 /* -O0 -> optimizing == -1, 0.98 behaviour */
663 /* -O1 -> optimizing == 0, 0.98.09 behaviour */
664 if (opt < 2)
665 optimizing = opt - 1;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800666 else
H. Peter Anvin34ec3002008-01-08 22:31:20 -0800667 optimizing = opt;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800668 break;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700669
H. Peter Anvin423e3812007-11-15 17:12:29 -0800670 case 'v':
671 case '+':
672 param++;
673 opt_verbose_info = true;
674 break;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700675
H. Peter Anvin423e3812007-11-15 17:12:29 -0800676 case 'x':
677 param++;
678 optimizing = INT_MAX >> 1; /* Almost unlimited */
679 break;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700680
H. Peter Anvin423e3812007-11-15 17:12:29 -0800681 default:
682 report_error(ERR_FATAL,
683 "unknown optimization option -O%c\n",
684 *param);
685 break;
H. Peter Anvinfd7dd112007-10-10 14:06:59 -0700686 }
687 }
H. Peter Anvin423e3812007-11-15 17:12:29 -0800688 }
689 break;
690 }
691
692 case 'p': /* pre-include */
693 case 'P':
694 pp_pre_include(param);
695 break;
696
697 case 'd': /* pre-define */
698 case 'D':
699 pp_pre_define(param);
700 break;
701
702 case 'u': /* un-define */
703 case 'U':
704 pp_pre_undefine(param);
705 break;
706
707 case 'i': /* include search path */
708 case 'I':
709 pp_include_path(param);
710 break;
711
712 case 'l': /* listing file */
H. Peter Anvindc242712007-11-18 11:55:10 -0800713 copy_filename(listname, param);
H. Peter Anvin423e3812007-11-15 17:12:29 -0800714 break;
715
716 case 'Z': /* error messages file */
717 strcpy(errname, param);
718 break;
719
720 case 'F': /* specify debug format */
721 ofmt->current_dfmt = dfmt_find(ofmt, param);
722 if (!ofmt->current_dfmt) {
723 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
724 "unrecognized debug format `%s' for"
725 " output format `%s'",
726 param, ofmt->shortname);
727 }
H. Peter Anvinca5ec7a2008-06-11 18:07:40 -0700728 using_debug_info = true;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800729 break;
730
731 case 'X': /* specify error reporting format */
732 if (nasm_stricmp("vc", param) == 0)
733 report_error = report_error_vc;
734 else if (nasm_stricmp("gnu", param) == 0)
735 report_error = report_error_gnu;
736 else
737 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
738 "unrecognized error reporting format `%s'",
739 param);
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 'g':
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700743 using_debug_info = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000744 break;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800745
H. Peter Anvine2c80182005-01-15 22:15:51 +0000746 case 'h':
747 printf
748 ("usage: nasm [-@ response file] [-o outfile] [-f format] "
749 "[-l listfile]\n"
750 " [options...] [--] filename\n"
H. Peter Anvin413fb902007-09-26 15:19:28 -0700751 " or nasm -v for version info\n\n"
H. Peter Anvine2c80182005-01-15 22:15:51 +0000752 " -t assemble in SciTech TASM compatible mode\n"
753 " -g generate debug information in selected format.\n");
754 printf
H. Peter Anvin413fb902007-09-26 15:19:28 -0700755 (" -E (or -e) preprocess only (writes output to stdout by default)\n"
H. Peter Anvine2c80182005-01-15 22:15:51 +0000756 " -a don't preprocess (assemble only)\n"
H. Peter Anvin37a321f2007-09-24 13:41:58 -0700757 " -M generate Makefile dependencies on stdout\n"
758 " -MG d:o, missing files assumed generated\n\n"
H. Peter Anvin413fb902007-09-26 15:19:28 -0700759 " -Z<file> redirect error messages to file\n"
H. Peter Anvine2c80182005-01-15 22:15:51 +0000760 " -s redirect error messages to stdout\n\n"
761 " -F format select a debugging format\n\n"
762 " -I<path> adds a pathname to the include file path\n");
763 printf
764 (" -O<digit> optimize branch offsets (-O0 disables, default)\n"
765 " -P<file> pre-includes a file\n"
766 " -D<macro>[=<value>] pre-defines a macro\n"
767 " -U<macro> undefines a macro\n"
768 " -X<format> specifies error reporting format (gnu or vc)\n"
H. Peter Anvinb030c922007-11-13 11:31:15 -0800769 " -w+foo enables warning foo (equiv. -Wfoo)\n"
770 " -w-foo disable warning foo (equiv. -Wno-foo)\n"
771 "Warnings:\n");
772 for (i = 0; i <= ERR_WARN_MAX; i++)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000773 printf(" %-23s %s (default %s)\n",
774 suppressed_names[i], suppressed_what[i],
Victor van den Elzen819703a2008-07-16 15:20:56 +0200775 suppressed_global[i] ? "off" : "on");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000776 printf
777 ("\nresponse files should contain command line parameters"
778 ", one per line.\n");
779 if (p[2] == 'f') {
780 printf("\nvalid output formats for -f are"
781 " (`*' denotes default):\n");
782 ofmt_list(ofmt, stdout);
783 } else {
784 printf("\nFor a list of valid output formats, use -hf.\n");
785 printf("For a list of debug formats, use -f <form> -y.\n");
786 }
787 exit(0); /* never need usage message here */
788 break;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800789
H. Peter Anvine2c80182005-01-15 22:15:51 +0000790 case 'y':
791 printf("\nvalid debug formats for '%s' output format are"
792 " ('*' denotes default):\n", ofmt->shortname);
793 dfmt_list(ofmt, stdout);
794 exit(0);
795 break;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800796
H. Peter Anvine2c80182005-01-15 22:15:51 +0000797 case 't':
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700798 tasm_compatible_mode = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000799 break;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800800
H. Peter Anvine2c80182005-01-15 22:15:51 +0000801 case 'v':
802 {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000803 const char *nasm_version_string =
H. Peter Anvine2c80182005-01-15 22:15:51 +0000804 "NASM version " NASM_VER " compiled on " __DATE__
H. Peter Anvineba20a72002-04-30 20:53:55 +0000805#ifdef DEBUG
H. Peter Anvine2c80182005-01-15 22:15:51 +0000806 " with -DDEBUG"
H. Peter Anvineba20a72002-04-30 20:53:55 +0000807#endif
H. Peter Anvine2c80182005-01-15 22:15:51 +0000808 ;
809 puts(nasm_version_string);
810 exit(0); /* never need usage message here */
811 }
812 break;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800813
H. Peter Anvine2c80182005-01-15 22:15:51 +0000814 case 'e': /* preprocess only */
H. Peter Anvin413fb902007-09-26 15:19:28 -0700815 case 'E':
H. Peter Anvine2c80182005-01-15 22:15:51 +0000816 operating_mode = op_preprocess;
817 break;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800818
H. Peter Anvine2c80182005-01-15 22:15:51 +0000819 case 'a': /* assemble only - don't preprocess */
820 preproc = &no_pp;
821 break;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800822
H. Peter Anvinb030c922007-11-13 11:31:15 -0800823 case 'W':
H. Peter Anvin423e3812007-11-15 17:12:29 -0800824 if (param[0] == 'n' && param[1] == 'o' && param[2] == '-') {
H. Peter Anvinb030c922007-11-13 11:31:15 -0800825 suppress = true;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800826 param += 3;
H. Peter Anvinb030c922007-11-13 11:31:15 -0800827 } else {
828 suppress = false;
H. Peter Anvinb030c922007-11-13 11:31:15 -0800829 }
830 goto set_warning;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800831
H. Peter Anvine2c80182005-01-15 22:15:51 +0000832 case 'w':
H. Peter Anvin423e3812007-11-15 17:12:29 -0800833 if (param[0] != '+' && param[0] != '-') {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000834 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
835 "invalid option to `-w'");
H. Peter Anvinb030c922007-11-13 11:31:15 -0800836 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000837 }
H. Peter Anvin423e3812007-11-15 17:12:29 -0800838 suppress = (param[0] == '-');
839 param++;
H. Peter Anvinb030c922007-11-13 11:31:15 -0800840 goto set_warning;
841 set_warning:
842 for (i = 0; i <= ERR_WARN_MAX; i++)
H. Peter Anvin423e3812007-11-15 17:12:29 -0800843 if (!nasm_stricmp(param, suppressed_names[i]))
H. Peter Anvinb030c922007-11-13 11:31:15 -0800844 break;
845 if (i <= ERR_WARN_MAX)
Victor van den Elzen819703a2008-07-16 15:20:56 +0200846 suppressed_global[i] = suppress;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800847 else if (!nasm_stricmp(param, "all"))
H. Peter Anvinb030c922007-11-13 11:31:15 -0800848 for (i = 1; i <= ERR_WARN_MAX; i++)
Victor van den Elzen819703a2008-07-16 15:20:56 +0200849 suppressed_global[i] = suppress;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800850 else if (!nasm_stricmp(param, "none"))
851 for (i = 1; i <= ERR_WARN_MAX; i++)
Victor van den Elzen819703a2008-07-16 15:20:56 +0200852 suppressed_global[i] = !suppress;
H. Peter Anvinb030c922007-11-13 11:31:15 -0800853 else
854 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
H. Peter Anvin423e3812007-11-15 17:12:29 -0800855 "invalid warning `%s'", param);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000856 break;
H. Peter Anvin423e3812007-11-15 17:12:29 -0800857
H. Peter Anvine2c80182005-01-15 22:15:51 +0000858 case 'M':
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700859 switch (p[2]) {
860 case 0:
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700861 operating_mode = op_depend;
862 break;
863 case 'G':
864 operating_mode = op_depend;
865 depend_missing_ok = true;
866 break;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700867 case 'P':
868 depend_emit_phony = true;
869 break;
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -0700870 case 'D':
871 depend_file = q;
872 advance = true;
873 break;
874 case 'T':
875 depend_target = q;
876 advance = true;
877 break;
878 case 'Q':
879 depend_target = quote_for_make(q);
880 advance = true;
881 break;
882 default:
883 report_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
884 "unknown dependency option `-M%c'", p[2]);
885 break;
886 }
887 if (advance && (!q || !q[0])) {
888 report_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
889 "option `-M%c' requires a parameter", p[2]);
890 break;
891 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000892 break;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000893
H. Peter Anvine2c80182005-01-15 22:15:51 +0000894 case '-':
895 {
896 int s;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000897
H. Peter Anvine2c80182005-01-15 22:15:51 +0000898 if (p[2] == 0) { /* -- => stop processing options */
899 stopoptions = 1;
900 break;
901 }
902 for (s = 0; textopts[s].label; s++) {
903 if (!nasm_stricmp(p + 2, textopts[s].label)) {
904 break;
905 }
906 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000907
H. Peter Anvine2c80182005-01-15 22:15:51 +0000908 switch (s) {
909
910 case OPT_PREFIX:
911 case OPT_POSTFIX:
912 {
913 if (!q) {
914 report_error(ERR_NONFATAL | ERR_NOFILE |
915 ERR_USAGE,
916 "option `--%s' requires an argument",
917 p + 2);
918 break;
919 } else {
920 advance = 1, param = q;
921 }
922
923 if (s == OPT_PREFIX) {
924 strncpy(lprefix, param, PREFIX_MAX - 1);
925 lprefix[PREFIX_MAX - 1] = 0;
926 break;
927 }
928 if (s == OPT_POSTFIX) {
929 strncpy(lpostfix, param, POSTFIX_MAX - 1);
930 lpostfix[POSTFIX_MAX - 1] = 0;
931 break;
932 }
933 break;
934 }
935 default:
936 {
937 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
938 "unrecognised option `--%s'", p + 2);
939 break;
940 }
941 }
942 break;
943 }
944
945 default:
946 if (!ofmt->setinfo(GI_SWITCH, &p))
947 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
948 "unrecognised option `-%c'", p[1]);
949 break;
950 }
951 } else {
952 if (*inname) {
953 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
954 "more than one input file specified");
H. Peter Anvindc242712007-11-18 11:55:10 -0800955 } else {
956 copy_filename(inname, p);
957 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000958 }
959
960 return advance;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000961}
962
H. Peter Anvineba20a72002-04-30 20:53:55 +0000963#define ARG_BUF_DELTA 128
964
H. Peter Anvine2c80182005-01-15 22:15:51 +0000965static void process_respfile(FILE * rfile)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000966{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000967 char *buffer, *p, *q, *prevarg;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000968 int bufsize, prevargsize;
969
970 bufsize = prevargsize = ARG_BUF_DELTA;
971 buffer = nasm_malloc(ARG_BUF_DELTA);
972 prevarg = nasm_malloc(ARG_BUF_DELTA);
973 prevarg[0] = '\0';
974
H. Peter Anvine2c80182005-01-15 22:15:51 +0000975 while (1) { /* Loop to handle all lines in file */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000976 p = buffer;
977 while (1) { /* Loop to handle long lines */
978 q = fgets(p, bufsize - (p - buffer), rfile);
979 if (!q)
980 break;
981 p += strlen(p);
982 if (p > buffer && p[-1] == '\n')
983 break;
984 if (p - buffer > bufsize - 10) {
985 int offset;
986 offset = p - buffer;
987 bufsize += ARG_BUF_DELTA;
988 buffer = nasm_realloc(buffer, bufsize);
989 p = buffer + offset;
990 }
991 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000992
H. Peter Anvine2c80182005-01-15 22:15:51 +0000993 if (!q && p == buffer) {
994 if (prevarg[0])
995 process_arg(prevarg, NULL);
996 nasm_free(buffer);
997 nasm_free(prevarg);
998 return;
999 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001000
H. Peter Anvine2c80182005-01-15 22:15:51 +00001001 /*
1002 * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
1003 * them are present at the end of the line.
1004 */
1005 *(p = &buffer[strcspn(buffer, "\r\n\032")]) = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +00001006
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001007 while (p > buffer && nasm_isspace(p[-1]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001008 *--p = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +00001009
H. Peter Anvine2c80182005-01-15 22:15:51 +00001010 p = buffer;
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001011 while (nasm_isspace(*p))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001012 p++;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001013
H. Peter Anvine2c80182005-01-15 22:15:51 +00001014 if (process_arg(prevarg, p))
1015 *p = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +00001016
Charles Crayne192d5b52007-10-18 19:02:42 -07001017 if ((int) strlen(p) > prevargsize - 10) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001018 prevargsize += ARG_BUF_DELTA;
1019 prevarg = nasm_realloc(prevarg, prevargsize);
1020 }
H. Peter Anvindc242712007-11-18 11:55:10 -08001021 strncpy(prevarg, p, prevargsize);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001022 }
1023}
1024
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001025/* Function to process args from a string of args, rather than the
1026 * argv array. Used by the environment variable and response file
1027 * processing.
1028 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001029static void process_args(char *args)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001030{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001031 char *p, *q, *arg, *prevarg;
1032 char separator = ' ';
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001033
1034 p = args;
1035 if (*p && *p != '-')
H. Peter Anvine2c80182005-01-15 22:15:51 +00001036 separator = *p++;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001037 arg = NULL;
1038 while (*p) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001039 q = p;
1040 while (*p && *p != separator)
1041 p++;
1042 while (*p == separator)
1043 *p++ = '\0';
1044 prevarg = arg;
1045 arg = q;
1046 if (process_arg(prevarg, arg))
1047 arg = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001048 }
1049 if (arg)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001050 process_arg(arg, NULL);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001051}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001052
H. Peter Anvinbe2678c2008-01-21 16:23:59 -08001053static void process_response_file(const char *file)
1054{
1055 char str[2048];
1056 FILE *f = fopen(file, "r");
1057 if (!f) {
1058 perror(file);
1059 exit(-1);
1060 }
1061 while (fgets(str, sizeof str, f)) {
1062 process_args(str);
1063 }
1064 fclose(f);
1065}
1066
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001067static void parse_cmdline(int argc, char **argv)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001068{
1069 FILE *rfile;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001070 char *envreal, *envcopy = NULL, *p, *arg;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001071
Charles Craynefcce07f2007-09-30 22:15:36 -07001072 *inname = *outname = *listname = *errname = '\0';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001073
1074 /*
H. Peter Anvinff7ccc02002-05-06 19:41:57 +00001075 * First, process the NASMENV environment variable.
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001076 */
H. Peter Anvinff7ccc02002-05-06 19:41:57 +00001077 envreal = getenv("NASMENV");
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001078 arg = NULL;
1079 if (envreal) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001080 envcopy = nasm_strdup(envreal);
1081 process_args(envcopy);
1082 nasm_free(envcopy);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001083 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001084
1085 /*
1086 * Now process the actual command line.
1087 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001088 while (--argc) {
H. Peter Anvin423e3812007-11-15 17:12:29 -08001089 bool advance;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001090 argv++;
1091 if (argv[0][0] == '@') {
1092 /* We have a response file, so process this as a set of
1093 * arguments like the environment variable. This allows us
1094 * to have multiple arguments on a single line, which is
1095 * different to the -@resp file processing below for regular
1096 * NASM.
1097 */
H. Peter Anvinbe2678c2008-01-21 16:23:59 -08001098 process_response_file(argv[0]+1);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001099 argc--;
1100 argv++;
1101 }
1102 if (!stopoptions && argv[0][0] == '-' && argv[0][1] == '@') {
H. Peter Anvin423e3812007-11-15 17:12:29 -08001103 p = get_param(argv[0], argc > 1 ? argv[1] : NULL, &advance);
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001104 if (p) {
1105 rfile = fopen(p, "r");
1106 if (rfile) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001107 process_respfile(rfile);
1108 fclose(rfile);
1109 } else
1110 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
1111 "unable to open response file `%s'", p);
1112 }
1113 } else
H. Peter Anvin423e3812007-11-15 17:12:29 -08001114 advance = process_arg(argv[0], argc > 1 ? argv[1] : NULL);
1115 argv += advance, argc -= advance;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001116 }
1117
H. Peter Anvin70c0bf22007-11-19 11:45:40 -08001118 /* Look for basic command line typos. This definitely doesn't
1119 catch all errors, but it might help cases of fumbled fingers. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001120 if (!*inname)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001121 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
1122 "no input file specified");
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001123 else if (!strcmp(inname, errname) ||
1124 !strcmp(inname, outname) ||
1125 !strcmp(inname, listname) ||
1126 (depend_file && !strcmp(inname, depend_file)))
H. Peter Anvin59ddd262007-10-01 11:26:31 -07001127 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
1128 "file `%s' is both input and output file",
1129 inname);
H. Peter Anvin59ddd262007-10-01 11:26:31 -07001130
H. Peter Anvin70653092007-10-19 14:42:29 -07001131 if (*errname) {
H. Peter Anvin59ddd262007-10-01 11:26:31 -07001132 error_file = fopen(errname, "w");
1133 if (!error_file) {
1134 error_file = stderr; /* Revert to default! */
1135 report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
1136 "cannot open file `%s' for error messages",
1137 errname);
1138 }
Charles Craynefcce07f2007-09-30 22:15:36 -07001139 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001140}
1141
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001142/* List of directives */
H. Peter Anvin70055962007-10-11 00:05:31 -07001143enum directives {
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001144 D_NONE, D_ABSOLUTE, D_BITS, D_COMMON, D_CPU, D_DEBUG, D_DEFAULT,
H. Peter Anvinf6c9e652007-10-16 14:40:27 -07001145 D_EXTERN, D_FLOAT, D_GLOBAL, D_LIST, D_SECTION, D_SEGMENT, D_WARNING
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001146};
1147static const char *directives[] = {
1148 "", "absolute", "bits", "common", "cpu", "debug", "default",
H. Peter Anvinf6c9e652007-10-16 14:40:27 -07001149 "extern", "float", "global", "list", "section", "segment", "warning"
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001150};
H. Peter Anvin70055962007-10-11 00:05:31 -07001151static enum directives getkw(char **directive, char **value);
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001152
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001153static void assemble_file(char *fname, StrList **depend_ptr)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001154{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001155 char *directive, *value, *p, *q, *special, *line, debugid[80];
H. Peter Anvine2c80182005-01-15 22:15:51 +00001156 insn output_ins;
H. Peter Anvin70055962007-10-11 00:05:31 -07001157 int i, validid;
1158 bool rn_error;
Charles Crayne5fbbc8c2007-11-07 19:03:46 -08001159 int32_t seg;
1160 int64_t offs;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001161 struct tokenval tokval;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001162 expr *e;
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001163 int pass_max;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001164
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001165 if (cmd_sb == 32 && cmd_cpu < IF_386)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001166 report_error(ERR_FATAL, "command line: "
1167 "32-bit segment size requires a higher cpu");
H. Peter Anvineba20a72002-04-30 20:53:55 +00001168
H. Peter Anvine2c80182005-01-15 22:15:51 +00001169 pass_max = (optimizing > 0 ? optimizing : 0) + 2; /* passes 1, optimizing, then 2 */
1170 pass0 = !(optimizing > 0); /* start at 1 if not optimizing */
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001171 for (passn = 1; pass0 <= 2; passn++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001172 int pass1, pass2;
1173 ldfunc def_label;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001174
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001175 pass1 = pass0 == 2 ? 2 : 1; /* 1, 1, 1, ..., 1, 2 */
1176 pass2 = passn > 1 ? 2 : 1; /* 1, 2, 2, ..., 2, 2 */
1177 /* pass0 0, 0, 0, ..., 1, 2 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001178
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001179 def_label = passn > 1 ? redefine_label : define_label;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001180
Keith Kaniosb7a89542007-04-12 02:40:54 +00001181 globalbits = sb = cmd_sb; /* set 'bits' to command line default */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001182 cpu = cmd_cpu;
1183 if (pass0 == 2) {
1184 if (*listname)
1185 nasmlist.init(listname, report_error);
1186 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001187 in_abs_seg = false;
1188 global_offset_changed = false; /* set by redefine_label */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001189 location.segment = ofmt->section(NULL, pass2, &sb);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001190 globalbits = sb;
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001191 if (passn > 1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001192 saa_rewind(forwrefs);
1193 forwref = saa_rstruct(forwrefs);
1194 raa_free(offsets);
1195 offsets = raa_init();
1196 }
H. Peter Anvin07b7b9e2008-05-29 19:09:11 -07001197 preproc->reset(fname, pass1, report_error, evaluate, &nasmlist,
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001198 pass1 == 2 ? depend_ptr : NULL);
Victor van den Elzen819703a2008-07-16 15:20:56 +02001199 memcpy(suppressed, suppressed_global, (ERR_WARN_MAX+1) * sizeof(bool));
1200
H. Peter Anvine2c80182005-01-15 22:15:51 +00001201 globallineno = 0;
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001202 if (passn == 1)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001203 location.known = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001204 location.offset = offs = GET_CURR_OFFS;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001205
H. Peter Anvine2c80182005-01-15 22:15:51 +00001206 while ((line = preproc->getline())) {
H. Peter Anvin70055962007-10-11 00:05:31 -07001207 enum directives d;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001208 globallineno++;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001209
H. Peter Anvine2c80182005-01-15 22:15:51 +00001210 /* here we parse our directives; this is not handled by the 'real'
1211 * parser. */
1212 directive = line;
H. Peter Anvin70055962007-10-11 00:05:31 -07001213 d = getkw(&directive, &value);
1214 if (d) {
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001215 int err = 0;
1216
H. Peter Anvin70055962007-10-11 00:05:31 -07001217 switch (d) {
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001218 case D_SEGMENT: /* [SEGMENT n] */
1219 case D_SECTION:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001220 seg = ofmt->section(value, pass2, &sb);
1221 if (seg == NO_SEG) {
1222 report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
Keith Kaniosb7a89542007-04-12 02:40:54 +00001223 "segment name `%s' not recognized",
H. Peter Anvine2c80182005-01-15 22:15:51 +00001224 value);
1225 } else {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001226 in_abs_seg = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001227 location.segment = seg;
1228 }
1229 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001230 case D_EXTERN: /* [EXTERN label:special] */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001231 if (*value == '$')
1232 value++; /* skip initial $ if present */
1233 if (pass0 == 2) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001234 q = value;
1235 while (*q && *q != ':')
H. Peter Anvine2c80182005-01-15 22:15:51 +00001236 q++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001237 if (*q == ':') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001238 *q++ = '\0';
1239 ofmt->symdef(value, 0L, 0L, 3, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001240 }
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001241 } else if (passn == 1) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001242 q = value;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001243 validid = true;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001244 if (!isidstart(*q))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001245 validid = false;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001246 while (*q && *q != ':') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001247 if (!isidchar(*q))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001248 validid = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001249 q++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001250 }
1251 if (!validid) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001252 report_error(ERR_NONFATAL,
1253 "identifier expected after EXTERN");
1254 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001255 }
1256 if (*q == ':') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001257 *q++ = '\0';
1258 special = q;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001259 } else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001260 special = NULL;
1261 if (!is_extern(value)) { /* allow re-EXTERN to be ignored */
1262 int temp = pass0;
1263 pass0 = 1; /* fake pass 1 in labels.c */
1264 declare_as_global(value, special,
1265 report_error);
1266 define_label(value, seg_alloc(), 0L, NULL,
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001267 false, true, ofmt, report_error);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001268 pass0 = temp;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001269 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001270 } /* else pass0 == 1 */
1271 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001272 case D_BITS: /* [BITS bits] */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001273 globalbits = sb = get_bits(value);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001274 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001275 case D_GLOBAL: /* [GLOBAL symbol:special] */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001276 if (*value == '$')
1277 value++; /* skip initial $ if present */
1278 if (pass0 == 2) { /* pass 2 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001279 q = value;
1280 while (*q && *q != ':')
H. Peter Anvine2c80182005-01-15 22:15:51 +00001281 q++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001282 if (*q == ':') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001283 *q++ = '\0';
1284 ofmt->symdef(value, 0L, 0L, 3, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001285 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001286 } else if (pass2 == 1) { /* pass == 1 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001287 q = value;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001288 validid = true;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001289 if (!isidstart(*q))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001290 validid = false;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001291 while (*q && *q != ':') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001292 if (!isidchar(*q))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001293 validid = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001294 q++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001295 }
1296 if (!validid) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001297 report_error(ERR_NONFATAL,
1298 "identifier expected after GLOBAL");
1299 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001300 }
1301 if (*q == ':') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001302 *q++ = '\0';
1303 special = q;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001304 } else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001305 special = NULL;
1306 declare_as_global(value, special, report_error);
1307 } /* pass == 1 */
1308 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001309 case D_COMMON: /* [COMMON symbol size:special] */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001310 if (*value == '$')
1311 value++; /* skip initial $ if present */
1312 if (pass0 == 1) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001313 p = value;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001314 validid = true;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001315 if (!isidstart(*p))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001316 validid = false;
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001317 while (*p && !nasm_isspace(*p)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001318 if (!isidchar(*p))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001319 validid = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001320 p++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001321 }
1322 if (!validid) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001323 report_error(ERR_NONFATAL,
1324 "identifier expected after COMMON");
1325 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001326 }
1327 if (*p) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001328 int64_t size;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001329
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001330 while (*p && nasm_isspace(*p))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001331 *p++ = '\0';
1332 q = p;
1333 while (*q && *q != ':')
1334 q++;
1335 if (*q == ':') {
1336 *q++ = '\0';
1337 special = q;
1338 } else
1339 special = NULL;
1340 size = readnum(p, &rn_error);
1341 if (rn_error)
1342 report_error(ERR_NONFATAL,
1343 "invalid size specified"
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001344 " in COMMON declaration");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001345 else
1346 define_common(value, seg_alloc(), size,
1347 special, ofmt, report_error);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001348 } else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001349 report_error(ERR_NONFATAL,
1350 "no size specified in"
1351 " COMMON declaration");
1352 } else if (pass0 == 2) { /* pass == 2 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001353 q = value;
1354 while (*q && *q != ':') {
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001355 if (nasm_isspace(*q))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001356 *q = '\0';
1357 q++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001358 }
1359 if (*q == ':') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001360 *q++ = '\0';
1361 ofmt->symdef(value, 0L, 0L, 3, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001362 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001363 }
1364 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001365 case D_ABSOLUTE: /* [ABSOLUTE address] */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001366 stdscan_reset();
1367 stdscan_bufptr = value;
1368 tokval.t_type = TOKEN_INVALID;
1369 e = evaluate(stdscan, NULL, &tokval, NULL, pass2,
1370 report_error, NULL);
1371 if (e) {
1372 if (!is_reloc(e))
1373 report_error(pass0 ==
1374 1 ? ERR_NONFATAL : ERR_PANIC,
1375 "cannot use non-relocatable expression as "
1376 "ABSOLUTE address");
1377 else {
1378 abs_seg = reloc_seg(e);
1379 abs_offset = reloc_value(e);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001380 }
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001381 } else if (passn == 1)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001382 abs_offset = 0x100; /* don't go near zero in case of / */
1383 else
1384 report_error(ERR_PANIC, "invalid ABSOLUTE address "
1385 "in pass two");
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001386 in_abs_seg = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001387 location.segment = NO_SEG;
1388 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001389 case D_DEBUG: /* [DEBUG] */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001390 p = value;
1391 q = debugid;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001392 validid = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001393 if (!isidstart(*p))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001394 validid = false;
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001395 while (*p && !nasm_isspace(*p)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001396 if (!isidchar(*p))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001397 validid = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001398 *q++ = *p++;
1399 }
1400 *q++ = 0;
1401 if (!validid) {
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001402 report_error(passn == 1 ? ERR_NONFATAL : ERR_PANIC,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001403 "identifier expected after DEBUG");
1404 break;
1405 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001406 while (*p && nasm_isspace(*p))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001407 p++;
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001408 if (pass0 == 2)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001409 ofmt->current_dfmt->debug_directive(debugid, p);
1410 break;
Victor van den Elzen819703a2008-07-16 15:20:56 +02001411 case D_WARNING: /* [WARNING {+|-|*}warn-name] */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001412 if (pass1 == 1) {
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001413 while (*value && nasm_isspace(*value))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001414 value++;
1415
Victor van den Elzen819703a2008-07-16 15:20:56 +02001416 switch(*value) {
1417 case '-': validid = 0; value++; break;
1418 case '+': validid = 1; value++; break;
1419 case '*': validid = 2; value++; break;
1420 default: /*
1421 * Should this error out?
1422 * I'll keep it so nothing breaks.
1423 */
1424 validid = 1; break;
1425 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001426
1427 for (i = 1; i <= ERR_WARN_MAX; i++)
1428 if (!nasm_stricmp(value, suppressed_names[i]))
1429 break;
Victor van den Elzen819703a2008-07-16 15:20:56 +02001430 if (i <= ERR_WARN_MAX) {
1431 switch(validid) {
1432 case 0: suppressed[i] = true; break;
1433 case 1: suppressed[i] = false; break;
1434 case 2: suppressed[i] = suppressed_global[i];
1435 break;
1436 }
1437 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001438 else
1439 report_error(ERR_NONFATAL,
1440 "invalid warning id in WARNING directive");
1441 }
1442 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001443 case D_CPU: /* [CPU] */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001444 cpu = get_cpu(value);
1445 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001446 case D_LIST: /* [LIST {+|-}] */
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001447 while (*value && nasm_isspace(*value))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001448 value++;
1449
1450 if (*value == '+') {
1451 user_nolist = 0;
1452 } else {
1453 if (*value == '-') {
1454 user_nolist = 1;
1455 } else {
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001456 err = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001457 }
1458 }
1459 break;
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001460 case D_DEFAULT: /* [DEFAULT] */
1461 stdscan_reset();
1462 stdscan_bufptr = value;
1463 tokval.t_type = TOKEN_INVALID;
1464 if (stdscan(NULL, &tokval) == TOKEN_SPECIAL) {
1465 switch ((int)tokval.t_integer) {
1466 case S_REL:
1467 globalrel = 1;
1468 break;
1469 case S_ABS:
1470 globalrel = 0;
1471 break;
1472 default:
1473 err = 1;
1474 break;
1475 }
1476 } else {
1477 err = 1;
1478 }
1479 break;
H. Peter Anvinf6c9e652007-10-16 14:40:27 -07001480 case D_FLOAT:
1481 if (float_option(value)) {
1482 report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
1483 "unknown 'float' directive: %s",
1484 value);
1485 }
1486 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001487 default:
1488 if (!ofmt->directive(directive, value, pass2))
1489 report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
1490 "unrecognised directive [%s]",
1491 directive);
1492 }
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001493 if (err) {
1494 report_error(ERR_NONFATAL,
1495 "invalid parameter to [%s] directive",
1496 directive);
1497 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001498 } else { /* it isn't a directive */
1499
1500 parse_line(pass1, line, &output_ins,
1501 report_error, evaluate, def_label);
1502
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001503 if (!(optimizing > 0) && pass0 == 2) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001504 if (forwref != NULL && globallineno == forwref->lineno) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001505 output_ins.forw_ref = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001506 do {
1507 output_ins.oprs[forwref->operand].opflags |=
1508 OPFLAG_FORWARD;
1509 forwref = saa_rstruct(forwrefs);
1510 } while (forwref != NULL
1511 && forwref->lineno == globallineno);
1512 } else
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001513 output_ins.forw_ref = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001514 }
1515
1516 if (!(optimizing > 0) && output_ins.forw_ref) {
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001517 if (passn == 1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001518 for (i = 0; i < output_ins.operands; i++) {
1519 if (output_ins.oprs[i].
1520 opflags & OPFLAG_FORWARD) {
1521 struct forwrefinfo *fwinf =
1522 (struct forwrefinfo *)
1523 saa_wstruct(forwrefs);
1524 fwinf->lineno = globallineno;
1525 fwinf->operand = i;
1526 }
1527 }
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001528 } else { /* passn > 1 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001529 /*
H. Peter Anvine2c80182005-01-15 22:15:51 +00001530 * Hack to prevent phase error in the code
1531 * rol ax,x
1532 * x equ 1
1533 *
1534 * If the second operand is a forward reference,
1535 * the UNITY property of the number 1 in that
1536 * operand is cancelled. Otherwise the above
1537 * sequence will cause a phase error.
1538 *
1539 * This hack means that the above code will
1540 * generate 286+ code.
1541 *
1542 * The forward reference will mean that the
1543 * operand will not have the UNITY property on
1544 * the first pass, so the pass behaviours will
1545 * be consistent.
1546 */
H. Peter Anvineba20a72002-04-30 20:53:55 +00001547
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001548 if (output_ins.operands >= 2 &&
H. Peter Anvin5a640e12007-05-29 23:57:12 +00001549 (output_ins.oprs[1].opflags & OPFLAG_FORWARD) &&
1550 !(IMMEDIATE & ~output_ins.oprs[1].type))
1551 {
1552 /* Remove special properties bits */
1553 output_ins.oprs[1].type &= ~REG_SMASK;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001554 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001555
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001556 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001557
H. Peter Anvine2c80182005-01-15 22:15:51 +00001558 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001559
H. Peter Anvine2c80182005-01-15 22:15:51 +00001560 /* forw_ref */
1561 if (output_ins.opcode == I_EQU) {
1562 if (pass1 == 1) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001563 /*
H. Peter Anvine2c80182005-01-15 22:15:51 +00001564 * Special `..' EQUs get processed in pass two,
1565 * except `..@' macro-processor EQUs which are done
1566 * in the normal place.
1567 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001568 if (!output_ins.label)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001569 report_error(ERR_NONFATAL,
1570 "EQU not preceded by label");
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001571
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001572 else if (output_ins.label[0] != '.' ||
1573 output_ins.label[1] != '.' ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001574 output_ins.label[2] == '@') {
1575 if (output_ins.operands == 1 &&
1576 (output_ins.oprs[0].type & IMMEDIATE) &&
1577 output_ins.oprs[0].wrt == NO_SEG) {
1578 int isext =
1579 output_ins.oprs[0].
1580 opflags & OPFLAG_EXTERN;
1581 def_label(output_ins.label,
1582 output_ins.oprs[0].segment,
1583 output_ins.oprs[0].offset, NULL,
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001584 false, isext, ofmt,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001585 report_error);
1586 } else if (output_ins.operands == 2
1587 && (output_ins.oprs[0].
1588 type & IMMEDIATE)
1589 && (output_ins.oprs[0].type & COLON)
1590 && output_ins.oprs[0].segment ==
1591 NO_SEG
1592 && output_ins.oprs[0].wrt == NO_SEG
1593 && (output_ins.oprs[1].
1594 type & IMMEDIATE)
1595 && output_ins.oprs[1].segment ==
1596 NO_SEG
1597 && output_ins.oprs[1].wrt ==
1598 NO_SEG) {
1599 def_label(output_ins.label,
1600 output_ins.oprs[0].
1601 offset | SEG_ABS,
1602 output_ins.oprs[1].offset, NULL,
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001603 false, false, ofmt,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001604 report_error);
1605 } else
1606 report_error(ERR_NONFATAL,
1607 "bad syntax for EQU");
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001608 }
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001609 } else {
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001610 /*
H. Peter Anvine2c80182005-01-15 22:15:51 +00001611 * Special `..' EQUs get processed here, except
1612 * `..@' macro processor EQUs which are done above.
1613 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001614 if (output_ins.label[0] == '.' &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001615 output_ins.label[1] == '.' &&
1616 output_ins.label[2] != '@') {
1617 if (output_ins.operands == 1 &&
1618 (output_ins.oprs[0].type & IMMEDIATE)) {
1619 define_label(output_ins.label,
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001620 output_ins.oprs[0].segment,
1621 output_ins.oprs[0].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 if (output_ins.operands == 2
1625 && (output_ins.oprs[0].
1626 type & IMMEDIATE)
1627 && (output_ins.oprs[0].type & COLON)
1628 && output_ins.oprs[0].segment ==
1629 NO_SEG
1630 && (output_ins.oprs[1].
1631 type & IMMEDIATE)
1632 && output_ins.oprs[1].segment ==
1633 NO_SEG) {
1634 define_label(output_ins.label,
1635 output_ins.oprs[0].
1636 offset | SEG_ABS,
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001637 output_ins.oprs[1].offset,
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001638 NULL, false, false, ofmt,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001639 report_error);
1640 } else
1641 report_error(ERR_NONFATAL,
1642 "bad syntax for EQU");
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001643 }
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001644 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001645 } else { /* instruction isn't an EQU */
H. Peter Anvineba20a72002-04-30 20:53:55 +00001646
H. Peter Anvine2c80182005-01-15 22:15:51 +00001647 if (pass1 == 1) {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001648
Charles Crayne5fbbc8c2007-11-07 19:03:46 -08001649 int64_t l = insn_size(location.segment, offs, sb, cpu,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001650 &output_ins, report_error);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001651
H. Peter Anvine2c80182005-01-15 22:15:51 +00001652 /* if (using_debug_info) && output_ins.opcode != -1) */
1653 if (using_debug_info)
1654 { /* fbk 03/25/01 */
1655 /* this is done here so we can do debug type info */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001656 int32_t typeinfo =
H. Peter Anvine2c80182005-01-15 22:15:51 +00001657 TYS_ELEMENTS(output_ins.operands);
1658 switch (output_ins.opcode) {
1659 case I_RESB:
1660 typeinfo =
1661 TYS_ELEMENTS(output_ins.oprs[0].
1662 offset) | TY_BYTE;
1663 break;
1664 case I_RESW:
1665 typeinfo =
1666 TYS_ELEMENTS(output_ins.oprs[0].
1667 offset) | TY_WORD;
1668 break;
1669 case I_RESD:
1670 typeinfo =
1671 TYS_ELEMENTS(output_ins.oprs[0].
1672 offset) | TY_DWORD;
1673 break;
1674 case I_RESQ:
1675 typeinfo =
1676 TYS_ELEMENTS(output_ins.oprs[0].
1677 offset) | TY_QWORD;
1678 break;
1679 case I_REST:
1680 typeinfo =
1681 TYS_ELEMENTS(output_ins.oprs[0].
1682 offset) | TY_TBYTE;
1683 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -07001684 case I_RESO:
1685 typeinfo =
1686 TYS_ELEMENTS(output_ins.oprs[0].
1687 offset) | TY_OWORD;
1688 break;
1689 case I_RESY:
1690 typeinfo =
1691 TYS_ELEMENTS(output_ins.oprs[0].
1692 offset) | TY_YWORD;
1693 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001694 case I_DB:
1695 typeinfo |= TY_BYTE;
1696 break;
1697 case I_DW:
1698 typeinfo |= TY_WORD;
1699 break;
1700 case I_DD:
1701 if (output_ins.eops_float)
1702 typeinfo |= TY_FLOAT;
1703 else
1704 typeinfo |= TY_DWORD;
1705 break;
1706 case I_DQ:
1707 typeinfo |= TY_QWORD;
1708 break;
1709 case I_DT:
1710 typeinfo |= TY_TBYTE;
1711 break;
H. Peter Anvin4408b622007-09-22 21:29:41 -07001712 case I_DO:
1713 typeinfo |= TY_OWORD;
1714 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -07001715 case I_DY:
1716 typeinfo |= TY_YWORD;
1717 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001718 default:
1719 typeinfo = TY_LABEL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001720
H. Peter Anvine2c80182005-01-15 22:15:51 +00001721 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001722
H. Peter Anvine2c80182005-01-15 22:15:51 +00001723 ofmt->current_dfmt->debug_typevalue(typeinfo);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001724
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001725 }
1726 if (l != -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001727 offs += l;
1728 SET_CURR_OFFS(offs);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001729 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001730 /*
H. Peter Anvine2c80182005-01-15 22:15:51 +00001731 * else l == -1 => invalid instruction, which will be
1732 * flagged as an error on pass 2
1733 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001734
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001735 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001736 offs += assemble(location.segment, offs, sb, cpu,
1737 &output_ins, ofmt, report_error,
1738 &nasmlist);
1739 SET_CURR_OFFS(offs);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001740
H. Peter Anvine2c80182005-01-15 22:15:51 +00001741 }
1742 } /* not an EQU */
1743 cleanup_insn(&output_ins);
1744 }
1745 nasm_free(line);
1746 location.offset = offs = GET_CURR_OFFS;
1747 } /* end while (line = preproc->getline... */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001748
H. Peter Anvine2c80182005-01-15 22:15:51 +00001749 if (pass1 == 2 && global_offset_changed)
1750 report_error(ERR_NONFATAL,
1751 "phase error detected at end of assembly.");
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001752
H. Peter Anvine2c80182005-01-15 22:15:51 +00001753 if (pass1 == 1)
1754 preproc->cleanup(1);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001755
H. Peter Anvine2c80182005-01-15 22:15:51 +00001756 if (pass1 == 1 && terminate_after_phase) {
1757 fclose(ofile);
1758 remove(outname);
1759 if (want_usage)
1760 usage();
1761 exit(1);
1762 }
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001763 if (passn >= pass_max - 2 ||
1764 (passn > 1 && !global_offset_changed))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001765 pass0++;
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001766 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001767
H. Peter Anvine2c80182005-01-15 22:15:51 +00001768 preproc->cleanup(0);
1769 nasmlist.cleanup();
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001770#if 1
H. Peter Anvine2c80182005-01-15 22:15:51 +00001771 if (optimizing > 0 && opt_verbose_info) /* -On and -Ov switches */
1772 fprintf(stdout,
H. Peter Anvin00835fe2008-01-08 23:03:57 -08001773 "info:: assembly required 1+%d+1 passes\n", passn-3);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001774#endif
H. Peter Anvine2c80182005-01-15 22:15:51 +00001775} /* exit from assemble_file (...) */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001776
H. Peter Anvin70055962007-10-11 00:05:31 -07001777static enum directives getkw(char **directive, char **value)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001778{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001779 char *p, *q, *buf;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001780
Michael K. Ter Louw1d392362003-08-15 22:25:53 +00001781 buf = *directive;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001782
H. Peter Anvincaa82a12002-04-30 21:03:11 +00001783 /* allow leading spaces or tabs */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001784 while (*buf == ' ' || *buf == '\t')
1785 buf++;
H. Peter Anvincaa82a12002-04-30 21:03:11 +00001786
H. Peter Anvine2c80182005-01-15 22:15:51 +00001787 if (*buf != '[')
1788 return 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001789
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001790 p = buf;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001791
H. Peter Anvine2c80182005-01-15 22:15:51 +00001792 while (*p && *p != ']')
1793 p++;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001794
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001795 if (!*p)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001796 return 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001797
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001798 q = p++;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001799
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001800 while (*p && *p != ';') {
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001801 if (!nasm_isspace(*p))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001802 return 0;
1803 p++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001804 }
1805 q[1] = '\0';
1806
H. Peter Anvine2c80182005-01-15 22:15:51 +00001807 *directive = p = buf + 1;
1808 while (*buf && *buf != ' ' && *buf != ']' && *buf != '\t')
1809 buf++;
1810 if (*buf == ']') {
1811 *buf = '\0';
1812 *value = buf;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001813 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001814 *buf++ = '\0';
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001815 while (nasm_isspace(*buf))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001816 buf++; /* beppu - skip leading whitespace */
1817 *value = buf;
1818 while (*buf != ']')
1819 buf++;
1820 *buf++ = '\0';
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001821 }
H. Peter Anvin62b24d72007-08-29 16:38:05 +00001822
1823 return bsii(*directive, directives, elements(directives));
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001824}
1825
Ed Berosetfa771012002-06-09 20:56:40 +00001826/**
1827 * gnu style error reporting
1828 * This function prints an error message to error_file in the
1829 * style used by GNU. An example would be:
1830 * file.asm:50: error: blah blah blah
H. Peter Anvin70653092007-10-19 14:42:29 -07001831 * where file.asm is the name of the file, 50 is the line number on
Ed Berosetfa771012002-06-09 20:56:40 +00001832 * which the error occurs (or is detected) and "error:" is one of
1833 * the possible optional diagnostics -- it can be "error" or "warning"
H. Peter Anvin70653092007-10-19 14:42:29 -07001834 * or something else. Finally the line terminates with the actual
Ed Berosetfa771012002-06-09 20:56:40 +00001835 * error message.
H. Peter Anvin70653092007-10-19 14:42:29 -07001836 *
1837 * @param severity the severity of the warning or error
Ed Berosetfa771012002-06-09 20:56:40 +00001838 * @param fmt the printf style format string
1839 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001840static void report_error_gnu(int severity, const char *fmt, ...)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001841{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001842 va_list ap;
1843
Ed Berosetfa771012002-06-09 20:56:40 +00001844 if (is_suppressed_warning(severity))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001845 return;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001846
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001847 if (severity & ERR_NOFILE)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001848 fputs("nasm: ", error_file);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001849 else {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001850 char *currentfile = NULL;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001851 int32_t lineno = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001852 src_get(&lineno, &currentfile);
Keith Kanios93f2e9a2007-04-14 00:10:59 +00001853 fprintf(error_file, "%s:%"PRId32": ", currentfile, lineno);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001854 nasm_free(currentfile);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001855 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001856 va_start(ap, fmt);
1857 report_error_common(severity, fmt, ap);
1858 va_end(ap);
Ed Berosetfa771012002-06-09 20:56:40 +00001859}
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001860
Ed Berosetfa771012002-06-09 20:56:40 +00001861/**
1862 * MS style error reporting
1863 * This function prints an error message to error_file in the
H. Peter Anvin70653092007-10-19 14:42:29 -07001864 * style used by Visual C and some other Microsoft tools. An example
Ed Berosetfa771012002-06-09 20:56:40 +00001865 * would be:
Ed Beroset6e61d0d2002-06-11 03:29:36 +00001866 * file.asm(50) : error: blah blah blah
H. Peter Anvin70653092007-10-19 14:42:29 -07001867 * where file.asm is the name of the file, 50 is the line number on
Ed Beroset6e61d0d2002-06-11 03:29:36 +00001868 * which the error occurs (or is detected) and "error:" is one of
1869 * the possible optional diagnostics -- it can be "error" or "warning"
H. Peter Anvin70653092007-10-19 14:42:29 -07001870 * or something else. Finally the line terminates with the actual
Ed Beroset6e61d0d2002-06-11 03:29:36 +00001871 * error message.
H. Peter Anvin70653092007-10-19 14:42:29 -07001872 *
1873 * @param severity the severity of the warning or error
Ed Berosetfa771012002-06-09 20:56:40 +00001874 * @param fmt the printf style format string
1875 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001876static void report_error_vc(int severity, const char *fmt, ...)
Ed Berosetfa771012002-06-09 20:56:40 +00001877{
1878 va_list ap;
1879
H. Peter Anvine2c80182005-01-15 22:15:51 +00001880 if (is_suppressed_warning(severity))
1881 return;
Ed Berosetfa771012002-06-09 20:56:40 +00001882
1883 if (severity & ERR_NOFILE)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001884 fputs("nasm: ", error_file);
Ed Berosetfa771012002-06-09 20:56:40 +00001885 else {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001886 char *currentfile = NULL;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001887 int32_t lineno = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001888 src_get(&lineno, &currentfile);
Keith Kanios93f2e9a2007-04-14 00:10:59 +00001889 fprintf(error_file, "%s(%"PRId32") : ", currentfile, lineno);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001890 nasm_free(currentfile);
Ed Berosetfa771012002-06-09 20:56:40 +00001891 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001892 va_start(ap, fmt);
1893 report_error_common(severity, fmt, ap);
1894 va_end(ap);
Ed Berosetfa771012002-06-09 20:56:40 +00001895}
1896
1897/**
1898 * check for supressed warning
H. Peter Anvin70653092007-10-19 14:42:29 -07001899 * checks for suppressed warning or pass one only warning and we're
Ed Berosetfa771012002-06-09 20:56:40 +00001900 * not in pass 1
1901 *
1902 * @param severity the severity of the warning or error
1903 * @return true if we should abort error/warning printing
1904 */
H. Peter Anvin2b046cf2008-01-22 14:08:36 -08001905static bool is_suppressed_warning(int severity)
Ed Berosetfa771012002-06-09 20:56:40 +00001906{
1907 /*
1908 * See if it's a suppressed warning.
1909 */
H. Peter Anvin2b046cf2008-01-22 14:08:36 -08001910 return (severity & ERR_MASK) == ERR_WARNING &&
1911 (((severity & ERR_WARN_MASK) != 0 &&
1912 suppressed[(severity & ERR_WARN_MASK) >> ERR_WARN_SHR]) ||
1913 /* See if it's a pass-one only warning and we're not in pass one. */
1914 ((severity & ERR_PASS1) && pass0 != 1));
Ed Berosetfa771012002-06-09 20:56:40 +00001915}
1916
1917/**
1918 * common error reporting
1919 * This is the common back end of the error reporting schemes currently
H. Peter Anvin70653092007-10-19 14:42:29 -07001920 * implemented. It prints the nature of the warning and then the
Ed Berosetfa771012002-06-09 20:56:40 +00001921 * specific error message to error_file and may or may not return. It
1922 * doesn't return if the error severity is a "panic" or "debug" type.
H. Peter Anvin70653092007-10-19 14:42:29 -07001923 *
1924 * @param severity the severity of the warning or error
Ed Berosetfa771012002-06-09 20:56:40 +00001925 * @param fmt the printf style format string
1926 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001927static void report_error_common(int severity, const char *fmt,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001928 va_list args)
Ed Berosetfa771012002-06-09 20:56:40 +00001929{
H. Peter Anvin7df04172008-06-10 18:27:38 -07001930 switch (severity & (ERR_MASK|ERR_NO_SEVERITY)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001931 case ERR_WARNING:
1932 fputs("warning: ", error_file);
1933 break;
1934 case ERR_NONFATAL:
1935 fputs("error: ", error_file);
1936 break;
1937 case ERR_FATAL:
1938 fputs("fatal: ", error_file);
1939 break;
1940 case ERR_PANIC:
1941 fputs("panic: ", error_file);
1942 break;
1943 case ERR_DEBUG:
1944 fputs("debug: ", error_file);
1945 break;
H. Peter Anvin7df04172008-06-10 18:27:38 -07001946 default:
1947 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001948 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001949
H. Peter Anvine2c80182005-01-15 22:15:51 +00001950 vfprintf(error_file, fmt, args);
H. Peter Anvind1fb15c2007-11-13 09:37:59 -08001951 putc('\n', error_file);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001952
1953 if (severity & ERR_USAGE)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001954 want_usage = true;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001955
1956 switch (severity & ERR_MASK) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001957 case ERR_DEBUG:
1958 /* no further action, by definition */
1959 break;
H. Peter Anvinb030c922007-11-13 11:31:15 -08001960 case ERR_WARNING:
1961 if (!suppressed[0]) /* Treat warnings as errors */
1962 terminate_after_phase = true;
1963 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001964 case ERR_NONFATAL:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001965 terminate_after_phase = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001966 break;
1967 case ERR_FATAL:
1968 if (ofile) {
1969 fclose(ofile);
1970 remove(outname);
1971 }
1972 if (want_usage)
1973 usage();
1974 exit(1); /* instantly die */
1975 break; /* placate silly compilers */
1976 case ERR_PANIC:
1977 fflush(NULL);
1978 /* abort(); *//* halt, catch fire, and dump core */
1979 exit(3);
1980 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001981 }
1982}
1983
H. Peter Anvin734b1882002-04-30 21:01:08 +00001984static void usage(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001985{
H. Peter Anvin620515a2002-04-30 20:57:38 +00001986 fputs("type `nasm -h' for help\n", error_file);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001987}
1988
H. Peter Anvin734b1882002-04-30 21:01:08 +00001989static void register_output_formats(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001990{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001991 ofmt = ofmt_register(report_error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001992}
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001993
1994#define BUF_DELTA 512
1995
1996static FILE *no_pp_fp;
1997static efunc no_pp_err;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001998static ListGen *no_pp_list;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001999static int32_t no_pp_lineinc;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002000
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002001static void no_pp_reset(char *file, int pass, efunc error, evalfunc eval,
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07002002 ListGen * listgen, StrList **deplist)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002003{
2004 src_set_fname(nasm_strdup(file));
2005 src_set_linnum(0);
2006 no_pp_lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002007 no_pp_err = error;
2008 no_pp_fp = fopen(file, "r");
2009 if (!no_pp_fp)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002010 no_pp_err(ERR_FATAL | ERR_NOFILE,
2011 "unable to open input file `%s'", file);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002012 no_pp_list = listgen;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002013 (void)pass; /* placate compilers */
2014 (void)eval; /* placate compilers */
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07002015
2016 if (deplist) {
2017 StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
2018 sl->next = NULL;
2019 strcpy(sl->str, file);
2020 *deplist = sl;
2021 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002022}
2023
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002024static char *no_pp_getline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002025{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002026 char *buffer, *p, *q;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002027 int bufsize;
2028
2029 bufsize = BUF_DELTA;
2030 buffer = nasm_malloc(BUF_DELTA);
H. Peter Anvineba20a72002-04-30 20:53:55 +00002031 src_set_linnum(src_get_linnum() + no_pp_lineinc);
2032
H. Peter Anvine2c80182005-01-15 22:15:51 +00002033 while (1) { /* Loop to handle %line */
H. Peter Anvineba20a72002-04-30 20:53:55 +00002034
H. Peter Anvine2c80182005-01-15 22:15:51 +00002035 p = buffer;
2036 while (1) { /* Loop to handle long lines */
2037 q = fgets(p, bufsize - (p - buffer), no_pp_fp);
2038 if (!q)
2039 break;
2040 p += strlen(p);
2041 if (p > buffer && p[-1] == '\n')
2042 break;
2043 if (p - buffer > bufsize - 10) {
2044 int offset;
2045 offset = p - buffer;
2046 bufsize += BUF_DELTA;
2047 buffer = nasm_realloc(buffer, bufsize);
2048 p = buffer + offset;
2049 }
2050 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00002051
H. Peter Anvine2c80182005-01-15 22:15:51 +00002052 if (!q && p == buffer) {
2053 nasm_free(buffer);
2054 return NULL;
2055 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00002056
H. Peter Anvine2c80182005-01-15 22:15:51 +00002057 /*
2058 * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
2059 * them are present at the end of the line.
2060 */
2061 buffer[strcspn(buffer, "\r\n\032")] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +00002062
H. Peter Anvin0a98f602007-10-03 21:22:16 -07002063 if (!nasm_strnicmp(buffer, "%line", 5)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002064 int32_t ln;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002065 int li;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002066 char *nm = nasm_malloc(strlen(buffer));
Keith Kanios93f2e9a2007-04-14 00:10:59 +00002067 if (sscanf(buffer + 5, "%"PRId32"+%d %s", &ln, &li, nm) == 3) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002068 nasm_free(src_set_fname(nm));
2069 src_set_linnum(ln);
2070 no_pp_lineinc = li;
2071 continue;
2072 }
2073 nasm_free(nm);
2074 }
2075 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002076 }
2077
H. Peter Anvine2c80182005-01-15 22:15:51 +00002078 no_pp_list->line(LIST_READ, buffer);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002079
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002080 return buffer;
2081}
2082
H. Peter Anvine2c80182005-01-15 22:15:51 +00002083static void no_pp_cleanup(int pass)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002084{
Keith Kaniosc7ae18d2007-04-14 00:46:25 +00002085 (void)pass; /* placate GCC */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002086 fclose(no_pp_fp);
2087}
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002088
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002089static uint32_t get_cpu(char *value)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002090{
H. Peter Anvine2c80182005-01-15 22:15:51 +00002091 if (!strcmp(value, "8086"))
2092 return IF_8086;
2093 if (!strcmp(value, "186"))
2094 return IF_186;
2095 if (!strcmp(value, "286"))
2096 return IF_286;
2097 if (!strcmp(value, "386"))
2098 return IF_386;
2099 if (!strcmp(value, "486"))
2100 return IF_486;
2101 if (!strcmp(value, "586") || !nasm_stricmp(value, "pentium"))
2102 return IF_PENT;
2103 if (!strcmp(value, "686") ||
2104 !nasm_stricmp(value, "ppro") ||
2105 !nasm_stricmp(value, "pentiumpro") || !nasm_stricmp(value, "p2"))
2106 return IF_P6;
2107 if (!nasm_stricmp(value, "p3") || !nasm_stricmp(value, "katmai"))
2108 return IF_KATMAI;
2109 if (!nasm_stricmp(value, "p4") || /* is this right? -- jrc */
2110 !nasm_stricmp(value, "willamette"))
2111 return IF_WILLAMETTE;
2112 if (!nasm_stricmp(value, "prescott"))
2113 return IF_PRESCOTT;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002114 if (!nasm_stricmp(value, "x64") ||
2115 !nasm_stricmp(value, "x86-64"))
H. Peter Anvin0db11e22007-04-17 20:23:11 +00002116 return IF_X86_64;
H. Peter Anvin3ab8de62002-05-28 01:25:06 +00002117 if (!nasm_stricmp(value, "ia64") ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00002118 !nasm_stricmp(value, "ia-64") ||
2119 !nasm_stricmp(value, "itanium") ||
2120 !nasm_stricmp(value, "itanic") || !nasm_stricmp(value, "merced"))
2121 return IF_IA64;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002122
H. Peter Anvine2c80182005-01-15 22:15:51 +00002123 report_error(pass0 < 2 ? ERR_NONFATAL : ERR_FATAL,
2124 "unknown 'cpu' type");
H. Peter Anvin734b1882002-04-30 21:01:08 +00002125
H. Peter Anvine2c80182005-01-15 22:15:51 +00002126 return IF_PLEVEL; /* the maximum level */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002127}
2128
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002129static int get_bits(char *value)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002130{
2131 int i;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002132
H. Peter Anvine2c80182005-01-15 22:15:51 +00002133 if ((i = atoi(value)) == 16)
2134 return i; /* set for a 16-bit segment */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002135 else if (i == 32) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002136 if (cpu < IF_386) {
2137 report_error(ERR_NONFATAL,
2138 "cannot specify 32-bit segment on processor below a 386");
2139 i = 16;
2140 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00002141 } else if (i == 64) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +00002142 if (cpu < IF_X86_64) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002143 report_error(ERR_NONFATAL,
2144 "cannot specify 64-bit segment on processor below an x86-64");
2145 i = 16;
2146 }
2147 if (i != maxbits) {
2148 report_error(ERR_NONFATAL,
2149 "%s output format does not support 64-bit code",
2150 ofmt->shortname);
2151 i = 16;
2152 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002153 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002154 report_error(pass0 < 2 ? ERR_NONFATAL : ERR_FATAL,
Keith Kaniosb7a89542007-04-12 02:40:54 +00002155 "`%s' is not a valid segment size; must be 16, 32 or 64",
H. Peter Anvine2c80182005-01-15 22:15:51 +00002156 value);
2157 i = 16;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002158 }
2159 return i;
2160}
2161
2162/* end of nasm.c */