diff options
Diffstat (limited to 'protocols/Telegram/docs/tgl/auto-static.c')
| -rw-r--r-- | protocols/Telegram/docs/tgl/auto-static.c | 328 | 
1 files changed, 328 insertions, 0 deletions
diff --git a/protocols/Telegram/docs/tgl/auto-static.c b/protocols/Telegram/docs/tgl/auto-static.c new file mode 100644 index 0000000000..89a0a176bf --- /dev/null +++ b/protocols/Telegram/docs/tgl/auto-static.c @@ -0,0 +1,328 @@ +/*  +    This file is part of tgl-library + +    This library is free software; you can redistribute it and/or +    modify it under the terms of the GNU Lesser General Public +    License as published by the Free Software Foundation; either +    version 2.1 of the License, or (at your option) any later version. + +    This library is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +    Lesser General Public License for more details. + +    You should have received a copy of the GNU Lesser General Public +    License along with this library; if not, write to the Free Software +    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + +    Copyright Vitaly Valtman 2014-2015 +*/ + +#include "mtproto-common.h" +#include "config.h" +#include <string.h> + +#ifndef DISABLE_EXTF +static int cur_token_len; +static char *cur_token; +static int cur_token_real_len; +static int cur_token_quoted; + +#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); +  assert (autocomplete_string); +  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; + +  if (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; + +  if (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)); +  assert (R); +  R->type = malloc (sizeof (*R->type)); +  assert (R->type); +  memcpy (R->type, P->type, sizeof (*P->type));  +  R->type->id = strdup (P->type->id); +  assert (R->type->id); + +  if (P->type->params_num) { +    R->params = malloc (sizeof (void *) * P->type->params_num); +    assert (R->params); +    int i; +    for (i = 0; i < P->type->params_num; i++) { +      R->params[i] = paramed_type_dup (P->params[i]); +    } +  } +  return R; +} + +void tgl_paramed_type_free (struct paramed_type *P) { +  if (ODDP (P)) { return; } +  if (P->type->params_num) { +    int i; +    for (i = 0; i < P->type->params_num; i++) { +      tgl_paramed_type_free (P->params[i]); +    } +    free (P->params); +  } +  free (P->type->id); +  free (P->type); +  free (P); +} + +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 ++; +  } +} + +static int is_letter (char c) { +  return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '.' || c == '_' || 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; +  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 ++; +    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 ++; +      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; +    } +    return; +  } else { +    if (c) { +      cur_token = buffer_pos ++; +      cur_token_len = 1; +    } else { +      cur_token_len = -3; +      cur_token_real_len = 0; +    } +  } +} + +#define MAX_FVARS 100 +static struct paramed_type *fvars[MAX_FVARS]; +static int fvars_pos; + +static void add_var_to_be_freed (struct paramed_type *P) { +  assert (fvars_pos < MAX_FVARS); +  fvars[fvars_pos ++] = P; +} + +static void free_vars_to_be_freed (void) { +  int i; +  for (i = 0; i < fvars_pos; i++) { +    tgl_paramed_type_free (fvars[i]); +  } +  fvars_pos = 0; +} + +int tglf_extf_autocomplete (struct tgl_state *TLS, 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 (); +    struct paramed_type *P = autocomplete_function_any (); +    free_vars_to_be_freed (); +    if (P) { tgl_paramed_type_free (P); } +  } +  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); +      assert (*R); +      return index; +    } else { +      return -1; +    } +  } else { +    return autocomplete_fun (text, len, index, R); +  } +} + +#endif  | 
