Commit 010de9a3 authored by dcw's avatar dcw

Initial revision

parents
/*
* DATA DECLARATION BUILDER
* ==== =========== =======
*
******* Author:
*
* Duncan White, Imperial College, London, England.
*
******* Description:
*
* This program builds C data declarations from a series
* of high-level data declarations.
*
* The C declarations produced are placed in pair of files
* ( x.c and x.h ) which together form a module provided the
* relevent data types.
*
******* History
*
* Version Who Date Comments
* ======= === ==== ========
*
* 1.0 dcw 31st Dec 1987 Created
* 1.1 dcw 1st Jan 1988 Recreated after screwup
* 1.2 dcw 2nd Jan 1988 Added lexfile stuff
*/
#include <dcw.h>
#include "struct.h"
#include "lexer.h"
#include "parser.h"
main( argc, argv ) int argc; char **argv;
{
FILE *infile, *cfile, *hfile;
char inname[256], tempname[256];
declnlist declns;
int len;
char *basename;
ASSERT( argc==2 || argc==3, ("Usage: datadecs outfile [infile]\n") );
basename = argv[1];
len = strlen( basename );
if( !strcmp( basename+len-2, ".c" ) ) {
basename[len-2] = '\0';
}
sprintf( tempname, "%s.c", basename );
cfile = fopen( tempname, "w" );
ASSERT( cfile != NULL, ("datadecs: can't create '%s'\n",tempname) );
sprintf( tempname, "%s.h", basename );
hfile = fopen( tempname, "w" );
ASSERT( hfile != NULL, ("datadecs: can't create '%s'\n",tempname) );
if( argc == 3 ) {
lexfile = fopen( argv[2], "r" );
ASSERT( lexfile != NULL,
("datadecs: can't open '%s'\n",argv[2]) );
} else {
lexfile = stdin;
}
ASSERT( parse_declns( &declns ),
("datadecs: can't parse input properly\n") );
make_declns( declns, cfile, hfile, basename );
fclose( cfile );
fclose( hfile );
exit(0);
}
#include <dcw.h>
#include "struct.h"
#include "decs.h"
#ifdef HASPROTOS
static void p_type( FILE * , char * , char , int );
static void make_init( FILE * , FILE * , char * );
static void make_data_decls( FILE * , declnlist );
static void make_1_proto( FILE * , char * , shapelist , BOOL );
static void make_protos( FILE * , declnlist , BOOL );
static void make_fn_hdr( FILE * , char * , shapelist );
static void make_fn_body( FILE * , char * , shapelist );
static void make_fns( FILE * , declnlist );
#else
static void p_type();
static void make_init();
static void make_data_decls();
static void make_1_proto();
static void make_protos();
static void make_fn_hdr();
static void make_fn_body();
static void make_fns();
#endif
static void p_type( f, type, sep, stars ) FILE *f; char sep, *type; int stars;
{
fprintf( f, "%s%c", type, sep );
for( ; stars; stars-- ) {
fputc( '*', f );
}
}
static void make_init( h, c, basename ) FILE *c, *h; char *basename;
{
fprintf( h, "/*\n" );
fprintf( h, "\tAutomatically Generated by DataDec\n" );
fprintf( h, " */\n\n");
fprintf( c, "/*\n" );
fprintf( c, "\tAutomatically Generated by DataDec\n" );
fprintf( c, " */\n\n");
fprintf( c, "#include <dcw.h>\n" );
fprintf( c, "#include <%s.h>\n\n\n", basename );
}
static void make_data_decls( f, dl ) FILE *f; declnlist dl;
{
declnlist d;
char *name;
shapelist s;
int n;
char *tag;
paramlist p;
for( d=dl; d; d=d->next ) {
name = d->name;
fprintf( f, "typedef struct %s_str *%s;\n", name, name );
}
for( d=dl; d; d=d->next ) {
name = d->name;
fprintf( f, "/* ---- Type %s ---- */\n\n", name );
n = 0;
for( s = d->shapes; s; s=s->next ) {
fprintf( f, "#define %s_%s_tag %d\n",
name, s->tagname, n++ );
}
fprintf( f, "\nstruct %s_str {\n", name );
fprintf( f, "\tint\ttag;\n" );
for( s = d->shapes; s; s=s->next ) {
tag = s->tagname;
for( p = s->params; p; p=p->next ) {
fputc( '\t', f );
p_type( f, p->type, '\t', p->stars );
fprintf( f, "%s_%s;\n", tag, p->name );
}
}
fprintf( f, "};\n\n" );
}
}
static void make_1_proto( f, name, s, protos ) FILE *f; char *name; shapelist s; BOOL protos;
{
char *tag;
paramlist p;
BOOL first;
tag = s->tagname;
fprintf( f, "extern %s %s_%s( ", name, name, tag );
if( protos ) {
if( s->params == NULL ) {
fprintf( f, "void" );
} else {
first = TRUE;
for( p = s->params; p ; p=p->next, first=FALSE ) {
if( !first ) fprintf( f, ", " );
p_type( f, p->type, ' ', p->stars );
}
}
}
fprintf( f, " );\n" );
}
static void make_protos( f, d, protos ) FILE *f; declnlist d; BOOL protos;
{
char *name;
shapelist s;
for( ; d; d = d->next ) {
name = d->name;
for( s = d->shapes; s; s=s->next ) {
make_1_proto( f, name, s );
}
}
}
static void make_fn_hdr( f, name, s ) FILE *f; char *name; shapelist s;
{
char *tag;
paramlist p;
BOOL first;
tag = s->tagname;
fprintf( f, "%s %s_%s( ", name, name, tag );
first = TRUE;
for( p=s->params; p; p=p->next, first=FALSE ) {
if( !first ) fprintf( f, ", " );
fprintf( f, "%s", p->name );
}
fprintf( f, " ) " );
for( p=s->params; p; p=p->next ) {
p_type( f, p->type, ' ', p->stars );
fprintf( f, "%s; ", p->name );
}
fputc( '\n', f );
}
static void make_fn_body( f, name, s ) FILE *f; char *name; shapelist s;
{
char *tag;
paramlist p;
tag = s->tagname;
fprintf( f, "{\n\t%s new;\n\n", name );
fprintf( f, "\tnew = NEW( struct %s_str );\n", name );
fprintf( f, "\tnew->tag = %s_%s_tag;\n", name, tag );
for( p=s->params; p; p=p->next ) {
fprintf( f, "\tnew->%s_%s = %s;\n", tag, p->name, p->name );
}
fprintf( f, "\treturn new;\n}\n" );
}
static void make_fns( f, d ) FILE *f; declnlist d;
{
char *name;
shapelist s;
for( ; d; d=d->next ) {
name = d->name;
for( s = d->shapes; s; s=s->next ) {
make_fn_hdr( f, name, s );
make_fn_body( f, name, s );
fprintf( f, "\n\n" );
}
}
}
void make_declns( d, c, h, basename ) declnlist d; FILE *c, *h; char *basename;
{
printf( "Making data declarations\n" );
make_init( h, c, basename );
make_data_decls( h, d );
fprintf( h, "#ifdef HASPROTOS\n" );
make_protos( h, d, TRUE );
fprintf( h, "#else\n" );
make_protos( h, d, FALSE );
fprintf( h, "#endif\n" );
make_fns( c, d );
}
#ifdef HASPROTOS
extern void make_declns( declnlist , FILE * , FILE * , char * );
#else
extern void make_declns();
#endif
/*
* LEXER FOR THE
* ===== === ===
*
* DATA DECLARATION BUILDER
* ==== =========== =======
*
* This module is the lexer used by the parser to
* interprete the high level data declarations.
*
******* Tokens:
*
* tERROR tEOF tSEMI tID tEQ tOR tOPENBR tCOMMA tCLOSEBR tSTAR
*
******* History
*
* Version Who Date Comments
* ======= === ==== ========
*
* 1.0 dcw 2nd Jan 1988 Created
*/
#include <dcw.h>
#include <ctype.h>
#include "lexer.h"
#ifdef DEBUG
static char *tokenname[] = {
"tERROR", "tEOF", "tSEMI", "tID", "tEQ", "tOR", "tOPENBR",
"tCOMMA", "tCLOSEBR", "tSTAR"
};
#endif
/* ----------------- Exported variables ---------------- */
#define MAXIDSIZE 32
int lineno = 1;
char lexidval[ MAXIDSIZE ];
FILE *lexfile;
/* ----------------- Private variables ---------------- */
static BOOL havepushedtok = FALSE;
static TOKEN curtok;
/* ----------------- Private procedures ---------------- */
static void white_space()
{
int c;
for(;;) {
c=getc(lexfile);
if( c==EOF ) break;
if( c=='\n' ) lineno++;
if( c != ' ' && c != '\t' && c != '\n' ) break;
}
ungetc( c, lexfile );
}
/* ----------------- Public procedures ---------------- */
void ungettok()
{
ASSERT( ! havepushedtok, ("ungettok: can't push 2 tokens\n") );
havepushedtok = TRUE;
#ifdef DEBUG
printf( "lexer: ungot token %s\n", tokenname[ curtok ] );
#endif
}
TOKEN nexttok()
{
int c;
int pos;
if( havepushedtok ) {
havepushedtok = FALSE;
} else {
white_space();
c = getc(lexfile);
if( c==EOF )
{
curtok = tEOF;
} else if( isalpha( c ) )
{
curtok = tID;
for( pos=0; isalpha(c) || isdigit(c); )
{
if( pos<MAXIDSIZE-1 ) lexidval[pos++] = c;
c=getc(lexfile);
}
ungetc( c, lexfile );
while( pos<MAXIDSIZE ) lexidval[pos++] = '\0';
} else if( c==';' ) curtok = tSEMI;
else if( c=='(' ) curtok = tOPENBR;
else if( c==')' ) curtok = tCLOSEBR;
else if( c==',' ) curtok = tCOMMA;
else if( c=='|' ) curtok = tOR;
else if( c=='=' ) curtok = tEQ;
else if( c=='*' ) curtok = tSTAR;
else curtok = tERROR;
}
#ifdef DEBUG
printf( "returning token %s\n", tokenname[ curtok ] );
#endif
return curtok;
}
/*
* LEXER FOR THE
* ===== === ===
*
* DATA DECLARATION BUILDER
* ==== =========== =======
*
* This module is the lexer used by the parser to
* interprete the high level data declarations.
*/
/* ----------------- Exported defns ---------------- */
typedef enum {
tERROR, tEOF, tSEMI, tID, tEQ, tOR,
tOPENBR, tCOMMA, tCLOSEBR, tSTAR
} TOKEN;
/* ----------------- Exported variables ---------------- */
extern char lexidval[];
extern int lineno;
extern FILE *lexfile;
/* ----------------- Public procedures ---------------- */
#ifdef HASPROTOS
extern TOKEN nexttok( void );
extern void pushbacktok( void );
#else
extern TOKEN nexttok();
extern void pushbacktok();
#endif
/*
* PARSER FOR THE
* ====== === ===
*
* DATA DECLARATION BUILDER
* ==== =========== =======
*
* This module is the parser used to interprete the high
* level data declarations.
*
******* Grammar for Declarations
*
* declns = ne-list( decln ) tEOF
* decln = tID tEQ shapes tSEMI
* shapes = ne-sep-list( shape, tOR )
* shape = tID [ tOPENBR params tCLOSEBR ]
* params = ne-sep-list( param, tCOMMA )
* param = tID list( tSTAR ) tID
*
******* History
*
* Version Who Date Comments
* ======= === ==== ========
*
* 1.0 dcw 1st Jan 1988 Created
* 1.1 dcw 24th Apr 1989 Major rewrite.
* 1.2 dcw 14th Nov 1989 Fixed a silly buggy wug..
* (empty params => previous params
* retained).
* Added MUSTBE & expected to simplify
* logic.
*/
#include <dcw.h>
#include "struct.h"
#include "lexer.h"
#include "parser.h"
#ifdef HASPROTOS
static BOOL parse_decln( char ** , shapelist * );
static BOOL parse_shapes( shapelist * );
static BOOL parse_shape( char ** , paramlist * );
static BOOL parse_params( paramlist * );
static BOOL parse_param( char ** , int * , char ** );
#else
static BOOL parse_decln();
static BOOL parse_shapes();
static BOOL parse_shape();
static BOOL parse_params();
static BOOL parse_param();
#endif
/* declns = ne-list( decln ) tEOF */
BOOL parse_declns( dp ) declnlist *dp;
{
char *name;
shapelist shapes;
for(;;) {
if( ! parse_decln( &name, &shapes ) ) return FALSE;
*dp = build_declnlist( name, shapes, NULL );
if( nexttok() == tEOF ) break;
ungettok();
dp = &( (*dp)->next );
}
return TRUE;
}
static void expected( s ) char *s;
{
fprintf( stderr, "%s expected at line %d\n", s, lineno );
}
#define MUSTBE(t,mesg) if( nexttok() != (t) ) {expected(mesg); return FALSE;}
/* decln = tID tEQ shapes tSEMI */
static BOOL parse_decln( name, shapes ) char **name; shapelist *shapes;
{
MUSTBE( tID, "declaration" );
COPYOF( *name, lexidval );
MUSTBE( tEQ, "'='" );
if( ! parse_shapes( shapes ) ) return FALSE;
MUSTBE( tSEMI, "';'" );
return TRUE;
}
/* shapes = ne-sep-list( shape, tOR ) */
static BOOL parse_shapes( sp ) shapelist *sp;
{
char *tagname;
paramlist paras;
for(;;) {
if( ! parse_shape( &tagname, &paras ) ) return FALSE;
*sp = build_shapelist( tagname, paras, NULL );
if( nexttok() != tOR ) break;
sp = &( (*sp)->next );
}
ungettok();
return TRUE;
}
/* shape = tID [ tOPENBR params tCLOSEBR ] */
static BOOL parse_shape( tagname, pl ) char **tagname; paramlist *pl;
{
MUSTBE( tID, "shape name" );
COPYOF( *tagname, lexidval );
*pl = NULL;
if( nexttok() != tOPENBR )
{
ungettok();
return TRUE;
}
if( ! parse_params( pl ) ) return FALSE;
MUSTBE( tCLOSEBR, "')'" );
return TRUE;
}
/* params = ne-sep-list( param, tCOMMA ) */
static BOOL parse_params( pp ) paramlist *pp;
{
int stars;
char *type;
char *name;
for(;;) {
if( !parse_param( &type, &stars, &name ) ) return FALSE;
*pp = build_paramlist( type, stars, name, NULL );
if( nexttok() != tCOMMA ) break;
pp = &( (*pp)->next );
}
ungettok();
return TRUE;
}
/* param = tID list( tSTAR ) tID */
static BOOL parse_param( type, stars, name ) char **type,**name; int *stars;
{
MUSTBE( tID, "Field type" );
COPYOF( *type, lexidval );
for( *stars = 0; nexttok()==tSTAR; (*stars)++ );
ungettok();
MUSTBE( tID, "Field name" );
COPYOF( *name, lexidval );
return TRUE;
}
#ifdef HASPROTOS
extern BOOL parse_declns( declnlist * );
#else
extern BOOL parse_declns();
#endif
/*
* DATA STRUCTURES
* ==== ==========
*
* FOR THE
* === ===
*
* DATA DECLARATION BUILDER
* ==== =========== =======
*
* This module provides the internal structures needed
* for the data declaration builder. It is itself the
* sort of output generated by the program.
*
******* History
*
* Version Who Date Comments
* ======= === ==== ========
*
* 1.0 dcw 31st Dec 1987 Created
* 1.1 dcw 1st Jan 1988 Recreated after screwup
* 1.2 dcw 24th Apr 1989 Had a look again.. lowercased the lot
*/