Fixed extended_functions mode. Small memory leak there. Should be fixed shorly.
This commit is contained in:
parent
c07d4c8033
commit
01ea879687
155
auto-static.c
155
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);
|
||||
|
125
generate.c
125
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");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user