|
@@ -352,6 +352,7 @@ typedef struct {
|
|
T_STRING,
|
|
T_STRING,
|
|
T_FSTRING,
|
|
T_FSTRING,
|
|
T_USTRING,
|
|
T_USTRING,
|
|
|
|
+ T_BSTRING,
|
|
T_NAME,
|
|
T_NAME,
|
|
|
|
|
|
T_TRUE,
|
|
T_TRUE,
|
|
@@ -454,6 +455,7 @@ typedef struct {
|
|
} tag;
|
|
} tag;
|
|
|
|
|
|
char *text;
|
|
char *text;
|
|
|
|
+ size_t z;
|
|
|
|
|
|
size_t fi;
|
|
size_t fi;
|
|
size_t pos;
|
|
size_t pos;
|
|
@@ -580,8 +582,9 @@ void format_error(char *filename, char *source, size_t pos, char *fmt, ...) {
|
|
exit(1); \
|
|
exit(1); \
|
|
}
|
|
}
|
|
|
|
|
|
-token_t *tokenize_string(char *source, size_t *pos) {
|
|
|
|
|
|
+token_t *tokenize_string(char *source, size_t *pos, size_t *size) {
|
|
char term = source[(*pos)++];
|
|
char term = source[(*pos)++];
|
|
|
|
+ int hx = 0;
|
|
|
|
|
|
buffer_t *text = buffer_new();
|
|
buffer_t *text = buffer_new();
|
|
|
|
|
|
@@ -617,7 +620,11 @@ token_t *tokenize_string(char *source, size_t *pos) {
|
|
buf[k] = 0;
|
|
buf[k] = 0;
|
|
|
|
|
|
buffer_fmt(text, "\\x%s", buf);
|
|
buffer_fmt(text, "\\x%s", buf);
|
|
- } break;
|
|
|
|
|
|
+
|
|
|
|
+ hx = 1;
|
|
|
|
+
|
|
|
|
+ if (size) (*size)++;
|
|
|
|
+ } continue;
|
|
|
|
|
|
case 'n':
|
|
case 'n':
|
|
buffer_appends(text, "\\n");
|
|
buffer_appends(text, "\\n");
|
|
@@ -668,6 +675,9 @@ token_t *tokenize_string(char *source, size_t *pos) {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (hx) hx = 0;
|
|
|
|
+ if (size) (*size)++;
|
|
|
|
+
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -676,9 +686,25 @@ token_t *tokenize_string(char *source, size_t *pos) {
|
|
else if (c == '\n') {
|
|
else if (c == '\n') {
|
|
buffer_appends(text, "\\n");
|
|
buffer_appends(text, "\\n");
|
|
|
|
|
|
|
|
+ if (size) (*size)++;
|
|
|
|
+
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (size) (*size)++;
|
|
|
|
+
|
|
|
|
+ if (hx) {
|
|
|
|
+ hx = 0;
|
|
|
|
+
|
|
|
|
+ if (strchr("0123456789abcdefABCDEF", c) != NULL) {
|
|
|
|
+ buffer_fmt(text, "\\x%x", c);
|
|
|
|
+
|
|
|
|
+ hx = 1;
|
|
|
|
+
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
buffer_append(text, c);
|
|
buffer_append(text, c);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -694,13 +720,13 @@ token_t *next_token(char *source, size_t *pos) {
|
|
return token(T_EOF, NULL);
|
|
return token(T_EOF, NULL);
|
|
|
|
|
|
if (source[*pos] == '"' || source[*pos] == '\'' || source[*pos] == '`')
|
|
if (source[*pos] == '"' || source[*pos] == '\'' || source[*pos] == '`')
|
|
- return tokenize_string(source, pos);
|
|
|
|
|
|
+ return tokenize_string(source, pos, NULL);
|
|
else if (source[*pos] == 'f' &&
|
|
else if (source[*pos] == 'f' &&
|
|
(source[(*pos) + 1] == '"' || source[(*pos) + 1] == '\'' ||
|
|
(source[(*pos) + 1] == '"' || source[(*pos) + 1] == '\'' ||
|
|
source[(*pos) + 1] == '`')) {
|
|
source[(*pos) + 1] == '`')) {
|
|
(*pos)++;
|
|
(*pos)++;
|
|
|
|
|
|
- token_t *t = tokenize_string(source, pos);
|
|
|
|
|
|
+ token_t *t = tokenize_string(source, pos, NULL);
|
|
t->tag = T_FSTRING;
|
|
t->tag = T_FSTRING;
|
|
|
|
|
|
return t;
|
|
return t;
|
|
@@ -709,11 +735,23 @@ token_t *next_token(char *source, size_t *pos) {
|
|
source[(*pos) + 1] == '`')) {
|
|
source[(*pos) + 1] == '`')) {
|
|
(*pos)++;
|
|
(*pos)++;
|
|
|
|
|
|
- token_t *t = tokenize_string(source, pos);
|
|
|
|
|
|
+ token_t *t = tokenize_string(source, pos, NULL);
|
|
t->tag = T_USTRING;
|
|
t->tag = T_USTRING;
|
|
|
|
|
|
NEEDS_UTF8 = 1;
|
|
NEEDS_UTF8 = 1;
|
|
|
|
|
|
|
|
+ return t;
|
|
|
|
+ } else if (source[*pos] == 'b' &&
|
|
|
|
+ (source[(*pos) + 1] == '"' || source[(*pos) + 1] == '\'' ||
|
|
|
|
+ source[(*pos) + 1] == '`')) {
|
|
|
|
+ (*pos)++;
|
|
|
|
+
|
|
|
|
+ size_t z = 0;
|
|
|
|
+
|
|
|
|
+ token_t *t = tokenize_string(source, pos, &z);
|
|
|
|
+ t->tag = T_BSTRING;
|
|
|
|
+ t->z = z;
|
|
|
|
+
|
|
return t;
|
|
return t;
|
|
} else if (source[*pos] == '0' &&
|
|
} else if (source[*pos] == '0' &&
|
|
(source[(*pos) + 1] == 'x' || source[(*pos) + 1] == 'b' ||
|
|
(source[(*pos) + 1] == 'x' || source[(*pos) + 1] == 'b' ||
|
|
@@ -1650,7 +1688,7 @@ node_t *parse_primary(list_t *tokens, size_t *pos) {
|
|
|
|
|
|
return NODEL(TABLE, pairs);
|
|
return NODEL(TABLE, pairs);
|
|
} else if (MATCH(NUMBER) || MATCH(STRING) || MATCH(FSTRING) ||
|
|
} else if (MATCH(NUMBER) || MATCH(STRING) || MATCH(FSTRING) ||
|
|
- MATCH(USTRING) || MATCH(NAME) || MATCH(TRUE) || MATCH(FALSE) ||
|
|
|
|
|
|
+ MATCH(USTRING) || MATCH(BSTRING) || MATCH(NAME) || MATCH(TRUE) || MATCH(FALSE) ||
|
|
MATCH(NIL))
|
|
MATCH(NIL))
|
|
return NODET(LITERAL, tokens->data[(*pos) - 1]);
|
|
return NODET(LITERAL, tokens->data[(*pos) - 1]);
|
|
|
|
|
|
@@ -5412,6 +5450,10 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
node->t->text);
|
|
node->t->text);
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case T_BSTRING:
|
|
|
|
+ EMIT("qi_make_bytes(state, (unsigned char *)\"%s\", %d)", node->t->text, node->t->z);
|
|
|
|
+ break;
|
|
|
|
+
|
|
case T_NAME: {
|
|
case T_NAME: {
|
|
char *name = node->t->text;
|
|
char *name = node->t->text;
|
|
node_t *n = const_get(name);
|
|
node_t *n = const_get(name);
|