pragma: use the directives hash to look up directive names

Very few things have any desire to do its own string parsing, and the
directives hash is already a plain string-to-numbers O(1) hash.  The
namespace is small enough that even if it makes some switch statements
compile a bit larger there is no real reason to have separate hashes,
even if the actual code as opposed to the data structure was shared.

So, for right now, just throw them together in one big happy pot.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin 2017-03-08 20:05:41 -08:00
parent d49a3bf6db
commit d9493fa440
3 changed files with 85 additions and 26 deletions

View File

@ -31,7 +31,18 @@
;;
;; --------------------------------------------------------------------------
;;
;; List of global NASM directives (including backend-specific ones)
;; List of global NASM directives and pragma operations codes
;;
;; ALL directives, including backend-specific, need to be added here.
;;
;; %pragma operation keywords (the second word, after facility) MAY
;; be added here too to assist in parsing, but it is not required.
;; See the definition of struct pragma in include/nasm.h.
;;
;; The same keyword can be used as a directive and as a pragma
;; operation, or as pragma operations in different namespaces. The
;; same D_ constant will be used for both, and this is perfectly
;; acceptable.
;;
; --- Global directives
@ -63,3 +74,5 @@ osabi ; outelf
safeseh ; outcoff
uppercase ; outieee, outobj
subsections_via_symbols ; outmacho
; --- Pragma operations

View File

@ -125,7 +125,38 @@ found_it:
return true;
pragma->facility = pf;
pf->handler(pragma);
switch (pf->handler(pragma)) {
case DIRR_UNKNOWN:
switch (pragma->opcode) {
case D_none:
nasm_error(ERR_WARNING|ERR_PASS2|ERR_WARN_BAD_PRAGMA,
"empty %%pragma %s", pragma->facility_name);
break;
default:
nasm_error(ERR_WARNING|ERR_PASS2|ERR_WARN_UNKNOWN_PRAGMA,
"unknown %%pragma %s %s",
pragma->facility_name, pragma->opname);
break;
}
break;
case DIRR_OK:
case DIRR_ERROR:
break; /* Nothing to do */
case DIRR_BADPARAM:
/*
* This one is an error. Don't use it if forward compatibility
* would be compromised, as opposed to an inherent error.
*/
nasm_error(ERR_NONFATAL, "bad argument to %%pragma %s %s",
pragma->facility_name, pragma->opname);
break;
default:
panic();
}
return true;
}
@ -143,12 +174,18 @@ void process_pragma(char *str)
return; /* Empty pragma */
}
pragma.operation = nasm_get_word(p, &p);
if (!pragma.operation) {
nasm_error(ERR_WARNING|ERR_PASS2|ERR_WARN_BAD_PRAGMA,
"pragma directive contains only facility namespace");
return; /* Facility name only */
}
/*
* The facility "ignore" means just that; don't even complain of
* the absence of an operation.
*/
if (!nasm_stricmp(pragma.facility_name, "ignore"))
return;
pragma.opname = nasm_get_word(p, &p);
if (!pragma.opname)
pragma.opcode = D_none;
else
pragma.opcode = find_directive(pragma.opname);
pragma.tail = nasm_skip_spaces(p);

View File

@ -684,11 +684,29 @@ enum geninfo { GI_SWITCH };
/* Instruction flags type: IF_* flags are defined in insns.h */
typedef uint64_t iflags_t;
/*
* What to return from a directive- or pragma-handling function.
* Currently DIRR_OK and DIRR_ERROR are treated the same way;
* in both cases the backend is expected to produce the appropriate
* error message on its own.
*
* DIRR_BADPARAM causes a generic error message to be printed. Note
* that it is an error, not a warning, even in the case of pragmas;
* don't use it where forward compatiblity would be compromised
* (instead consider adding a DIRR_WARNPARAM.)
*/
enum directive_result {
DIRR_UNKNOWN, /* Directive not handled by backend */
DIRR_OK, /* Directive processed */
DIRR_ERROR, /* Directive processed unsuccessfully */
DIRR_BADPARAM /* Print bad argument error message */
};
/*
* A pragma facility: this structure is used to request passing a
* parsed pragma directive for a specific facility. If the handler is
* NULL then this pragma facility is recognized but ignored; pragma
* processing stops at that point, as if the handler had returned true.
* processing stops at that point.
*
* Note that the handler is passed a pointer to the facility structure
* as part of the struct pragma.
@ -697,33 +715,24 @@ struct pragma;
struct pragma_facility {
const char *name;
void (*handler)(const struct pragma *);
enum directive_result (*handler)(const struct pragma *);
};
/*
* This structure defines how a pragma directive is passed to a
* facility. This structure may be augmented in the future.
*
* Any facility MAY, but is not required to, add its operations
* keywords or a subset thereof into asm/directiv.dat, in which case
* the "opcode" field will be set to the corresponding D_ constant
* from directiv.h; otherwise it will be D_unknown.
*/
struct pragma {
const struct pragma_facility *facility;
const char *facility_name; /* Facility name exactly as entered by user */
const char *operation; /* First word after the facility name */
const char *opname; /* First word after the facility name */
const char *tail; /* Anything after the operation */
};
/*
* What to return from a directive-handling function.
* Currently DIRR_OK and DIRR_ERROR are treated the same way;
* in both cases the backend is expected to produce the appropriate
* error message on its own.
*
* DIRR_BADPARAM causes a generic error message to be printed.
*/
enum directive_result {
DIRR_UNKNOWN, /* Directive not handled by backend */
DIRR_OK, /* Directive processed */
DIRR_ERROR, /* Directive processed unsuccessfully */
DIRR_BADPARAM /* Print bad argument error message */
enum directives opcode; /* Operation as a D_ directives constant */
};
/*