Fixed numerous memory leaks.
Canonicalised the test output file names.
+Fri Jan 21 19:54:14 WST 2005 John Darrington <john@darrington.wattle.id.au>
+
+ * linked-list.[ch] Added
+
+ * examine.q file-handle.[hq] font.h glob.c groff-font.c postscript.c
+ set.q: Yet more memory leaks
+
Tue Jan 18 23:12:40 WST 2005 John Darrington <john@darrington.wattle.id.au>
* t-test.q examine.q : More memory leaks fixed.
format.h formats.c get.c getline.c getline.h glob.c glob.h \
groff-font.c group.c group.h group_proc.h \
hash.c hash.h histogram.c histogram.h \
-html.c htmlP.h include.c inpt-pgm.c lexer.c \
-lexer.h levene.c levene.h log.h loop.c magic.c magic.h main.c main.h \
+html.c htmlP.h include.c inpt-pgm.c lexer.c lexer.h levene.c levene.h \
+linked-list.c linked-list.h log.h loop.c magic.c magic.h main.c main.h \
matrix-data.c mis-val.c misc.c misc.h modify-vars.c \
moments.c moments.h numeric.c output.c output.h \
percentiles.c percentiles.h permissions.c \
if ( dependent_vars )
free (dependent_vars);
+ {
+ struct factor *f = factors ;
+ while ( f )
+ {
+ struct factor *ff = f;
+
+ f = f->next;
+ free ( ff->fs );
+ hsh_destroy ( ff->fstats ) ;
+ free ( ff ) ;
+ }
+ }
+
subc_list_double_destroy(&percentile_list);
return CMD_SUCCESS;
MODE_BINARY /* Fixed-length records. */
};
+
+
+void fh_init(void);
+void fh_done(void);
+
/* Parsing handles. */
struct file_handle *fh_parse (void);
+
/* Opening and closing handles. */
void **fh_open (struct file_handle *, const char *type, const char *mode);
int fh_close (struct file_handle *, const char *type, const char *mode);
#include "error.h"
#include "magic.h"
#include "var.h"
+#include "linked-list.h"
+
/* (headers) */
/* File handle. */
return handle;
}
+void
+destroy_file_handle(struct file_handle *fh, void *aux UNUSED)
+{
+ free (fh->name);
+ free (fh->filename);
+ fn_free_identity (fh->identity);
+ free (fh);
+}
+
static const char *
mode_name (const char *mode)
{
return h->open_cnt;
}
+
+static struct linked_list *handle_list;
+
+
/* Parses a file handle name, which may be a filename as a string or
a file handle name as an identifier. Returns the file handle or
NULL on failure. */
char *handle_name = xmalloc (strlen (filename) + 3);
sprintf (handle_name, "\"%s\"", filename);
handle = create_file_handle (handle_name, filename);
+ ll_push_front(handle_list, handle);
free (handle_name);
}
lex_get ();
+
return handle;
}
return handle->tab_width;
}
+
+void
+fh_init(void)
+{
+ handle_list = ll_create(destroy_file_handle,0);
+}
+
+void
+fh_done(void)
+{
+ assert(handle_list);
+
+ ll_destroy(handle_list);
+ handle_list = 0;
+}
+
+
/*
Local variables:
mode: c
struct font_desc *groff_find_font (const char *dev, const char *name);
int groff_read_DESC (const char *dev_name, struct groff_device_info * dev);
void groff_init (void);
+void groff_done (void);
struct font_desc *default_font (void);
#endif /* ENABLE_NLS */
fn_init ();
+ fh_init ();
getl_initialize ();
/* PORTME: If your system/OS has the nasty tendency to halt with a
free(logfn);
done_settings();
ds_destroy (&tokstr);
+
+ fh_done();
}
static void
/* Typical whitespace characters for tokenizing. */
static const char whitespace[] = " \t\n\r\v";
-void
-groff_init (void)
-{
- space_index = font_char_name_to_index ("space");
-}
-
/* Some notes on the groff_font(8) manpage:
DESC file format: A typical PostScript `res' would be 72000, with
}
hash;
+void
+groff_init (void)
+{
+ space_index = font_char_name_to_index ("space");
+}
+
+void
+groff_done (void)
+{
+ free (hash.tab) ;
+ pool_destroy(hash.ar);
+}
+
+
/* Searches for NAME in the global character code table, returns the
index if found; otherwise inserts NAME and returns the new
index. */
--- /dev/null
+/* PSPP - computes sample statistics.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+ Written by John Darrington <john@darrington.wattle.id.au>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include <config.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "alloc.h"
+#include "linked-list.h"
+
+/* Iteration */
+
+/* Return the first element in LL */
+void *
+ll_first (const struct linked_list *ll, struct ll_iterator *li)
+{
+ assert(ll);
+
+ li->p = ll->head;
+
+ return ll->head->entry;
+}
+
+/* Return the next element in LL iterated by LI */
+void *
+ll_next (const struct linked_list *ll, struct ll_iterator *li)
+{
+ assert( ll ) ;
+
+ li->p = li->p->next;
+
+ if ( ! li->p )
+ return 0;
+
+ return li->p->entry;
+}
+
+
+/* Create a linked list.
+ Elements will be freed using F and AUX
+*/
+struct linked_list *
+ll_create( ll_free_func *f , void *aux)
+{
+ struct linked_list *ll = xmalloc ( sizeof(struct linked_list) ) ;
+
+ ll->head = 0;
+ ll->free = f;
+ ll->aux = aux;
+
+ return ll;
+}
+
+
+/* Destroy a linked list */
+void
+ll_destroy(struct linked_list *ll)
+{
+ struct node *n = ll->head;
+
+ while (n)
+ {
+ struct node *nn = n->next;
+ if ( ll->free )
+ ll->free(n->entry, ll->aux);
+ free (n);
+ n = nn;
+ }
+
+ free (ll);
+}
+
+
+/* Push a an element ENTRY onto the list LL */
+void
+ll_push_front(struct linked_list *ll, void *entry)
+{
+ struct node *n ;
+ assert (ll);
+
+ n = xmalloc (sizeof(struct node) );
+ n->next = ll->head;
+ n->entry = entry;
+ ll->head = n;
+}
+
--- /dev/null
+#ifndef LL_H
+#define LL_H
+
+
+struct node
+{
+ void *entry;
+ struct node *next;
+};
+
+
+
+typedef void ll_free_func (void *, void *aux);
+
+struct linked_list
+{
+ struct node *head;
+ ll_free_func *free;
+ void *aux;
+};
+
+
+struct ll_iterator
+{
+ struct node *p;
+};
+
+
+/* Iteration */
+
+/* Return the first element in LL */
+void * ll_first (const struct linked_list *ll, struct ll_iterator *li);
+
+/* Return the next element in LL iterated by LI */
+void * ll_next (const struct linked_list *ll, struct ll_iterator *li);
+
+/* Create a linked list.
+ Elements will be freed using F and AUX
+*/
+struct linked_list * ll_create( ll_free_func *F , void *aux);
+
+/* Destroy a linked list LL */
+void ll_destroy(struct linked_list *ll);
+
+/* Push a an element ENTRY onto the list LL */
+void ll_push_front(struct linked_list *ll, void *entry);
+
+#endif
static void free_font_entry (void *, void *foo);
static struct font_entry *load_font (struct outp_driver *, const char *dit);
static void init_fonts (void);
+static void done_fonts (void);
static void dump_lines (struct outp_driver *this);
static int
ps_close_global (struct outp_class *this UNUSED)
{
+ groff_done ();
+ done_fonts ();
return 1;
}
NULL, NULL);
}
+static void
+done_fonts (void)
+{
+ hsh_destroy (ps_fonts);
+}
+
/* Loads the font having Groff name DIT into THIS driver instance.
Specifically, adds it into the THIS driver's `loaded' hash
table. */
ps_text_get_size,
ps_text_metrics,
ps_text_draw,
+
+ NULL,
+ NULL
};
/* EPSF driver class. FIXME: Probably doesn't work right. */
ps_text_get_size,
ps_text_metrics,
ps_text_draw,
+
+ NULL,
+ NULL
};
#endif /* NO_POSTSCRIPT */
void
done_settings(void)
{
- free(set_pager);
- free(set_journal);
-
- free(cmd.s_endcmd);
- free(cmd.s_prompt);
- free(cmd.s_cprompt);
- free(cmd.s_dprompt);
+ if ( rng )
+ gsl_rng_free (rng);
+ free (set_pager);
+ free (set_journal);
+
+ free (cmd.s_endcmd);
+ free (cmd.s_prompt);
+ free (cmd.s_cprompt);
+ free (cmd.s_dprompt);
}
# crash if given an alphanumeric variable
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
TEMPDIR=/tmp/pspp-tst-$$
TESTFILE=$TEMPDIR/`basename $0`.sps
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
# infinite loop. Thus, this test passes as long as it completes.
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
# This program tests for a bug in the `compute' command
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
# This program tests for a bug which crashed pspp when doing a crosstabs
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
# invalid input
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
# Commands existed in a input file
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
# would crash if a data file with only one case was presented
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
cd $TEMPDIR
activity="create program"
-cat > $TEMPDIR/rnd.sps <<EOF
+cat > $TESTFILE <<EOF
data list list /id * abc *.
begin data.
1 3.5
EOF
if [ $? -ne 0 ] ; then no_result ; fi
-$SUPERVISOR $here/../src/pspp -o raw-ascii $TEMPDIR/rnd.sps
+$SUPERVISOR $here/../src/pspp -o raw-ascii $TESTFILE
if [ $? -ne 0 ] ; then no_result ; fi
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
cd $TEMPDIR
activity="create program"
-cat > $TEMPDIR/rnd.sps <<EOF
+cat > $TESTFILE <<EOF
set seed=10.
input program.
+ loop #i = 1 to 20.
if [ $? -ne 0 ] ; then no_result ; fi
activity="run program"
-$SUPERVISOR $here/../src/pspp -o raw-ascii $TEMPDIR/rnd.sps
+$SUPERVISOR $here/../src/pspp -o raw-ascii $TESTFILE
if [ $? -ne 0 ] ; then no_result ; fi
# This program tests ....
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
# BUG #11227
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
# a single alpha variable is specified for the independent variable
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
# works ok with a TEMPORARY transformation
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
cd $TEMPDIR
activity="create program"
-cat > $TEMPDIR/rnd.sps <<EOF
+cat > $TESTFILE <<EOF
DATA LIST LIST /id * a * .
BEGIN DATA.
1 3.5
#The syntax was invalid. Therefore pspp must return non zero.
activity="run program"
-$SUPERVISOR $here/../src/pspp -o raw-ascii $TEMPDIR/rnd.sps > /dev/null
+$SUPERVISOR $here/../src/pspp -o raw-ascii $TESTFILE > /dev/null
if [ $? -ne 1 ] ; then fail ; fi
pass;
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
cd $TEMPDIR
activity="create program"
-cat > $TEMPDIR/rnd.sps <<EOF
+cat > $TESTFILE <<EOF
DATA LIST LIST NOTABLE /x *.
begin data.
1
EOF
if [ $? -ne 0 ] ; then no_result ; fi
-$SUPERVISOR $here/../src/pspp -o raw-ascii $TEMPDIR/rnd.sps
+$SUPERVISOR $here/../src/pspp -o raw-ascii $TESTFILE
if [ $? -ne 0 ] ; then no_result ; fi
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
# which caused a crash if it had a trailing /
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
here=`pwd`;
cd $TEMPDIR
activity="create program"
-cat > $TEMPDIR/rnd.sps <<EOF
+cat > $TESTFILE <<EOF
DATA LIST LIST /a * pref * .
BEGIN DATA.
1.00 1.00
#Invalid syntax --- return value is non zero.
activity="run program"
-$SUPERVISOR $here/../src/pspp -o raw-ascii $TEMPDIR/rnd.sps > /dev/null
+$SUPERVISOR $here/../src/pspp -o raw-ascii $TESTFILE > /dev/null
if [ $? -ne 1 ] ; then fail ; fi
pass;