mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-10-10 00:25:06 -04:00
Add %defstr, %idefstr
Add %defstr and %idefstr, to define a macro as a quoted string.
This commit is contained in:
1
CHANGES
1
CHANGES
@@ -20,6 +20,7 @@
|
|||||||
* %substr can now be used to get other than one-character substrings.
|
* %substr can now be used to get other than one-character substrings.
|
||||||
* New type of character/string constants, using backquotes (`...`),
|
* New type of character/string constants, using backquotes (`...`),
|
||||||
which support C-style escape sequences.
|
which support C-style escape sequences.
|
||||||
|
* %defstr and %idefstr to stringize macro definitions before creation.
|
||||||
|
|
||||||
2.02
|
2.02
|
||||||
----
|
----
|
||||||
|
@@ -1957,7 +1957,7 @@ You can \i{pre-define} single-line macros using the `-d' option on
|
|||||||
the NASM command line: see \k{opt-d}.
|
the NASM command line: see \k{opt-d}.
|
||||||
|
|
||||||
|
|
||||||
\S{xdefine} Enhancing %define: \I\c{%ixdefine}\i\c{%xdefine}
|
\S{xdefine} Enhancing \c{%define}: \I\c{%ixdefine}\i\c{%xdefine}
|
||||||
|
|
||||||
To have a reference to an embedded single-line macro resolved at the
|
To have a reference to an embedded single-line macro resolved at the
|
||||||
time that it is embedded, as opposed to when the calling macro is
|
time that it is embedded, as opposed to when the calling macro is
|
||||||
@@ -2074,7 +2074,7 @@ instruction has been used as a label in older code. For example:
|
|||||||
|
|
||||||
\c %idefine pause $%? ; Hide the PAUSE instruction
|
\c %idefine pause $%? ; Hide the PAUSE instruction
|
||||||
|
|
||||||
\S{undef} Undefining macros: \i\c{%undef}
|
\S{undef} Undefining Macros: \i\c{%undef}
|
||||||
|
|
||||||
Single-line macros can be removed with the \c{%undef} command. For
|
Single-line macros can be removed with the \c{%undef} command. For
|
||||||
example, the following sequence:
|
example, the following sequence:
|
||||||
@@ -2121,6 +2121,27 @@ a relocatable reference such as a code or data address, or anything
|
|||||||
involving a register).
|
involving a register).
|
||||||
|
|
||||||
|
|
||||||
|
\S{defstr} Defining Strings: \I\c{%idefstr}\i\c{%defstr}
|
||||||
|
|
||||||
|
\c{%defstr}, and its case-insensitive counterpart \c{%idefstr}, define
|
||||||
|
or redefine a single-line macro without parameters, but converts the
|
||||||
|
entire right-hand side, after macro expansion, to a quoted string
|
||||||
|
before definition.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
\c %defstr test TEST
|
||||||
|
|
||||||
|
is equivalent to
|
||||||
|
|
||||||
|
\c %define test 'TEST'
|
||||||
|
|
||||||
|
This can be used, for example, with the \c{%!} construct (see
|
||||||
|
\k{getenv}):
|
||||||
|
|
||||||
|
\c %defstr PATH %!PATH ; The operating system PATH variable
|
||||||
|
|
||||||
|
|
||||||
\H{strlen} \i{String Handling in Macros}: \i\c{%strlen} and \i\c{%substr}
|
\H{strlen} \i{String Handling in Macros}: \i\c{%strlen} and \i\c{%substr}
|
||||||
|
|
||||||
It's often useful to be able to handle strings in macros. NASM
|
It's often useful to be able to handle strings in macros. NASM
|
||||||
@@ -3637,18 +3658,9 @@ For example, suppose that you have an environment variable \c{FOO}, and
|
|||||||
you want the contents of \c{FOO} to be embedded in your program. You
|
you want the contents of \c{FOO} to be embedded in your program. You
|
||||||
could do that as follows:
|
could do that as follows:
|
||||||
|
|
||||||
\c %define FOO %!FOO
|
\c %defstr FOO %!FOO
|
||||||
\c %define quote '
|
|
||||||
\c
|
|
||||||
\c tmpstr db quote FOO quote
|
|
||||||
|
|
||||||
At the time of writing, this will generate an "unterminated string"
|
See \k{defstr} for notes on the \c{%defstr} directive.
|
||||||
warning at the time of defining "quote", and it will add a space
|
|
||||||
before and after the string that is read in. I was unable to find
|
|
||||||
a simple workaround (although a workaround can be created using a
|
|
||||||
multi-line macro), so I believe that you will need to either learn how
|
|
||||||
to create more complex macros, or allow for the extra spaces if you
|
|
||||||
make use of this feature in that way.
|
|
||||||
|
|
||||||
|
|
||||||
\C{directive} \i{Assembler Directives}
|
\C{directive} \i{Assembler Directives}
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
%assign
|
%assign
|
||||||
%clear
|
%clear
|
||||||
%define
|
%define
|
||||||
|
%defstr
|
||||||
%depend
|
%depend
|
||||||
%elif*
|
%elif*
|
||||||
%else
|
%else
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
%exitrep
|
%exitrep
|
||||||
%iassign
|
%iassign
|
||||||
%idefine
|
%idefine
|
||||||
|
%idefstr
|
||||||
%if*
|
%if*
|
||||||
%imacro
|
%imacro
|
||||||
%include
|
%include
|
||||||
|
45
preproc.c
45
preproc.c
@@ -1028,7 +1028,7 @@ static Token *delete_Token(Token * t)
|
|||||||
* If expand_locals is not zero, identifiers of the form "%$*xxx"
|
* If expand_locals is not zero, identifiers of the form "%$*xxx"
|
||||||
* will be transformed into ..@ctxnum.xxx
|
* will be transformed into ..@ctxnum.xxx
|
||||||
*/
|
*/
|
||||||
static char *detoken(Token * tlist, int expand_locals)
|
static char *detoken(Token * tlist, bool expand_locals)
|
||||||
{
|
{
|
||||||
Token *t;
|
Token *t;
|
||||||
int len;
|
int len;
|
||||||
@@ -2647,6 +2647,49 @@ static int do_directive(Token * tline)
|
|||||||
free_tlist(origline);
|
free_tlist(origline);
|
||||||
return DIRECTIVE_FOUND;
|
return DIRECTIVE_FOUND;
|
||||||
|
|
||||||
|
case PP_DEFSTR:
|
||||||
|
case PP_IDEFSTR:
|
||||||
|
casesense = (i == PP_DEFSTR);
|
||||||
|
|
||||||
|
tline = tline->next;
|
||||||
|
skip_white_(tline);
|
||||||
|
tline = expand_id(tline);
|
||||||
|
if (!tline || (tline->type != TOK_ID &&
|
||||||
|
(tline->type != TOK_PREPROC_ID ||
|
||||||
|
tline->text[1] != '$'))) {
|
||||||
|
error(ERR_NONFATAL, "`%s' expects a macro identifier",
|
||||||
|
pp_directives[i]);
|
||||||
|
free_tlist(origline);
|
||||||
|
return DIRECTIVE_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = get_ctx(tline->text, false);
|
||||||
|
|
||||||
|
mname = tline->text;
|
||||||
|
last = tline;
|
||||||
|
tline = expand_smacro(tline->next);
|
||||||
|
last->next = NULL;
|
||||||
|
|
||||||
|
while (tok_type_(tline, TOK_WHITESPACE))
|
||||||
|
tline = delete_Token(tline);
|
||||||
|
|
||||||
|
p = detoken(tline, false);
|
||||||
|
macro_start = nasm_malloc(sizeof(*macro_start));
|
||||||
|
macro_start->next = NULL;
|
||||||
|
macro_start->text = nasm_quote(p, strlen(p));
|
||||||
|
macro_start->type = TOK_STRING;
|
||||||
|
macro_start->mac = NULL;
|
||||||
|
nasm_free(p);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We now have a macro name, an implicit parameter count of
|
||||||
|
* zero, and a string token to use as an expansion. Create
|
||||||
|
* and store an SMacro.
|
||||||
|
*/
|
||||||
|
define_smacro(ctx, mname, casesense, 0, macro_start);
|
||||||
|
free_tlist(origline);
|
||||||
|
return DIRECTIVE_FOUND;
|
||||||
|
|
||||||
case PP_PATHSEARCH:
|
case PP_PATHSEARCH:
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
Reference in New Issue
Block a user