awk: shuffle functions to reduce forward declarations, no code changes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
		
							
								
								
									
										192
									
								
								editors/awk.c
									
									
									
									
									
								
							
							
						
						
									
										192
									
								
								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)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user