You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

758 lines
19 KiB

/* config.y - yacc input file for the Xinu config program */
/************************************************************************/
/* */
/* This file contains the yacc grammar and semantic functions */
/* that read a Xinu Configuration file and generate output files */
/* conf.h and conf.c that are then compiled along with the rest of */
/* Xinu. */
/* */
/************************************************************************/
%token DEFBRK IFBRK COLON OCTAL INTEGER IDENT CSR IRQ INTR INIT OPEN
CLOSE READ WRITE SEEK CONTROL IS ON GETC PUTC
%{
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
extern char *yytext;
/*
Work-around for the type conflict that results from unmatched versions
of flex and bison (lex and yacc). The idea is to force the new flex
style so the output file (lex.yy.c) treats yyleng as an int (as was
done by oldest lex versions) instead of a size_t. We override the
new flex typedef of yy_size_t.
*/
#ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
typedef int yy_size_t;
#endif
/* End work-around */
extern int yyleng;
/********************************************************************************/
/* */
/* Start of Definitions */
/* */
/********************************************************************************/
#define NIL (struct dev_ent *)0x00
#define CONFC "conf.c" /* Name of .c output */
#define CONFH "conf.h" /* Name of .h output */
#define CONFHREF "<conf.h>" /* How conf.h referenced */
#define INFILE "Configuration" /* Name of input file */
// RAFA #define MAXNAME 16 /* Max length of names */
#define MAXNAME 16 /* Max length of names */
// RAFA #define NDEVS 250 /* Max devices */
// RAFA #define NTYPES 250 /* Max device types */
#define NDEVS 5 /* Max devices */
#define NTYPES 5 /* Max device types */
int linectr = 1;
FILE *confc;
FILE *confh;
int brkcount = 0; /* Count of %% separators till now in */
/* the input file */
char *doing = "device type declarations";
struct dev_ent { /* Entry for a device or device type */
char name[MAXNAME]; /* device name (unused in a type) */
char tname[MAXNAME]; /* Type name */
char ison[MAXNAME]; /* Name is "on" XXX */
int tindex; /* Index in dtypes (unused in a type) */
int csr; /* Control Status Register addr */
int irq; /* interrupt request */
char intr[MAXNAME]; /* interrupt function name */
char init[MAXNAME]; /* init function name */
char open[MAXNAME]; /* open function name */
char close[MAXNAME]; /* close function name */
char read[MAXNAME]; /* read function name */
char write[MAXNAME]; /* write function name */
char control[MAXNAME]; /* control function name */
char seek[MAXNAME]; /* seek function name */
char getc[MAXNAME]; /* getc function name */
char putc[MAXNAME]; /* putc function name */
int minor; /* In a device, the minor device */
/* assigned to the device 0,1,... */
/* in a type, the next minor number */
/* to assign */
};
struct dev_ent dtypes[NTYPES];/* Table of all device types */
int ntypes = 0; /* Number of device types found */
struct dev_ent devs[NDEVS]; /* Table of all devices */
int ndevs = 0; /* Number of devices found */
char *devstab[] = {
"/* Device table entry */",
"struct\tdentry\t{",
"\tint32 dvnum;",
"\tint32 dvminor;",
// RAFA "\tchar *dvname;",
// "\tchar dvname[16];",
// RAFA BIEN "\tchar dvname[8];",
"\tchar dvname[10];",
"\tdevcall (*dvinit) (struct dentry *);",
"\tdevcall (*dvopen) (struct dentry *, char *, char *);",
"\tdevcall (*dvclose)(struct dentry *);",
"\tdevcall (*dvread) (struct dentry *, void *, uint32);",
"\tdevcall (*dvwrite)(struct dentry *, void *, uint32);",
"\tdevcall (*dvseek) (struct dentry *, int32);",
"\tdevcall (*dvgetc) (struct dentry *);",
"\tdevcall (*dvputc) (struct dentry *, char);",
"\tdevcall (*dvcntl) (struct dentry *, int32, int32, int32);",
"\tvoid *dvcsr;",
"\tvoid (*dvintr)(void);",
"\tbyte dvirq;",
"};\n",
"extern const __flash struct dentry devtab[] ; /* one entry per device */",
// "extern struct dentry devtab[] ; /* one entry per device */",
NULL
};
//"};\n",
// "extern struct dentry devtab[] PROGMEM; /* one entry per device */",
char saveattrid[MAXNAME]; /* Holds the IDENT from an attribute */
/********************************************************************************/
/* */
/* Function prototypes */
/* */
/********************************************************************************/
void addattr(int, int);
int addton(char *);
int config_atoi(char *, int);
void devisid(char *);
void devonid(char *);
void getattrid(char *);
void newdev(char *);
int newtype(char *);
void yyerror(char *);
%}
%%
/************************************************************************/
/* */
/* Grammar rules for the entire Configuration */
/* */
/************************************************************************/
configuration: devtypes DEFBRK devices
;
/************************************************************************/
/* */
/* Grammar rules for device types */
/* */
/************************************************************************/
devtypes: /* nothing */ { doing = "device definitions"; }
| devtypes devtype
;
devtype: tname COLON dev_tlist
;
tname: IDENT { $$ = newtype(yytext); }
;
dev_tlist: theader attr_list
| dev_tlist theader attr_list
;
theader: ON tonid { $$ = $2; }
;
tonid: IDENT { $$ = addton(yytext); }
;
attr_list: /* nothing */
| attr_list attr
;
attr: CSR number { addattr(CSR, $2); }
| IRQ number { addattr(IRQ, $2); }
| INTR id { addattr(INTR, 0); }
| OPEN id { addattr(OPEN, 0); }
| CLOSE id { addattr(CLOSE, 0); }
| INIT id { addattr(INIT, 0); }
| GETC id { addattr(GETC, 0); }
| PUTC id { addattr(PUTC, 0); }
| READ id { addattr(READ, 0); }
| WRITE id { addattr(WRITE, 0); }
| SEEK id { addattr(SEEK, 0); }
| CONTROL id { addattr(CONTROL, 0); }
;
id: IDENT { $$ = 0; getattrid(yytext); }
;
number: INTEGER { $$ = config_atoi(yytext, yyleng); }
;
/************************************************************************/
/* */
/* Grammar rules for device definitions */
/* */
/************************************************************************/
devices: /* nothing */ { doing = "interface types"; }
| devices device
;
device: dheader attr_list
;
dheader: dname devis devon
;
dname: IDENT { newdev(yytext); }
;
devis: IS devisid
;
devisid: IDENT { devisid(yytext); }
;
devon: ON devonid
;
devonid: IDENT { devonid(yytext); }
;
%%
#include "lex.yy.c"
/************************************************************************/
/* */
/* main - main program: parse arguments, invoke the parser, and */
/* write the conf.h and conf.c files */
/* */
/************************************************************************/
int main(int argc, char **argv) {
int n, i, j, l, fcount;
struct dev_ent *s;
int verbose = 0;
char *p;
int c;
if ( argc > 1 && (strncmp("-v", argv[1], 2) == 0) ) {
argc--;
argv++;
verbose++;
}
if ( argc > 4 ) {
fprintf(stderr, "use: config [-v] [input_file] [conf.c] [conf.h]\n");
exit(1);
}
if (verbose) { printf("Opening input file...\n"); }
if (argc >= 2) {
if (freopen(argv[1], "r", stdin) == NULL) {
fprintf(stderr, "Can't open %s\n", argv[1]);
exit(1);
}
}
else { /* try to open Configuration file */
if (freopen(INFILE, "r", stdin) == NULL) {
fprintf(stderr, "Can't open %s\n", INFILE);
exit(1);
}
}
/****************************************************************/
/* */
/* Parse the Configuration file */
/* */
/****************************************************************/
if (verbose) { printf("Parsing configuration specs...\n"); }
if ( (n = yyparse()) != 0 ) { exit(n); }
/* Open conf.h and conf.c for writing */
if (verbose) { printf("Opening output files...\n"); }
if (argc >= 3) {
if ( (confc = fopen(argv[2],"w") ) == NULL) {
fprintf(stderr, "Can't write on %s\n", argv[2]);
exit(1);
}
}
else { /* try to open conf.c file */
if ( (confc = fopen(CONFC,"w") ) == NULL) {
fprintf(stderr, "Can't write on %s\n", CONFC);
exit(1);
}
}
if (argc >= 4) {
if ( (confh = fopen(argv[3],"w") ) == NULL) {
fprintf(stderr, "Can't write on %s\n", argv[3]);
exit(1);
}
}
else { /* try to open conf.h file */
if ( (confh = fopen(CONFH,"w") ) == NULL) {
fprintf(stderr, "Can't write on %s\n", CONFH);
exit(1);
}
}
/****************************************************************/
/* */
/* produce conf.h */
/* */
/****************************************************************/
fprintf(confh, "/* conf.h (GENERATED FILE; DO NOT EDIT) */\n\n");
if (verbose) { printf("Writing output...\n"); }
fprintf(confh, "/* Device switch table declarations */\n\n");
for (i = 0; (p = devstab[i]) != NULL; i++) {
fprintf(confh, "%s\n", p);
}
fprintf(confh, "\n");
/* write device declarations and definitions */
fprintf(confh, "/* Device name definitions */\n\n");
for (i = 0; i<ndevs; i++) {
s = &devs[i];
fprintf(confh, "#define %-20s%2d\t/* type %-8s */\n",
s->name, i, s->tname);
}
fprintf(confh, "\n");
/* write count of device types */
fprintf(confh, "/* Control block sizes */\n\n");
for (i = 0; i < ntypes; i++) {
s = &dtypes[i];
if (s->minor > 0) {
fprintf(confh, "#define\tN%s\t%d\n",
s->tname, s->minor);
}
}
fprintf(confh, "\n");
if (ndevs > 0) { fprintf(confh, "#define NDEVS %d\n", ndevs); }
/* Copy definitions to output */
if (brkcount >= 4 && verbose) {
printf("Copying definitions to %s...\n", CONFH);
}
if (brkcount >= 2) {
while ( (c = input()) > 0) { /* lex input function */
putc(c, confh);
}
}
fclose(confh);
/****************************************************************/
/* */
/* produce conf.c */
/* */
/****************************************************************/
fprintf(confc, "/* conf.c (GENERATED FILE; DO NOT EDIT) */\n\n");
fprintf(confc, "#include <xinu.h>\n\n");
fprintf(confc, "\n");
fprintf(confc, "extern\tdevcall\tioerr(void);\n");
fprintf(confc, "extern\tdevcall\tionull(void);\n\n");
/* produce devtab (giant I/O switch table) */
fprintf(confc, "/* Device independent I/O switch */\n\n");
if (ndevs > 0)
{
// fprintf(confc, "typedef unsigned int size_t;\n");
// fprintf(confc, "#include <avr/pgmspace.h>\n");
fprintf(confc, "const __flash struct dentry devtab[] =\n{\n");
// fprintf(confc, "struct dentry devtab[] =\n{\n");
fprintf(confc, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n\n",
"/**",
" * Format of entries is:",
" * dev-number, minor-number, dev-name,",
" * init, open, close,",
" * read, write, seek,",
" * getc, putc, control,",
" * dev-csr-address, intr-handler, irq",
" */");
}
for (i=0; i<ndevs; i++) {
s = &devs[i];
fprintf(confc, "/* %s is %s */\n", s->name, s->tname);
fprintf(confc, "\t{ %d, %d, \"%s\",\n", i, s->minor, s->name);
fprintf(confc, "\t (void *)%s, (void *)%s, (void *)%s,\n",
s->init, s->open, s->close);
fprintf(confc, "\t (void *)%s, (void *)%s, (void *)%s,\n",
s->read, s->write, s->seek);
fprintf(confc, "\t (void *)%s, (void *)%s, (void *)%s,\n",
s->getc, s->putc, s->control);
fprintf(confc, "\t (void *)0x%x, (void *)%s, %d }",
s->csr, s->intr, s->irq);
if (i< ndevs-1) {
fprintf(confc, ",\n\n");
} else {
fprintf(confc, "\n};");
}
}
/* we must guarantee conf.c written later than conf.h for make */
fprintf(confc, "\n");
fclose(confc);
/* finish up and write report for user if requested */
if (verbose) {
printf("Configuration complete. Number of devs=%d:\n", ndevs);
for (i=0; i<ndevs; i++) {
s = &devs[i];
printf("Device %s (on %s)\n", s->name, s->ison);
printf(" csr=0x%04x, irq=0x%04x, minor=%d\n",
s->csr, s->irq, s->minor);
}
}
}
/************************************************************************/
/* */
/* addattr - add a new attribute spec to current type/device description*/
/* tok: token type (attribute type) */
/* val: symbol number of value */
/* */
/************************************************************************/
void addattr(int tok, int val) {
struct dev_ent *s;
char *c;
if (brkcount == 0) {
/* Doing types */
s = &dtypes[ntypes-1];
} else {
/* Doing devices */
s = &devs[ndevs-1];
}
switch (tok) {
case CSR: s->csr = val; break;
case IRQ: s->irq = val; break;
case INTR: strcpy(s->intr, saveattrid); break;
case READ: strcpy(s->read, saveattrid); break;
case WRITE: strcpy(s->write,saveattrid); break;
case GETC: strcpy(s->getc, saveattrid); break;
case PUTC: strcpy(s->putc, saveattrid); break;
case OPEN: strcpy(s->open, saveattrid); break;
case CLOSE: strcpy(s->close,saveattrid); break;
case INIT: strcpy(s->init, saveattrid); break;
case SEEK: strcpy(s->seek, saveattrid); break;
case CONTROL: strcpy(s->control,saveattrid); break;
default: fprintf(stderr, "Internal error 1\n");
}
}
/************************************************************************/
/* */
/* addton -- add an "on XXX" to the current type */
/* */
/************************************************************************/
int addton(char *tonid) {
int currtype; /* The current type */
if (strlen(tonid) >= MAXNAME) {
fprintf(stderr,"string %s is too long on line %d\n",
tonid, linectr);
exit(1);
}
currtype = ntypes - 1;
strcpy(dtypes[currtype].ison, tonid);
return currtype;
}
/************************************************************************/
/* */
/* config_atoi - convert an ascii string of text to an integer, */
/* honoring octal, decimal, and hex */
/* */
/************************************************************************/
int config_atoi(char *p, int len) {
int base, rv;
if (*p == '0')
{
++p;
--len;
if (*p == 'x' || *p == 'X')
{
++p; --len; /* skip 'x' */
base = 16;
}
else
{
base = 8;
}
}
else
{
base = 10;
}
rv = 0;
for (; len > 0; ++p, --len)
{
rv *= base;
if (isdigit(*p)) { rv += *p - '0'; }
else if (isupper(*p)) { rv += *p - 'A' + 10; }
else { rv += *p - 'a' + 10; }
}
return rv;
}
/************************************************************************/
/* */
/* devisid -- add an "is XXX" to the current device */
/* */
/************************************************************************/
void devisid(char *tname) {
int currdev; /* The current device */
int i;
if (strlen(tname) >= MAXNAME) {
fprintf(stderr,"string %s is too long on line %d\n",
tname, linectr);
exit(1);
}
/* Verify the type exists */
for (i=0; i<ntypes; i++) {
if (strcmp(tname, dtypes[i].tname) == 0) {
break;
}
}
if (i >= ntypes) {
fprintf(stderr, "Illegal type name %s on line %d\n",
tname, linectr);
exit(1);
}
currdev = ndevs - 1;
strcpy(devs[currdev].tname, tname);
return;
}
/************************************************************************/
/* */
/* devonid -- add an "on XXX" to the current device, lookup the type, */
/* and copy attributes into the device from the type */
/* */
/************************************************************************/
void devonid(char *onname) {
int currdev; /* The current device */
int i;
struct dev_ent *dptr; /* Pointer to current device */
struct dev_ent *tptr; /* Pointer to a type */
char tmp[MAXNAME]; /* Holds the device name during */
/* copy */
if (strlen(onname) >= MAXNAME) {
fprintf(stderr,"string %s is too long on line %d\n",
onname, linectr);
exit(1);
}
if (ndevs <=0) {
fprintf(stderr,"Internal error 3\n");
exit(1);
}
currdev = ndevs - 1;
dptr = &devs[currdev];
strcpy(dptr->ison, onname);
/* Lookup the device type */
for (i=0; i<ntypes; i++) {
tptr = &dtypes[i];
if ( (strcmp(dptr->tname,tptr->tname) == 0 ) &&
(strcmp(dptr->ison, tptr->ison) == 0 ) ){
/* The specified type matches the ith entry, so */
/* set all attributes equal to the ones in the */
/* type definition. */
strcpy(tmp, dptr->name);
bcopy (tptr, dptr, sizeof(struct dev_ent));
/* Increment the minor device number for the */
/* next time the type is used */
tptr->minor++;
strcpy(dptr->name, tmp);
return;
}
}
fprintf(stderr, "Ileagal device specification on line %d\n", linectr);
exit(1);
}
/************************************************************************/
/* */
/* getattrid -- pick up and save the attribute string from an id */
/* */
/************************************************************************/
void getattrid(char *str) {
if (strlen(str) >= MAXNAME) {
fprintf(stderr,"atribute string %s is too long on line %d\n",
str, linectr);
exit(1);
}
strcpy(saveattrid, str);
return;
}
/************************************************************************/
/* */
/* newdev -- allocate an entry in devs, initialize, and fill in the name*/
/* */
/************************************************************************/
void newdev(char *name) {
struct dev_ent *dptr; /* Ptr. to an entry in devs */
int i;
if (ndevs >= NDEVS) {
fprintf(stderr,"Too many devices on line %d", linectr);
exit(1);
}
if (strlen(name) >= MAXNAME) {
fprintf(stderr,"Device name %s is too long on line %d\n",
name, linectr);
exit(1);
}
/* Verify that the device name is unique */
for (i=0; i<ndevs; i++) {
if (strcmp(name, devs[i].name) == 0) {
fprintf(stderr, "Duplicate device name %s on line %d\n",
name, linectr);
exit(1);
}
}
dptr = &devs[ndevs];
/* Initialize fields in the entry */
bzero((void *)dptr, sizeof(struct dev_ent));
strcpy(dptr->name, name);
ndevs++;
return;
}
/************************************************************************/
/* */
/* newtype -- allocate an entry in the type array and fill in the name */
/* */
/************************************************************************/
int newtype(char *name) {
struct dev_ent *dptr; /* Ptr. to an entry in dtypes */
int i; /* Index into the type table */
if (ntypes >= NTYPES) {
fprintf(stderr,"Too many types on line %d", linectr);
exit(1);
}
if (strlen(name) >= MAXNAME) {
fprintf(stderr,"Type name %s is too long on line %d\n",
name, linectr);
exit(1);
}
/* Verify that the type name is unique */
for (i=0; i<ntypes; i++) {
if (strcmp(name, dtypes[i].tname) == 0) {
fprintf(stderr, "Duplicate type name %s on line %d\n",
name, linectr);
exit(1);
}
}
dptr = &dtypes[ntypes];
/* Initialize fields in the entry */
bzero((void *)dptr, sizeof(struct dev_ent));
strcpy(dptr->tname, name);
strncpy(dptr->intr, "ioerr", 5);
strncpy(dptr->init, "ioerr", 5);
strncpy(dptr->open, "ioerr", 5);
strncpy(dptr->close, "ioerr", 5);
strncpy(dptr->read, "ioerr", 5);
strncpy(dptr->write, "ioerr", 5);
strncpy(dptr->control, "ioerr", 5);
strncpy(dptr->seek, "ioerr", 5);
strncpy(dptr->getc, "ioerr", 5);
strncpy(dptr->putc, "ioerr", 5);
return ntypes++;
}
/************************************************************************/
/* */
/* yyerror - print an error message with the line number */
/* */
/************************************************************************/
void yyerror(char *s) {
fprintf(stderr, "Syntax error in %s on line %d\n", doing, linectr);
}