diff options
-rw-r--r-- | editors/awk.c | 192 |
1 files changed, 94 insertions, 98 deletions
diff --git a/editors/awk.c b/editors/awk.c index 0be044e..6833c2f 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -619,18 +619,6 @@ struct globals2 { G.evaluate__seed = 1; \ } while (0) - -/* function prototypes */ -static void handle_special(var *); -static node *parse_expr(uint32_t); -static void chain_group(void); -static var *evaluate(node *, var *); -static rstream *next_input_file(void); -static int fmt_num(char *, int, const char *, double, int); -static int awk_exit(int) NORETURN; - -/* ---- error handling ---- */ - static const char EMSG_UNEXP_EOS[] ALIGN1 = "Unexpected end of string"; static const char EMSG_UNEXP_TOKEN[] ALIGN1 = "Unexpected token"; static const char EMSG_DIV_BY_ZERO[] ALIGN1 = "Division by zero"; @@ -642,10 +630,7 @@ static const char EMSG_UNDEF_FUNC[] ALIGN1 = "Call to undefined function"; static const char EMSG_NO_MATH[] ALIGN1 = "Math support is not compiled in"; static const char EMSG_NEGATIVE_FIELD[] ALIGN1 = "Access to negative field"; -static void zero_out_var(var *vp) -{ - memset(vp, 0, sizeof(*vp)); -} +static int awk_exit(int) NORETURN; static void syntax_error(const char *message) NORETURN; static void syntax_error(const char *message) @@ -653,6 +638,11 @@ static void syntax_error(const char *message) bb_error_msg_and_die("%s:%i: %s", g_progname, g_lineno, message); } +static void zero_out_var(var *vp) +{ + memset(vp, 0, sizeof(*vp)); +} + /* ---- hash stuff ---- */ static unsigned hashidx(const char *name) @@ -885,10 +875,29 @@ static double my_strtod(char **pp) /* -------- working with variables (set/get/copy/etc) -------- */ -static xhash *iamarray(var *v) +static int fmt_num(char *b, int size, const char *format, double n, int int_as_int) { - var *a = v; + int r = 0; + char c; + const char *s = format; + + if (int_as_int && n == (long long)n) { + r = snprintf(b, size, "%lld", (long long)n); + } else { + do { c = *s; } while (c && *++s); + if (strchr("diouxX", c)) { + r = snprintf(b, size, format, (int)n); + } else if (strchr("eEfgG", c)) { + r = snprintf(b, size, format, n); + } else { + syntax_error(EMSG_INV_FMT); + } + } + return r; +} +static xhash *iamarray(var *a) +{ while (a->type & VF_CHILD) a = a->x.parent; @@ -913,6 +922,8 @@ static var *clrvar(var *v) return v; } +static void handle_special(var *); + /* assign string value to variable */ static var *setvar_p(var *v, char *value) { @@ -1284,6 +1295,8 @@ static void mk_re_node(const char *s, node *n, regex_t *re) xregcomp(re + 1, s, REG_EXTENDED | REG_ICASE); } +static node *parse_expr(uint32_t); + static node *parse_lrparen_list(void) { next_token(TC_LPAREN); @@ -1488,6 +1501,8 @@ static void chain_expr(uint32_t info) rollback_token(); } +static void chain_group(void); + static node *chain_loop(node *nn) { node *n, *n2, *save_brk, *save_cont; @@ -1770,6 +1785,8 @@ static node *mk_splitter(const char *s, tsplitter *spl) return n; } +static var *evaluate(node *, var *); + /* Use node as a regular expression. Supplied with node ptr and regex_t * storage space. Return ptr to regex (if result points to preg, it should * be later regfree'd manually). @@ -2222,27 +2239,6 @@ static int awk_getline(rstream *rsm, var *v) return r; } -static int fmt_num(char *b, int size, const char *format, double n, int int_as_int) -{ - int r = 0; - char c; - const char *s = format; - - if (int_as_int && n == (long long)n) { - r = snprintf(b, size, "%lld", (long long)n); - } else { - do { c = *s; } while (c && *++s); - if (strchr("diouxX", c)) { - r = snprintf(b, size, format, (int)n); - } else if (strchr("eEfgG", c)) { - r = snprintf(b, size, format, n); - } else { - syntax_error(EMSG_INV_FMT); - } - } - return r; -} - /* formatted output into an allocated buffer, return ptr to buffer */ #if !ENABLE_FEATURE_AWK_GNU_EXTENSIONS # define awk_printf(a, b) awk_printf(a) @@ -2306,7 +2302,7 @@ static char *awk_printf(node *n, int *len) } free(fmt); -// nvfree(tmpvar, 1); + //nvfree(tmpvar, 1); #undef TMPVAR b = xrealloc(b, i + 1); @@ -2652,6 +2648,64 @@ static NOINLINE var *exec_builtin(node *op, var *res) #undef tspl } +/* if expr looks like "var=value", perform assignment and return 1, + * otherwise return 0 */ +static int is_assignment(const char *expr) +{ + char *exprc, *val; + + if (!isalnum_(*expr) || (val = strchr(expr, '=')) == NULL) { + return FALSE; + } + + exprc = xstrdup(expr); + val = exprc + (val - expr); + *val++ = '\0'; + + unescape_string_in_place(val); + setvar_u(newvar(exprc), val); + free(exprc); + return TRUE; +} + +/* switch to next input file */ +static rstream *next_input_file(void) +{ +#define rsm (G.next_input_file__rsm) +#define files_happen (G.next_input_file__files_happen) + + FILE *F; + const char *fname, *ind; + + if (rsm.F) + fclose(rsm.F); + rsm.F = NULL; + rsm.pos = rsm.adv = 0; + + for (;;) { + if (getvar_i(intvar[ARGIND])+1 >= getvar_i(intvar[ARGC])) { + if (files_happen) + return NULL; + fname = "-"; + F = stdin; + break; + } + ind = getvar_s(incvar(intvar[ARGIND])); + fname = getvar_s(findvar(iamarray(intvar[ARGV]), ind)); + if (fname && *fname && !is_assignment(fname)) { + F = xfopen_stdin(fname); + break; + } + } + + files_happen = TRUE; + setvar_s(intvar[FILENAME], fname); + rsm.F = F; + return &rsm; +#undef rsm +#undef files_happen +} + /* * Evaluate node - the heart of the program. Supplied with subtree * and place where to store result. Returns ptr to result. @@ -3338,64 +3392,6 @@ static int awk_exit(int r) exit(r); } -/* if expr looks like "var=value", perform assignment and return 1, - * otherwise return 0 */ -static int is_assignment(const char *expr) -{ - char *exprc, *val; - - if (!isalnum_(*expr) || (val = strchr(expr, '=')) == NULL) { - return FALSE; - } - - exprc = xstrdup(expr); - val = exprc + (val - expr); - *val++ = '\0'; - - unescape_string_in_place(val); - setvar_u(newvar(exprc), val); - free(exprc); - return TRUE; -} - -/* switch to next input file */ -static rstream *next_input_file(void) -{ -#define rsm (G.next_input_file__rsm) -#define files_happen (G.next_input_file__files_happen) - - FILE *F; - const char *fname, *ind; - - if (rsm.F) - fclose(rsm.F); - rsm.F = NULL; - rsm.pos = rsm.adv = 0; - - for (;;) { - if (getvar_i(intvar[ARGIND])+1 >= getvar_i(intvar[ARGC])) { - if (files_happen) - return NULL; - fname = "-"; - F = stdin; - break; - } - ind = getvar_s(incvar(intvar[ARGIND])); - fname = getvar_s(findvar(iamarray(intvar[ARGV]), ind)); - if (fname && *fname && !is_assignment(fname)) { - F = xfopen_stdin(fname); - break; - } - } - - files_happen = TRUE; - setvar_s(intvar[FILENAME], fname); - rsm.F = F; - return &rsm; -#undef rsm -#undef files_happen -} - int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int awk_main(int argc UNUSED_PARAM, char **argv) { |