summaryrefslogtreecommitdiff
path: root/asm
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2019-08-10 06:45:12 -0700
committerH. Peter Anvin <hpa@zytor.com>2019-08-10 06:45:12 -0700
commit59d4ccc2b06a25e30a4ba0a62ad64905d88e562b (patch)
tree2ddfe78a83a02388197ac9d1db1032d51a8da715 /asm
parent06335873ae360054ae08c67762cbe3d8ee9ca489 (diff)
downloadnasm-59d4ccc2b06a25e30a4ba0a62ad64905d88e562b.tar.gz
Add %pragma list options
Add a %pragma to set (or clear) listing options. It only takes effect on the next assembly pass, however! Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'asm')
-rw-r--r--asm/directiv.dat5
-rw-r--r--asm/listing.c44
-rw-r--r--asm/listing.h28
-rw-r--r--asm/nasm.c26
-rw-r--r--asm/pragma.c3
5 files changed, 88 insertions, 18 deletions
diff --git a/asm/directiv.dat b/asm/directiv.dat
index 185568a6..4b0ca3f0 100644
--- a/asm/directiv.dat
+++ b/asm/directiv.dat
@@ -95,7 +95,10 @@ lprefix
lsuffix
limit
-; --- Pragma operations
+; --- Listing pragmas
+options
+
+; --- Backend pragmas
subsections_via_symbols ; macho
no_dead_strip ; macho
maxdump ; dbg
diff --git a/asm/listing.c b/asm/listing.c
index 1104d8ea..224af714 100644
--- a/asm/listing.c
+++ b/asm/listing.c
@@ -61,10 +61,12 @@ static const char xdigit[] = "0123456789ABCDEF";
#define HEX(a,b) (*(a)=xdigit[((b)>>4)&15],(a)[1]=xdigit[(b)&15]);
+uint64_t list_options, active_list_options;
+
static char listline[LIST_MAX_LEN];
static bool listlinep;
-struct strlist *list_errors;
+static struct strlist *list_errors;
static char listdata[2 * LIST_INDENT]; /* we need less than that actually */
static int32_t listoffset;
@@ -395,6 +397,46 @@ static void list_set_offset(uint64_t offset)
listoffset = offset;
}
+static void list_update_options(const char *str)
+{
+ bool state = true;
+ unsigned char c;
+ uint64_t mask;
+
+ while ((c = *str++)) {
+ switch (c) {
+ case '+':
+ state = true;
+ break;
+ case '-':
+ state = false;
+ break;
+ default:
+ c -= '@';
+ if (c > 63)
+ break;
+ mask = UINT64_C(1) << c;
+ if (state)
+ list_options |= mask;
+ else
+ list_options &= ~mask;
+ break;
+ }
+ }
+}
+
+enum directive_result list_pragma(const struct pragma *pragma)
+{
+ switch (pragma->opcode) {
+ case D_OPTIONS:
+ list_update_options(pragma->tail);
+ return DIRR_OK;
+
+ default:
+ return DIRR_UNKNOWN;
+ }
+}
+
static const struct lfmt nasm_list = {
list_init,
list_cleanup,
diff --git a/asm/listing.h b/asm/listing.h
index 9d4a3353..88931556 100644
--- a/asm/listing.h
+++ b/asm/listing.h
@@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------- *
- *
+ *
* Copyright 1996-2019 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
@@ -14,7 +14,7 @@
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
@@ -31,13 +31,15 @@
*
* ----------------------------------------------------------------------- */
-/*
+/*
* listing.h header file for listing.c
*/
#ifndef NASM_LISTING_H
#define NASM_LISTING_H
+#include "nasm.h"
+
/*
* List-file generators should look like this:
*/
@@ -113,7 +115,15 @@ struct lfmt {
extern const struct lfmt *lfmt;
extern bool user_nolist;
-extern uint64_t active_list_options; /* Simply a bitmask of ASCII-64 */
+
+/*
+ * list_options are the requested options; active_list_options gets
+ * set when a pass starts.
+ *
+ * These are simple bitmasks of ASCII-64 mapping directly to option
+ * letters.
+ */
+extern uint64_t list_options, active_list_options;
static inline bool list_option(char x)
{
@@ -123,4 +133,14 @@ static inline bool list_option(char x)
return unlikely(active_list_options & (UINT64_C(1) << p));
}
+/* We can't test this using active_list_options for obvious reasons... */
+static inline bool list_on_every_pass(void)
+{
+ const unsigned int p = 'p' - '@';
+ return unlikely(list_options & (UINT64_C(1) << p));
+}
+
+/* Pragma handler */
+enum directive_result list_pragma(const struct pragma *);
+
#endif
diff --git a/asm/nasm.c b/asm/nasm.c
index 517ac187..bd6ccf83 100644
--- a/asm/nasm.c
+++ b/asm/nasm.c
@@ -117,9 +117,6 @@ const char *outname;
static const char *listname;
static const char *errname;
-static uint64_t list_options;
-uint64_t active_list_options; /* Set during the final pass only */
-
static int64_t globallineno; /* for forward-reference tracking */
const struct ofmt *ofmt = &OF_DEFAULT;
@@ -1020,10 +1017,6 @@ static bool process_arg(char *p, char *q, int pass)
list_options |= (UINT64_C(1) << p);
param++;
}
- if (list_options & (UINT64_C(1) << ('p' - '@'))) {
- /* Do listings for every pass */
- active_list_options = list_options;
- }
}
break;
@@ -1601,9 +1594,20 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
globalbits = cmd_sb; /* set 'bits' to command line default */
cpu = cmd_cpu;
- if (pass_final() || list_option('p')) {
- active_list_options = list_options;
- lfmt->init(listname);
+ if (listname) {
+ if (pass_final() || list_on_every_pass()) {
+ active_list_options = list_options;
+ lfmt->init(listname);
+ } else if (active_list_options) {
+ /*
+ * Looks like we used the list engine on a previous pass,
+ * but now it is turned off, presumably via %pragma -p
+ */
+ lfmt->cleanup();
+ if (!keep_all)
+ remove(listname);
+ active_list_options = 0;
+ }
}
in_absolute = false;
@@ -1705,8 +1709,8 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
nasm_info("assembly required 1+%"PRId64"+2 passes\n", pass_count()-3);
}
- strlist_free(&warn_list);
lfmt->cleanup();
+ strlist_free(&warn_list);
}
/**
diff --git a/asm/pragma.c b/asm/pragma.c
index 43de6e2c..8cfbafb8 100644
--- a/asm/pragma.c
+++ b/asm/pragma.c
@@ -45,6 +45,7 @@
#include "nasmlib.h"
#include "assemble.h"
#include "error.h"
+#include "listing.h"
static enum directive_result output_pragma(const struct pragma *pragma);
static enum directive_result limit_pragma(const struct pragma *pragma);
@@ -86,7 +87,7 @@ static struct pragma_facility global_pragmas[] =
{
{ "asm", NULL },
{ "limit", limit_pragma },
- { "list", NULL },
+ { "list", list_pragma },
{ "file", NULL },
{ "input", NULL },