summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eval.c45
-rw-r--r--test/utf.asm18
2 files changed, 63 insertions, 0 deletions
diff --git a/eval.c b/eval.c
index eb5af88..917dcfc 100644
--- a/eval.c
+++ b/eval.c
@@ -662,6 +662,48 @@ static expr *eval_floatize(enum floatize type)
return finishtemp();
}
+static expr *eval_strfunc(enum strfunc type)
+{
+ char *string;
+ size_t string_len;
+ int64_t val;
+ bool parens, rn_warn;
+
+ i = scan(scpriv, tokval);
+ if (i == '(') {
+ parens = true;
+ i = scan(scpriv, tokval);
+ }
+ if (i != TOKEN_STR) {
+ error(ERR_NONFATAL, "expecting string");
+ return NULL;
+ }
+ string_len = string_transform(tokval->t_charptr, tokval->t_inttwo,
+ &string, type);
+ if (string_len == (size_t)-1) {
+ error(ERR_NONFATAL, "invalid string for transform");
+ return NULL;
+ }
+
+ val = readstrnum(string, string_len, &rn_warn);
+ if (parens) {
+ i = scan(scpriv, tokval);
+ if (i != ')') {
+ error(ERR_NONFATAL, "expecting `)'");
+ return NULL;
+ }
+ }
+
+ if (rn_warn)
+ error(ERR_WARNING|ERR_PASS1, "character constant too long");
+
+ begintemp();
+ addtotemp(EXPR_SIMPLE, val);
+
+ i = scan(scpriv, tokval);
+ return finishtemp();
+}
+
static expr *expr6(int critical)
{
int32_t type;
@@ -730,6 +772,9 @@ static expr *expr6(int critical)
case TOKEN_FLOATIZE:
return eval_floatize(tokval->t_integer);
+ case TOKEN_STRFUNC:
+ return eval_strfunc(tokval->t_integer);
+
case '(':
i = scan(scpriv, tokval);
e = bexpr(critical);
diff --git a/test/utf.asm b/test/utf.asm
new file mode 100644
index 0000000..3dc8410
--- /dev/null
+++ b/test/utf.asm
@@ -0,0 +1,18 @@
+%define u(x) __utf16__(x)
+%define w(x) __utf32__(x)
+
+ db `Test \u306a\U0001abcd\n`
+ dw u(`Test \u306a\U0001abcd\n`)
+ dd w(`Test \u306a\U0001abcd\n`)
+
+ db `\u306a`
+ db `\xe3\x81\xaa`
+
+ nop
+
+ mov ax,u(`a`)
+ mov bx,u(`\u306a`)
+ mov cx,u(`\xe3\x81\xaa`)
+ mov eax,u(`ab`)
+ mov ebx,u(`\U0001abcd`)
+ mov ecx,w(`\U0001abcd`)