git: 9front

Download patch

ref: 3987f58adb408cfaa79fc980240c22b31bcbfbb5
parent: 730d25360bc162030fb5ef3e0c559095f75a328a
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Sat Jun 29 07:56:18 EDT 2013

libaml: add Concatenate instruction, fix type conversions

--- a/sys/src/libaml/aml.c
+++ b/sys/src/libaml/aml.c
@@ -167,7 +167,7 @@
 	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,
 };
 
@@ -440,20 +440,6 @@
 }
 
 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)
 {
 	Region *r;
@@ -481,7 +467,7 @@
 		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 @@
 	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 @@
 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':
+			d = mk(tag, n);
+			rwreg(d, 0, n, v, 1);
+			return d;
 		case 's':
-			n = SIZE(s);
-			if(tag == 's' && TAG(s) == 'b')
-				n++;
+			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':
+			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);
-			if(tag == 's')
-				((uchar*)d)[n-1] = 0;
 			return d;
-		case 'i':
-			return mki(ival(s));
 		}
 	}
 	return s;
@@ -640,24 +688,25 @@
 		/* 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':
@@ -664,9 +713,12 @@
 			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 @@
 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 @@
 		if(c < 0) return mki(1);
 		break;
 	}
-
 	return nil;
 }
 
@@ -1457,6 +1507,44 @@
 }
 
 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)
 {
 	Field *f;
@@ -1731,6 +1819,7 @@
 	[Oref]		"RefOf",		"@",		evaliarg0,
 	[Ocref]		"CondRefOf",		"@@",		evalcondref,
 	[Oderef]	"DerefOf",		"@",		evalderef,
+	[Ocat]		"Concatenate",		"**@",		evalcat,
 
 	[Oacq]		"Acquire",		"@2",		evalnop,
 	[Orel]		"Release",		"@",		evalnop,
@@ -1755,7 +1844,7 @@
 /* 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,
--