diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-06-29 18:33:25 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-06-29 19:06:59 +0200 |
commit | b3c91a127f8baecee0265ba92898ae1e718bdb31 (patch) | |
tree | 2f5f35d1bc4e92d10633fbb21abc1df446551907 | |
parent | 21fbee2e87ddf7b47bb501b6529b63ac2b3af0bd (diff) | |
download | busybox-w32-b3c91a127f8baecee0265ba92898ae1e718bdb31.tar.gz busybox-w32-b3c91a127f8baecee0265ba92898ae1e718bdb31.tar.bz2 busybox-w32-b3c91a127f8baecee0265ba92898ae1e718bdb31.zip |
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.c | 74 |
1 files changed, 47 insertions, 27 deletions
diff --git a/editors/awk.c b/editors/awk.c index 6142144bb..4e29b28cf 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -530,7 +530,8 @@ struct globals { | |||
530 | xhash *ahash; /* argument names, used only while parsing function bodies */ | 530 | xhash *ahash; /* argument names, used only while parsing function bodies */ |
531 | xhash *fnhash; /* function names, used only in parsing stage */ | 531 | xhash *fnhash; /* function names, used only in parsing stage */ |
532 | xhash *vhash; /* variables and arrays */ | 532 | xhash *vhash; /* variables and arrays */ |
533 | xhash *fdhash; /* file objects, used only in execution stage */ | 533 | //xhash *fdhash; /* file objects, used only in execution stage */ |
534 | //we are reusing ahash as fdhash, via define (see later) | ||
534 | const char *g_progname; | 535 | const char *g_progname; |
535 | int g_lineno; | 536 | int g_lineno; |
536 | int nfields; | 537 | int nfields; |
@@ -592,10 +593,13 @@ struct globals2 { | |||
592 | #define break_ptr (G1.break_ptr ) | 593 | #define break_ptr (G1.break_ptr ) |
593 | #define continue_ptr (G1.continue_ptr) | 594 | #define continue_ptr (G1.continue_ptr) |
594 | #define iF (G1.iF ) | 595 | #define iF (G1.iF ) |
595 | #define vhash (G1.vhash ) | ||
596 | #define ahash (G1.ahash ) | 596 | #define ahash (G1.ahash ) |
597 | #define fdhash (G1.fdhash ) | ||
598 | #define fnhash (G1.fnhash ) | 597 | #define fnhash (G1.fnhash ) |
598 | #define vhash (G1.vhash ) | ||
599 | #define fdhash ahash | ||
600 | //^^^^^^^^^^^^^^^^^^ ahash is cleared after every function parsing, | ||
601 | // and ends up empty after parsing phase. Thus, we can simply reuse it | ||
602 | // for fdhash in execution stage. | ||
599 | #define g_progname (G1.g_progname ) | 603 | #define g_progname (G1.g_progname ) |
600 | #define g_lineno (G1.g_lineno ) | 604 | #define g_lineno (G1.g_lineno ) |
601 | #define nfields (G1.nfields ) | 605 | #define nfields (G1.nfields ) |
@@ -682,6 +686,33 @@ static xhash *hash_init(void) | |||
682 | return newhash; | 686 | return newhash; |
683 | } | 687 | } |
684 | 688 | ||
689 | static void hash_clear(xhash *hash) | ||
690 | { | ||
691 | unsigned i; | ||
692 | hash_item *hi, *thi; | ||
693 | |||
694 | for (i = 0; i < hash->csize; i++) { | ||
695 | hi = hash->items[i]; | ||
696 | while (hi) { | ||
697 | thi = hi; | ||
698 | hi = hi->next; | ||
699 | free(thi->data.v.string); | ||
700 | free(thi); | ||
701 | } | ||
702 | hash->items[i] = NULL; | ||
703 | } | ||
704 | hash->glen = hash->nel = 0; | ||
705 | } | ||
706 | |||
707 | #if 0 //UNUSED | ||
708 | static void hash_free(xhash *hash) | ||
709 | { | ||
710 | hash_clear(hash); | ||
711 | free(hash->items); | ||
712 | free(hash); | ||
713 | } | ||
714 | #endif | ||
715 | |||
685 | /* find item in hash, return ptr to data, NULL if not found */ | 716 | /* find item in hash, return ptr to data, NULL if not found */ |
686 | static void *hash_search(xhash *hash, const char *name) | 717 | static void *hash_search(xhash *hash, const char *name) |
687 | { | 718 | { |
@@ -869,23 +900,7 @@ static xhash *iamarray(var *v) | |||
869 | return a->x.array; | 900 | return a->x.array; |
870 | } | 901 | } |
871 | 902 | ||
872 | static void clear_array(xhash *array) | 903 | #define clear_array(array) hash_clear(array) |
873 | { | ||
874 | unsigned i; | ||
875 | hash_item *hi, *thi; | ||
876 | |||
877 | for (i = 0; i < array->csize; i++) { | ||
878 | hi = array->items[i]; | ||
879 | while (hi) { | ||
880 | thi = hi; | ||
881 | hi = hi->next; | ||
882 | free(thi->data.v.string); | ||
883 | free(thi); | ||
884 | } | ||
885 | array->items[i] = NULL; | ||
886 | } | ||
887 | array->glen = array->nel = 0; | ||
888 | } | ||
889 | 904 | ||
890 | /* clear a variable */ | 905 | /* clear a variable */ |
891 | static var *clrvar(var *v) | 906 | static var *clrvar(var *v) |
@@ -1742,7 +1757,7 @@ static void parse_program(char *p) | |||
1742 | } | 1757 | } |
1743 | seq = &f->body; | 1758 | seq = &f->body; |
1744 | chain_group(); | 1759 | chain_group(); |
1745 | clear_array(ahash); | 1760 | hash_clear(ahash); |
1746 | } else if (tclass & TS_OPSEQ) { | 1761 | } else if (tclass & TS_OPSEQ) { |
1747 | debug_printf_parse("%s: TS_OPSEQ\n", __func__); | 1762 | debug_printf_parse("%s: TS_OPSEQ\n", __func__); |
1748 | rollback_token(); | 1763 | rollback_token(); |
@@ -3471,11 +3486,16 @@ int awk_main(int argc UNUSED_PARAM, char **argv) | |||
3471 | bb_show_usage(); | 3486 | bb_show_usage(); |
3472 | parse_program(*argv++); | 3487 | parse_program(*argv++); |
3473 | } | 3488 | } |
3474 | //free_hash(ahash) // ~250 bytes, arg names, used only during parse of function bodies | 3489 | /* Free unused parse structures */ |
3475 | //ahash = NULL; // debug | 3490 | //hash_free(fnhash); // ~250 bytes when empty, used only for function names |
3476 | //free_hash(fnhash) // ~250 bytes, used only for function names | 3491 | //^^^^^^^^^^^^^^^^^ does not work, hash_clear() inside SEGVs |
3477 | //fnhash = NULL; // debug | 3492 | // (IOW: hash_clear() assumes it's a hash of variables. fnhash is not). |
3478 | /* parsing done, on to executing */ | 3493 | free(fnhash->items); |
3494 | free(fnhash); | ||
3495 | fnhash = NULL; // debug | ||
3496 | //hash_free(ahash); // empty after parsing, will reuse as fdhash instead of freeing | ||
3497 | |||
3498 | /* Parsing done, on to executing */ | ||
3479 | 3499 | ||
3480 | /* fill in ARGV array */ | 3500 | /* fill in ARGV array */ |
3481 | setari_u(intvar[ARGV], 0, "awk"); | 3501 | setari_u(intvar[ARGV], 0, "awk"); |
@@ -3484,7 +3504,7 @@ int awk_main(int argc UNUSED_PARAM, char **argv) | |||
3484 | setari_u(intvar[ARGV], ++i, *argv++); | 3504 | setari_u(intvar[ARGV], ++i, *argv++); |
3485 | setvar_i(intvar[ARGC], i + 1); | 3505 | setvar_i(intvar[ARGC], i + 1); |
3486 | 3506 | ||
3487 | fdhash = hash_init(); | 3507 | //fdhash = ahash - done via define |
3488 | newfile("/dev/stdin")->F = stdin; | 3508 | newfile("/dev/stdin")->F = stdin; |
3489 | newfile("/dev/stdout")->F = stdout; | 3509 | newfile("/dev/stdout")->F = stdout; |
3490 | newfile("/dev/stderr")->F = stderr; | 3510 | newfile("/dev/stderr")->F = stderr; |