From 88d420583db5bb680e9e55e37783817b17ac7102 Mon Sep 17 00:00:00 2001 From: Vysheng Date: Wed, 10 Sep 2014 15:52:42 +0400 Subject: [PATCH] Added support for direct queries enter --- auto-static.c | 249 ++++++++++++-- auto.h | 6 +- generate.c | 875 ++++++++++++++++++++++++++++++++++++++++++----- interface.c | 17 +- mtproto-common.h | 10 + queries.c | 29 +- queries.h | 1 + tgl.h | 5 + 8 files changed, 1064 insertions(+), 128 deletions(-) diff --git a/auto-static.c b/auto-static.c index 5e7d844..60870ef 100644 --- a/auto-static.c +++ b/auto-static.c @@ -18,50 +18,231 @@ Copyright Vitaly Valtman 2014 */ -int skip_double (void) { - if (in_ptr + 2 <= in_end) { - in_ptr += 2; - return 0; - } else { - return -1; +#include "mtproto-common.h" +#include + +static int cur_token_len; +static char *cur_token; +static int cur_token_real_len; +static int cur_token_quoted; +static int multiline_output; +static int multiline_offset; +static int multiline_offset_size = 2; + +static int disable_field_names; + +#define expect_token(token,len) \ + if (len != cur_token_len || memcmp (cur_token, token, cur_token_len)) { return -1; } \ + local_next_token (); + +#define expect_token_ptr(token,len) \ + if (len != cur_token_len || memcmp (cur_token, token, cur_token_len)) { return 0; } \ + local_next_token (); + +#define expect_token_autocomplete(token,len) \ + if (cur_token_len == -3 && len >= cur_token_real_len && !memcmp (cur_token, token, cur_token_real_len)) { set_autocomplete_string (token); return -1; }\ + if (len != cur_token_len || memcmp (cur_token, token, cur_token_len)) { return -1; } \ + local_next_token (); + +#define expect_token_ptr_autocomplete(token,len) \ + if (cur_token_len == -3 && len >= cur_token_real_len && !memcmp (cur_token, token, cur_token_real_len)) { set_autocomplete_string (token); return 0; }\ + if (len != cur_token_len || memcmp (cur_token, token, cur_token_len)) { return 0; } \ + local_next_token (); + + +static int autocomplete_mode; +static char *autocomplete_string; +static int (*autocomplete_fun)(const char *, int, int, char **); + +static void set_autocomplete_string (const char *s) { + if (autocomplete_string) { free (autocomplete_string); } + autocomplete_string = strdup (s); + autocomplete_mode = 1; +} + +static void set_autocomplete_type (int (*f)(const char *, int, int, char **)) { + autocomplete_fun = f; + autocomplete_mode = 2; +} + +static int is_int (void) { + if (cur_token_len <= 0) { return 0; } + char c = cur_token[cur_token_len]; + cur_token[cur_token_len] = 0; + char *p = 0; + + strtoll (cur_token, &p, 10); + cur_token[cur_token_len] = c; + + return p == cur_token + cur_token_len; +} + +static long long get_int (void) { + if (cur_token_len <= 0) { return 0; } + char c = cur_token[cur_token_len]; + cur_token[cur_token_len] = 0; + char *p = 0; + + long long val = strtoll (cur_token, &p, 0); + cur_token[cur_token_len] = c; + + return val; +} + +static int is_double (void) { + if (cur_token_len <= 0) { return 0; } + char c = cur_token[cur_token_len]; + cur_token[cur_token_len] = 0; + char *p = 0; + + strtod (cur_token, &p); + cur_token[cur_token_len] = c; + + return p == cur_token + cur_token_len; +} + +static double get_double (void) { + if (cur_token_len <= 0) { return 0; } + char c = cur_token[cur_token_len]; + cur_token[cur_token_len] = 0; + char *p = 0; + + double val = strtod (cur_token, &p); + cur_token[cur_token_len] = c; + + return val; +} + +static struct paramed_type *paramed_type_dup (struct paramed_type *P) { + if (ODDP (P)) { return P; } + struct paramed_type *R = malloc (sizeof (*R)); + R->type = malloc (sizeof (*R->type)); + memcpy (R->type, P->type, sizeof (*P->type)); + R->type->id = strdup (P->type->id); + + if (P->type->params_num) { + R->params = malloc (sizeof (void *) * P->type->params_num); + int i; + for (i = 0; i < P->type->params_num; i++) { + R->params[i] = paramed_type_dup (P->params[i]); + } + } + return R; +} + +static void print_offset (void) { + int i; + for (i = 0; i < multiline_offset; i++) { + printf (" "); } } -int skip_long (void) { - if (in_ptr + 2 <= in_end) { - in_ptr += 2; - return 0; - } else { - return -1; + +static char *buffer_pos, *buffer_end; + +static int is_wspc (char c) { + return c <= 32 && c > 0; +} + +static void skip_wspc (void) { + while (buffer_pos < buffer_end && is_wspc (*buffer_pos)) { + buffer_pos ++; } } -int skip_int (void) { - if (in_ptr + 1 <= in_end) { - in_ptr += 1; - return 0; + +static int is_letter (char c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '.' || c == '_' || c == '-'; +} + + +static void local_next_token (void) { + skip_wspc (); + cur_token_quoted = 0; + if (buffer_pos >= buffer_end) { + cur_token_len = -3; + cur_token_real_len = 0; + return; + } + char c = *buffer_pos; + if (is_letter (c)) { + cur_token = buffer_pos; + while (buffer_pos < buffer_end && is_letter (*buffer_pos)) { + buffer_pos ++; + } + if (buffer_pos < buffer_end) { + cur_token_len = buffer_pos - cur_token; + } else { + cur_token_real_len = buffer_pos - cur_token; + cur_token_len = -3; + } + return; + } else if (c == '"') { + cur_token_quoted = 1; + cur_token = buffer_pos ++; + while (buffer_pos < buffer_end && *buffer_pos != '"') { + buffer_pos ++; + } + if (*buffer_pos == '"') { + buffer_pos ++; + cur_token_len = buffer_pos - cur_token - 2; + cur_token ++; + } else { + cur_token_len = -2; + } + return; } else { - return -1; + if (c) { + cur_token = buffer_pos ++; + cur_token_len = 1; + } else { + cur_token_len = -3; + cur_token_real_len = 0; + } } } -int skip_string (void) { - if (in_ptr == in_end) { return -1; } - unsigned len = *(unsigned char *)in_ptr; - if (len == 0xff) { return -1; } - if (len < 0xfe) { - unsigned size = (len + 4) >> 2; - if (in_ptr + size <= in_end) { - in_ptr += size; - return 0; + +int tglf_extf_autocomplete (const char *text, int text_len, int index, char **R, char *data, int data_len) { + if (index == -1) { + buffer_pos = data; + buffer_end = data + data_len; + autocomplete_mode = 0; + local_next_token (); + autocomplete_function_any (); + } + if (autocomplete_mode == 0) { return -1; } + int len = strlen (text); + if (autocomplete_mode == 1) { + if (index >= 0) { return -1; } + index = 0; + if (!strncmp (text, autocomplete_string, len)) { + *R = strdup (autocomplete_string); + return index; } else { return -1; } } else { - len = (*(unsigned *)in_ptr) >> 8; - unsigned size = (len + 7) >> 2; - if (in_ptr + size <= in_end) { - in_ptr += size; - return 0; - } else { - return -1; - } + return autocomplete_fun (text, len, index, R); } } + +struct paramed_type *tglf_extf_store (const char *data, int data_len) { + buffer_pos = (char *)data; + buffer_end = (char *)(data + data_len); + local_next_token (); + return store_function_any (); +} + +#define OUT_BUF_SIZE (1 << 25) +static char out_buf[OUT_BUF_SIZE]; +static int out_buf_pos; + +#define eprintf(...) \ + do { \ + out_buf_pos += snprintf (out_buf + out_buf_pos, OUT_BUF_SIZE - out_buf_pos, __VA_ARGS__);\ + assert (out_buf_pos < OUT_BUF_SIZE);\ + } while (0)\ + +char *tglf_extf_fetch (struct paramed_type *T) { + out_buf_pos = 0; + fetch_type_any (T); + return out_buf; +} diff --git a/auto.h b/auto.h index 375da58..94aa6a4 100644 --- a/auto.h +++ b/auto.h @@ -20,13 +20,15 @@ #ifndef __AUTO_H__ #define __AUTO_H__ -struct tl_type { +struct tl_type_descr { unsigned name; char *id; + int params_num; + long long params_types; }; struct paramed_type { - struct tl_type *type; + struct tl_type_descr *type; struct paramed_type **params; }; diff --git a/generate.c b/generate.c index be8a27c..cca32d9 100644 --- a/generate.c +++ b/generate.c @@ -20,6 +20,7 @@ Copyright 2012-2013 Vkontakte Ltd 2012-2013 Vitaliy Valtman */ + #define _GNU_SOURCE #include @@ -64,6 +65,19 @@ void tl_type_insert_by_name (struct tl_type *t) { type_tree = tree_insert_tl_type (type_tree, t, lrand48 ()); } +int is_empty (struct tl_type *t) { + if (t->name == NAME_INT || t->name == NAME_LONG || t->name == NAME_DOUBLE || t->name == NAME_STRING) { return 1; } + if (t->constructors_num != 1) { return 0; } + int count = 0; + int i; + struct tl_combinator *c = t->constructors[0]; + for (i = 0; i < c->args_num; i++) { + if (!(c->args[i]->flags & FLAG_OPT_VAR)) { count ++; } + } + return count == 1; +} + + static char buf[1 << 20]; int buf_size; int *buf_ptr = (int *)buf; @@ -216,7 +230,7 @@ struct tl_tree *read_num_const (int *var_num) { } -int gen_uni (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) { assert (t); int x = TL_TREE_METHODS (t)->type (t); int l = 0; @@ -236,7 +250,7 @@ int gen_uni (struct tl_tree *t, char *cur_name, int *vars, int first) { } for (i = 0; i < t1->children_num; i++) { sprintf (cur_name + L, "->params[%d]", i); - gen_uni (t1->children[i], cur_name, vars, 0); + gen_uni_skip (t1->children[i], cur_name, vars, 0); cur_name[L] = 0; } return 0; @@ -248,11 +262,11 @@ int gen_uni (struct tl_tree *t, char *cur_name, int *vars, int first) { t2 = (void *)t; sprintf (cur_name + L, "->params[0]"); - y = gen_uni (t2->multiplicity, cur_name, vars, 0); + y = gen_uni_skip (t2->multiplicity, cur_name, vars, 0); cur_name[L] = 0; sprintf (cur_name + L, "->params[1]"); - y += gen_uni (t2->args[0]->type, cur_name, vars, 0); + y += gen_uni_skip (t2->args[0]->type, cur_name, vars, 0); cur_name[L] = 0; return 0; case NODE_TYPE_VAR_TYPE: @@ -305,9 +319,9 @@ int gen_create (struct tl_tree *t, int *vars, int offset) { print_offset (offset + 2); t1 = (void *)t; if (t1->self.flags & FLAG_BARE) { - printf (".type = &(struct tl_type) {.name = 0x%08x, .id = \"Bare_%s\"},\n", ~t1->type->name, t1->type->id); + printf (".type = &(struct tl_type_descr) {.name = 0x%08x, .id = \"Bare_%s\", .params_num = %d, .params_types = %lld},\n", ~t1->type->name, t1->type->id, t1->type->arity, t1->type->params_types); } else { - printf (".type = &(struct tl_type) {.name = 0x%08x, .id = \"%s\"},\n", t1->type->name, t1->type->id); + printf (".type = &(struct tl_type_descr) {.name = 0x%08x, .id = \"%s\", .params_num = %d, .params_types = %lld},\n", t1->type->name, t1->type->id, t1->type->arity, t1->type->params_types); } if (t1->children_num) { print_offset (offset + 2); @@ -334,7 +348,7 @@ int gen_create (struct tl_tree *t, int *vars, int offset) { printf ("&(struct paramed_type){\n"); print_offset (offset + 2); t2 = (void *)t; - printf (".type = &(struct tl_type) {.name = NAME_ARRAY, .id = \"array\"},\n"); + printf (".type = &(struct tl_type_descr) {.name = NAME_ARRAY, .id = \"array\", .params_num = 2, .params_types = 1},\n"); print_offset (offset + 2); printf (".params = (struct paramed_type **){\n"); gen_create (t2->multiplicity, vars, offset + 4); @@ -360,7 +374,7 @@ int gen_create (struct tl_tree *t, int *vars, int offset) { } } -int gen_field_fetch (struct arg *arg, int *vars, int num) { +int gen_field_skip (struct arg *arg, int *vars, int num) { assert (arg); char *offset = " "; int o = 0; @@ -378,12 +392,12 @@ int gen_field_fetch (struct arg *arg, int *vars, int num) { } else { assert (t == NAME_VAR_NUM); if (vars[arg->var_num] == 0) { - printf ("%sstruct paramed_type *var%d = INT2PTR (*in_ptr);\n", offset, arg->var_num); - printf ("%sif (skip_int () < 0) { return -1;}\n", offset); + printf ("%sif (in_remaining () < 4) { return -1;}\n", offset); + printf ("%sstruct paramed_type *var%d = INT2PTR (fetch_int ());\n", offset, arg->var_num); vars[arg->var_num] = 2; } else if (vars[arg->var_num] == 2) { - printf ("%sif (vars%d != INT2PTR (*in_ptr)) { return -1; }\n", offset, arg->var_num); - printf ("%sif (skip_int () < 0) { return -1;}\n", offset); + printf ("%sif (in_remaining () < 4) { return -1;}\n", offset); + printf ("%sif (vars%d != INT2PTR (fetch_int ())) { return -1; }\n", offset, arg->var_num); } else { assert (0); return -1; @@ -423,49 +437,491 @@ int gen_field_fetch (struct arg *arg, int *vars, int num) { return 0; } -void gen_constructor_fetch (struct tl_combinator *c) { +int gen_field_fetch (struct arg *arg, int *vars, int num, int empty) { + assert (arg); + char *offset = " "; + int o = 0; + if (arg->exist_var_num >= 0) { + printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit); + offset = " "; + o = 2; + } + if (!empty) { + printf("%sif (multiline_output >= 2) { print_offset (); }\n", offset); + } + if (arg->id && strlen (arg->id) && !empty) { + printf ("%sif (!disable_field_names) { eprintf (\" %s :\"); }\n", offset, arg->id); + } + if (arg->var_num >= 0) { + assert (TL_TREE_METHODS (arg->type)->type (arg->type) == NODE_TYPE_TYPE); + int t = ((struct tl_tree_type *)arg->type)->type->name; + if (t == NAME_VAR_TYPE) { + fprintf (stderr, "Not supported yet\n"); + assert (0); + } else { + assert (t == NAME_VAR_NUM); + if (vars[arg->var_num] == 0) { + printf ("%sif (in_remaining () < 4) { return -1;}\n", offset); + printf ("%seprintf (\" %%d\", prefetch_int ());\n", offset); + printf ("%sstruct paramed_type *var%d = INT2PTR (fetch_int ());\n", offset, arg->var_num); + vars[arg->var_num] = 2; + } else if (vars[arg->var_num] == 2) { + printf ("%sif (in_remaining () < 4) { return -1;}\n", offset); + printf ("%seprintf (\" %%d\", prefetch_int ());\n", offset); + printf ("%sif (vars%d != INT2PTR (fetch_int ())) { return -1; }\n", offset, arg->var_num); + } else { + assert (0); + return -1; + } + } + } else { + int t = TL_TREE_METHODS (arg->type)->type (arg->type); + if (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE) { + printf ("%sstruct paramed_type *field%d = \n", offset, num); + assert (gen_create (arg->type, vars, 2 + o) >= 0); + printf (";\n"); + int bare = arg->flags & FLAG_BARE; + if (!bare && t == NODE_TYPE_TYPE) { + bare = ((struct tl_tree_type *)arg->type)->self.flags & FLAG_BARE; + } + if (!bare) { + printf ("%sif (fetch_type_%s (field%d) < 0) { return -1;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num); + } else { + printf ("%sif (fetch_type_bare_%s (field%d) < 0) { return -1;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num); + } + } else { + assert (t == NODE_TYPE_ARRAY); + printf ("%sint multiplicity%d = PTR2INT (\n", offset, num); + assert (gen_create (((struct tl_tree_array *)arg->type)->multiplicity, vars, 2 + o) >= 0); + printf ("%s);\n", offset); + printf ("%sstruct paramed_type *field%d = \n", offset, num); + assert (gen_create (((struct tl_tree_array *)arg->type)->args[0]->type, vars, 2 + o) >= 0); + printf (";\n"); + printf ("%seprintf (\" [\");\n", offset); + printf ("%sif (multiline_output >= 1) { eprintf (\"\\n\"); }\n", offset); + printf ("%sif (multiline_output >= 1) { multiline_offset += multiline_offset_size;}\n", offset); + printf ("%swhile (multiplicity%d -- > 0) {\n", offset, num); + printf ("%s if (multiline_output >= 1) { print_offset (); }\n", offset); + printf ("%s if (fetch_type_%s (field%d) < 0) { return -1;}\n", offset, "any", num); + printf ("%s if (multiline_output >= 1) { eprintf (\"\\n\"); }\n", offset); + printf ("%s}\n", offset); + printf ("%sif (multiline_output >= 1) { multiline_offset -= multiline_offset_size; print_offset ();}\n", offset); + printf ("%seprintf (\" ]\");\n", offset); + } + } + if (!empty) { + printf("%sif (multiline_output >= 2) { eprintf (\"\\n\"); }\n", offset); + } + if (arg->exist_var_num >= 0) { + printf (" }\n"); + } + return 0; +} + +int gen_field_store (struct arg *arg, int *vars, int num, int from_func) { + assert (arg); + char *offset = " "; + int o = 0; + if (arg->exist_var_num >= 0) { + printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit); + offset = " "; + o = 2; + } + char *fail = from_func ? "0" : "-1"; + 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); + } + if (arg->var_num >= 0) { + printf ("%sif (cur_token_len < 0) { return %s; }\n", offset, fail); + assert (TL_TREE_METHODS (arg->type)->type (arg->type) == NODE_TYPE_TYPE); + int t = ((struct tl_tree_type *)arg->type)->type->name; + if (t == NAME_VAR_TYPE) { + fprintf (stderr, "Not supported yet\n"); + assert (0); + } else { + assert (t == NAME_VAR_NUM); + if (vars[arg->var_num] == 0) { + printf ("%sif (!is_int ()) { return %s;}\n", offset, fail); + printf ("%sstruct paramed_type *var%d = INT2PTR (get_int ());\n", offset, arg->var_num); + printf ("%sout_int (get_int ());\n", offset); + printf ("%sassert (var%d);\n", offset, arg->var_num); + printf ("%slocal_next_token ();\n", offset); + vars[arg->var_num] = 2; + } else if (vars[arg->var_num] == 2) { + printf ("%sif (!is_int ()) { return %s;}\n", offset, fail); + printf ("%sif (vars%d != INT2PTR (get_int ())) { return %s; }\n", offset, arg->var_num, fail); + printf ("%sout_int (get_int ());\n", offset); + printf ("%slocal_next_token ();\n", offset); + } else { + assert (0); + return -1; + } + } + } else { + int t = TL_TREE_METHODS (arg->type)->type (arg->type); + if (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE) { + printf ("%sstruct paramed_type *field%d = \n", offset, num); + assert (gen_create (arg->type, vars, 2 + o) >= 0); + printf (";\n"); + int bare = arg->flags & FLAG_BARE; + if (!bare && t == NODE_TYPE_TYPE) { + bare = ((struct tl_tree_type *)arg->type)->self.flags & FLAG_BARE; + } + if (!bare) { + printf ("%sif (store_type_%s (field%d) < 0) { return %s;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num, fail); + } else { + printf ("%sif (store_type_bare_%s (field%d) < 0) { return %s;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num, fail); + } + } else { + printf ("%s%s (\"[\", 1);\n", offset, expect); + + assert (t == NODE_TYPE_ARRAY); + printf ("%sint multiplicity%d = PTR2INT (\n", offset, num); + assert (gen_create (((struct tl_tree_array *)arg->type)->multiplicity, vars, 2 + o) >= 0); + printf ("%s);\n", offset); + printf ("%sstruct paramed_type *field%d = \n", offset, num); + assert (gen_create (((struct tl_tree_array *)arg->type)->args[0]->type, vars, 2 + o) >= 0); + printf (";\n"); + printf ("%swhile (multiplicity%d -- > 0) {\n", offset, num); + printf ("%s if (store_type_%s (field%d) < 0) { return %s;}\n", offset, "any", num, fail); + printf ("%s}\n", offset); + + printf ("%s%s (\"]\", 1);\n", offset, expect); + } + } + if (arg->exist_var_num >= 0) { + printf (" }\n"); + } + return 0; +} + +int gen_field_autocomplete (struct arg *arg, int *vars, int num, int from_func) { + assert (arg); + char *offset = " "; + int o = 0; + if (arg->exist_var_num >= 0) { + printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit); + offset = " "; + o = 2; + } + 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); + } + if (arg->var_num >= 0) { + printf ("%sif (cur_token_len < 0) { return %s; }\n", offset, fail); + assert (TL_TREE_METHODS (arg->type)->type (arg->type) == NODE_TYPE_TYPE); + int t = ((struct tl_tree_type *)arg->type)->type->name; + if (t == NAME_VAR_TYPE) { + fprintf (stderr, "Not supported yet\n"); + assert (0); + } else { + assert (t == NAME_VAR_NUM); + if (vars[arg->var_num] == 0) { + printf ("%sif (!is_int ()) { return %s;}\n", offset, fail); + printf ("%sstruct paramed_type *var%d = INT2PTR (get_int ());\n", offset, arg->var_num); + printf ("%sassert (var%d);\n", offset, arg->var_num); + printf ("%slocal_next_token ();\n", offset); + vars[arg->var_num] = 2; + } else if (vars[arg->var_num] == 2) { + printf ("%sif (!is_int ()) { return %s;}\n", offset, fail); + printf ("%sif (vars%d != INT2PTR (get_int ())) { return %s; }\n", offset, arg->var_num, fail); + printf ("%slocal_next_token ();\n", offset); + } else { + assert (0); + return -1; + } + } + } else { + int t = TL_TREE_METHODS (arg->type)->type (arg->type); + if (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE) { + printf ("%sstruct paramed_type *field%d = \n", offset, num); + assert (gen_create (arg->type, vars, 2 + o) >= 0); + printf (";\n"); + int bare = arg->flags & FLAG_BARE; + if (!bare && t == NODE_TYPE_TYPE) { + bare = ((struct tl_tree_type *)arg->type)->self.flags & FLAG_BARE; + } + if (!bare) { + printf ("%sif (autocomplete_type_%s (field%d) < 0) { return %s;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num, fail); + } else { + printf ("%sif (autocomplete_type_bare_%s (field%d) < 0) { return %s;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num, fail); + } + } else { + printf ("%s%s (\"[\", 1);\n", offset, expect); + + assert (t == NODE_TYPE_ARRAY); + printf ("%sint multiplicity%d = PTR2INT (\n", offset, num); + assert (gen_create (((struct tl_tree_array *)arg->type)->multiplicity, vars, 2 + o) >= 0); + printf ("%s);\n", offset); + printf ("%sstruct paramed_type *field%d = \n", offset, num); + assert (gen_create (((struct tl_tree_array *)arg->type)->args[0]->type, vars, 2 + o) >= 0); + printf (";\n"); + printf ("%swhile (multiplicity%d -- > 0) {\n", offset, num); + printf ("%s if (autocomplete_type_%s (field%d) < 0) { return %s;}\n", offset, "any", num, fail); + printf ("%s}\n", offset); + + printf ("%s%s (\"]\", 1);\n", offset, expect); + } + } + 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; + for (i = 0; i < c->args_num; i++) if (c->args[i]->flags & FLAG_EXCL) { + printf (" return -1;\n"); + printf ("}\n"); + return; + } static char s[10000]; sprintf (s, "T"); int *vars = malloc0 (c->var_num * 4);; - gen_uni (c->result, s, vars, 1); + gen_uni_skip (c->result, s, vars, 1); if (c->name == NAME_INT) { - printf (" if (skip_int () < 0) { return -1; }\n"); + printf (" if (in_remaining () < 4) { return -1;}\n"); + printf (" fetch_int ();\n"); printf (" return 0;\n"); printf ("}\n"); return; } else if (c->name == NAME_LONG) { - printf (" if (skip_long () < 0) { return -1; }\n"); + printf (" if (in_remaining () < 8) { return -1;}\n"); + printf (" fetch_long ();\n"); printf (" return 0;\n"); printf ("}\n"); return; } else if (c->name == NAME_STRING) { - printf (" if (skip_string () < 0) { return -1; }\n"); + printf (" int l = prefetch_strlen ();\n"); + printf (" if (l < 0) { return -1;}\n"); + printf (" fetch_str (l);\n"); printf (" return 0;\n"); printf ("}\n"); return; } else if (c->name == NAME_DOUBLE) { - printf (" if (skip_double () < 0) { return -1; }\n"); + printf (" if (in_remaining () < 8) { return -1;}\n"); + printf (" fetch_double ();\n"); printf (" return 0;\n"); printf ("}\n"); return; } - int i; for (i = 0; i < c->args_num; i++) if (!(c->args[i]->flags & FLAG_OPT_VAR)) { - assert (gen_field_fetch (c->args[i], vars, i + 1) >= 0); + assert (gen_field_skip (c->args[i], vars, i + 1) >= 0); } free (vars); printf (" return 0;\n"); printf ("}\n"); } -void gen_type_fetch (struct tl_type *t) { +void gen_constructor_fetch (struct tl_combinator *c) { + printf ("int fetch_constructor_%s (struct paramed_type *T) {\n", c->print_id); + int i; + for (i = 0; i < c->args_num; i++) if (c->args[i]->flags & FLAG_EXCL) { + printf (" return -1;\n"); + printf ("}\n"); + return; + } + static char s[10000]; + sprintf (s, "T"); + + int *vars = malloc0 (c->var_num * 4);; + gen_uni_skip (c->result, s, vars, 1); + + if (c->name == NAME_INT) { + printf (" if (in_remaining () < 4) { return -1;}\n"); + printf (" eprintf (\" %%d\", fetch_int ());\n"); + printf (" return 0;\n"); + printf ("}\n"); + return; + } else if (c->name == NAME_LONG) { + printf (" if (in_remaining () < 8) { return -1;}\n"); + printf (" eprintf (\" %%lld\", fetch_long ());\n"); + printf (" return 0;\n"); + printf ("}\n"); + return; + } else if (c->name == NAME_STRING) { + printf (" static char buf[1 << 22];\n"); + printf (" int l = prefetch_strlen ();\n"); + 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 (" return 0;\n"); + printf ("}\n"); + return; + } else if (c->name == NAME_DOUBLE) { + printf (" if (in_remaining () < 8) { return -1;}\n"); + printf (" eprintf (\" %%lf\", fetch_double ());\n"); + printf (" return 0;\n"); + printf ("}\n"); + return; + } + + assert (c->result->methods->type (c->result) == NODE_TYPE_TYPE); + int empty = is_empty (((struct tl_tree_type *)c->result)->type); + if (!empty) { + printf (" eprintf (\" %s\");\n", c->id); + printf (" if (multiline_output >= 2) { eprintf (\"\\n\"); }\n"); + } + + + for (i = 0; i < c->args_num; i++) if (!(c->args[i]->flags & FLAG_OPT_VAR)) { + assert (gen_field_fetch (c->args[i], vars, i + 1, empty) >= 0); + } + free (vars); + printf (" return 0;\n"); + printf ("}\n"); +} + +void gen_constructor_store (struct tl_combinator *c) { + printf ("int store_constructor_%s (struct paramed_type *T) {\n", c->print_id); + int i; + for (i = 0; i < c->args_num; i++) if (c->args[i]->flags & FLAG_EXCL) { + printf (" return -1;\n"); + printf ("}\n"); + return; + } + static char s[10000]; + sprintf (s, "T"); + + int *vars = malloc0 (c->var_num * 4);; + gen_uni_skip (c->result, s, vars, 1); + + if (c->name == NAME_INT) { + printf (" if (is_int ()) {\n"); + printf (" out_int (get_int ());\n"); + printf (" local_next_token ();\n"); + printf (" return 0;\n"); + printf (" } else {\n"); + printf (" return -1;\n"); + printf (" }\n"); + printf ("}\n"); + return; + } else if (c->name == NAME_LONG) { + printf (" if (is_int ()) {\n"); + printf (" out_long (get_int ());\n"); + printf (" local_next_token ();\n"); + printf (" return 0;\n"); + printf (" } else {\n"); + printf (" return -1;\n"); + printf (" }\n"); + printf ("}\n"); + return; + } else if (c->name == NAME_STRING) { + printf (" if (cur_token_len >= 0) {\n"); + printf (" out_cstring (cur_token, cur_token_len);\n"); + printf (" local_next_token ();\n"); + printf (" return 0;\n"); + printf (" } else {\n"); + printf (" return -1;\n"); + printf (" }\n"); + printf ("}\n"); + return; + } else if (c->name == NAME_DOUBLE) { + printf (" if (is_double ()) {\n"); + printf (" out_double (get_double());\n"); + printf (" local_next_token ();\n"); + printf (" return 0;\n"); + printf (" } else {\n"); + printf (" return -1;\n"); + printf (" }\n"); + printf ("}\n"); + return; + } + + for (i = 0; i < c->args_num; i++) if (!(c->args[i]->flags & FLAG_OPT_VAR)) { + assert (gen_field_store (c->args[i], vars, i + 1, 0) >= 0); + } + + free (vars); + printf (" return 0;\n"); + printf ("}\n"); +} + +void gen_constructor_autocomplete (struct tl_combinator *c) { + printf ("int autocomplete_constructor_%s (struct paramed_type *T) {\n", c->print_id); + int i; + for (i = 0; i < c->args_num; i++) if (c->args[i]->flags & FLAG_EXCL) { + printf (" return -1;\n"); + printf ("}\n"); + return; + } + static char s[10000]; + sprintf (s, "T"); + + int *vars = malloc0 (c->var_num * 4);; + gen_uni_skip (c->result, s, vars, 1); + + if (c->name == NAME_INT) { + printf (" if (is_int ()) {\n"); + printf (" local_next_token ();\n"); + printf (" return 0;\n"); + printf (" } else {\n"); + printf (" return -1;\n"); + printf (" }\n"); + printf ("}\n"); + return; + } else if (c->name == NAME_LONG) { + printf (" if (is_int ()) {\n"); + printf (" local_next_token ();\n"); + printf (" return 0;\n"); + printf (" } else {\n"); + printf (" return -1;\n"); + printf (" }\n"); + printf ("}\n"); + return; + } else if (c->name == NAME_STRING) { + printf (" if (cur_token_len >= 0) {\n"); + printf (" local_next_token ();\n"); + printf (" return 0;\n"); + printf (" } else {\n"); + printf (" return -1;\n"); + printf (" }\n"); + printf ("}\n"); + return; + } else if (c->name == NAME_DOUBLE) { + printf (" if (is_double ()) {\n"); + printf (" local_next_token ();\n"); + printf (" return 0;\n"); + printf (" } else {\n"); + printf (" return -1;\n"); + printf (" }\n"); + printf ("}\n"); + return; + } + + for (i = 0; i < c->args_num; i++) if (!(c->args[i]->flags & FLAG_OPT_VAR)) { + assert (gen_field_autocomplete (c->args[i], vars, i + 1, 0) >= 0); + } + + free (vars); + printf (" return 0;\n"); + printf ("}\n"); +} + +void gen_type_skip (struct tl_type *t) { printf ("int skip_type_%s (struct paramed_type *T) {\n", t->print_id); - printf (" int magic = *in_ptr;\n"); - printf (" if (skip_int () < 0) { return -1; }\n"); + printf (" if (in_remaining () < 4) { return -1;}\n"); + printf (" int magic = fetch_int ();\n"); printf (" switch (magic) {\n"); int i; for (i = 0; i < t->constructors_num; i++) { @@ -475,15 +931,204 @@ void gen_type_fetch (struct tl_type *t) { printf (" }\n"); printf ("}\n"); printf ("int skip_type_bare_%s (struct paramed_type *T) {\n", t->print_id); - printf (" int *save = in_ptr;\n"); - for (i = 0; i < t->constructors_num; i++) { - printf (" if (skip_constructor_%s (T) >= 0) { return 0; }\n", t->constructors[i]->print_id); - printf (" in_ptr = save;\n"); + if (t->constructors_num > 1) { + printf (" int *save_in_ptr = in_ptr;\n"); + for (i = 0; i < t->constructors_num; i++) { + printf (" if (skip_constructor_%s (T) >= 0) { return 0; }\n", t->constructors[i]->print_id); + printf (" in_ptr = save_in_ptr;\n"); + } + } else { + for (i = 0; i < t->constructors_num; i++) { + printf (" if (skip_constructor_%s (T) >= 0) { return 0; }\n", t->constructors[i]->print_id); + } } printf (" return -1;\n"); printf ("}\n"); } +void gen_type_fetch (struct tl_type *t) { + int empty = is_empty (t);; + printf ("int fetch_type_%s (struct paramed_type *T) {\n", t->print_id); + printf (" if (in_remaining () < 4) { return -1;}\n"); + if (!empty) { + printf (" if (multiline_output >= 2) { multiline_offset += multiline_offset_size; }\n"); + printf (" eprintf (\" (\");\n"); + } + printf (" int magic = fetch_int ();\n"); + printf (" int res = -1;\n"); + printf (" switch (magic) {\n"); + int i; + for (i = 0; i < t->constructors_num; i++) { + printf (" case 0x%08x: res = fetch_constructor_%s (T); break;\n", t->constructors[i]->name, t->constructors[i]->print_id); + } + printf (" default: return -1;\n"); + printf (" }\n"); + if (!empty) { + printf (" if (res >= 0) {\n"); + printf (" if (multiline_output >= 2) { multiline_offset -= multiline_offset_size; print_offset (); }\n"); + printf (" eprintf (\" )\");\n"); + //printf (" if (multiline_output >= 2) { printf (\"\\n\"); }\n"); + printf (" }\n"); + } + printf (" return res;\n"); + printf ("}\n"); + printf ("int fetch_type_bare_%s (struct paramed_type *T) {\n", t->print_id); + if (t->constructors_num > 1) { + printf (" int *save_in_ptr = in_ptr;\n"); + + if (!empty) { + printf (" if (multiline_output >= 2) { multiline_offset += multiline_offset_size; }\n"); + } + for (i = 0; i < t->constructors_num; i++) { + printf (" if (skip_constructor_%s (T) >= 0) { in_ptr = save_in_ptr; %sassert (!fetch_constructor_%s (T)); %sreturn 0; }\n", t->constructors[i]->print_id, empty ? "" : "eprintf (\" (\"); ", t->constructors[i]->print_id , empty ? "" : "if (multiline_output >= 2) { multiline_offset -= multiline_offset_size; print_offset (); } eprintf (\" )\");"); + printf (" in_ptr = save_in_ptr;\n"); + } + } else { + for (i = 0; i < t->constructors_num; i++) { + if (!empty) { + printf (" if (multiline_output >= 2) { multiline_offset += multiline_offset_size; }\n"); + printf (" eprintf (\" (\");\n"); + } + printf (" if (fetch_constructor_%s (T) >= 0) { %sreturn 0; }\n", t->constructors[i]->print_id, empty ? "" : "if (multiline_output >= 2) { multiline_offset -= multiline_offset_size; print_offset (); } eprintf (\" )\");" ); + } + } + printf (" return -1;\n"); + printf ("}\n"); +} + +void gen_type_store (struct tl_type *t) { + int empty = is_empty (t);; + int k = 0; + for (k = 0; k < 2; k++) { + printf ("int store_type_%s%s (struct paramed_type *T) {\n", k == 0 ? "" : "bare_", t->print_id); + if (empty) { + printf (" if (store_constructor_%s (T) < 0) { return -1; }\n", t->constructors[0]->print_id); + printf (" return 0;\n"); + printf ("}\n"); + } else { + printf (" expect_token (\"(\", 1);\n"); + printf (" if (cur_token_len < 0) { return -1; }\n"); + printf (" if (cur_token_len < 0) { return -1; }\n"); + int i; + for (i = 0; i < t->constructors_num; i++) { + printf (" if (cur_token_len == %d && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", (int)strlen (t->constructors[i]->id), t->constructors[i]->id); + if (!k) { + printf (" out_int (0x%08x);\n", t->constructors[i]->name); + } + printf (" local_next_token ();\n"); + printf (" if (store_constructor_%s (T) < 0) { return -1; }\n", t->constructors[i]->print_id); + printf (" expect_token (\")\", 1);\n"); + printf (" return 0;\n"); + printf (" }\n"); + } + /*if (t->constructors_num == 1) { + printf (" if (!force) {\n"); + if (!k) { + printf (" out_int (0x%08x);\n", t->constructors[0]->name); + } + printf (" if (store_constructor_%s (T) < 0) { return -1; }\n", t->constructors[0]->print_id); + printf (" expect_token (\")\", 1);\n"); + printf (" return 0;\n"); + printf (" }\n"); + }*/ + printf (" return -1;\n"); + printf ("}\n"); + } + } +} + +void gen_type_autocomplete (struct tl_type *t) { + int empty = is_empty (t);; + int k = 0; + for (k = 0; k < 2; k++) { + printf ("int autocomplete_type_%s%s (struct paramed_type *T) {\n", k == 0 ? "" : "bare_", t->print_id); + if (empty) { + printf (" if (autocomplete_constructor_%s (T) < 0) { return -1; }\n", t->constructors[0]->print_id); + printf (" return 0;\n"); + printf ("}\n"); + } else { + printf (" expect_token_autocomplete (\"(\", 1);\n"); + printf (" if (cur_token_len == -3) { set_autocomplete_type (do_autocomplete_type_%s); return -1; }\n", t->print_id); + printf (" if (cur_token_len < 0) { return -1; }\n"); + int i; + for (i = 0; i < t->constructors_num; i++) { + printf (" if (cur_token_len == %d && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", (int)strlen (t->constructors[i]->id), t->constructors[i]->id); + printf (" local_next_token ();\n"); + printf (" if (autocomplete_constructor_%s (T) < 0) { return -1; }\n", t->constructors[i]->print_id); + printf (" expect_token_autocomplete (\")\", 1);\n"); + printf (" return 0;\n"); + printf (" }\n"); + } + /*if (t->constructors_num == 1) { + printf (" if (!force) {\n"); + printf (" if (autocomplete_constructor_%s (T) < 0) { return -1; }\n", t->constructors[0]->print_id); + printf (" expect_token_autocomplete (\")\", 1);\n"); + printf (" return 0;\n"); + printf (" }\n"); + }*/ + printf (" return -1;\n"); + printf ("}\n"); + } + } +} + +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); + } + + + printf (" struct paramed_type *R = \n"); + assert (gen_create (f->result, vars, 2) >= 0); + printf (";\n"); + + free (vars); + printf (" return paramed_type_dup (R);\n"); + printf ("}\n"); +} + +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); + } + + free (vars); + printf (" return (void *)1;\n"); + printf ("}\n"); +} + +void gen_type_do_autocomplete (struct tl_type *t) { + printf ("int do_autocomplete_type_%s (const char *text, int text_len, int index, char **R) {\n", t->print_id); + printf (" index ++;\n"); + int i; + for (i = 0; i < t->constructors_num; i++) { + printf (" if (index == %d) { if (!strncmp (text, \"%s\", text_len)) { *R = tstrdup (\"%s\"); return index; } else { index ++; }}\n", i, t->constructors[i]->id, t->constructors[i]->id); + } + printf (" *R = 0;\n"); + printf (" return 0;\n"); + printf ("}\n"); +} + struct tl_tree *read_num_var (int *var_num) { struct tl_tree_var_num *T = malloc0 (sizeof (*T)); T->self.flags = 0; @@ -667,6 +1312,11 @@ int read_args_list (struct arg **args, int args_num, int *var_num) { args[i]->var_num = -1; } + int x = args[i]->flags & 6; + args[i]->flags &= ~6; + if (x & 2) { args[i]->flags |= 4; } + if (x & 4) { args[i]->flags |= 2; } + if (args[i]->var_num >= *var_num) { *var_num = args[i]->var_num + 1; } @@ -839,49 +1489,6 @@ int parse_tlo_file (void) { } assert (buf_ptr == buf_end); - /* - static void *IP[10000]; - if (gen_function_fetch (IP, 100) < 0) { - return -2; - } - for (i = 0; i < tn; i++) { - if (tps[i]->extra < tps[i]->constructors_num) { - tl_config_back (); - return -1; - } - } - int j; - for (i = 0; i < tn; i++) { - for (j = 0; j < tps[i]->constructors_num; j ++) { - if (gen_constructor_store (tps[i]->constructors[j], IP, 10000) < 0) { - return -2; - } - if (gen_constructor_fetch (tps[i]->constructors[j], IP, 10000) < 0) { - return -2; - } - } - } - for (i = 0; i < fn; i++) { - if (gen_function_store (fns[i], IP, 10000) < 0) { - return -2; - } - } - if (tl_config_name) { - ADD_PFREE (strlen (tl_config_name)); - zzstrfree (tl_config_name); - } - tl_config_name = 0; - config_crc64 = new_crc64; - tl_config_version = new_tl_config_version ; - tl_config_date = new_tl_config_date; - - int i; - - int types_num = get_int (); - - for (i = 0; i < types_num; i++) { - if (parse_type () < 0) { return -1; } - }*/ int j; for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { @@ -895,59 +1502,153 @@ int parse_tlo_file (void) { printf ("#include \"auto.h\"\n"); printf ("#include \n"); - printf ("extern int *tgl_in_ptr, *tgl_in_end;\n"); - printf ("#define in_ptr tgl_in_ptr\n"); - printf ("#define in_end tgl_in_end\n"); printf ("#include \"auto-static.c\"\n"); for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { + gen_constructor_skip (tps[i]->constructors[j]); + gen_constructor_store (tps[i]->constructors[j]); gen_constructor_fetch (tps[i]->constructors[j]); + gen_constructor_autocomplete (tps[i]->constructors[j]); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { + gen_type_skip (tps[i]); + gen_type_store (tps[i]); gen_type_fetch (tps[i]); + gen_type_autocomplete (tps[i]); + gen_type_do_autocomplete (tps[i]); + } + for (i = 0; i < fn; i++) { + gen_function_store (fns[i]); + gen_function_autocomplete (fns[i]); } - /*for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#') { - printf ("struct tl_type tl_type_%s = {\n", tps[i]->id); - printf (" .name = 0x%08x,\n", tps[i]->name); - printf (" .id = \"%s\"\n", tps[i]->id); - printf ("};\n"); - }*/ - printf ("int skip_type_any (struct paramed_type *T) {\n"); printf (" switch (T->type->name) {\n"); - for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { + for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type") && tps[i]->name) { printf (" case 0x%08x: return skip_type_%s (T);\n", tps[i]->name, tps[i]->print_id); printf (" case 0x%08x: return skip_type_bare_%s (T);\n", ~tps[i]->name, tps[i]->print_id); } printf (" default: return -1; }\n"); printf ("}\n"); + printf ("int store_type_any (struct paramed_type *T) {\n"); + printf (" switch (T->type->name) {\n"); + for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type") && tps[i]->name) { + printf (" case 0x%08x: return store_type_%s (T);\n", tps[i]->name, tps[i]->print_id); + printf (" case 0x%08x: return store_type_bare_%s (T);\n", ~tps[i]->name, tps[i]->print_id); + } + printf (" default: return -1; }\n"); + printf ("}\n"); + printf ("int fetch_type_any (struct paramed_type *T) {\n"); + printf (" switch (T->type->name) {\n"); + for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type") && tps[i]->name) { + printf (" case 0x%08x: return fetch_type_%s (T);\n", tps[i]->name, tps[i]->print_id); + printf (" case 0x%08x: return fetch_type_bare_%s (T);\n", ~tps[i]->name, tps[i]->print_id); + } + printf (" default: return -1; }\n"); + printf ("}\n"); + printf ("int autocomplete_type_any (struct paramed_type *T) {\n"); + printf (" switch (T->type->name) {\n"); + for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type") && tps[i]->name) { + printf (" case 0x%08x: return autocomplete_type_%s (T);\n", tps[i]->name, tps[i]->print_id); + printf (" case 0x%08x: return autocomplete_type_bare_%s (T);\n", ~tps[i]->name, tps[i]->print_id); + } + printf (" default: return -1; }\n"); + printf ("}\n"); + printf ("struct paramed_type *store_function_any (void) {\n"); + printf (" if (cur_token_len != 1 || *cur_token != '(') { return 0; }\n"); + printf (" local_next_token ();\n"); + printf (" if (cur_token_len == 1 || *cur_token == '.') { \n"); + printf (" local_next_token ();\n"); + printf (" if (cur_token_len != 1 || *cur_token != '=') { return 0; }\n"); + printf (" local_next_token ();\n"); + printf (" };\n"); + printf (" if (cur_token_len < 0) { return 0; }\n"); + for (i = 0; i < fn; i++) { + printf (" if (cur_token_len == %d && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", (int)strlen (fns[i]->id), fns[i]->id); + printf (" out_int (0x%08x);\n", fns[i]->name); + printf (" local_next_token ();\n"); + printf (" struct paramed_type *P = store_function_%s ();\n", fns[i]->print_id); + printf (" if (!P) { return 0; }\n"); + printf (" if (cur_token_len != 1 || *cur_token != ')') { return 0; }\n"); + printf (" local_next_token ();\n"); + printf (" return P;\n"); + printf (" }\n"); + } + printf (" return 0;\n"); + printf ("}\n"); + printf ("int do_autocomplete_function (const char *text, int text_len, int index, char **R) {\n"); + printf (" index ++;\n"); + int i; + for (i = 0; i < fn; i++) { + printf (" if (index == %d) { if (!strncmp (text, \"%s\", text_len)) { *R = tstrdup (\"%s\"); return index; } else { index ++; }}\n", i, fns[i]->id, fns[i]->id); + } + printf (" *R = 0;\n"); + printf (" return 0;\n"); + printf ("}\n"); + printf ("struct paramed_type *autocomplete_function_any (void) {\n"); + printf (" expect_token_ptr_autocomplete (\"(\", 1);\n"); + printf (" if (cur_token_len == -3) { set_autocomplete_type (do_autocomplete_function); }\n"); + printf (" if (cur_token_len < 0) { return 0; }\n"); + for (i = 0; i < fn; i++) { + printf (" if (cur_token_len == %d && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", (int)strlen (fns[i]->id), fns[i]->id); + printf (" local_next_token ();\n"); + printf (" struct paramed_type *P = autocomplete_function_%s ();\n", fns[i]->print_id); + printf (" if (!P) { return 0; }\n"); + printf (" expect_token_ptr_autocomplete (\")\", 1);\n"); + printf (" return P;\n"); + printf (" }\n"); + } + printf (" return 0;\n"); + printf ("}\n"); } else { for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { printf ("int skip_constructor_%s (struct paramed_type *T);\n", tps[i]->constructors[j]->print_id); + printf ("int store_constructor_%s (struct paramed_type *T);\n", tps[i]->constructors[j]->print_id); + printf ("int fetch_constructor_%s (struct paramed_type *T);\n", tps[i]->constructors[j]->print_id); + printf ("int autocomplete_constructor_%s (struct paramed_type *T);\n", tps[i]->constructors[j]->print_id); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { printf ("int skip_type_%s (struct paramed_type *T);\n", tps[i]->print_id); printf ("int skip_type_bare_%s (struct paramed_type *T);\n", tps[i]->print_id); + printf ("int store_type_%s (struct paramed_type *T);\n", tps[i]->print_id); + printf ("int store_type_bare_%s (struct paramed_type *T);\n", tps[i]->print_id); + printf ("int fetch_type_%s (struct paramed_type *T);\n", tps[i]->print_id); + printf ("int fetch_type_bare_%s (struct paramed_type *T);\n", tps[i]->print_id); + printf ("int autocomplete_type_%s (struct paramed_type *T);\n", tps[i]->print_id); + printf ("int do_autocomplete_type_%s (const char *text, int len, int index, char **R);\n", tps[i]->print_id); + printf ("int autocomplete_type_bare_%s (struct paramed_type *T);\n", tps[i]->print_id); + } + for (i = 0; i < fn; i++) { + printf ("struct paramed_type *store_function_%s (void);\n", fns[i]->print_id); + printf ("struct paramed_type *autocomplete_function_%s (void);\n", fns[i]->print_id); } printf ("int skip_type_any (struct paramed_type *T);\n"); + printf ("int store_type_any (struct paramed_type *T);\n"); + printf ("int fetch_type_any (struct paramed_type *T);\n"); + printf ("int autocomplete_type_any (struct paramed_type *T);\n"); + printf ("struct paramed_type *store_function_any (void);\n"); + printf ("struct paramed_type *autocomplete_function_any (void);\n"); /*for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#') { printf ("extern struct tl_type tl_type_%s;\n", tps[i]->id); }*/ for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { - printf ("static struct tl_type tl_type_%s __attribute__ ((unused));\n", tps[i]->print_id); - printf ("static struct tl_type tl_type_%s = {\n", tps[i]->print_id); + printf ("static struct tl_type_descr tl_type_%s __attribute__ ((unused));\n", tps[i]->print_id); + printf ("static struct tl_type_descr tl_type_%s = {\n", tps[i]->print_id); printf (" .name = 0x%08x,\n", tps[i]->name); - printf (" .id = \"%s\"\n", tps[i]->id); + printf (" .id = \"%s\"\n,", tps[i]->id); + printf (" .params_num = %d,\n", tps[i]->arity); + printf (" .params_types = %lld\n", tps[i]->params_types); printf ("};\n"); - printf ("static struct tl_type tl_type_bare_%s __attribute__ ((unused));\n", tps[i]->print_id); - printf ("static struct tl_type tl_type_bare_%s = {\n", tps[i]->print_id); + printf ("static struct tl_type_descr tl_type_bare_%s __attribute__ ((unused));\n", tps[i]->print_id); + printf ("static struct tl_type_descr tl_type_bare_%s = {\n", tps[i]->print_id); printf (" .name = 0x%08x,\n", ~tps[i]->name); - printf (" .id = \"Bare_%s\"\n", tps[i]->id); + printf (" .id = \"Bare_%s\",\n", tps[i]->id); + printf (" .params_num = %d,\n", tps[i]->arity); + printf (" .params_types = %lld\n", tps[i]->params_types); printf ("};\n"); } } diff --git a/interface.c b/interface.c index cdd8c3d..0369f87 100644 --- a/interface.c +++ b/interface.c @@ -340,7 +340,8 @@ enum command_argument { ca_string_end, ca_string, ca_modifier, - ca_command + ca_command, + ca_extf }; struct command { @@ -411,6 +412,7 @@ enum command_argument get_complete_mode (void) { int l = 0; char *r = next_token (&l); if (!r) { return ca_command; } + if (*r == '(') { return ca_extf; } while (r && r[0] == '[' && r[l - 1] == ']') { r = next_token (&l); if (!r) { return ca_command; } @@ -537,6 +539,9 @@ char *command_generator (const char *text, int state) { index = complete_string_list (modifiers, index, text, len, &R); if (c) { rl_line_buffer[rl_point] = c; } return R; + case ca_extf: + index = tglf_extf_autocomplete (text, len, index, &R, rl_line_buffer, rl_point); + return R; default: if (c) { rl_line_buffer[rl_point] = c; } return 0; @@ -1026,6 +1031,12 @@ void print_card_gw (void *extra, int success, int size, int *card) { print_end (); } +void callback_extf (void *extra, int success, char *buf) { + print_start (); + printf ("%s\n", buf); + print_end (); +} + struct tgl_update_callback upd_cb = { .new_msg = print_message_gw, .marked_read = mark_read_upd, @@ -1114,7 +1125,9 @@ void interpreter (char *line UU) { RET; \ } - if (IS_WORD ("contact_list")) { + if (command && *command == '(') { + tgl_do_send_extf (line, strlen (line), callback_extf, 0); + } else if (IS_WORD ("contact_list")) { tgl_do_update_contact_list (print_user_list_gw, 0); } else if (IS_WORD ("dialog_list")) { tgl_do_get_dialog_list (print_dialog_list_gw, 0); diff --git a/mtproto-common.h b/mtproto-common.h index 7ccee61..2ef2aae 100644 --- a/mtproto-common.h +++ b/mtproto-common.h @@ -146,6 +146,12 @@ static inline void out_long (long long x) { packet_ptr += 2; } +static inline void out_double (double x) { + assert (packet_ptr + 2 <= packet_buffer + PACKET_BUFFER_SIZE); + *(double *)packet_ptr = x; + packet_ptr += 2; +} + static inline void clear_packet (void) { packet_ptr = packet_buffer; } @@ -347,6 +353,10 @@ static inline void fetch256 (void *buf) { } } +static inline int in_remaining (void) { + return 4 * (in_end - in_ptr); +} + //int get_random_bytes (unsigned char *buf, int n); int tgl_pad_rsa_encrypt (char *from, int from_len, char *to, int size, BIGNUM *N, BIGNUM *E); diff --git a/queries.c b/queries.c index a927b1b..7144b8d 100644 --- a/queries.c +++ b/queries.c @@ -162,6 +162,7 @@ struct query *tglq_send_query_ex (struct tgl_dc *DC, int ints, void *data, struc } vlogprintf (E_DEBUG, "Msg_id is %lld %p\n", q->msg_id, q); q->methods = methods; + q->type = methods->type; q->DC = DC; q->flags = flags & QUERY_FORCE_SEND; if (queries_tree) { @@ -271,11 +272,11 @@ void tglq_query_result (long long id UU) { } queries_tree = tree_delete_query (queries_tree, q); if (q->methods && q->methods->on_answer) { - if (q->methods->type) { + if (q->type) { int *save = in_ptr; vlogprintf (E_DEBUG, "in_ptr = %p, end_ptr = %p\n", in_ptr, in_end); - if (skip_type_any (q->methods->type) < 0) { - vlogprintf (E_ERROR, "Skipped %ld int out of %ld (type %s)\n", (long)(in_ptr - save), (long)(in_end - save), q->methods->type->type->id); + if (skip_type_any (q->type) < 0) { + vlogprintf (E_ERROR, "Skipped %ld int out of %ld (type %s)\n", (long)(in_ptr - save), (long)(in_end - save), q->type->type->id); assert (0); } @@ -3431,6 +3432,28 @@ void tgl_do_import_card (int size, int *card, void (*callback)(void *callback_ex } /* }}} */ +static int ext_query_on_answer (struct query *q UU) { + if (q->callback) { + char *buf = tglf_extf_fetch (q->type); + ((void (*)(void *, int, char *))q->callback) (q->callback_extra, 1, buf); + } + return 0; +} + +static struct query_methods ext_query_methods = { + .on_answer = ext_query_on_answer, +}; + +void tgl_do_send_extf (char *data, int data_len, void (*callback)(void *callback_extra, int success, char *buf), void *callback_extra) { + clear_packet (); + + ext_query_methods.type = tglf_extf_store (data, data_len); + + if (ext_query_methods.type) { + tglq_send_query (tgl_state.DC_working, packet_ptr - packet_buffer, packet_buffer, &ext_query_methods, 0, callback, callback_extra); + } +} + static void set_flag_4 (void *_D, int success) { struct tgl_dc *D = _D; assert (success); diff --git a/queries.h b/queries.h index 7bf746f..b4a4448 100644 --- a/queries.h +++ b/queries.h @@ -48,6 +48,7 @@ struct query { struct event *ev; struct tgl_dc *DC; struct tgl_session *session; + struct paramed_type *type; void *extra; void *callback; void *callback_extra; diff --git a/tgl.h b/tgl.h index 550f1df..da7ec5d 100644 --- a/tgl.h +++ b/tgl.h @@ -312,4 +312,9 @@ double tglt_get_double_time (void); void tgl_insert_empty_user (int id); void tgl_insert_empty_chat (int id); +int tglf_extf_autocomplete (const char *text, int text_len, int index, char **R, char *data, int data_len); +struct paramed_type *tglf_extf_store (const char *data, int data_len); +void tgl_do_send_extf (char *data, int data_len, void (*callback)(void *callback_extra, int success, char *data), void *callback_extra); +char *tglf_extf_fetch (struct paramed_type *T); + #endif