mirror of
git://projects.qi-hardware.com/fped.git
synced 2024-11-24 23:05:56 +02:00
- delete.c: added more destructor functions
- deallocate all our data structures on exit (to help find memory leaks, bad pointers, and general logic errors) - fixed memory leak when allocating pad names in instantiation - added "magic" environment variable FPED_NO_GUI to run fped without initializing Gtk+ - added valgrind wrapper "leakcheck" - delete.c: destroy() now requires a deletion to exist - vacate_op: free string expressions - destroy_obj: free measurement labels - delete_references: use do_delete_obj so the we don't bump the group number - delete_frame: delete references after deleting the frame itself, so they end up on the stack above the frame and get destroyed first - do_delete_vec: like above, even though it doesn't matter here git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5506 99fdad57-331a-0410-800a-d7fa5415bdb3
This commit is contained in:
parent
2737f8a3fa
commit
9e7e804d1a
112
delete.c
112
delete.c
@ -146,9 +146,6 @@ static void do_delete_vec(struct vec *vec)
|
||||
struct vec *walk, *prev;
|
||||
struct deletion *del;
|
||||
|
||||
delete_vecs_by_ref(vec->frame->vecs, vec);
|
||||
delete_objs_by_ref(&vec->frame->objs, vec);
|
||||
|
||||
prev = NULL;
|
||||
for (walk = vec->frame->vecs; walk != vec; walk = walk->next)
|
||||
prev = walk;
|
||||
@ -159,6 +156,9 @@ static void do_delete_vec(struct vec *vec)
|
||||
del = new_deletion(dt_vec);
|
||||
del->u.vec.ref = vec;
|
||||
del->u.vec.prev = prev;
|
||||
|
||||
delete_vecs_by_ref(vec->frame->vecs, vec);
|
||||
delete_objs_by_ref(&vec->frame->objs, vec);
|
||||
}
|
||||
|
||||
|
||||
@ -204,6 +204,8 @@ static void destroy_obj(struct obj *obj)
|
||||
free_expr(obj->u.arc.width);
|
||||
break;
|
||||
case ot_meas:
|
||||
if (obj->u.meas.label)
|
||||
free(obj->u.meas.label);
|
||||
if (obj->u.meas.offset)
|
||||
free_expr(obj->u.meas.offset);
|
||||
break;
|
||||
@ -257,6 +259,20 @@ static void undelete_obj(struct obj *obj, struct obj *prev)
|
||||
/* ----- rows -------------------------------------------------------------- */
|
||||
|
||||
|
||||
static void destroy_row(struct row *row)
|
||||
{
|
||||
struct value *next_value;
|
||||
|
||||
while (row->values) {
|
||||
next_value = row->values->next;
|
||||
free_expr(row->values->expr);
|
||||
free(row->values);
|
||||
row->values = next_value;
|
||||
}
|
||||
free(row);
|
||||
}
|
||||
|
||||
|
||||
void delete_row(struct row *row)
|
||||
{
|
||||
struct deletion *del;
|
||||
@ -355,6 +371,23 @@ static void undelete_column(const struct column *col)
|
||||
/* ----- tables ------------------------------------------------------------ */
|
||||
|
||||
|
||||
static void destroy_table(struct table *table)
|
||||
{
|
||||
struct var *next_var;
|
||||
|
||||
while (table->vars) {
|
||||
next_var = table->vars->next;
|
||||
free(table->vars);
|
||||
table->vars = next_var;
|
||||
}
|
||||
while (table->rows) {
|
||||
delete_row(table->rows);
|
||||
destroy();
|
||||
}
|
||||
free(table);
|
||||
}
|
||||
|
||||
|
||||
void delete_table(struct table *table)
|
||||
{
|
||||
struct frame *frame = table->vars->frame;
|
||||
@ -392,6 +425,14 @@ static void undelete_table(struct table *table, struct table *prev)
|
||||
/* ----- loops ------------------------------------------------------------- */
|
||||
|
||||
|
||||
static void destroy_loop(struct loop *loop)
|
||||
{
|
||||
free_expr(loop->from.expr);
|
||||
free_expr(loop->to.expr);
|
||||
free(loop);
|
||||
}
|
||||
|
||||
|
||||
void delete_loop(struct loop *loop)
|
||||
{
|
||||
struct frame *frame = loop->var.frame;
|
||||
@ -429,6 +470,28 @@ static void undelete_loop(struct loop *loop, struct loop *prev)
|
||||
/* ----- frames ------------------------------------------------------------ */
|
||||
|
||||
|
||||
static void destroy_frame(struct frame *frame)
|
||||
{
|
||||
while (frame->tables) {
|
||||
delete_table(frame->tables);
|
||||
destroy();
|
||||
}
|
||||
while (frame->loops) {
|
||||
delete_loop(frame->loops);
|
||||
destroy();
|
||||
}
|
||||
while (frame->vecs) {
|
||||
delete_vec(frame->vecs);
|
||||
destroy();
|
||||
}
|
||||
while (frame->objs) {
|
||||
delete_obj(frame->objs);
|
||||
destroy();
|
||||
}
|
||||
free(frame);
|
||||
}
|
||||
|
||||
|
||||
static void delete_references(const struct frame *ref)
|
||||
{
|
||||
struct frame *frame;
|
||||
@ -438,7 +501,7 @@ static void delete_references(const struct frame *ref)
|
||||
for (obj = frame->objs; obj; obj = obj->next)
|
||||
if (obj->type == ot_frame)
|
||||
if (obj->u.frame.ref == ref)
|
||||
delete_obj(obj);
|
||||
do_delete_obj(obj);
|
||||
}
|
||||
|
||||
|
||||
@ -447,7 +510,6 @@ void delete_frame(struct frame *frame)
|
||||
struct deletion *del;
|
||||
|
||||
groups++;
|
||||
delete_references(frame);
|
||||
|
||||
del = new_deletion(dt_frame);
|
||||
del->u.frame.ref = frame;
|
||||
@ -459,6 +521,8 @@ void delete_frame(struct frame *frame)
|
||||
frame->prev->next = frame->next;
|
||||
else
|
||||
frames = frame->next;
|
||||
|
||||
delete_references(frame);
|
||||
}
|
||||
|
||||
|
||||
@ -478,12 +542,10 @@ static void undelete_frame(struct frame *frame, struct frame *prev)
|
||||
/* ----- destroy/undelete interface ---------------------------------------- */
|
||||
|
||||
|
||||
int destroy(void)
|
||||
static void destroy_one(void)
|
||||
{
|
||||
struct deletion *del;
|
||||
|
||||
if (!deletions)
|
||||
return 0;
|
||||
del = deletions;
|
||||
switch (del->type) {
|
||||
case dt_vec:
|
||||
@ -493,15 +555,36 @@ int destroy(void)
|
||||
destroy_obj(del->u.obj.ref);
|
||||
break;
|
||||
case dt_frame:
|
||||
abort();
|
||||
/* @@@ later */
|
||||
destroy_frame(del->u.frame.ref);
|
||||
break;
|
||||
case dt_loop:
|
||||
destroy_loop(del->u.loop.ref);
|
||||
break;
|
||||
case dt_table:
|
||||
destroy_table(del->u.table.ref);
|
||||
break;
|
||||
case dt_row:
|
||||
destroy_row(del->u.row.ref);
|
||||
break;
|
||||
case dt_column:
|
||||
abort(); /* @@@ later */
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
deletions = del->next;
|
||||
free(del);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void destroy(void)
|
||||
{
|
||||
int group;
|
||||
|
||||
assert(deletions);
|
||||
group = deletions->group;
|
||||
while (deletions && deletions->group == group)
|
||||
destroy_one();
|
||||
}
|
||||
|
||||
|
||||
@ -554,3 +637,10 @@ int undelete(void)
|
||||
undelete_one();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void purge(void)
|
||||
{
|
||||
while (deletions)
|
||||
destroy();
|
||||
}
|
||||
|
3
delete.h
3
delete.h
@ -25,7 +25,8 @@ void delete_column(struct table *table, int n);
|
||||
void delete_table(struct table *table);
|
||||
void delete_loop(struct loop *loop);
|
||||
void delete_frame(struct frame *frame);
|
||||
int destroy(void);
|
||||
void destroy(void);
|
||||
int undelete(void);
|
||||
void purge(void);
|
||||
|
||||
#endif /* !DELETE_H */
|
||||
|
7
expr.c
7
expr.c
@ -459,9 +459,12 @@ struct expr *parse_expr(const char *s)
|
||||
|
||||
static void vacate_op(struct expr *expr)
|
||||
{
|
||||
if (expr->op == op_num || expr->op == op_string ||
|
||||
expr->op == op_var)
|
||||
if (expr->op == op_num || expr->op == op_var)
|
||||
return;
|
||||
if (expr->op == op_string) {
|
||||
free(expr->u.str);
|
||||
return;
|
||||
}
|
||||
if (expr->op == op_minus) {
|
||||
free_expr(expr->u.op.a);
|
||||
return;
|
||||
|
15
fped.c
15
fped.c
@ -22,6 +22,7 @@
|
||||
#include "inst.h"
|
||||
#include "file.h"
|
||||
#include "gui.h"
|
||||
#include "delete.h"
|
||||
#include "fpd.h"
|
||||
|
||||
|
||||
@ -55,10 +56,13 @@ int main(int argc, char **argv)
|
||||
int error;
|
||||
int batch_write_kicad = 0, batch_write_ps = 0;
|
||||
int c;
|
||||
int have_gui = !getenv("FPED_NO_GUI");
|
||||
|
||||
if (have_gui) {
|
||||
error = gui_init(&argc, &argv);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
while ((c = getopt(argc, argv, "kp")) != EOF)
|
||||
switch (c) {
|
||||
@ -102,15 +106,16 @@ int main(int argc, char **argv)
|
||||
write_kicad();
|
||||
if (batch_write_ps)
|
||||
write_ps();
|
||||
if (batch_write_kicad || batch_write_ps)
|
||||
exit(0);
|
||||
|
||||
// inst_debug();
|
||||
if (have_gui && !batch_write_kicad && !batch_write_ps) {
|
||||
error = gui_main();
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
// dump(stdout);
|
||||
purge();
|
||||
inst_revert();
|
||||
obj_cleanup();
|
||||
unique_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
13
inst.c
13
inst.c
@ -956,6 +956,18 @@ struct bbox inst_get_bbox(void)
|
||||
}
|
||||
|
||||
|
||||
static void cleanup_inst(enum inst_prio prio, const struct inst *inst)
|
||||
{
|
||||
switch (prio) {
|
||||
case ip_pad:
|
||||
free(inst->u.pad.name);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void free_pkgs(struct pkg *pkg)
|
||||
{
|
||||
enum inst_prio prio;
|
||||
@ -967,6 +979,7 @@ static void free_pkgs(struct pkg *pkg)
|
||||
FOR_INST_PRIOS_UP(prio)
|
||||
for (inst = pkg->insts[prio]; inst; inst = next) {
|
||||
next = inst->next;
|
||||
cleanup_inst(prio, inst);
|
||||
free(inst);
|
||||
}
|
||||
reset_samples(pkg->samples, pkg->n_samples);
|
||||
|
2
inst.h
2
inst.h
@ -88,7 +88,7 @@ struct inst {
|
||||
unit_type width;
|
||||
} rect;
|
||||
struct {
|
||||
const char *name;
|
||||
char *name;
|
||||
struct coord other;
|
||||
} pad;
|
||||
struct {
|
||||
|
13
leakcheck
Executable file
13
leakcheck
Executable file
@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
#valgrind --leak-check=full --show-reachable=yes --suppressions=leak.supp \
|
||||
# ./fped "$@"
|
||||
|
||||
#
|
||||
# Seems that we can't suppress warnings from gtk_init, so we use FPED_NO_GUI
|
||||
# to avoid bringing up Gtk+ at all.
|
||||
#
|
||||
FPED_NO_GUI=y valgrind --leak-check=full --show-reachable=yes \
|
||||
./fped "$@"
|
||||
|
||||
#valgrind --leak-check=full --show-reachable=no \
|
||||
# ./fped "$@"
|
14
obj.c
14
obj.c
@ -20,6 +20,7 @@
|
||||
#include "expr.h"
|
||||
#include "meas.h"
|
||||
#include "inst.h"
|
||||
#include "delete.h"
|
||||
#include "obj.h"
|
||||
|
||||
|
||||
@ -288,3 +289,16 @@ int instantiate(void)
|
||||
inst_revert();
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
/* ----- deallocation ------------------------------------------------------ */
|
||||
|
||||
|
||||
void obj_cleanup(void)
|
||||
{
|
||||
free(pkg_name);
|
||||
while (frames) {
|
||||
delete_frame(frames);
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
1
obj.h
1
obj.h
@ -191,5 +191,6 @@ extern void *instantiation_error;
|
||||
|
||||
|
||||
int instantiate(void);
|
||||
void obj_cleanup(void);
|
||||
|
||||
#endif /* !OBJ_H */
|
||||
|
16
util.c
16
util.c
@ -79,7 +79,7 @@ int is_id(const char *s)
|
||||
|
||||
|
||||
static struct unique {
|
||||
const char *s;
|
||||
char *s;
|
||||
struct unique *next;
|
||||
} *uniques = NULL;
|
||||
|
||||
@ -98,3 +98,17 @@ const char *unique(const char *s)
|
||||
(*walk)->next = NULL;
|
||||
return (*walk)->s;
|
||||
}
|
||||
|
||||
|
||||
void unique_cleanup(void)
|
||||
{
|
||||
struct unique *next;
|
||||
|
||||
while (uniques) {
|
||||
next = uniques->next;
|
||||
free(uniques->s);
|
||||
free(uniques);
|
||||
uniques = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user