libaml: add Concatenate instruction, fix type conversions
This commit is contained in:
parent
b34a1394c2
commit
61aeb582ca
1 changed files with 150 additions and 61 deletions
|
@ -167,7 +167,7 @@ enum {
|
|||
Oindex, Omutex, Oevent,
|
||||
Ocfld, Ocfld0, Ocfld1, Ocfld2, Ocfld4, Ocfld8,
|
||||
Oif, Oelse, Owhile, Obreak, Oret, Ocall,
|
||||
Ostore, Oderef, Osize, Oref, Ocref,
|
||||
Ostore, Oderef, Osize, Oref, Ocref, Ocat,
|
||||
Oacq, Orel, Ostall, Osleep, Oload, Ounload,
|
||||
};
|
||||
|
||||
|
@ -439,20 +439,6 @@ getname(Name *dot, char *path, int new)
|
|||
return dot;
|
||||
}
|
||||
|
||||
static uvlong
|
||||
ival(void *p)
|
||||
{
|
||||
if(p != nil){
|
||||
switch(TAG(p)){
|
||||
case 'i':
|
||||
return *((uvlong*)p);
|
||||
case 's':
|
||||
return strtoull((char*)p, 0, 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uvlong
|
||||
rwreg(void *reg, int off, int len, uvlong v, int write)
|
||||
{
|
||||
|
@ -481,7 +467,7 @@ rwreg(void *reg, int off, int len, uvlong v, int write)
|
|||
if((off+len) > r->len)
|
||||
break;
|
||||
if(amldebug){
|
||||
print("rwreg: %s %-8s [%llux+%x]/%d %llux\n",
|
||||
print("\nrwreg: %s %-8s [%llux+%x]/%d %llux\n",
|
||||
write ? "W" : "R",
|
||||
spacename[r->space],
|
||||
r->off, off, len, v);
|
||||
|
@ -497,6 +483,30 @@ rwreg(void *reg, int off, int len, uvlong v, int write)
|
|||
return ~0;
|
||||
}
|
||||
|
||||
static uvlong
|
||||
ival(void *p)
|
||||
{
|
||||
int n;
|
||||
|
||||
if(p != nil){
|
||||
switch(TAG(p)){
|
||||
case 'i':
|
||||
return *((uvlong*)p);
|
||||
case 's':
|
||||
if(*((char*)p) == 0)
|
||||
break;
|
||||
return strtoull((char*)p, 0, 16);
|
||||
case 'b':
|
||||
n = SIZE(p);
|
||||
if(n > 0){
|
||||
if(n > 8) n = 8;
|
||||
return rwreg(p, 0, n, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *deref(void *p);
|
||||
static void *store(void *s, void *d);
|
||||
|
||||
|
@ -601,25 +611,63 @@ deref(void *p)
|
|||
static void*
|
||||
copy(int tag, void *s)
|
||||
{
|
||||
static char hex[] = "0123456789ABCDEF";
|
||||
uvlong v;
|
||||
void *d;
|
||||
int i, n;
|
||||
|
||||
if(s != nil){
|
||||
int n;
|
||||
if(tag == 0)
|
||||
tag = TAG(s);
|
||||
if(tag == 0){
|
||||
if(s == nil)
|
||||
return nil;
|
||||
tag = TAG(s);
|
||||
}
|
||||
if(s == nil || TAG(s) == 'i'){
|
||||
n = 4;
|
||||
v = ival(s);
|
||||
if(v > 0xFFFFFFFFULL)
|
||||
n <<= 1;
|
||||
switch(tag){
|
||||
case 'b':
|
||||
case 's':
|
||||
n = SIZE(s);
|
||||
if(tag == 's' && TAG(s) == 'b')
|
||||
n++;
|
||||
d = mk(tag, n);
|
||||
memmove(d, s, n);
|
||||
if(tag == 's')
|
||||
((uchar*)d)[n-1] = 0;
|
||||
rwreg(d, 0, n, v, 1);
|
||||
return d;
|
||||
case 's':
|
||||
n <<= 1;
|
||||
d = mk(tag, n+1);
|
||||
((char*)d)[n] = 0;
|
||||
while(n > 0){
|
||||
((char*)d)[--n] = hex[v & 0xF];
|
||||
v >>= 4;
|
||||
}
|
||||
return d;
|
||||
case 'i':
|
||||
return mki(ival(s));
|
||||
if(v == 0ULL)
|
||||
return nil;
|
||||
return mki(v);
|
||||
}
|
||||
} else {
|
||||
n = SIZE(s);
|
||||
switch(tag){
|
||||
case 's':
|
||||
if(TAG(s) == 'b'){
|
||||
d = mk(tag, n*3 + 1);
|
||||
for(i=0; i<n; i++){
|
||||
((char*)d)[i*3 + 0] = hex[((uchar*)s)[i] >> 4];
|
||||
((char*)d)[i*3 + 1] = hex[((uchar*)s)[i] & 0xF];
|
||||
((char*)d)[i*3 + 2] = ' ';
|
||||
}
|
||||
((char*)d)[n*3] = 0;
|
||||
return d;
|
||||
}
|
||||
/* no break */
|
||||
case 'b':
|
||||
if(TAG(s) == 's'){
|
||||
n = strlen(s);
|
||||
/* zero length string is converted to zero length buffer */ if(n > 0) n++;
|
||||
}
|
||||
d = mk(tag, n);
|
||||
memmove(d, s, n);
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
|
@ -640,33 +688,37 @@ store(void *s, void *d)
|
|||
/* no break */
|
||||
case 'R': case 'L':
|
||||
pp = ((Ref*)d)->ptr;
|
||||
while(p = *pp){
|
||||
while((p = *pp) != nil){
|
||||
switch(TAG(p)){
|
||||
case 'R': case 'A': case 'L':
|
||||
pp = ((Ref*)p)->ptr;
|
||||
continue;
|
||||
break;
|
||||
case 'N':
|
||||
pp = &((Name*)p)->v;
|
||||
if(*pp != p)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
if(*pp == p)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'N':
|
||||
pp = &((Name*)d)->v;
|
||||
break;
|
||||
}
|
||||
p = *pp;
|
||||
if(p && TAG(p) != 'N'){
|
||||
if(p != nil && TAG(p) != 'N'){
|
||||
switch(TAG(p)){
|
||||
case 'f':
|
||||
case 'u':
|
||||
rwfield(p, s, 1);
|
||||
return d;
|
||||
}
|
||||
*pp = copy(TAG(p), s);
|
||||
} else
|
||||
*pp = copy(0, s);
|
||||
if(TAG(d) != 'A' && TAG(d) != 'L'){
|
||||
*pp = copy(TAG(p), s);
|
||||
return d;
|
||||
}
|
||||
}
|
||||
*pp = copy(0, s);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
@ -1331,30 +1383,29 @@ static void*
|
|||
evalcmp(void)
|
||||
{
|
||||
void *a, *b;
|
||||
int c;
|
||||
int tag, c;
|
||||
|
||||
if((a = FP->arg[0]) == nil)
|
||||
a = mki(0);
|
||||
if((b = FP->arg[1]) == nil)
|
||||
b = mki(0);
|
||||
|
||||
switch(TAG(a)){
|
||||
default:
|
||||
return nil;
|
||||
case 'i':
|
||||
a = FP->arg[0];
|
||||
b = FP->arg[1];
|
||||
if(a == nil || TAG(a) == 'i'){
|
||||
c = ival(a) - ival(b);
|
||||
break;
|
||||
case 's':
|
||||
if(TAG(b) != 's')
|
||||
b = copy('s', b);
|
||||
c = strcmp((char*)a, (char*)b);
|
||||
break;
|
||||
case 'b':
|
||||
if(TAG(b) != 'b')
|
||||
b = copy('b', b);
|
||||
if((c = SIZE(a) - SIZE(b)) == 0)
|
||||
c = memcmp(a, b, SIZE(a));
|
||||
break;
|
||||
} else {
|
||||
tag = TAG(a);
|
||||
if(b == nil || TAG(b) != tag)
|
||||
b = copy(tag, b);
|
||||
if(TAG(b) != tag)
|
||||
return nil; /* botch */
|
||||
switch(tag){
|
||||
default:
|
||||
return nil; /* botch */
|
||||
case 's':
|
||||
c = strcmp((char*)a, (char*)b);
|
||||
break;
|
||||
case 'b':
|
||||
if((c = SIZE(a) - SIZE(b)) == 0)
|
||||
c = memcmp(a, b, SIZE(a));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(FP->op - optab){
|
||||
|
@ -1368,7 +1419,6 @@ evalcmp(void)
|
|||
if(c < 0) return mki(1);
|
||||
break;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
@ -1456,6 +1506,44 @@ evalstore(void)
|
|||
return store(FP->arg[0], FP->arg[1]);
|
||||
}
|
||||
|
||||
static void*
|
||||
evalcat(void)
|
||||
{
|
||||
void *r, *a, *b;
|
||||
int tag, n, m;
|
||||
|
||||
a = FP->arg[0];
|
||||
b = FP->arg[1];
|
||||
if(a == nil || TAG(a) == 'i')
|
||||
a = copy('b', a); /* Concat(Int, ???) -> Buf */
|
||||
tag = TAG(a);
|
||||
if(b == nil || TAG(b) != tag)
|
||||
b = copy(tag, b);
|
||||
if(TAG(b) != tag)
|
||||
return nil; /* botch */
|
||||
switch(tag){
|
||||
default:
|
||||
return nil; /* botch */
|
||||
case 'b':
|
||||
n = SIZE(a);
|
||||
m = SIZE(b);
|
||||
r = mk('b', n + m);
|
||||
memmove(r, a, n);
|
||||
memmove((uchar*)r + n, b, m);
|
||||
break;
|
||||
case 's':
|
||||
n = strlen((char*)a);
|
||||
m = strlen((char*)b);
|
||||
r = mk('s', n + m + 1);
|
||||
memmove(r, a, n);
|
||||
memmove((char*)r + n, b, m);
|
||||
((char*)r)[n+m] = 0;
|
||||
break;
|
||||
}
|
||||
store(r, FP->arg[2]);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void*
|
||||
evalindex(void)
|
||||
{
|
||||
|
@ -1731,6 +1819,7 @@ static Op optab[] = {
|
|||
[Oref] "RefOf", "@", evaliarg0,
|
||||
[Ocref] "CondRefOf", "@@", evalcondref,
|
||||
[Oderef] "DerefOf", "@", evalderef,
|
||||
[Ocat] "Concatenate", "**@", evalcat,
|
||||
|
||||
[Oacq] "Acquire", "@2", evalnop,
|
||||
[Orel] "Release", "@", evalnop,
|
||||
|
@ -1755,7 +1844,7 @@ static uchar octab1[] = {
|
|||
/* 58 */ Onamec, Onamec, Onamec, Obad, Onamec, Obad, Onamec, Onamec,
|
||||
/* 60 */ Oenv, Oenv, Oenv, Oenv, Oenv, Oenv, Oenv, Oenv,
|
||||
/* 68 */ Oenv, Oenv, Oenv, Oenv, Oenv, Oenv, Oenv, Obad,
|
||||
/* 70 */ Ostore, Oref, Oadd, Obad, Osub, Oinc, Odec, Omul,
|
||||
/* 70 */ Ostore, Oref, Oadd, Ocat, Osub, Oinc, Odec, Omul,
|
||||
/* 78 */ Odiv, Oshl, Oshr, Oand, Onand, Oor, Onor, Oxor,
|
||||
/* 80 */ Onot, Obad, Obad, Oderef, Obad, Omod, Obad, Osize,
|
||||
/* 88 */ Oindex, Obad, Ocfld4, Ocfld2, Ocfld1, Ocfld0, Obad, Ocfld8,
|
||||
|
|
Loading…
Reference in a new issue