aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Chambers <[email protected]>2021-10-08 16:38:02 +1300
committerAndrew Chambers <[email protected]>2021-10-08 16:38:02 +1300
commitdebe8291e0c9642d7bc909efbc03efed0efd611e (patch)
treeaa69d306701535992d923e1f3113d72c060244c8
parente8fdb5043d8de0921d06a054b780c8254145e11d (diff)
Refactor string handling.
-rw-r--r--asm.peg13
-rw-r--r--main.c26
2 files changed, 21 insertions, 18 deletions
diff --git a/asm.peg b/asm.peg
index 3e396c3..a1d517f 100644
--- a/asm.peg
+++ b/asm.peg
@@ -45,7 +45,6 @@ instr =
| i:sub { $$ = i; }
| i:xor { $$ = i; }
-
jmp =
"jmp" ws t:ident
{ $$.jmp = (Jmp){ .kind = ASM_JMP, .target=t.ident.name } ; }
@@ -241,7 +240,17 @@ r64 =
| "%r14" ![lwb] { $$ = REG(ASM_R14); }
| "%r15" ![lwb] { $$ = REG(ASM_R15); }
-string = '"' <(('\\\"')|( !'"' .))*> '"' { $$.string = decodestring(yytext); }
+# We disallow newlines in our strings, it is simpler for error messages.
+string = '"' <(string-escape | ( ! '\n' ! '\\' !'"' .))*> '"'
+ { $$.string = decodestring(yytext); }
+
+string-escape = '\\' (
+ '\\'
+ | '"'
+ | [nrt]
+ | 'x' [0-9A-Fa-f]+
+ | [0-7][0-7][0-7]
+)
ident =
<[._a-zA-Z][._a-zA-Z0-9]*>
diff --git a/main.c b/main.c
index 5725569..70fad61 100644
--- a/main.c
+++ b/main.c
@@ -151,25 +151,26 @@ static String decodestring(char *s) {
size_t cap = 0;
uint8_t *data = NULL;
uint8_t c = 0;
+
+ /* The string is already validated by the parser so we omit some checks*/
while (*s) {
if (*s == '\\') {
s++;
- if (!*s) {
- lfatal("bad escape in string");
- } else if (*s >= '0' && *s <= '7') {
+ if (*s >= '0' && *s <= '7') {
c = strtoul(s, &end, 8);
s += 3;
- if (s != end)
- lfatal("invalid octal sequence");
} else if (*s == 'x') {
s++;
c = strtoul(s, &end, 16);
- if (s == end)
- lfatal("invalid hex sequence");
s = end;
+ } else if (*s == 'r') {
+ c = '\r';
+ } else if (*s == 'n') {
+ c = '\n';
+ } else if (*s == 't') {
+ c = '\t';
} else {
- c = *s;
- s++;
+ unreachable();
}
} else {
c = *s;
@@ -253,16 +254,9 @@ static void sl(uint32_t l) {
/* Convert an AsmKind to register bits in reg/rm style. */
static uint8_t regbits(AsmKind k) { return (k - (ASM_REG_BEGIN + 1)) % 16; }
-/* Is a register. */
static uint8_t isreg(AsmKind k) { return k > ASM_REG_BEGIN && k < ASM_REG_END; }
-
-/* Is an r$n style register variant. */
static uint8_t isreg8(AsmKind k) { return k >= ASM_AL && k <= ASM_R15B; }
-
-/* Is an r$n style register variant. */
static uint8_t isreg16(AsmKind k) { return k >= ASM_AX && k <= ASM_R15W; }
-
-/* Is an r$n style register variant. */
static uint8_t isreg64(AsmKind k) { return k >= ASM_RAX && k <= ASM_R15; }
/* Is an r$n style register variant. */