Commit 37d82980 authored by Duncan White's avatar Duncan White

datadec-1.3: converted the code (and the code generated) to use stdbool.h...

datadec-1.3: converted the code (and the code generated) to use stdbool.h throughout, and added code into decs.c to generate a .basename.dd file listing the types, the shapes, and the parameter types per shape.
parent 8ea91dcb
CC = gcc # destination: home dir..
#CC = cc # DEST = $(HOME)
DEST = $(PREFIX)/usr # or can install into TOOLDIR (env var, eg ~/c-tools)
DEST = $(TOOLDIR)
# or can install systemwide, with optional $(PREFIX) support for packaging
# DEST = $(PREFIX)/usr
#
BINDIR = $(DEST)/bin BINDIR = $(DEST)/bin
ARCHDIR = $(BINDIR)/$(ARCH)
MANDIR = $(DEST)/man/man1 MANDIR = $(DEST)/man/man1
CC = gcc
#CC = cc
CFLAGS = -g -UDEBUGGING -Wall CFLAGS = -g -UDEBUGGING -Wall
LDLIBS = LDLIBS =
EXECS = datadec EXECS = datadec
......
datadac-1.3, June 2018
Datadec takes inductive (or recursive) data types modelled on those found in Datadec takes inductive (or recursive) data types modelled on those found in
functional languages (Hope, Miranda, Haskell etc) and generates ANSI C code functional languages (Hope, Miranda, Haskell etc) and generates ISO/ANSI C
to implement them. code to implement them.
Duncan C. White, dcw@doc.ic.ac.uk Duncan C. White, d.white@imperial.ac.uk
19th March 2002 19th March 2002
New! experimental free functions (run datadec with new -f option) New May 2014! experimental free functions for every inductive data type
(run datadec with new -f option)
Duncan C. White, d.white@imperial.ac.uk New June 2018! converted to use stdbool.h at last, and added new code to
28th May 2014 quietly write out a .basename.dd file listing all the types and shapes,
and for each shape, the parameter types. This will be useful for add-on
tools such as the experimental "CPM.perl" script, which tackles client
side use of datadec-generated types, translating C+Pattern Matches to C.
An Example of Datadec in Action An Example of Datadec in Action
------------------------------- -------------------------------
...@@ -34,6 +40,7 @@ nil() and cons() are called constructors, and define different ...@@ -34,6 +40,7 @@ nil() and cons() are called constructors, and define different
"shapes" that objects of the type can take. "shapes" that objects of the type can take.
However, because the second argument of a cons() constructor is itself However, because the second argument of a cons() constructor is itself
an intlist, this type is said to be recursively or inductively defined. an intlist, this type is said to be recursively or inductively defined.
Functional programmers will recognise nil or cons() as the standard Functional programmers will recognise nil or cons() as the standard
way of defining a list, so more intuitively, intlist is simply way of defining a list, so more intuitively, intlist is simply
a list of integers! a list of integers!
...@@ -42,13 +49,13 @@ Reading on, an illist is declared as a list of intlists, ...@@ -42,13 +49,13 @@ Reading on, an illist is declared as a list of intlists,
and an idtree is declared as a binary tree where each leaf node and an idtree is declared as a binary tree where each leaf node
contains a (string, illist) pair. contains a (string, illist) pair.
Given this input, datadec can automatically construct an ANSI C Given this input, datadec can automatically construct an ISO C
module which implements all the data types, a constructor function for module which implements all the data types, a constructor function for
each constructor, deconstructor functions to help you to take objects each constructor, deconstructor functions to help you to take objects
apart again and printing functions to help you with debugging. apart again and printing functions to help you with debugging.
(Plus, new May 2014: a tree-walking free function if you invoke datadec (Plus, new May 2014: a tree-walking free function for every type if you
with the new -f option). invoke datadec with the new -f option).
Building and Packaging datadec Building and Packaging datadec
------------------------------ ------------------------------
......
...@@ -8,17 +8,21 @@ ...@@ -8,17 +8,21 @@
* *
******* Description: ******* Description:
* *
* This program builds C or Modula-2 data declarations, * This program builds C data declarations,
* constructor and deconstructor functions and write functions * constructor and deconstructor functions and write functions
* from a series of HOPE/Miranda style recursive data declarations. * from a series of Haskell/Miranda/Hope style recursive data declarations.
* (with optional hints on printing) * (with optional hints on printing, and optionally, free_* functions)
* *
* The output produced is placed in pair of files (eg. x.c and x.h ) * The output produced is placed in pair of files (eg. x.c and x.h )
* which together form a module provided the relevent data types. * which together form a module provided the relevant data types.
* NEW in 2018: in addition, we write a useful summary of types,
* shapes and the types of the shape parameters into a .x.dd file,
* this can be used by experimental client-side tools such as "CPM.perl".
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <string.h> #include <string.h>
#include "struct.h" #include "struct.h"
...@@ -28,7 +32,7 @@ ...@@ -28,7 +32,7 @@
#include "optimize.h" #include "optimize.h"
#define MUSTBE(b) {if(!(b)){fprintf(stderr,"Usage: datadec [-vno] outfile [infile]\n");exit(1);}} #define MUSTBE(b) {if(!(b)){fprintf(stderr,"Usage: datadec [-vnof] outfile [infile]\n");exit(1);}}
#define NEED_ANOTHER_ARG MUSTBE( IS_ANOTHER_ARG ) #define NEED_ANOTHER_ARG MUSTBE( IS_ANOTHER_ARG )
#define REQUIRE_NO_MORE_ARGS MUSTBE( argc == arg ) #define REQUIRE_NO_MORE_ARGS MUSTBE( argc == arg )
...@@ -52,7 +56,7 @@ int main( int argc, char **argv ) ...@@ -52,7 +56,7 @@ int main( int argc, char **argv )
arg = 1; arg = 1;
NEED_ANOTHER_ARG; NEED_ANOTHER_ARG;
verbose = FALSE; opt = TRUE; verbose = false; opt = true;
while( *(s=argv[arg]) == '-' ) while( *(s=argv[arg]) == '-' )
{ {
for( s++; *s; s++ ) for( s++; *s; s++ )
...@@ -60,16 +64,16 @@ int main( int argc, char **argv ) ...@@ -60,16 +64,16 @@ int main( int argc, char **argv )
switch( *s ) switch( *s )
{ {
case 'v': case 'v':
verbose = TRUE; verbose = true;
break; break;
case 'f': case 'f':
makefree = TRUE; makefree = true;
break; break;
case 'n': case 'n':
opt = FALSE; opt = false;
break; break;
case 'o': case 'o':
opt = TRUE; opt = true;
break; break;
default: default:
fprintf( stderr, fprintf( stderr,
...@@ -103,22 +107,21 @@ int main( int argc, char **argv ) ...@@ -103,22 +107,21 @@ int main( int argc, char **argv )
REQUIRE_NO_MORE_ARGS; REQUIRE_NO_MORE_ARGS;
if( parse_data( exports, globals, begin, &declns ) ) if( ! parse_data( exports, globals, begin, &declns ) )
{
if( verbose )
{
printf( "datadec: declns are:\n\n" );
print_declnlist( declns );
printf( "exports = {%s}\n", exports );
printf( "globals = {%s}\n", globals );
printf( "begin = {%s}\n", begin );
}
optimize( declns );
make_declns( exports, globals, begin, declns, basename );
} else
{ {
fprintf( stderr, "datadec: can't parse input properly\n" ); fprintf( stderr, "datadec: can't parse input properly\n" );
exit(1);
}
if( verbose )
{
printf( "datadec: declns are:\n\n" );
print_declnlist( declns );
printf( "exports = {%s}\n", exports );
printf( "globals = {%s}\n", globals );
printf( "begin = {%s}\n", begin );
} }
optimize( declns );
make_declns( exports, globals, begin, declns, basename );
exit(0); exit(0);
/*NOTREACHED*/ /*NOTREACHED*/
} }
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <string.h> #include <string.h>
#include "struct.h" #include "struct.h"
#include "decs.h" #include "decs.h"
BOOL makefree = FALSE; bool makefree = false;
//static void line( char * fmt, long a, long b, long c, long d );
static void literalline( char * mesg ); static void literalline( char * mesg );
static void h_declns( char * base, char * exports, BOOL init, declnlist d ); static void h_declns( char * base, char * exports, bool init, declnlist d );
static void c_declns( char * base, char * globals, char * begin, declnlist d ); static void c_declns( char * base, char * globals, char * begin, declnlist d );
static void dd_declns( char * base, declnlist d );
static void ddtypes( declnlist d );
static void ddoneshape( decln d, shapelist s );
static void data_decls( declnlist decs ); static void data_decls( declnlist decs );
static void declare_type( decln d ); static void declare_type( decln d );
static void declfields( paramlist p ); static void declfields( paramlist p );
static void protos( BOOL init, char * base, declnlist d, BOOL prot ); static void protos( bool init, char * base, declnlist d, bool prot );
static void proto_type( decln d, BOOL prot ); static void proto_type( decln d, bool prot );
static void cons_fns( declnlist d ); static void cons_fns( declnlist d );
static void cons_fn_proto( decln d, shapelist s, BOOL prot ); static void cons_fn_proto( decln d, shapelist s, bool prot );
static void cons_fn( decln d, shapelist s ); static void cons_fn( decln d, shapelist s );
static void decons_fns( declnlist d ); static void decons_fns( declnlist d );
static void decons_fns_type( decln d ); static void decons_fns_type( decln d );
static void deconskind_proto( decln d, BOOL prot ); static void deconskind_proto( decln d, bool prot );
static void deconskind_fn( decln d ); static void deconskind_fn( decln d );
static void decons_fn_proto( decln d, shapelist s, BOOL prot ); static void decons_fn_proto( decln d, shapelist s, bool prot );
static void decons_fn( decln d, shapelist s ); static void decons_fn( decln d, shapelist s );
static void print_fn_proto( char * name, BOOL prot ); static void print_fn_proto( char * name, bool prot );
static void print_fns( declnlist d ); static void print_fns( declnlist d );
static void print_fn_shape( declnlist d, shapelist s ); static void print_fn_shape( declnlist d, shapelist s );
static void print_all_params( 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 print_param( shapelist s, paramlist p, bool Union );
static void free_fn_proto( char * name, BOOL prot ); static void free_fn_proto( char * name, bool prot );
static void free_fns( declnlist d ); static void free_fns( declnlist d );
static void free_fn_shape( declnlist d, shapelist s ); static void free_fn_shape( declnlist d, shapelist s );
static void free_all_params( declnlist d, shapelist s ); static void free_all_params( declnlist d, shapelist s );
static void free_param( shapelist s, paramlist p, BOOL Union ); static void free_param( shapelist s, paramlist p, bool Union );
static int numtabs = 0; static int numtabs = 0;
...@@ -76,10 +81,11 @@ void make_declns( char *exports, char *globals, char *begin, declnlist d, char * ...@@ -76,10 +81,11 @@ void make_declns( char *exports, char *globals, char *begin, declnlist d, char *
printf( "datadec: Making data declarations in %s.[ch]\n", base ); printf( "datadec: Making data declarations in %s.[ch]\n", base );
h_declns( base, exports, *begin != '\0', d ); h_declns( base, exports, *begin != '\0', d );
c_declns( base, globals, begin, d ); c_declns( base, globals, begin, d );
dd_declns( base, d );
} }
static void h_declns( char *base, char *exports, BOOL init, declnlist d ) static void h_declns( char *base, char *exports, bool init, declnlist d )
{ {
char tempname[256]; char tempname[256];
char *exportptr; char *exportptr;
...@@ -99,9 +105,11 @@ static void h_declns( char *base, char *exports, BOOL init, declnlist d ) ...@@ -99,9 +105,11 @@ static void h_declns( char *base, char *exports, BOOL init, declnlist d )
line( " * Automatically Generated by DataDec" ); line( " * Automatically Generated by DataDec" );
line( " */\n" ); line( " */\n" );
line( "typedef char *string;\n" ); line( "typedef char *string;\n" );
line( "typedef char BOOL;" );
line( "#define TRUE 1" ); //line( "typedef char bool;" );
line( "#define FALSE 0\n" ); //line( "#define TRUE 1" );
//line( "#define FALSE 0\n" );
line( "#define NEW(t) ((t)malloc(sizeof(struct t)))\n\n" ); line( "#define NEW(t) ((t)malloc(sizeof(struct t)))\n\n" );
exportptr = exports; exportptr = exports;
...@@ -126,7 +134,7 @@ static void h_declns( char *base, char *exports, BOOL init, declnlist d ) ...@@ -126,7 +134,7 @@ static void h_declns( char *base, char *exports, BOOL init, declnlist d )
data_decls( d ); data_decls( d );
line( "\n/* Prototypes for all types */\n" ); line( "\n/* Prototypes for all types */\n" );
protos( init, base, d, TRUE ); protos( init, base, d, true );
if( *exportptr != '\0' ) if( *exportptr != '\0' )
{ {
...@@ -161,6 +169,7 @@ static void c_declns( char *base, char *globals, char *begin, declnlist d ) ...@@ -161,6 +169,7 @@ static void c_declns( char *base, char *globals, char *begin, declnlist d )
line( " */\n" ); line( " */\n" );
line( "#include <stdio.h>" ); line( "#include <stdio.h>" );
line( "#include <stdlib.h>" ); line( "#include <stdlib.h>" );
line( "#include <stdbool.h>" );
line( "#include \"%s.h\"\n\n", base ); line( "#include \"%s.h\"\n\n", base );
globalptr=globals; globalptr=globals;
...@@ -211,6 +220,57 @@ static void c_declns( char *base, char *globals, char *begin, declnlist d ) ...@@ -211,6 +220,57 @@ static void c_declns( char *base, char *globals, char *begin, declnlist d )
} }
static void dd_declns( char *base, declnlist d )
{
char tempname[256];
FILE *file;
sprintf( tempname, ".%s.dd", base );
file = fopen( tempname, "w" );
if( file == NULL )
{
fprintf( stderr, "datadec: can't create '%s'\n", tempname );
exit(1);
}
usefile( file );
ddtypes( d );
fclose( file );
}
static void ddtypes( declnlist d )
{
for( ; d != NULL; d=d->next )
{
shapelist s = d->shapes;
for( ; s != NULL; s=s->next )
{
ddoneshape( d, s );
}
}
}
static void ddoneshape( decln d, shapelist s )
{
paramlist p;
bool first;
fprintf( outfile, "%s %s ", d->name, s->name );
first = true;
for( p=s->params; p != NULL; p=p->next, first = false )
{
if( !first ) fputs( ",", outfile );
fputs( p->type, outfile );
}
fputc( '\n', outfile );
}
/* ------------------------ Declare the types ------------------------------ */ /* ------------------------ Declare the types ------------------------------ */
...@@ -320,7 +380,7 @@ static void declfields( paramlist p ) ...@@ -320,7 +380,7 @@ static void declfields( paramlist p )
/* ---------------------- Declare all prototypes -------------------------- */ /* ---------------------- Declare all prototypes -------------------------- */
static void protos( BOOL init, char *base, declnlist d, BOOL prot ) static void protos( bool init, char *base, declnlist d, bool prot )
{ {
for( ; d != NULL; d = d->next ) for( ; d != NULL; d = d->next )
{ {
...@@ -338,7 +398,7 @@ static void protos( BOOL init, char *base, declnlist d, BOOL prot ) ...@@ -338,7 +398,7 @@ static void protos( BOOL init, char *base, declnlist d, BOOL prot )
} }
static void proto_type( decln d, BOOL prot ) static void proto_type( decln d, bool prot )
{ {
shapelist s; shapelist s;
...@@ -426,10 +486,10 @@ static void cons_fns( declnlist d ) ...@@ -426,10 +486,10 @@ static void cons_fns( declnlist d )
} }
static void cons_fn_proto( decln d, shapelist s, BOOL prot ) static void cons_fn_proto( decln d, shapelist s, bool prot )
{ {
paramlist p; paramlist p;
BOOL first; bool first;
if( ! d->Struct ) if( ! d->Struct )
{ {
...@@ -445,8 +505,8 @@ static void cons_fn_proto( decln d, shapelist s, BOOL prot ) ...@@ -445,8 +505,8 @@ static void cons_fn_proto( decln d, shapelist s, BOOL prot )
fputs( "void ", outfile ); fputs( "void ", outfile );
} else } else
{ {
first = TRUE; first = true;
for( p = s->params; p != NULL ; p=p->next, first=FALSE ) for( p = s->params; p != NULL ; p=p->next, first=false )
{ {
if( !first ) fputs( ", ", outfile ); if( !first ) fputs( ", ", outfile );
fputs( p->type, outfile ); fputs( p->type, outfile );
...@@ -461,22 +521,22 @@ static void cons_fn_proto( decln d, shapelist s, BOOL prot ) ...@@ -461,22 +521,22 @@ static void cons_fn_proto( decln d, shapelist s, BOOL prot )
static void cons_fn( decln d, shapelist s ) static void cons_fn( decln d, shapelist s )
{ {
paramlist p; paramlist p;
BOOL first; bool first;
if( ! d->Struct ) if( ! d->Struct )
{ {
fprintf( stderr, "cons_fn: d->Struct is FALSE!\n" ); fprintf( stderr, "cons_fn: d->Struct is false!\n" );
exit(1); exit(1);
} }
fprintf( outfile, "%s %s_%s( ", d->name, d->name, s->name ); fprintf( outfile, "%s %s_%s( ", d->name, d->name, s->name );
first = TRUE; first = true;
if( s->params == NULL ) if( s->params == NULL )
{ {
fprintf( outfile, "void" ); fprintf( outfile, "void" );
} }
for( p=s->params; p != NULL; p=p->next, first = FALSE ) for( p=s->params; p != NULL; p=p->next, first = false )
{ {
if( !first ) fputs( ", ", outfile ); if( !first ) fputs( ", ", outfile );
fprintf( outfile, "%s %s", p->type, p->name ); fprintf( outfile, "%s %s", p->type, p->name );
...@@ -541,7 +601,7 @@ static void decons_fns_type( decln d ) ...@@ -541,7 +601,7 @@ static void decons_fns_type( decln d )
if( ! d->Struct ) if( ! d->Struct )
{ {
fprintf( stderr, "decons_fns_type: d->Struct is FALSE!\n" ); fprintf( stderr, "decons_fns_type: d->Struct is false!\n" );
exit(1); exit(1);
} }
...@@ -564,17 +624,17 @@ static void decons_fns_type( decln d ) ...@@ -564,17 +624,17 @@ static void decons_fns_type( decln d )
/* ------------------- Deconstructor Kind procedure ----------------------- */ /* ------------------- Deconstructor Kind procedure ----------------------- */
static void deconskind_proto( decln d, BOOL prot ) static void deconskind_proto( decln d, bool prot )
{ {
if( ! d->ManyShapes ) if( ! d->ManyShapes )
{ {
fprintf( stderr, fprintf( stderr,
"deconskind_proto: d->ManyShapes is FALSE!\n" ); "deconskind_proto: d->ManyShapes is false!\n" );
exit(1); exit(1);
} }
if( ! d->Struct ) if( ! d->Struct )
{ {
fprintf( stderr, "deconskind_proto: d->Struct is FALSE!\n" ); fprintf( stderr, "deconskind_proto: d->Struct is false!\n" );
exit(1); exit(1);
} }
...@@ -593,12 +653,12 @@ static void deconskind_fn( decln d ) ...@@ -593,12 +653,12 @@ static void deconskind_fn( decln d )
if( ! d->ManyShapes ) if( ! d->ManyShapes )
{ {
fprintf( stderr, "deconskind_fn: d->ManyShapes is FALSE!\n" ); fprintf( stderr, "deconskind_fn: d->ManyShapes is false!\n" );
exit(1); exit(1);
} }
if( ! d->Struct ) if( ! d->Struct )
{ {
fprintf( stderr, "deconskind_fn: d->Struct is FALSE!\n" ); fprintf( stderr, "deconskind_fn: d->Struct is false!\n" );
exit(1); exit(1);
} }
...@@ -634,11 +694,11 @@ static void deconskind_fn( decln d ) ...@@ -634,11 +694,11 @@ static void deconskind_fn( decln d )
/* ----------------------- Deconstructor functions ------------------------ */ /* ----------------------- Deconstructor functions ------------------------ */
static void decons_fn_proto( decln d, shapelist s, BOOL prot ) static void decons_fn_proto( decln d, shapelist s, bool prot )
{ {
if( ! d->Struct ) if( ! d->Struct )
{ {
fprintf( stderr, "decons_fn_proto: d->Struct is FALSE!\n" ); fprintf( stderr, "decons_fn_proto: d->Struct is false!\n" );
exit(1); exit(1);
} }
if( s->params == NULL ) if( s->params == NULL )
...@@ -668,7 +728,7 @@ static void decons_fn( decln d, shapelist s ) ...@@ -668,7 +728,7 @@ static void decons_fn( decln d, shapelist s )
if( ! d->Struct ) if( ! d->Struct )
{ {
fprintf( stderr, "decons_fn: d->Struct is FALSE!\n" ); fprintf( stderr, "decons_fn: d->Struct is false!\n" );
exit(1); exit(1);
} }
if( s->params == NULL ) if( s->params == NULL )
...@@ -715,7 +775,7 @@ static void decons_fn( decln d, shapelist s ) ...@@ -715,7 +775,7 @@ static void decons_fn( decln d, shapelist s )
/* -------------------------- Print functions ----------------------------- */ /* -------------------------- Print functions ----------------------------- */
static void print_fn_proto( char *name, BOOL prot ) static void print_fn_proto( char *name, bool prot )
{ {
fprintf( outfile, "extern void print_%s(", name ); fprintf( outfile, "extern void print_%s(", name );
if( prot )