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
#CC = cc
DEST = $(PREFIX)/usr
# destination: home dir..
# DEST = $(HOME)
# 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
ARCHDIR = $(BINDIR)/$(ARCH)
MANDIR = $(DEST)/man/man1
CC = gcc
#CC = cc
CFLAGS = -g -UDEBUGGING -Wall
LDLIBS =
EXECS = datadec
......
datadac-1.3, June 2018
Datadec takes inductive (or recursive) data types modelled on those found in
functional languages (Hope, Miranda, Haskell etc) and generates ANSI C code
to implement them.
functional languages (Hope, Miranda, Haskell etc) and generates ISO/ANSI C
code to implement them.
Duncan C. White, dcw@doc.ic.ac.uk
Duncan C. White, d.white@imperial.ac.uk
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
28th May 2014
New June 2018! converted to use stdbool.h at last, and added new code to
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
-------------------------------
......@@ -34,6 +40,7 @@ nil() and cons() are called constructors, and define different
"shapes" that objects of the type can take.
However, because the second argument of a cons() constructor is itself
an intlist, this type is said to be recursively or inductively defined.
Functional programmers will recognise nil or cons() as the standard
way of defining a list, so more intuitively, intlist is simply
a list of integers!
......@@ -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
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
each constructor, deconstructor functions to help you to take objects
apart again and printing functions to help you with debugging.
(Plus, new May 2014: a tree-walking free function if you invoke datadec
with the new -f option).
(Plus, new May 2014: a tree-walking free function for every type if you
invoke datadec with the new -f option).
Building and Packaging datadec
------------------------------
......
......@@ -8,17 +8,21 @@
*
******* Description:
*
* This program builds C or Modula-2 data declarations,
* This program builds C data declarations,
* constructor and deconstructor functions and write functions
* from a series of HOPE/Miranda style recursive data declarations.
* (with optional hints on printing)
* from a series of Haskell/Miranda/Hope style recursive data declarations.
* (with optional hints on printing, and optionally, free_* functions)
*
* 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 <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "struct.h"
......@@ -28,7 +32,7 @@
#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 REQUIRE_NO_MORE_ARGS MUSTBE( argc == arg )
......@@ -52,7 +56,7 @@ int main( int argc, char **argv )
arg = 1;
NEED_ANOTHER_ARG;
verbose = FALSE; opt = TRUE;
verbose = false; opt = true;
while( *(s=argv[arg]) == '-' )
{
for( s++; *s; s++ )
......@@ -60,16 +64,16 @@ int main( int argc, char **argv )
switch( *s )
{
case 'v':
verbose = TRUE;
verbose = true;
break;
case 'f':
makefree = TRUE;
makefree = true;
break;
case 'n':
opt = FALSE;
opt = false;
break;
case 'o':
opt = TRUE;
opt = true;
break;
default:
fprintf( stderr,
......@@ -103,22 +107,21 @@ int main( int argc, char **argv )
REQUIRE_NO_MORE_ARGS;
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
if( ! parse_data( exports, globals, begin, &declns ) )
{
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);
/*NOTREACHED*/
}
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "struct.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 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 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 declare_type( decln d );
static void declfields( paramlist p );
static void protos( BOOL init, char * base, declnlist d, BOOL prot );
static void proto_type( decln d, BOOL prot );
static void protos( bool init, char * base, declnlist d, bool prot );
static void proto_type( decln d, bool prot );
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 decons_fns( declnlist 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 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 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_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 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 void free_param( shapelist s, paramlist p, bool Union );
static int numtabs = 0;
......@@ -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 );
h_declns( base, exports, *begin != '\0', 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 *exportptr;
......@@ -99,9 +105,11 @@ static void h_declns( char *base, char *exports, BOOL init, declnlist d )
line( " * Automatically Generated by DataDec" );
line( " */\n" );
line( "typedef char *string;\n" );
line( "typedef char BOOL;" );
line( "#define TRUE 1" );
line( "#define FALSE 0\n" );
//line( "typedef char bool;" );
//line( "#define TRUE 1" );
//line( "#define FALSE 0\n" );
line( "#define NEW(t) ((t)malloc(sizeof(struct t)))\n\n" );
exportptr = exports;
......@@ -126,7 +134,7 @@ static void h_declns( char *base, char *exports, BOOL init, declnlist d )
data_decls( d );
line( "\n/* Prototypes for all types */\n" );
protos( init, base, d, TRUE );
protos( init, base, d, true );
if( *exportptr != '\0' )
{
......@@ -161,6 +169,7 @@ static void c_declns( char *base, char *globals, char *begin, declnlist d )
line( " */\n" );
line( "#include <stdio.h>" );
line( "#include <stdlib.h>" );
line( "#include <stdbool.h>" );
line( "#include \"%s.h\"\n\n", base );
globalptr=globals;
......@@ -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 ------------------------------ */
......@@ -320,7 +380,7 @@ static void declfields( paramlist p )
/* ---------------------- 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 )
{
......@@ -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;
......@@ -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;
BOOL first;
bool first;
if( ! d->Struct )
{
......@@ -445,8 +505,8 @@ static void cons_fn_proto( decln d, shapelist s, BOOL prot )
fputs( "void ", outfile );
} else
{
first = TRUE;
for( p = s->params; p != NULL ; p=p->next, first=FALSE )
first = true;
for( p = s->params; p != NULL ; p=p->next, first=false )
{
if( !first ) fputs( ", ", outfile );
fputs( p->type, outfile );
......@@ -461,22 +521,22 @@ static void cons_fn_proto( decln d, shapelist s, BOOL prot )
static void cons_fn( decln d, shapelist s )
{
paramlist p;
BOOL first;
bool first;
if( ! d->Struct )
{
fprintf( stderr, "cons_fn: d->Struct is FALSE!\n" );
fprintf( stderr, "cons_fn: d->Struct is false!\n" );
exit(1);
}
fprintf( outfile, "%s %s_%s( ", d->name, d->name, s->name );
first = TRUE;
first = true;
if( s->params == NULL )
{
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 );
fprintf( outfile, "%s %s", p->type, p->name );
......@@ -541,7 +601,7 @@ static void decons_fns_type( decln d )
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);
}
......@@ -564,17 +624,17 @@ static void decons_fns_type( decln d )
/* ------------------- Deconstructor Kind procedure ----------------------- */
static void deconskind_proto( decln d, BOOL prot )
static void deconskind_proto( decln d, bool prot )
{
if( ! d->ManyShapes )
{
fprintf( stderr,
"deconskind_proto: d->ManyShapes is FALSE!\n" );
"deconskind_proto: d->ManyShapes is false!\n" );
exit(1);
}
if( ! d->Struct )
{
fprintf( stderr, "deconskind_proto: d->Struct is FALSE!\n" );
fprintf( stderr, "deconskind_proto: d->Struct is false!\n" );
exit(1);
}
......@@ -593,12 +653,12 @@ static void deconskind_fn( decln d )
if( ! d->ManyShapes )
{
fprintf( stderr, "deconskind_fn: d->ManyShapes is FALSE!\n" );
fprintf( stderr, "deconskind_fn: d->ManyShapes is false!\n" );
exit(1);
}
if( ! d->Struct )
{
fprintf( stderr, "deconskind_fn: d->Struct is FALSE!\n" );
fprintf( stderr, "deconskind_fn: d->Struct is false!\n" );
exit(1);
}
......@@ -634,11 +694,11 @@ static void deconskind_fn( decln d )
/* ----------------------- 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 )
{
fprintf( stderr, "decons_fn_proto: d->Struct is FALSE!\n" );
fprintf( stderr, "decons_fn_proto: d->Struct is false!\n" );
exit(1);
}
if( s->params == NULL )
......@@ -668,7 +728,7 @@ static void decons_fn( decln d, shapelist s )
if( ! d->Struct )
{
fprintf( stderr, "decons_fn: d->Struct is FALSE!\n" );
fprintf( stderr, "decons_fn: d->Struct is false!\n" );
exit(1);
}
if( s->params == NULL )
......@@ -715,7 +775,7 @@ static void decons_fn( decln d, shapelist s )
/* -------------------------- 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 );
if( prot )
......@@ -857,7 +917,7 @@ 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 )
{
char pname[200];
......@@ -883,7 +943,7 @@ static void print_param( shapelist s, paramlist p, BOOL Union )
} else if( streq( p->type, "char" ) )
{
line( "fputc( %s, f );", pname );
} else if( streq( p->type, "BOOL" ) )
} else if( streq( p->type, "BOOL" ) || streq( p->type, "bool" ) )
{
line( "fputs( %s?\"true\":\"false\", f );", pname );
} else if( streq( p->type, "string" ) )
......@@ -899,7 +959,7 @@ static void print_param( shapelist s, paramlist p, BOOL Union )
/* ------------------- experimental free functions ------------------------ */
static void free_fn_proto( char *name, BOOL prot )
static void free_fn_proto( char *name, bool prot )
{
fprintf( outfile, "extern void free_%s(", name );
if( prot )
......@@ -1001,7 +1061,7 @@ 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 )
{
char pname[200];
......
extern BOOL makefree;
extern bool makefree;
extern void make_declns( char * , char * , char * , declnlist , char * );
......@@ -17,6 +17,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
......@@ -45,7 +46,7 @@ FILE *lexfile;
/* ----------------- Private variables ---------------- */
static BOOL havepushedtok = FALSE;
static bool havepushedtok = false;
static TOKEN curtok;
static char curid[ MAXIDSIZE ];
static int curint;
......@@ -80,7 +81,7 @@ void ungettok( void )
fprintf( stderr, "ungettok: can't push 2 tokens\n" );
exit(1);
}
havepushedtok = TRUE;
havepushedtok = true;
#ifdef DEBUGGING
printf( "lexer: ungot token %s\n", tokenname[ curtok ] );
#endif
......@@ -94,7 +95,7 @@ TOKEN nexttok( void )
if( havepushedtok )
{
havepushedtok = FALSE;
havepushedtok = false;
} else
{
white_space();
......@@ -184,7 +185,7 @@ printf( "returning token %s\n", tokenname[ curtok ] );
}
BOOL readnextline( char *line )
bool readnextline( char *line )
{
int c;
char *s = line;
......
......@@ -33,4 +33,4 @@ extern FILE *lexfile;
extern void ungettok( void );
extern TOKEN nexttok( void );
extern BOOL readnextline( char * line );
extern bool readnextline( char * line );
......@@ -3,18 +3,19 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "struct.h"
#include "optimize.h"
BOOL opt; /* opt == perform optimizations */
BOOL verbose; /* verbose == be verbose - diagnostics */
bool opt; /* opt == perform optimizations */
bool verbose; /* verbose == be verbose - diagnostics */
static void optimize_decln( decln );
static BOOL tail_optimize( decln );
static bool tail_optimize( decln );
#define implies( a, b ) (!(a) || (b))
......@@ -29,8 +30,8 @@ void optimize( declnlist d )
optimize_decln( d );
} else
{
d->ManyShapes = d->TagField = d->Struct = d->Union = TRUE;
d->UseNull = d->PutLoop = FALSE;
d->ManyShapes = d->TagField = d->Struct = d->Union = true;
d->UseNull = d->PutLoop = false;
}
}
}
......@@ -40,7 +41,7 @@ static void optimize_decln( decln d )
{
int t, e, ne;
shapelist s;
BOOL firstempty = d->shapes->params == NULL;
bool firstempty = d->shapes->params == NULL;
e = ne = 0;
for( s = d->shapes; s != NULL; s = s->next )
......@@ -120,10 +121,10 @@ static void optimize_decln( decln d )
This is when the last print item of any shape is a number corresponding
to a field that is the same type as the decln itself.
Return TRUE if the optimization is possible.
Return true if the optimization is possible.
*/
static BOOL tail_optimize( decln d )
static bool tail_optimize( decln d )
{
shapelist s;
printlist pl;
......@@ -143,10 +144,10 @@ static BOOL tail_optimize( decln d )
s->name, d->name );
if( streq( p->type, d->name ) )
{
return TRUE;
return true;
}
}
}
}
return FALSE;
return false;
}
/* optimize.h */
extern BOOL opt; /* perform optimizations */
extern BOOL verbose; /* be verbose */
extern bool opt; /* perform optimizations */
extern bool verbose; /* be verbose */
extern void optimize( declnlist );
......@@ -28,6 +28,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include "struct.h"
#include "lexer.h"
#include "parser.h"
......@@ -36,20 +37,20 @@
#define COPYOF(new,old) {new=malloc(1+strlen(old));if(new)strcpy(new,old);}
static BOOL parse_chunk( char * s );
static BOOL parse_declns( declnlist * dp );
static bool parse_chunk( char * s );
static bool parse_declns( declnlist * dp );
static void error( char * s );
static BOOL parse_decln( char ** name, shapelist * shapes );
static BOOL parse_shapes( shapelist * sp );
static BOOL parse_shape( char ** tagname, paramlist * pl, printlist * print );
static BOOL parse_params( paramlist * pp );
static BOOL parse_printlist( printlist * pp );
static BOOL parse_printitem( printitem * item );
static BOOL neverfreetype( char * typename );
static BOOL parse_param( BOOL * dontfree, char ** type, char ** name );
static bool parse_decln( char ** name, shapelist * shapes );
static bool parse_shapes( shapelist * sp );
static bool parse_shape( char ** tagname, paramlist * pl, printlist * print );
static bool parse_params( paramlist * pp );
static bool parse_printlist( printlist * pp );
static bool parse_printitem( printitem * item );
static bool neverfreetype( char * typename );
static bool parse_param( bool * dontfree, char ** type, char ** name );