summaryrefslogtreecommitdiffstats
path: root/txr.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-06-07 06:14:05 -0700
committerKaz Kylheku <kaz@kylheku.com>2016-06-07 06:14:05 -0700
commitca0bcafd671f24481441bb7e9b30293758fe032b (patch)
tree34e6cdf24b6ec5a3e89f0b85fb8eed69e8a7c62d /txr.c
parente1e8eedfd994463db4a3db048117c4bcd9aaf416 (diff)
downloadtxr-ca0bcafd671f24481441bb7e9b30293758fe032b.tar.gz
txr-ca0bcafd671f24481441bb7e9b30293758fe032b.tar.bz2
txr-ca0bcafd671f24481441bb7e9b30293758fe032b.zip
New --free-all option for freeing memory on exit.
Although we are garbage-collected, being able to clean up on shutdown is nevertheless useful for uncovering leaks. Leaks can occur, for instance, due to neglect to free out-of-heap satellite data from objects that are reclaimed by gc. This feature is long overdue. * arith.c, arith.h (arith_free_all): New function. * gc.c, gc.h (gc_free_all): New function. * lib.c (init): Remove program name parameter and redundant initialization of progname globl variable. * lib.h (progname): Superfluous declaration removed. This is already declared in txr.h. (init): Declaration updated. * regex.c (char_set_destroy): Do not check the static allocation flag here; just destroy the object. Do check for a null pointer, though. (char_set_cobj_destroy): This cobj destructor now checks the static flag of the char set object and avoids freeing it. Thus our char set singletons are left alone by gc, but our global freeing function takes care of them. (wide_cs): New static variable moved out of wide_display_char_p to static scope. (regex_free_all): New function. * regex.h (regex_free_all): Declared. * txr.c (progname): const qualifier and initializer removed. (main): Ensure progname is always dynamically allocated, even in the argv[0] == 0 case. Do not pass progname to init; it doesn't take that argument any more. (free_all): New static function. (txr_main): Implement --free-all option. * txr.h (progname): Declaration updated.
Diffstat (limited to 'txr.c')
-rw-r--r--txr.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/txr.c b/txr.c
index 56d67771..ad6f834d 100644
--- a/txr.c
+++ b/txr.c
@@ -56,7 +56,7 @@
#include "txr.h"
const wchli_t *version = wli(TXR_VER);
-const wchar_t *progname = L"txr";
+wchar_t *progname;
static const char *progname_u8;
static val prog_path = nil, sysroot_path = nil;
int opt_noninteractive;
@@ -372,9 +372,9 @@ int main(int argc, char **argv)
{
val stack_bottom = nil;
repress_privilege();
- progname = argv[0] ? utf8_dup_from(argv[0]) : progname;
+ progname = utf8_dup_from(argv[0] ? argv[0]: "txr");
progname_u8 = argv[0];
- init(progname, oom_realloc_handler, &stack_bottom);
+ init(oom_realloc_handler, &stack_bottom);
match_init();
debug_init();
sysroot_init();
@@ -436,6 +436,19 @@ static int gc_delta(val optval)
return 1;
}
+static void free_all(void)
+{
+ static int called;
+
+ if (!called) {
+ called = 1;
+ regex_free_all();
+ gc_free_all();
+ arith_free_all();
+ free(progname);
+ }
+}
+
#ifndef CONFIG_DEBUG_SUPPORT
static void no_dbg_support(val arg)
{
@@ -688,6 +701,9 @@ int txr_main(int argc, char **argv)
opt_noninteractive = 1;
stream_set_prop(std_input, real_time_k, nil);
continue;
+ } else if (equal(opt, lit("free-all"))) {
+ atexit(free_all);
+ continue;
} else {
drop_privilege();
format(std_error, lit("~a: unrecognized long option: --~a\n"),