mirror of
git://projects.qi-hardware.com/fped.git
synced 2024-11-22 08:38:26 +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 vec *walk, *prev;
|
||||||
struct deletion *del;
|
struct deletion *del;
|
||||||
|
|
||||||
delete_vecs_by_ref(vec->frame->vecs, vec);
|
|
||||||
delete_objs_by_ref(&vec->frame->objs, vec);
|
|
||||||
|
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
for (walk = vec->frame->vecs; walk != vec; walk = walk->next)
|
for (walk = vec->frame->vecs; walk != vec; walk = walk->next)
|
||||||
prev = walk;
|
prev = walk;
|
||||||
@ -159,6 +156,9 @@ static void do_delete_vec(struct vec *vec)
|
|||||||
del = new_deletion(dt_vec);
|
del = new_deletion(dt_vec);
|
||||||
del->u.vec.ref = vec;
|
del->u.vec.ref = vec;
|
||||||
del->u.vec.prev = prev;
|
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);
|
free_expr(obj->u.arc.width);
|
||||||
break;
|
break;
|
||||||
case ot_meas:
|
case ot_meas:
|
||||||
|
if (obj->u.meas.label)
|
||||||
|
free(obj->u.meas.label);
|
||||||
if (obj->u.meas.offset)
|
if (obj->u.meas.offset)
|
||||||
free_expr(obj->u.meas.offset);
|
free_expr(obj->u.meas.offset);
|
||||||
break;
|
break;
|
||||||
@ -257,6 +259,20 @@ static void undelete_obj(struct obj *obj, struct obj *prev)
|
|||||||
/* ----- rows -------------------------------------------------------------- */
|
/* ----- 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)
|
void delete_row(struct row *row)
|
||||||
{
|
{
|
||||||
struct deletion *del;
|
struct deletion *del;
|
||||||
@ -355,6 +371,23 @@ static void undelete_column(const struct column *col)
|
|||||||
/* ----- tables ------------------------------------------------------------ */
|
/* ----- 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)
|
void delete_table(struct table *table)
|
||||||
{
|
{
|
||||||
struct frame *frame = table->vars->frame;
|
struct frame *frame = table->vars->frame;
|
||||||
@ -392,6 +425,14 @@ static void undelete_table(struct table *table, struct table *prev)
|
|||||||
/* ----- loops ------------------------------------------------------------- */
|
/* ----- 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)
|
void delete_loop(struct loop *loop)
|
||||||
{
|
{
|
||||||
struct frame *frame = loop->var.frame;
|
struct frame *frame = loop->var.frame;
|
||||||
@ -429,6 +470,28 @@ static void undelete_loop(struct loop *loop, struct loop *prev)
|
|||||||
/* ----- frames ------------------------------------------------------------ */
|
/* ----- 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)
|
static void delete_references(const struct frame *ref)
|
||||||
{
|
{
|
||||||
struct frame *frame;
|
struct frame *frame;
|
||||||
@ -438,7 +501,7 @@ static void delete_references(const struct frame *ref)
|
|||||||
for (obj = frame->objs; obj; obj = obj->next)
|
for (obj = frame->objs; obj; obj = obj->next)
|
||||||
if (obj->type == ot_frame)
|
if (obj->type == ot_frame)
|
||||||
if (obj->u.frame.ref == ref)
|
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;
|
struct deletion *del;
|
||||||
|
|
||||||
groups++;
|
groups++;
|
||||||
delete_references(frame);
|
|
||||||
|
|
||||||
del = new_deletion(dt_frame);
|
del = new_deletion(dt_frame);
|
||||||
del->u.frame.ref = frame;
|
del->u.frame.ref = frame;
|
||||||
@ -459,6 +521,8 @@ void delete_frame(struct frame *frame)
|
|||||||
frame->prev->next = frame->next;
|
frame->prev->next = frame->next;
|
||||||
else
|
else
|
||||||
frames = frame->next;
|
frames = frame->next;
|
||||||
|
|
||||||
|
delete_references(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -478,12 +542,10 @@ static void undelete_frame(struct frame *frame, struct frame *prev)
|
|||||||
/* ----- destroy/undelete interface ---------------------------------------- */
|
/* ----- destroy/undelete interface ---------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
int destroy(void)
|
static void destroy_one(void)
|
||||||
{
|
{
|
||||||
struct deletion *del;
|
struct deletion *del;
|
||||||
|
|
||||||
if (!deletions)
|
|
||||||
return 0;
|
|
||||||
del = deletions;
|
del = deletions;
|
||||||
switch (del->type) {
|
switch (del->type) {
|
||||||
case dt_vec:
|
case dt_vec:
|
||||||
@ -493,15 +555,36 @@ int destroy(void)
|
|||||||
destroy_obj(del->u.obj.ref);
|
destroy_obj(del->u.obj.ref);
|
||||||
break;
|
break;
|
||||||
case dt_frame:
|
case dt_frame:
|
||||||
abort();
|
destroy_frame(del->u.frame.ref);
|
||||||
/* @@@ later */
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
deletions = del->next;
|
deletions = del->next;
|
||||||
free(del);
|
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();
|
undelete_one();
|
||||||
return 1;
|
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_table(struct table *table);
|
||||||
void delete_loop(struct loop *loop);
|
void delete_loop(struct loop *loop);
|
||||||
void delete_frame(struct frame *frame);
|
void delete_frame(struct frame *frame);
|
||||||
int destroy(void);
|
void destroy(void);
|
||||||
int undelete(void);
|
int undelete(void);
|
||||||
|
void purge(void);
|
||||||
|
|
||||||
#endif /* !DELETE_H */
|
#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)
|
static void vacate_op(struct expr *expr)
|
||||||
{
|
{
|
||||||
if (expr->op == op_num || expr->op == op_string ||
|
if (expr->op == op_num || expr->op == op_var)
|
||||||
expr->op == op_var)
|
|
||||||
return;
|
return;
|
||||||
|
if (expr->op == op_string) {
|
||||||
|
free(expr->u.str);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (expr->op == op_minus) {
|
if (expr->op == op_minus) {
|
||||||
free_expr(expr->u.op.a);
|
free_expr(expr->u.op.a);
|
||||||
return;
|
return;
|
||||||
|
15
fped.c
15
fped.c
@ -22,6 +22,7 @@
|
|||||||
#include "inst.h"
|
#include "inst.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
|
#include "delete.h"
|
||||||
#include "fpd.h"
|
#include "fpd.h"
|
||||||
|
|
||||||
|
|
||||||
@ -55,10 +56,13 @@ int main(int argc, char **argv)
|
|||||||
int error;
|
int error;
|
||||||
int batch_write_kicad = 0, batch_write_ps = 0;
|
int batch_write_kicad = 0, batch_write_ps = 0;
|
||||||
int c;
|
int c;
|
||||||
|
int have_gui = !getenv("FPED_NO_GUI");
|
||||||
|
|
||||||
|
if (have_gui) {
|
||||||
error = gui_init(&argc, &argv);
|
error = gui_init(&argc, &argv);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "kp")) != EOF)
|
while ((c = getopt(argc, argv, "kp")) != EOF)
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@ -102,15 +106,16 @@ int main(int argc, char **argv)
|
|||||||
write_kicad();
|
write_kicad();
|
||||||
if (batch_write_ps)
|
if (batch_write_ps)
|
||||||
write_ps();
|
write_ps();
|
||||||
if (batch_write_kicad || batch_write_ps)
|
if (have_gui && !batch_write_kicad && !batch_write_ps) {
|
||||||
exit(0);
|
|
||||||
|
|
||||||
// inst_debug();
|
|
||||||
error = gui_main();
|
error = gui_main();
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
// dump(stdout);
|
purge();
|
||||||
|
inst_revert();
|
||||||
|
obj_cleanup();
|
||||||
|
unique_cleanup();
|
||||||
|
|
||||||
return 0;
|
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)
|
static void free_pkgs(struct pkg *pkg)
|
||||||
{
|
{
|
||||||
enum inst_prio prio;
|
enum inst_prio prio;
|
||||||
@ -967,6 +979,7 @@ static void free_pkgs(struct pkg *pkg)
|
|||||||
FOR_INST_PRIOS_UP(prio)
|
FOR_INST_PRIOS_UP(prio)
|
||||||
for (inst = pkg->insts[prio]; inst; inst = next) {
|
for (inst = pkg->insts[prio]; inst; inst = next) {
|
||||||
next = inst->next;
|
next = inst->next;
|
||||||
|
cleanup_inst(prio, inst);
|
||||||
free(inst);
|
free(inst);
|
||||||
}
|
}
|
||||||
reset_samples(pkg->samples, pkg->n_samples);
|
reset_samples(pkg->samples, pkg->n_samples);
|
||||||
|
2
inst.h
2
inst.h
@ -88,7 +88,7 @@ struct inst {
|
|||||||
unit_type width;
|
unit_type width;
|
||||||
} rect;
|
} rect;
|
||||||
struct {
|
struct {
|
||||||
const char *name;
|
char *name;
|
||||||
struct coord other;
|
struct coord other;
|
||||||
} pad;
|
} pad;
|
||||||
struct {
|
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 "expr.h"
|
||||||
#include "meas.h"
|
#include "meas.h"
|
||||||
#include "inst.h"
|
#include "inst.h"
|
||||||
|
#include "delete.h"
|
||||||
#include "obj.h"
|
#include "obj.h"
|
||||||
|
|
||||||
|
|
||||||
@ -288,3 +289,16 @@ int instantiate(void)
|
|||||||
inst_revert();
|
inst_revert();
|
||||||
return ok;
|
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);
|
int instantiate(void);
|
||||||
|
void obj_cleanup(void);
|
||||||
|
|
||||||
#endif /* !OBJ_H */
|
#endif /* !OBJ_H */
|
||||||
|
16
util.c
16
util.c
@ -79,7 +79,7 @@ int is_id(const char *s)
|
|||||||
|
|
||||||
|
|
||||||
static struct unique {
|
static struct unique {
|
||||||
const char *s;
|
char *s;
|
||||||
struct unique *next;
|
struct unique *next;
|
||||||
} *uniques = NULL;
|
} *uniques = NULL;
|
||||||
|
|
||||||
@ -98,3 +98,17 @@ const char *unique(const char *s)
|
|||||||
(*walk)->next = NULL;
|
(*walk)->next = NULL;
|
||||||
return (*walk)->s;
|
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