From b63f05e87b3e87159077a88b22132829fd2928f4 Mon Sep 17 00:00:00 2001 From: dcw Date: Fri, 30 May 2014 17:28:05 +0100 Subject: [PATCH] added experimental free support, triggered by -f flag (sets makefree variable) --- datadec.c | 3 ++ decs.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ decs.h | 2 + 3 files changed, 151 insertions(+) diff --git a/datadec.c b/datadec.c index 1c49203..4e40507 100644 --- a/datadec.c +++ b/datadec.c @@ -62,6 +62,9 @@ int main( int argc, char **argv ) case 'v': verbose = TRUE; break; + case 'f': + makefree = TRUE; + break; case 'n': opt = FALSE; break; diff --git a/decs.c b/decs.c index 79fc6cc..e2c2a98 100644 --- a/decs.c +++ b/decs.c @@ -5,6 +5,7 @@ #include "struct.h" #include "decs.h" +BOOL makefree = FALSE; static void literalline( char * mesg ); static void h_declns( char * base, char * exports, BOOL init, declnlist d ); @@ -28,6 +29,11 @@ static void print_fns( declnlist d ); static void print_fn_shape( declnlist d, shapelist s ); static void print_all_params( declnlist d, shapelist s ); static void print_param( shapelist s, paramlist p, BOOL Union ); +static void free_fn_proto( char * name, BOOL prot ); +static void free_fns( declnlist d ); +static void free_fn_shape( declnlist d, shapelist s ); +static void free_all_params( declnlist d, shapelist s ); +static void free_param( shapelist s, paramlist p, BOOL Union ); static int numtabs = 0; @@ -179,6 +185,10 @@ static void c_declns( char *base, char *globals, char *begin, declnlist d ) cons_fns( d ); decons_fns( d ); print_fns( d ); + if( makefree ) + { + free_fns( d ); + } if( *globalptr != '\0' ) { @@ -382,6 +392,10 @@ static void proto_type( decln d, BOOL prot ) } } print_fn_proto( d->name, prot ); + if( makefree ) + { + free_fn_proto( d->name, prot ); + } } @@ -880,3 +894,135 @@ static void print_param( shapelist s, paramlist p, BOOL Union ) line( "print_%s( f, %s );", p->type, pname ); } } + + +/* ------------------- experimental free functions ------------------------ */ + + +static void free_fn_proto( char *name, BOOL prot ) +{ + fprintf( outfile, "extern void free_%s(", name ); + if( prot ) + { + fprintf( outfile, " %s ", name ); + } + fputs( ");\n", outfile ); +} + + +static void free_fns( declnlist d ) +{ + for( ; d != NULL; d = d->next ) + { + shapelist s; + + line( "void free_%s( %s p )",d->name, d->name ); + line( "{" ); + indent(); + s = d->shapes; + if( d->UseNull ) + { + line( "if( p == NULL )" ); + line( "{" ); + indent(); + line( "return;" ); + outdent(); + line( "}" ); + s = s->next; + } + if( d->TagField ) + { + line( "switch( p->tag )" ); + line( "{" ); + for( ; s != NULL; s = s->next ) + { + free_fn_shape( d, s ); + } + line( "default:" ); + indent(); + line( "fprintf( stderr," ); + line( " \"free_%s: impossible tag %%d\\n\", p->tag );", + d->name ); + line( "exit(1);" ); + outdent(); + line( "}" ); + } + else if( ! d->TagField && d->Struct ) /* one shape left */ + { + free_all_params( d, s ); + } + else if( ! d->Struct && d->ManyShapes ) /* enumerated type */ + { + line( "switch( p )" ); + line( "{" ); + for( ; s != NULL; s = s->next ) + { + line( "case %s_%s():", d->name, s->name ); + indent(); + free_all_params( d, s ); + line( "break;" ); + outdent(); + } + line( "}" ); + } else + { + fprintf( stderr, + "datadec: internal error in free_fns\n" ); + exit(1); + } + if( d->Struct ) /* now need to free the node itself */ + { + line( "free( p );" ); + } + outdent(); + line( "}\n\n" ); + } +} + + +static void free_fn_shape( declnlist d, shapelist s ) +{ + line( "case %s_is_%s:", d->name, s->name ); + indent(); + free_all_params( d, s ); + line( "break;" ); + outdent(); +} + + +static void free_all_params( declnlist d, shapelist s ) +{ + paramlist p; + + for( p = s->params; p != NULL; p = p->next ) + { + free_param( s, p, d->Union ); + } +} + + +static void free_param( shapelist s, paramlist p, BOOL Union ) +{ + char pname[200]; + + if( Union ) + { + if( s->params->next == NULL ) + { + /* no internal struct */ + sprintf( pname, "p->u.%s_%s", s->name, p->name ); + } else + { + /* internal struct */ + sprintf( pname, "p->u.%s.%s", s->name, p->name ); + } + } else + { + sprintf( pname, "p->%s", p->name ); + } + + if( ! p->dontfree ) + { + line( "free_%s( %s );", p->type, pname ); + } +} diff --git a/decs.h b/decs.h index 4717e9a..55ccd49 100644 --- a/decs.h +++ b/decs.h @@ -1 +1,3 @@ +extern BOOL makefree; + extern void make_declns( char * , char * , char * , declnlist , char * ); -- GitLab