summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko2021-06-29 18:33:25 +0200
committerDenys Vlasenko2021-06-29 19:06:59 +0200
commitb3c91a127f8baecee0265ba92898ae1e718bdb31 (patch)
tree2f5f35d1bc4e92d10633fbb21abc1df446551907
parent21fbee2e87ddf7b47bb501b6529b63ac2b3af0bd (diff)
downloadbusybox-b3c91a127f8baecee0265ba92898ae1e718bdb31.zip
busybox-b3c91a127f8baecee0265ba92898ae1e718bdb31.tar.gz
awk: free unused parsing structures after parse is done
function old new delta hash_clear - 90 +90 awk_main 827 849 +22 clear_array 90 - -90 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 1/0 up/down: 112/-90) Total: 22 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--editors/awk.c74
1 files changed, 47 insertions, 27 deletions
diff --git a/editors/awk.c b/editors/awk.c
index 6142144..4e29b28 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -530,7 +530,8 @@ struct globals {
xhash *ahash; /* argument names, used only while parsing function bodies */
xhash *fnhash; /* function names, used only in parsing stage */
xhash *vhash; /* variables and arrays */
- xhash *fdhash; /* file objects, used only in execution stage */
+ //xhash *fdhash; /* file objects, used only in execution stage */
+ //we are reusing ahash as fdhash, via define (see later)
const char *g_progname;
int g_lineno;
int nfields;
@@ -592,10 +593,13 @@ struct globals2 {
#define break_ptr (G1.break_ptr )
#define continue_ptr (G1.continue_ptr)
#define iF (G1.iF )
-#define vhash (G1.vhash )
#define ahash (G1.ahash )
-#define fdhash (G1.fdhash )
#define fnhash (G1.fnhash )
+#define vhash (G1.vhash )
+#define fdhash ahash
+//^^^^^^^^^^^^^^^^^^ ahash is cleared after every function parsing,
+// and ends up empty after parsing phase. Thus, we can simply reuse it
+// for fdhash in execution stage.
#define g_progname (G1.g_progname )
#define g_lineno (G1.g_lineno )
#define nfields (G1.nfields )
@@ -682,6 +686,33 @@ static xhash *hash_init(void)
return newhash;
}
+static void hash_clear(xhash *hash)
+{
+ unsigned i;
+ hash_item *hi, *thi;
+
+ for (i = 0; i < hash->csize; i++) {
+ hi = hash->items[i];
+ while (hi) {
+ thi = hi;
+ hi = hi->next;
+ free(thi->data.v.string);
+ free(thi);
+ }
+ hash->items[i] = NULL;
+ }
+ hash->glen = hash->nel = 0;
+}
+
+#if 0 //UNUSED
+static void hash_free(xhash *hash)
+{
+ hash_clear(hash);
+ free(hash->items);
+ free(hash);
+}
+#endif
+
/* find item in hash, return ptr to data, NULL if not found */
static void *hash_search(xhash *hash, const char *name)
{
@@ -869,23 +900,7 @@ static xhash *iamarray(var *v)
return a->x.array;
}
-static void clear_array(xhash *array)
-{
- unsigned i;
- hash_item *hi, *thi;
-
- for (i = 0; i < array->csize; i++) {
- hi = array->items[i];
- while (hi) {
- thi = hi;
- hi = hi->next;
- free(thi->data.v.string);
- free(thi);
- }
- array->items[i] = NULL;
- }
- array->glen = array->nel = 0;
-}
+#define clear_array(array) hash_clear(array)
/* clear a variable */
static var *clrvar(var *v)
@@ -1742,7 +1757,7 @@ static void parse_program(char *p)
}
seq = &f->body;
chain_group();
- clear_array(ahash);
+ hash_clear(ahash);
} else if (tclass & TS_OPSEQ) {
debug_printf_parse("%s: TS_OPSEQ\n", __func__);
rollback_token();
@@ -3471,11 +3486,16 @@ int awk_main(int argc UNUSED_PARAM, char **argv)
bb_show_usage();
parse_program(*argv++);
}
- //free_hash(ahash) // ~250 bytes, arg names, used only during parse of function bodies
- //ahash = NULL; // debug
- //free_hash(fnhash) // ~250 bytes, used only for function names
- //fnhash = NULL; // debug
- /* parsing done, on to executing */
+ /* Free unused parse structures */
+ //hash_free(fnhash); // ~250 bytes when empty, used only for function names
+ //^^^^^^^^^^^^^^^^^ does not work, hash_clear() inside SEGVs
+ // (IOW: hash_clear() assumes it's a hash of variables. fnhash is not).
+ free(fnhash->items);
+ free(fnhash);
+ fnhash = NULL; // debug
+ //hash_free(ahash); // empty after parsing, will reuse as fdhash instead of freeing
+
+ /* Parsing done, on to executing */
/* fill in ARGV array */
setari_u(intvar[ARGV], 0, "awk");
@@ -3484,7 +3504,7 @@ int awk_main(int argc UNUSED_PARAM, char **argv)
setari_u(intvar[ARGV], ++i, *argv++);
setvar_i(intvar[ARGC], i + 1);
- fdhash = hash_init();
+ //fdhash = ahash - done via define
newfile("/dev/stdin")->F = stdin;
newfile("/dev/stdout")->F = stdout;
newfile("/dev/stderr")->F = stderr;