From cbf768d67d5540681df5e6ea41fe1fb270c95eec Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sat, 16 Feb 2008 16:41:25 -0800 Subject: [PATCH] Implement %iftoken, test for a single token Implement %iftoken, a test for a single token. This is useful in cases using %+ to splice a macro-provided token. --- doc/nasmdoc.src | 16 ++++++- pptok.dat | 1 + preproc.c | 16 ++++++- test/iftoken.asm | 108 +++++++++++++++++++++++++++++++++++++++++++++++ test/iftoken.pl | 19 +++++++++ 5 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 test/iftoken.asm create mode 100755 test/iftoken.pl diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src index e0e44f45..ebb0f159 100644 --- a/doc/nasmdoc.src +++ b/doc/nasmdoc.src @@ -2659,7 +2659,6 @@ Like most other \c{%if} constructs, \c{%ifidn} has a counterpart Similarly, \c{%ifidni} has counterparts \i\c{%elifidni}, \i\c{%ifnidni} and \i\c{%elifnidni}. - \S{iftyp} \i\c{%ifid}, \i\c{%ifnum}, \i\c{%ifstr}: Testing Token Types\I{testing, token types} @@ -2721,6 +2720,21 @@ which case, all but the first two would be lumped together into The usual \c{%elifXXX}, \c{%ifnXXX} and \c{%elifnXXX} versions exist for each of \c{%ifid}, \c{%ifnum} and \c{%ifstr}. +\S{iftoken} \i\c{%iftoken}: Test For A Single Token + +Some macros will want to do different things depending on if it is +passed a single token (e.g. paste it to something else using \c{%+}) +versus a multi-token sequence. + +The conditional assembly construct \c{%iftoken} assembles the +subsequent code if and only if the expanded parameters consist of +exactly one token, possibly surrounded by whitespace. + +For example, \c{1} will assemble the subsequent code, but \c{-1} will +not (\c{-} being an operator.) + +The usual \i\c{%eliftoken}, \i\c\{%ifntoken}, and \i\c{%elifntoken} +variants are also provided. \S{pperror} \i\c{%error}: Reporting \i{User-Defined Errors} diff --git a/pptok.dat b/pptok.dat index 1c07d4b2..f9bfb43c 100644 --- a/pptok.dat +++ b/pptok.dat @@ -10,6 +10,7 @@ *idni *macro *num +*token *str %arg %assign diff --git a/preproc.c b/preproc.c index 841ca202..b8b6ff2f 100644 --- a/preproc.c +++ b/preproc.c @@ -1594,7 +1594,21 @@ static bool if_condition(Token * tline, enum preproc_token ct) !t->text[1])) t = t->next; - j = t && t->type == needtype; + j = tok_type_(t, needtype); + break; + + case PPC_IFTOKEN: + t = tline = expand_smacro(tline); + while (tok_type_(t, TOK_WHITESPACE)) + t = t->next; + + j = false; + if (t) { + t = t->next; /* Skip the actual token */ + while (tok_type_(t, TOK_WHITESPACE)) + t = t->next; + j = !t; /* Should be nothing left */ + } break; case PPC_IF: diff --git a/test/iftoken.asm b/test/iftoken.asm new file mode 100644 index 00000000..c53c74c5 --- /dev/null +++ b/test/iftoken.asm @@ -0,0 +1,108 @@ + db 'N "1": ' +%iftoken 1 + db 'Yes', 10 +%else + db 'No', 10 +%endif + db 'C "1": ' +%iftoken 1 ; With a comment! + db 'Yes', 10 +%else + db 'No', 10 +%endif + db 'N "+1": ' +%iftoken +1 + db 'Yes', 10 +%else + db 'No', 10 +%endif + db 'C "+1": ' +%iftoken +1 ; With a comment! + db 'Yes', 10 +%else + db 'No', 10 +%endif + db 'N "1 2": ' +%iftoken 1 2 + db 'Yes', 10 +%else + db 'No', 10 +%endif + db 'C "1 2": ' +%iftoken 1 2 ; With a comment! + db 'Yes', 10 +%else + db 'No', 10 +%endif + db 'N "1,2": ' +%iftoken 1,2 + db 'Yes', 10 +%else + db 'No', 10 +%endif + db 'C "1,2": ' +%iftoken 1,2 ; With a comment! + db 'Yes', 10 +%else + db 'No', 10 +%endif + db 'N "foo": ' +%iftoken foo + db 'Yes', 10 +%else + db 'No', 10 +%endif + db 'C "foo": ' +%iftoken foo ; With a comment! + db 'Yes', 10 +%else + db 'No', 10 +%endif + db 'N "foo bar": ' +%iftoken foo bar + db 'Yes', 10 +%else + db 'No', 10 +%endif + db 'C "foo bar": ' +%iftoken foo bar ; With a comment! + db 'Yes', 10 +%else + db 'No', 10 +%endif + db 'N "%": ' +%iftoken % + db 'Yes', 10 +%else + db 'No', 10 +%endif + db 'C "%": ' +%iftoken % ; With a comment! + db 'Yes', 10 +%else + db 'No', 10 +%endif + db 'N "+foo": ' +%iftoken +foo + db 'Yes', 10 +%else + db 'No', 10 +%endif + db 'C "+foo": ' +%iftoken +foo ; With a comment! + db 'Yes', 10 +%else + db 'No', 10 +%endif + db 'N "<<": ' +%iftoken << + db 'Yes', 10 +%else + db 'No', 10 +%endif + db 'C "<<": ' +%iftoken << ; With a comment! + db 'Yes', 10 +%else + db 'No', 10 +%endif diff --git a/test/iftoken.pl b/test/iftoken.pl new file mode 100755 index 00000000..bbbb5bcd --- /dev/null +++ b/test/iftoken.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl + +@list = ('1', '+1', '1 2', '1,2', 'foo', 'foo bar', '%', '+foo', '<<'); + +foreach $t (@list) { + print "\tdb 'N \"$t\": '\n"; + print "%iftoken $t\n"; + print "\tdb 'Yes', 10\n"; + print "%else\n"; + print "\tdb 'No', 10\n"; + print "%endif\n"; + + print "\tdb 'C \"$t\": '\n"; + print "%iftoken $t ; With a comment!\n"; + print "\tdb 'Yes', 10\n"; + print "%else\n"; + print "\tdb 'No', 10\n"; + print "%endif\n"; +}