diff --git a/auto-static.c b/auto-static.c index a455ffa..8ed8624 100644 --- a/auto-static.c +++ b/auto-static.c @@ -154,6 +154,67 @@ static int is_letter (char c) { } +static char exp_buffer[1 << 25];; +static int exp_buffer_pos; + +static inline int is_hex (char c) { + return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'); +} + +static inline int hex2dec (char c) { + if (c >= '0' && c <= '9') { return c - '0'; } + else { return c - 'a' + 10; } +} + +static void expand_backslashed (char *s, int len) { + int backslashed = 0; + exp_buffer_pos = 0; + int i = 0; + while (i < len) { + assert (i + 3 <= (1 << 25)); + if (backslashed) { + backslashed = 0; + switch (s[i ++]) { + case 'n': + exp_buffer[exp_buffer_pos ++] = '\n'; + break; + case 'r': + exp_buffer[exp_buffer_pos ++] = '\r'; + break; + case 't': + exp_buffer[exp_buffer_pos ++] = '\t'; + break; + case 'b': + exp_buffer[exp_buffer_pos ++] = '\b'; + break; + case 'a': + exp_buffer[exp_buffer_pos ++] = '\a'; + break; + case '\\': + exp_buffer[exp_buffer_pos ++] = '\\'; + break; + case 'x': + if (i + 2 > len || !is_hex (s[i]) || !is_hex (s[i + 1])) { + exp_buffer_pos = -1; + return; + } + exp_buffer[exp_buffer_pos ++] = hex2dec (s[i]) * 16 + hex2dec (s[i + 1]); + i += 2; + break; + default: + break; + } + } else { + if (s[i] == '\\') { + backslashed = 1; + i ++; + } else { + exp_buffer[exp_buffer_pos ++] = s[i ++]; + } + } + } +} + static void local_next_token (void) { skip_wspc (); cur_token_quoted = 0; @@ -178,13 +239,24 @@ static void local_next_token (void) { } else if (c == '"') { cur_token_quoted = 1; cur_token = buffer_pos ++; - while (buffer_pos < buffer_end && *buffer_pos != '"') { + int backslashed = 0; + while (buffer_pos < buffer_end && (*buffer_pos != '"' || backslashed)) { + if (*buffer_pos == '\\') { + backslashed ^= 1; + } else { + backslashed = 0; + } buffer_pos ++; } if (*buffer_pos == '"') { buffer_pos ++; - cur_token_len = buffer_pos - cur_token - 2; - cur_token ++; + expand_backslashed (cur_token + 1, buffer_pos - cur_token - 2); + if (exp_buffer_pos < 0) { + cur_token_len = -2; + } else { + cur_token_len = exp_buffer_pos; + cur_token = exp_buffer; + } } else { cur_token_len = -2; } @@ -241,6 +313,83 @@ static int out_buf_pos; assert (out_buf_pos < OUT_BUF_SIZE);\ } while (0)\ +static int valid_utf8_char (const char *str) { + unsigned char c = (unsigned char) *str; + int n = 0; + + if ((c & 0x80) == 0x00) { + n = 0; + } else if ((c & 0xe0) == 0xc0) { + n = 1; + } else if ((c & 0xf0) == 0xe0) { + n = 2; + } else if ((c & 0xf8) == 0xf0) { + n = 3; + } else if ((c & 0xfc) == 0xf8) { + n = 4; + } else if ((c & 0xfe) == 0xfc) { + n = 5; + } else { + return -1; + } + + int i; + for (i = 0; i < n; i ++) { + if ((((unsigned char)(str[i])) & 0xc0) != 0x80) { + return -1; + } + } + return n + 1; +} + +static void print_escaped_string (const char *str) { + eprintf ("\""); + while (*str) { + int n = valid_utf8_char (str); + if (n < 0) { + eprintf ("\\x%02x", (int)(unsigned char)*str); + str ++; + } else if (n >= 2) { + int i; + for (i = 0; i < n; i++) { + eprintf ("%c", *(str ++)); + } + } else if (((unsigned char)*str) >= ' ' && *str != '"' && *str != '\\') { + eprintf ("%c", *str); + str ++; + } else { + switch (*str) { + case '\n': + eprintf("\\n"); + break; + case '\r': + eprintf("\\r"); + break; + case '\t': + eprintf("\\t"); + break; + case '\b': + eprintf("\\b"); + break; + case '\a': + eprintf("\\a"); + break; + case '\\': + eprintf ("\\\\"); + break; + case '"': + eprintf ("\""); + break; + default: + eprintf ("\\x%02x", (int)(unsigned char)*str); + break; + } + str ++; + } + } + eprintf ("\""); +} + char *tglf_extf_fetch (struct paramed_type *T) { out_buf_pos = 0; fetch_type_any (T); diff --git a/generate.c b/generate.c index cca32d9..3b0900d 100644 --- a/generate.c +++ b/generate.c @@ -230,7 +230,7 @@ struct tl_tree *read_num_const (int *var_num) { } -int gen_uni_skip (struct tl_tree *t, char *cur_name, int *vars, int first) { +int gen_uni_skip (struct tl_tree *t, char *cur_name, int *vars, int first, int fun) { assert (t); int x = TL_TREE_METHODS (t)->type (t); int l = 0; @@ -240,57 +240,58 @@ int gen_uni_skip (struct tl_tree *t, char *cur_name, int *vars, int first) { struct tl_tree_array *t2; int y; int L = strlen (cur_name); + char *fail = fun ? "return 0;" : "return -1;"; switch (x) { case NODE_TYPE_TYPE: t1 = (void *)t; if (!first) { - printf (" if (ODDP(%s) || %s->type->name != 0x%08x) { return -1; }\n", cur_name, cur_name, t1->type->name); + printf (" if (ODDP(%s) || %s->type->name != 0x%08x) { %s }\n", cur_name, cur_name, t1->type->name, fail); } else { - printf (" if (ODDP(%s) || (%s->type->name != 0x%08x && %s->type->name != 0x%08x)) { return -1; }\n", cur_name, cur_name, t1->type->name, cur_name, ~t1->type->name); + printf (" if (ODDP(%s) || (%s->type->name != 0x%08x && %s->type->name != 0x%08x)) { %s }\n", cur_name, cur_name, t1->type->name, cur_name, ~t1->type->name, fail); } for (i = 0; i < t1->children_num; i++) { sprintf (cur_name + L, "->params[%d]", i); - gen_uni_skip (t1->children[i], cur_name, vars, 0); + gen_uni_skip (t1->children[i], cur_name, vars, 0, fun); cur_name[L] = 0; } return 0; case NODE_TYPE_NAT_CONST: - printf (" if (EVENP(%s) || ((long)%s) != %lld) { return -1; }\n", cur_name, cur_name, var_nat_const_to_int (t) * 2 + 1); + printf (" if (EVENP(%s) || ((long)%s) != %lld) { %s }\n", cur_name, cur_name, var_nat_const_to_int (t) * 2 + 1, fail); return 0; case NODE_TYPE_ARRAY: - printf (" if (ODDP(%s) || %s->type->name != TL_TYPE_ARRAY) { return -1; }\n", cur_name, cur_name); + printf (" if (ODDP(%s) || %s->type->name != TL_TYPE_ARRAY) { %s }\n", cur_name, cur_name, fail); t2 = (void *)t; sprintf (cur_name + L, "->params[0]"); - y = gen_uni_skip (t2->multiplicity, cur_name, vars, 0); + y = gen_uni_skip (t2->multiplicity, cur_name, vars, 0, fun); cur_name[L] = 0; sprintf (cur_name + L, "->params[1]"); - y += gen_uni_skip (t2->args[0]->type, cur_name, vars, 0); + y += gen_uni_skip (t2->args[0]->type, cur_name, vars, 0, fun); cur_name[L] = 0; return 0; case NODE_TYPE_VAR_TYPE: - printf (" if (ODDP(%s)) { return -1; }\n", cur_name); + printf (" if (ODDP(%s)) { %s }\n", cur_name, fail); i = ((struct tl_tree_var_type *)t)->var_num; if (!vars[i]) { printf (" struct paramed_type *var%d = %s; assert (var%d);\n", i, cur_name, i); vars[i] = 1; } else if (vars[i] == 1) { - printf (" if (compare_types (var%d, %s) < 0) { return -1; }\n", i, cur_name); + printf (" if (compare_types (var%d, %s) < 0) { %s }\n", i, cur_name, fail); } else { assert (0); return -1; } return l; case NODE_TYPE_VAR_NUM: - printf (" if (EVENP(%s)) { return -1; }\n", cur_name); + printf (" if (EVENP(%s)) { %s }\n", cur_name, fail); i = ((struct tl_tree_var_num *)t)->var_num; j = ((struct tl_tree_var_num *)t)->dif; if (!vars[i]) { printf (" struct paramed_type *var%d = ((void *)%s) + %d; assert (var%d);\n", i, cur_name, 2 * j, i); vars[i] = 2; } else if (vars[i] == 2) { - printf (" if (var%d != ((void *)%s) + %d) { return -1; }\n", i, cur_name, 2 * j); + printf (" if (var%d != ((void *)%s) + %d) { %s }\n", i, cur_name, 2 * j, fail); } else { assert (0); return -1; @@ -683,6 +684,68 @@ int gen_field_autocomplete (struct arg *arg, int *vars, int num, int from_func) return 0; } +int gen_field_autocomplete_excl (struct arg *arg, int *vars, int num, int from_func) { + assert (arg); + assert (arg->var_num < 0); + char *offset = " "; + if (arg->exist_var_num >= 0) { + printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit); + offset = " "; + } + char *fail = from_func ? "0" : "-1"; + char *expect = from_func ? "expect_token_ptr_autocomplete" : "expect_token_autocomplete"; + if (arg->id && strlen (arg->id) > 0) { + printf ("%sif (cur_token_len == -3 && cur_token_real_len <= %d && !cur_token_quoted && !memcmp (cur_token, \"%s\", cur_token_real_len)) {\n", offset, (int)(strlen (arg->id)), arg->id); + printf ("%s set_autocomplete_string (\"%s\");\n", offset, arg->id); + printf ("%s return %s;\n", offset, fail); + printf ("%s}\n", offset); + + printf ("%sif (cur_token_len >= 0 && cur_token_len == %d && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", offset, (int)(strlen (arg->id)), arg->id); + printf ("%s local_next_token ();\n", offset); + printf ("%s %s (\":\", 1);\n", offset, expect); + printf ("%s}\n", offset); + } + int t = TL_TREE_METHODS (arg->type)->type (arg->type); + assert (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE); + printf ("%sstruct paramed_type *field%d = autocomplete_function_any ();\n", offset, num); + printf ("%sif (!field%d) { return 0; }\n", offset, num); + static char s[20]; + sprintf (s, "field%d", num); + gen_uni_skip (arg->type, s, vars, 1, 1); + if (arg->exist_var_num >= 0) { + printf (" }\n"); + } + return 0; +} + +int gen_field_store_excl (struct arg *arg, int *vars, int num, int from_func) { + assert (arg); + assert (arg->var_num < 0); + char *offset = " "; + if (arg->exist_var_num >= 0) { + printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit); + offset = " "; + } + char *expect = from_func ? "expect_token_ptr" : "expect_token"; + if (arg->id && strlen (arg->id) > 0) { + printf ("%sif (cur_token_len >= 0 && cur_token_len == %d && !cur_token_quoted && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", offset, (int)(strlen (arg->id)), arg->id); + printf ("%s local_next_token ();\n", offset); + printf ("%s %s (\":\", 1);\n", offset, expect); + printf ("%s}\n", offset); + } + int t = TL_TREE_METHODS (arg->type)->type (arg->type); + assert (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE); + printf ("%sstruct paramed_type *field%d = store_function_any ();\n", offset, num); + printf ("%sif (!field%d) { return 0; }\n", offset, num); + static char s[20]; + sprintf (s, "field%d", num); + gen_uni_skip (arg->type, s, vars, 1, 1); + if (arg->exist_var_num >= 0) { + printf (" }\n"); + } + return 0; +} + void gen_constructor_skip (struct tl_combinator *c) { printf ("int skip_constructor_%s (struct paramed_type *T) {\n", c->print_id); int i; @@ -695,7 +758,7 @@ void gen_constructor_skip (struct tl_combinator *c) { sprintf (s, "T"); int *vars = malloc0 (c->var_num * 4);; - gen_uni_skip (c->result, s, vars, 1); + gen_uni_skip (c->result, s, vars, 1, 0); if (c->name == NAME_INT) { printf (" if (in_remaining () < 4) { return -1;}\n"); @@ -744,7 +807,7 @@ void gen_constructor_fetch (struct tl_combinator *c) { sprintf (s, "T"); int *vars = malloc0 (c->var_num * 4);; - gen_uni_skip (c->result, s, vars, 1); + gen_uni_skip (c->result, s, vars, 1, 0); if (c->name == NAME_INT) { printf (" if (in_remaining () < 4) { return -1;}\n"); @@ -764,7 +827,7 @@ void gen_constructor_fetch (struct tl_combinator *c) { printf (" if (l < 0 || (l >= (1 << 22) - 2)) { return -1; }\n"); printf (" memcpy (buf, fetch_str (l), l);\n"); printf (" buf[l] = 0;\n"); - printf (" eprintf (\" \\\"%%s\\\"\", buf);\n"); + printf (" print_escaped_string (buf);\n"); printf (" return 0;\n"); printf ("}\n"); return; @@ -804,7 +867,7 @@ void gen_constructor_store (struct tl_combinator *c) { sprintf (s, "T"); int *vars = malloc0 (c->var_num * 4);; - gen_uni_skip (c->result, s, vars, 1); + gen_uni_skip (c->result, s, vars, 1, 0); if (c->name == NAME_INT) { printf (" if (is_int ()) {\n"); @@ -869,7 +932,7 @@ void gen_constructor_autocomplete (struct tl_combinator *c) { sprintf (s, "T"); int *vars = malloc0 (c->var_num * 4);; - gen_uni_skip (c->result, s, vars, 1); + gen_uni_skip (c->result, s, vars, 1, 0); if (c->name == NAME_INT) { printf (" if (is_int ()) {\n"); @@ -1075,16 +1138,15 @@ void gen_type_autocomplete (struct tl_type *t) { void gen_function_store (struct tl_combinator *f) { printf ("struct paramed_type *store_function_%s (void) {\n", f->print_id); int i; - for (i = 0; i < f->args_num; i++) if (f->args[i]->flags & FLAG_EXCL) { - printf (" return 0;\n"); - printf ("}\n"); - return; - } int *vars = malloc0 (f->var_num * 4);; for (i = 0; i < f->args_num; i++) if (!(f->args[i]->flags & FLAG_OPT_VAR)) { - assert (gen_field_store (f->args[i], vars, i + 1, 1) >= 0); + if (f->args[i]->flags & FLAG_EXCL) { + assert (gen_field_store_excl (f->args[i], vars, i + 1, 1) >= 0); + } else { + assert (gen_field_store (f->args[i], vars, i + 1, 1) >= 0); + } } @@ -1100,20 +1162,23 @@ void gen_function_store (struct tl_combinator *f) { void gen_function_autocomplete (struct tl_combinator *f) { printf ("struct paramed_type *autocomplete_function_%s (void) {\n", f->print_id); int i; - for (i = 0; i < f->args_num; i++) if (f->args[i]->flags & FLAG_EXCL) { - printf (" return 0;\n"); - printf ("}\n"); - return; - } int *vars = malloc0 (f->var_num * 4);; for (i = 0; i < f->args_num; i++) if (!(f->args[i]->flags & FLAG_OPT_VAR)) { - assert (gen_field_autocomplete (f->args[i], vars, i + 1, 1) >= 0); + if (f->args[i]->flags & FLAG_EXCL) { + assert (gen_field_autocomplete_excl (f->args[i], vars, i + 1, 1) >= 0); + } else { + assert (gen_field_autocomplete (f->args[i], vars, i + 1, 1) >= 0); + } } + printf (" struct paramed_type *R = \n"); + assert (gen_create (f->result, vars, 2) >= 0); + printf (";\n"); + free (vars); - printf (" return (void *)1;\n"); + printf (" return paramed_type_dup (R);\n"); printf ("}\n"); }