diff options
Diffstat (limited to 'libs/tgl/src/auto-static-print.c')
-rw-r--r-- | libs/tgl/src/auto-static-print.c | 461 |
1 files changed, 461 insertions, 0 deletions
diff --git a/libs/tgl/src/auto-static-print.c b/libs/tgl/src/auto-static-print.c new file mode 100644 index 0000000000..3c4e810fad --- /dev/null +++ b/libs/tgl/src/auto-static-print.c @@ -0,0 +1,461 @@ +/* + 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 <string.h> +#include <stdlib.h> +#include <stdio.h> + +static int cur_token_len; +static char *cur_token; +static int cur_token_real_len; +static int cur_token_quoted; +static int multiline_output = 1; +static int multiline_offset; +static int multiline_offset_size = 2; + +static int *in_ptr, *in_end; + +static inline int fetch_int (void) { + return *(in_ptr ++); +} + +static inline int fetch_long (void) { + long long r = *(long long *)in_ptr; + in_ptr += 2; + return r; +} + +static inline int fetch_long (void) { + long long r = *(long long *)in_ptr; + in_ptr += 2; + return r; +} + +static inline void out_int (int a) {} +static inline void out_double (double a) {} +static inline void out_string (char *s, int l) {} +static inline void out_long (long long a) {} + +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); + 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 (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); + } +} + +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)\ + +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 + 1])) & 0xc0) != 0x80) { + return -1; + } + } + return n + 1; +} + +static void print_escaped_string (const char *str, int len) { + eprintf ("\""); + const char *end = str + len; + while (str < end) { + 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 ("\""); +} + +static void print_offset (void) { + int i; + for (i = 0; i < multiline_offset; i++) { + eprintf (" "); + } +} + +char *tglf_extf_fetch (struct paramed_type *T) { + out_buf_pos = 0; + fetch_type_any (T); + return out_buf; +} |