Merge branch 'indirect'

This commit is contained in:
H. Peter Anvin 2008-10-23 23:13:44 -07:00
commit 912595dfc0
9 changed files with 322 additions and 130 deletions

View File

@ -2026,6 +2026,24 @@ as that is what the embedded macro \c{isTrue} expanded to at
the time that \c{isFalse} was defined.
\S{indmacro} \i{Macro Indirection}: \I\c{%[}\c{%[...]}
The \c{%[...]} construct can be used to expand macros in contexts
where macro expansion would otherwise not occur, including in the
names other macros. For example, if you have a set of macros named
\c{Foo16}, \c{Foo32} and \c{Foo64}, you could write:
\c mov ax,Foo%[__BITS__] ; The Foo value
to use the builtin macro \c{__BITS__} (see \k{bitsm}) to automatically
select between them. Similarly, the two statements:
\c %xdefine Bar Quux ; Expands due to %xdefine
\c %define Bar %[Quux] ; Expands due to %[...]
have, in fact, the exactly same effect.
\S{concat%+} Concatenating Single Line Macro Tokens: \i\c{%+}
Individual tokens in single line macros can be concatenated, to produce
@ -2097,6 +2115,7 @@ instruction has been used as a label in older code. For example:
\c %idefine pause $%? ; Hide the PAUSE instruction
\S{undef} Undefining Single-Line Macros: \i\c{%undef}
Single-line macros can be removed with the \c{%undef} directive. For

View File

@ -66,6 +66,12 @@ foreach $fname ( @ARGV ) {
while (<INPUT>) {
$line++;
chomp;
while (/^(.*)\\$/) {
$_ = $1;
$_ .= <INPUT>;
chomp;
$line++;
}
if (m/^\s*\*END\*TASM\*MACROS\*\s*$/) {
$tasm_count = $index;
print OUT " /* End of TASM macros */\n";

View File

@ -15,6 +15,7 @@ USE: smartalign
%define __ALIGN_16BIT_6B__ 0x90,0x90,0x90,0x90,0x90,0x90
%define __ALIGN_16BIT_7B__ 0x90,0x90,0x90,0x90,0x90,0x90,0x90
%define __ALIGN_16BIT_8B__ 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90
%define __ALIGN_16BIT_GROUP__ 8
%define __ALIGN_32BIT_1B__ 0x90
%define __ALIGN_32BIT_2B__ 0x90,0x90
@ -24,6 +25,7 @@ USE: smartalign
%define __ALIGN_32BIT_6B__ 0x90,0x90,0x90,0x90,0x90,0x90
%define __ALIGN_32BIT_7B__ 0x90,0x90,0x90,0x90,0x90,0x90,0x90
%define __ALIGN_32BIT_8B__ 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90
%define __ALIGN_32BIT_GROUP__ 8
%define __ALIGN_64BIT_1B__ 0x90
%define __ALIGN_64BIT_2B__ 0x90,0x90
@ -33,6 +35,7 @@ USE: smartalign
%define __ALIGN_64BIT_6B__ 0x90,0x90,0x90,0x90,0x90,0x90
%define __ALIGN_64BIT_7B__ 0x90,0x90,0x90,0x90,0x90,0x90,0x90
%define __ALIGN_64BIT_8B__ 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90
%define __ALIGN_64BIT_GROUP__ 8
%elifidni %1,generic
%define __ALIGN_JMP_THRESHOLD__ 8
@ -44,6 +47,7 @@ USE: smartalign
%define __ALIGN_16BIT_6B__ 0x89,0xf6,0x8d,0xbd,0x00,0x00
%define __ALIGN_16BIT_7B__ 0x8d,0x74,0x00,0x8d,0xbd,0x00,0x00
%define __ALIGN_16BIT_8B__ 0x8d,0xb4,0x00,0x00,0x8d,0xbd,0x00,0x00
%define __ALIGN_16BIT_GROUP__ 8
%define __ALIGN_32BIT_1B__ 0x90
%define __ALIGN_32BIT_2B__ 0x89,0xf6
@ -53,6 +57,7 @@ USE: smartalign
%define __ALIGN_32BIT_6B__ 0x8d,0xb6,0x00,0x00,0x00,0x00
%define __ALIGN_32BIT_7B__ 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00
%undef __ALIGN_32BIT_8B__
%define __ALIGN_32BIT_GROUP__ 7
%define __ALIGN_64BIT_1B__ 0x90
%define __ALIGN_64BIT_2B__ 0x66,0x90
@ -62,6 +67,7 @@ USE: smartalign
%define __ALIGN_64BIT_6B__ 0x66,0x66,0x90,0x66,0x66,0x90
%define __ALIGN_64BIT_7B__ 0x66,0x66,0x66,0x90,0x66,0x66,0x90
%define __ALIGN_64BIT_8B__ 0x66,0x66,0x66,0x90,0x66,0x66,0x66,0x90
%define __ALIGN_64BIT_GROUP__ 8
%elifidni %1,k8
%define __ALIGN_JMP_THRESHOLD__ 16
@ -73,6 +79,7 @@ USE: smartalign
%define __ALIGN_16BIT_6B__ 0x66,0x66,0x90,0x66,0x66,0x90
%define __ALIGN_16BIT_7B__ 0x66,0x66,0x66,0x90,0x66,0x66,0x90
%define __ALIGN_16BIT_8B__ 0x66,0x66,0x66,0x90,0x66,0x66,0x66,0x90
%define __ALIGN_16BIT_GROUP__ 8
%define __ALIGN_32BIT_1B__ 0x90
%define __ALIGN_32BIT_2B__ 0x66,0x90
@ -82,6 +89,7 @@ USE: smartalign
%define __ALIGN_32BIT_6B__ 0x66,0x66,0x90,0x66,0x66,0x90
%define __ALIGN_32BIT_7B__ 0x66,0x66,0x66,0x90,0x66,0x66,0x90
%define __ALIGN_32BIT_8B__ 0x66,0x66,0x66,0x90,0x66,0x66,0x66,0x90
%define __ALIGN_32BIT_GROUP__ 8
%define __ALIGN_64BIT_1B__ 0x90
%define __ALIGN_64BIT_2B__ 0x66,0x90
@ -91,6 +99,7 @@ USE: smartalign
%define __ALIGN_64BIT_6B__ 0x66,0x66,0x90,0x66,0x66,0x90
%define __ALIGN_64BIT_7B__ 0x66,0x66,0x66,0x90,0x66,0x66,0x90
%define __ALIGN_64BIT_8B__ 0x66,0x66,0x66,0x90,0x66,0x66,0x66,0x90
%define __ALIGN_64BIT_GROUP__ 8
%elifidni %1,k7
%define __ALIGN_JMP_THRESHOLD__ 16
@ -102,6 +111,7 @@ USE: smartalign
%define __ALIGN_16BIT_6B__ 0x66,0x66,0x90,0x66,0x66,0x90
%define __ALIGN_16BIT_7B__ 0x66,0x66,0x66,0x90,0x66,0x66,0x90
%define __ALIGN_16BIT_8B__ 0x66,0x66,0x66,0x90,0x66,0x66,0x66,0x90
%define __ALIGN_64BIT_GROUP__ 8
%define __ALIGN_32BIT_1B__ 0x90
%define __ALIGN_32BIT_2B__ 0x8b,0xc0
@ -111,6 +121,7 @@ USE: smartalign
%define __ALIGN_32BIT_6B__ 0x8d,0x80,0x00,0x00,0x00,0x00
%define __ALIGN_32BIT_7B__ 0x8d,0x04,0x05,0x00,0x00,0x00,0x00
%undef __ALIGN_32BIT_8B__
%define __ALIGN_32BIT_GROUP__ 7
%define __ALIGN_64BIT_1B__ 0x90
%define __ALIGN_64BIT_2B__ 0x66,0x90
@ -120,6 +131,7 @@ USE: smartalign
%define __ALIGN_64BIT_6B__ 0x66,0x66,0x90,0x66,0x66,0x90
%define __ALIGN_64BIT_7B__ 0x66,0x66,0x66,0x90,0x66,0x66,0x90
%define __ALIGN_64BIT_8B__ 0x66,0x66,0x66,0x90,0x66,0x66,0x66,0x90
%define __ALIGN_64BIT_GROUP__ 8
%elifidni %1,p6
%define __ALIGN_JMP_THRESHOLD__ 16
@ -131,6 +143,7 @@ USE: smartalign
%define __ALIGN_16BIT_6B__ 0x0f,0x1f,0x00,0x0f,0x1f,0x00
%define __ALIGN_16BIT_7B__ 0x0f,0x1f,0x00,0x0f,0x1f,0x40,0x00
%define __ALIGN_16BIT_8B__ 0x0f,0x1f,0x40,0x00,0x0f,0x1f,0x40,0x00
%define __ALIGN_16BIT_GROUP__ 8
%define __ALIGN_32BIT_1B__ 0x90
%define __ALIGN_32BIT_2B__ 0x66,0x90
@ -140,6 +153,7 @@ USE: smartalign
%define __ALIGN_32BIT_6B__ 0x66,0x0f,0x1f,0x44,0x00,0x00
%define __ALIGN_32BIT_7B__ 0x0f,0x1f,0x80,0x00,0x00,0x00,0x00
%define __ALIGN_32BIT_8B__ 0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00
%define __ALIGN_32BIT_GROUP__ 8
%define __ALIGN_64BIT_1B__ 0x90
%define __ALIGN_64BIT_2B__ 0x66,0x90
@ -149,6 +163,7 @@ USE: smartalign
%define __ALIGN_64BIT_6B__ 0x66,0x0f,0x1f,0x44,0x00,0x00
%define __ALIGN_64BIT_7B__ 0x0f,0x1f,0x80,0x00,0x00,0x00,0x00
%define __ALIGN_64BIT_8B__ 0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00
%define __ALIGN_64BIT_GROUP__ 8
%else
%error unknown alignment mode: %1
%endif
@ -171,89 +186,11 @@ USE: smartalign
times (((%1) - (($-$$) % (%1))) % (%1)) nop
%$end:
%else
%if __BITS__ == 16
%ifdef __ALIGN_16BIT_8B__
%rep %$pad / 8
db __ALIGN_16BIT_8B__
%endrep
%assign %$pad %$pad % 8
%else
%rep %$pad / 7
db __ALIGN_16BIT_7B__
%endrep
%assign %$pad %$pad % 7
%endif
%if %$pad == 1
db __ALIGN_16BIT_1B__
%elif %$pad == 2
db __ALIGN_16BIT_2B__
%elif %$pad == 3
db __ALIGN_16BIT_3B__
%elif %$pad == 4
db __ALIGN_16BIT_4B__
%elif %$pad == 5
db __ALIGN_16BIT_5B__
%elif %$pad == 6
db __ALIGN_16BIT_6B__
%elif %$pad == 7
db __ALIGN_16BIT_7B__
%endif
%elif __BITS__ == 32
%ifdef __ALIGN_32BIT_8B__
%rep %$pad / 8
db __ALIGN_32BIT_8B__
%endrep
%assign %$pad %$pad % 8
%else
%rep %$pad / 7
db __ALIGN_32BIT_7B__
%endrep
%assign %$pad %$pad % 7
%endif
%if %$pad == 1
db __ALIGN_32BIT_1B__
%elif %$pad == 2
db __ALIGN_32BIT_2B__
%elif %$pad == 3
db __ALIGN_32BIT_3B__
%elif %$pad == 4
db __ALIGN_32BIT_4B__
%elif %$pad == 5
db __ALIGN_32BIT_5B__
%elif %$pad == 6
db __ALIGN_32BIT_6B__
%elif %$pad == 7
db __ALIGN_32BIT_7B__
%endif
%elif __BITS__ == 64
%ifdef __ALIGN_64BIT_8B__
%rep %$pad / 8
db __ALIGN_64BIT_8B__
%endrep
%assign %$pad %$pad % 8
%else
%rep %$pad / 7
db __ALIGN_64BIT_7B__
%endrep
%assign %$pad %$pad % 7
%endif
%if %$pad == 1
db __ALIGN_64BIT_1B__
%elif %$pad == 2
db __ALIGN_64BIT_2B__
%elif %$pad == 3
db __ALIGN_64BIT_3B__
%elif %$pad == 4
db __ALIGN_64BIT_4B__
%elif %$pad == 5
db __ALIGN_64BIT_5B__
%elif %$pad == 6
db __ALIGN_64BIT_6B__
%elif %$pad == 7
db __ALIGN_64BIT_7B__
%endif
%else
%error "Invalid __BITS__ value"
times (%$pad / __ALIGN_%[__BITS__]BIT_GROUP__) \
db __ALIGN_%[__BITS__]BIT_%[__ALIGN_%[__BITS__]BIT_GROUP__]B__
%assign %$pad %$pad % __ALIGN_%[__BITS__]BIT_GROUP__
%if %$pad > 0
db __ALIGN_%[__BITS__]BIT_%[%$pad]B__
%endif
%endif
%pop

140
preproc.c
View File

@ -159,6 +159,7 @@ enum pp_token_type {
TOK_NUMBER, TOK_FLOAT, TOK_SMAC_END, TOK_OTHER,
TOK_INTERNAL_STRING,
TOK_PREPROC_Q, TOK_PREPROC_QQ,
TOK_INDIRECT, /* %[...] */
TOK_SMAC_PARAM, /* MUST BE LAST IN THE LIST!!! */
TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
};
@ -396,6 +397,7 @@ static Blocks blocks = { NULL, NULL };
static Token *expand_mmac_params(Token * tline);
static Token *expand_smacro(Token * tline);
static Token *expand_id(Token * tline);
static Token *expand_indirect(Token * tline, int level);
static Context *get_ctx(const char *name, bool all_contexts);
static void make_tok_num(Token * tok, int64_t val);
static void error(int severity, const char *fmt, ...);
@ -777,7 +779,7 @@ static char *read_line(void)
*/
static Token *tokenize(char *line)
{
char *p = line;
char c, *p = line;
enum pp_token_type type;
Token *list = NULL;
Token *t, **tail = &list;
@ -804,6 +806,34 @@ static Token *tokenize(char *line)
if (*p)
p++;
type = TOK_PREPROC_ID;
} else if (*p == '[') {
int lvl = 1;
line += 2; /* Skip the leading %[ */
p++;
while (lvl && (c = *p++)) {
switch (c) {
case ']':
lvl--;
break;
case '%':
if (*p == '[')
lvl++;
break;
case '\'':
case '\"':
case '`':
p = nasm_skip_string(p)+1;
break;
default:
break;
}
}
p--;
if (*p)
*p++ = '\0';
if (lvl)
error(ERR_NONFATAL, "unterminated %[ construct");
type = TOK_INDIRECT;
} else if (*p == '?') {
type = TOK_PREPROC_Q; /* %? */
p++;
@ -2446,10 +2476,13 @@ static int do_directive(Token * tline)
* called expand_mmac_params(); however, if we're
* processing an %elif we must have been in a
* non-emitting mode, which would have inhibited
* the normal invocation of expand_mmac_params(). Therefore,
* we have to do it explicitly here.
* the normal invocation of expand_indirect() and
* expand_mmac_params(). Therefore, we have to do it
* explicitly here.
*/
j = if_condition(expand_mmac_params(tline->next), i);
t = expand_indirect(tline->next,0);
t = expand_mmac_params(t);
j = if_condition(expand_mmac_params(t), i);
tline->next = NULL; /* it got freed */
istk->conds->state =
j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
@ -3442,15 +3475,8 @@ static Token *expand_mmac_params(Token * tline)
}
break;
case TOK_ID:
if (tt->type == TOK_ID || tt->type == TOK_NUMBER) {
char *tmp = nasm_strcat(t->text, tt->text);
nasm_free(t->text);
t->text = tmp;
t->next = delete_Token(tt);
}
break;
case TOK_NUMBER:
if (tt->type == TOK_NUMBER) {
if (tt->type == t->type || tt->type == TOK_NUMBER) {
char *tmp = nasm_strcat(t->text, tt->text);
nasm_free(t->text);
t->text = tmp;
@ -3886,6 +3912,92 @@ static Token *expand_id(Token * tline)
return tline;
}
/*
* Expand indirect tokens, %[...]. Just like expand_smacro(),
* the input is considered destroyed.
*
* XXX: fix duplicated code in this function and in expand_mmac_params()
*/
static Token *expand_indirect(Token * tline, int level)
{
const int max_indirect_level = 1000;
Token *t, *thead, **tp;
Token *it;
bool skip;
if (level >= max_indirect_level) {
error(ERR_NONFATAL, "interminable indirect expansion");
} else {
thead = NULL;
tp = &tline;
while ((t = *tp)) {
if (t->type != TOK_INDIRECT) {
thead = t;
tp = &t->next;
} else {
it = tokenize(t->text);
it = expand_indirect(it, level+1);
it = expand_smacro(it);
while (it) {
skip = false;
switch (thead ? thead->type : TOK_NONE) {
case TOK_WHITESPACE:
skip = (it->type == TOK_WHITESPACE);
break;
case TOK_ID:
case TOK_NUMBER:
if (it->type == thead->type || it->type == TOK_NUMBER) {
char *tmp = nasm_strcat(thead->text, it->text);
nasm_free(thead->text);
thead->text = tmp;
skip = true;
}
break;
default:
break;
}
if (skip) {
it = delete_Token(it);
} else {
*tp = thead = it;
tp = &it->next;
it = it->next;
}
}
skip = false;
it = t->next;
if (it) {
switch (thead ? thead->type : TOK_NONE) {
case TOK_WHITESPACE:
skip = (it->type == TOK_WHITESPACE);
break;
case TOK_ID:
case TOK_NUMBER:
if (it->type == thead->type || it->type == TOK_NUMBER) {
char *tmp = nasm_strcat(thead->text, it->text);
nasm_free(thead->text);
thead->text = tmp;
skip = true;
}
break;
default:
break;
}
}
if (skip) {
*tp = thead = it->next;
t = delete_Token(t);
} else {
*tp = thead = it;
}
t = delete_Token(t);
}
}
}
return tline;
}
/*
* Determine whether the given line constitutes a multi-line macro
* call, and return the MMacro structure called if so. Doesn't have
@ -4428,8 +4540,10 @@ static char *pp_getline(void)
* anything.
*/
if (!defining && !(istk->conds && !emitting(istk->conds->state))
&& !(istk->mstk && !istk->mstk->in_progress))
&& !(istk->mstk && !istk->mstk->in_progress)) {
tline = expand_indirect(tline,0);
tline = expand_mmac_params(tline);
}
/*
* Check the line to see if it's a preprocessor directive.

42
test/ppindirect.asm Normal file
View File

@ -0,0 +1,42 @@
;Testname=test; Arguments=-E -o ppindirect.out; Files=ppindirect.out
; Fun tests of the preprocessor indirection mode...
%assign foo1 11
%assign foo11 1111
%assign foo2 22
%assign foo22 2222
%assign foo3 33
%assign foo33 3333
%assign n 2
foo%[foo%[n]]*100
foo%[n]*100
%assign foo%[foo%[n]] foo%[foo%[n]]*100
;%assign foo%[n] foo%[n]*100
foo1
foo2
foo3
foo11
foo22
foo33
%define foo33bar 999999
%[foo%[foo3]bar]
%assign bctr 0
%macro bluttan 0
%assign bctr bctr+1
%assign bluttan%[bctr] bctr
%defstr bstr bluttan%[bctr]
bluttan%[bctr]
bstr
%endmacro
%rep 20
bluttan
%endrep
%rep 20
bluttan%[bctr]
%assign bctr bctr-1
%endrep

View File

@ -1,34 +0,0 @@
%use smartalign
bits 32
alignmode nop
add ax,ax
align 16
alignmode generic
add ax,ax
align 16
alignmode k7
add ax,ax
align 16
alignmode k8
add ax,ax
align 16
alignmode p6
add ax,ax
align 16
add ecx,ecx
align 32
add edx,edx
align 128
add ebx,ebx
align 256
add esi,esi
align 512
add edi,edi

36
test/smartalign16.asm Normal file
View File

@ -0,0 +1,36 @@
;Testname=test; Arguments=-fbin -osmartalign16.bin; Files=stdout stderr smartalign16.bin
%use smartalign
bits 16
alignmode nop, 32
add ax,ax
align 32
alignmode generic, 32
add ax,ax
align 32
alignmode k7, 32
add ax,ax
align 32
alignmode k8, 32
add ax,ax
align 32
alignmode p6, 32
add ax,ax
align 32
add ecx,ecx
align 32
add edx,edx
align 128
add ebx,ebx
align 256
add esi,esi
align 512
add edi,edi

36
test/smartalign32.asm Normal file
View File

@ -0,0 +1,36 @@
;Testname=test; Arguments=-fbin -osmartalign32.bin; Files=stdout stderr smartalign32.bin
%use smartalign
bits 32
alignmode nop, 32
add ax,ax
align 32
alignmode generic, 32
add ax,ax
align 32
alignmode k7, 32
add ax,ax
align 32
alignmode k8, 32
add ax,ax
align 32
alignmode p6, 32
add ax,ax
align 32
add ecx,ecx
align 32
add edx,edx
align 128
add ebx,ebx
align 256
add esi,esi
align 512
add edi,edi

36
test/smartalign64.asm Normal file
View File

@ -0,0 +1,36 @@
;Testname=test; Arguments=-fbin -osmartalign64.bin; Files=stdout stderr smartalign64.bin
%use smartalign
bits 64
alignmode nop, 32
add ax,ax
align 32
alignmode generic, 32
add ax,ax
align 32
alignmode k7, 32
add ax,ax
align 32
alignmode k8, 32
add ax,ax
align 32
alignmode p6, 32
add ax,ax
align 32
add ecx,ecx
align 32
add edx,edx
align 128
add ebx,ebx
align 256
add esi,esi
align 512
add edi,edi