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>
This commit is contained in:
H. Peter Anvin 2019-08-10 06:45:12 -07:00
parent 06335873ae
commit 59d4ccc2b0
6 changed files with 90 additions and 18 deletions

View File

@ -95,7 +95,10 @@ lprefix
lsuffix
limit
; --- Pragma operations
; --- Listing pragmas
options
; --- Backend pragmas
subsections_via_symbols ; macho
no_dead_strip ; macho
maxdump ; dbg

View File

@ -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,

View File

@ -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

View File

@ -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);
}
/**

View File

@ -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 },

View File

@ -42,6 +42,8 @@ bar equ 0xcc
%endmacro
%pragma list options +bempf
;; k_rr op kreg size_suffix size_name
%macro k_rr 4
%1%3 %2,%2