Category : C Source Code
Archive   : CDBDEV.ZIP
Filename : SCHEMA.C
/* Read a file from the standard input.
* Write one of three schema files to the standard output
* depending on the runtime switch.
* If -1 is on the command line,
* the #define statements are built.
* If -2 is on the command line,
* the file of ascii strings for
* file and data element names is built.
* If -3 is on the command line,
* the data base schema array source file is built.
*/
#include
#define SCHEMA
#include "cdata.h"
#define MXCAT 3 /* maximum elements concatenated per index */
#define NAMLEN 31
struct dict { /* data element dictionary */
char dename [NAMLEN+1]; /* name */
char detype; /* type */
int delen; /* length */
char *demask; /* display mask */
} dc [MXELE];
int dectr = 0; /* data elements in dictionary */
int fctr = 0; /* files in data base */
char filename [MXFILS] [NAMLEN+1]; /* file name strings */
int fileele [MXFILS] [MXELE]; /* elements in files */
int ndxele [MXFILS] [MXINDEX] [MXCAT]; /* indices */
char word[NAMLEN+1];
char *malloc();
int lnctr = 0; /* input stream line counter */
char ln [160];
/* -------- error messages ----------- */
char *ers[] = { "invalid name", /* 1 */
"invalid length", /* 2 */
"comma missing", /* 3 */
"invalid data type", /* 4 */
"quote missing", /* 5 */
"#schema missing", /* 6 */
"#
"unexpected end of file", /* 8 */
"duplicate file name", /* 9 */
"unknown data element", /* 10 */
"too many data elements", /* 11 */
"out of memory", /* 12 */
"unknown file name", /* 13 */
"too many indices in file", /* 14 */
"too many elements in index", /* 15 */
"duplicate data element", /* 16 */
"too many files", /* 17 */
"invalid command line switch" /* 18 */
};
void de_dict(), files(), keys(), schout(), defout(),
lcase(), strout(), error(), get_line(), skip_white(),
name_val(), numb_val(), expect_comma(), depart();
char *get_word();
#define iswhite(c) ((c)==' '||(c)=='\t')
#define REMARK ';'
/* ----------------- main program -------------- */
main(argc, argv)
int argc;
char *argv[];
{
get_line();
if (strncmp(ln, "#schema ", 8))
error(6);
else {
get_word(ln + 8);
name_val();
printf("\n/");
printf("* ------------- %s ------------ */\n", word);
}
get_line();
while (strncmp(ln, "#end schema", 11)) {
if (strncmp(ln, "#dictionary", 11) == 0)
de_dict();
else if (strncmp(ln, "#file ", 6) == 0)
files();
else if (strncmp(ln, "#key ", 5) == 0)
keys();
else
error(7);
get_line();
}
if (argc > 1) {
if (strcmp(argv[1], "-1") == 0)
defout();
else if (strcmp(argv[1], "-2") == 0)
strout();
else if (strcmp(argv[1], "-3") == 0)
schout();
else
error(18);
}
else
error(18);
depart(0);
}
/* -------- build the data element dictionary ---------- */
static void de_dict()
{
char *cp, *cp1;
int el;
while (TRUE) {
get_line();
if (strncmp(ln, "#end dictionary", 15) == 0)
break;
if (dectr == MXELE) {
error(11);
continue;
}
cp = get_word(ln);
name_val();
for (el = 0; el < dectr; el++)
if (strcmp(word, dc[el].dename) == 0) {
error(16);
continue;
}
strcpy(dc[dectr].dename, word);
expect_comma(&cp);
skip_white(&cp);
switch (*cp) {
case 'A':
case 'Z':
case 'C':
case 'N':
case 'D': break;
default : error(4);
continue;
}
dc[dectr].detype = *cp++;
expect_comma(&cp);
cp = get_word(cp);
numb_val();
dc[dectr].delen = atoi(word);
expect_comma(&cp);
skip_white(&cp);
if (*cp != '"') {
error(5);
continue;
}
cp1 = cp + 1;
while (*cp1 != '"' && *cp1 && *cp1 != '\n')
cp1++;
if (*cp1++ != '"') {
error(5);
continue;
}
*cp1 = '\0';
if ((dc[dectr].demask = malloc((cp1-cp)+1)) == 0) {
error(12);
depart(1);
}
strcpy(dc[dectr].demask, cp);
dectr++;
}
}
/* ----------- build the file definitions ---------------- */
static void files()
{
int i, el = 0;
if (fctr == MXFILS)
error(17);
get_word(ln + 6); /* get the file name */
name_val(); /* validate it */
for (i = 0; i < fctr; i++) /* already assigned? */
if (strcmp(word, filename[i]) == 0)
error(9);
strcpy(filename[fctr], word);
/* ---------- process the file's data elements -------- */
while (TRUE) {
get_line();
if (strncmp(ln, "#end file", 9) == 0)
break;
if (el == MXELE) {
error(11);
continue;
}
get_word(ln); /* get a data element */
for (i = 0; i < dectr; i++) /* in dictionary? */
if (strcmp(word, dc[i].dename) == 0)
break;
if (i == dectr)
error(10);
else if (fctr < MXFILS)
fileele [fctr] [el++] = i + 1; /* post to file */
}
if (fctr < MXFILS)
fctr++;
}
/* ----------- build the index descriptions ------------ */
static void keys()
{
char *cp;
int f, el, x, cat = 0;
cp = get_word(ln + 5); /* get the file name */
for (f = 0; f < fctr; f++) /* in the schema? */
if (strcmp(word, filename[f]) == 0)
break;
if (f == fctr) {
error(13);
return;
}
for (x = 0; x < MXINDEX; x++)
if (*ndxele [f] [x] == 0)
break;
if (x == MXINDEX) {
error(14);
return;
}
while (cat < MXCAT) {
cp = get_word(cp); /* get index name */
for (el = 0; el < dectr; el++) /* in dictionary? */
if (strcmp(word, dc[el].dename) == 0)
break;
if (el == dectr) {
error(10);
break;
}
ndxele [f] [x] [cat++] = el + 1; /* post element */
skip_white(&cp);
if (*cp++ != ',') /* concatenated index? */
break;
if (cat == MXCAT) {
error(15);
break;
}
}
}
/* ---------- write the schema source language ---------- */
static void schout()
{
int f, el, x, x1, cat, fel;
char name [NAMLEN+1];
/* --------- data element lengths ---------- */
printf("\n\nint ellen [] = {");
for (el = 0; el < dectr; el++) {
if ((el % 25) == 0)
printf("\n\t");
printf((el < dectr-1 ? "%d," : "%d"),dc[el].delen);
}
printf("\n};\n");
/* ---------- write the file contents arrays ------- */
for (f = 0; f < fctr; f++) {
lcase(name, filename [f]);
printf("\n\nint f_%s [] = {", name);
el = 0;
while ((fel = fileele[f] [el++]) != 0)
printf("\n\t%s,", dc[fel-1].dename);
printf("\n\t0\n};");
}
/* ------- write the file list pointer array ------- */
printf("\n\nint *file_ele [] = {");
for (f = 0; f < fctr; f++) {
lcase(name, filename [f]);
printf("\n\tf_%s,", name);
}
printf("\n\t0\n};\n");
/* ----------- write the index arrays -------------- */
for (f = 0; f < fctr; f++) {
lcase(name, filename [f]);
for (x = 0; x < MXINDEX; x++) {
if (*ndxele [f] [x] == 0)
break;
printf("\nint x%d_%s [] = {", x + 1, name);
for (cat = 0; cat < MXCAT; cat++)
if (ndxele [f] [x] [cat])
printf("\n\t%s,",
dc[ndxele [f] [x] [cat] - 1].dename);
printf("\n\t0\n};\n");
}
printf("\nint *x_%s [] = {", name);
for (x1 = 0; x1 < x; x1++)
printf("\n\tx%d_%s,", x1 + 1, name);
printf("\n\t0\n};\n");
}
printf("\nint **index_ele [] = {");
for (f = 0; f < fctr; f++) {
lcase(name, filename [f]);
printf("\n\tx_%s,", name);
}
printf("\n\t0\n};\n");
}
/* -- write the schema #defines and struct definitions -- */
static void defout()
{
int f, el, fel;
char name [NAMLEN+1];
/* -------- data element defines --------- */
for (el = 0; el < dectr; el++)
printf("\n#define %s %d", dc[el].dename, el + 1);
putchar('\n');
/* ------- write the file #define statements -------- */
for (f = 0; f < fctr; f++)
printf("\n#define %s %d", filename [f], f);
putchar('\n');
/* ---------- write the record structures ------------ */
for (f = 0; f < fctr; f++) {
lcase(name, filename [f]);
printf("\nstruct %s {", name);
el = 0;
while ((fel = fileele[f] [el++]) != 0) {
lcase(name, dc[fel-1].dename);
printf("\n\tchar %s [%d];",
name, dc[fel-1].delen + 1);
}
printf("\n};\n");
}
}
/* ----- write the file and data element ascii strings ---- */
static void strout()
{
int el, f;
/* -------- data element ascii names --------- */
printf("\nchar *denames [] = {");
for (el = 0; el < dectr; el++)
printf("\n\t\"%s\",", dc[el].dename);
printf("\n\t0\n};\n");
/* -------- data element types ------------ */
printf("\nchar eltype [] = \"");
for (el = 0; el < dectr; el++)
putchar(dc[el].detype);
printf("\";\n");
/* ---------- data element display masks --------- */
printf ("\nchar *elmask [] = {");
for (el = 0; el < dectr; el++)
printf((el < dectr-1 ?
"\n\t%s," :
"\n\t%s"),dc[el].demask);
printf("\n};\n");
/* ------ write the ascii file name strings -------- */
printf("\nchar *dbfiles [] = {");
for (f = 0; f < fctr; f++)
printf("\n\t\"%s\",", filename [f]);
printf("\n\t0\n};\n");
}
/* -------- convert a name to lower case ---------- */
static void lcase(s1, s2)
char *s1, *s2;
{
while (*s2) {
*s1 = tolower(*s2);
s1++;
s2++;
}
*s1 = '\0';
}
/* ----------- errors -------------- */
static void error(n)
int n;
{
static int erct = 0;
static int erlin = 0;
if (erlin != lnctr) {
erlin = lnctr;
fprintf(stderr, "\nLine %d: %s", lnctr, ln);
}
fprintf(stderr, "\n Error %d: %s", n, ers[n-1]);
if (erct++ == 5) {
erct =0;
fprintf(stderr, "\nContinue? (y/n) ... ");
if (tolower(getc(stderr)) != 'y')
depart(1);
}
}
/* --- get a line of data from the schema input stream --- */
static void get_line()
{
*ln = '\0';
while (*ln == '\0' || *ln == REMARK || *ln == '\n') {
if (fgets(ln,120,stdin) == 0) {
error(8);
depart(1);
}
lnctr++;
}
}
/* ---------- skip over white space --------- */
static void skip_white(s)
char **s;
{
while (iswhite(**s))
(*s)++;
}
/* ----------- get a word from a line of input ----------- */
static char *get_word(cp)
char *cp;
{
int wl = 0, fst = 0;
skip_white(&cp);
while (*cp && *cp != '\n' &&
*cp != ',' &&
iswhite(*cp) == 0) {
if (wl == NAMLEN && fst == 0) {
error(1);
fst++;
}
else
word [wl++] = *cp++;
}
word [wl] = '\0';
return cp;
}
/* ---------- validate a name --------------- */
static void name_val()
{
char *s = word;
if (isalpha(*s)) {
while (isalpha(*s) || isdigit(*s) || *s == '_') {
*s = toupper(*s);
s++;
}
if (*s == '\0')
return;
}
error(1);
}
/* ---------- validate a number ------------- */
static void numb_val()
{
char *s = word;
do {
if (isdigit(*s++) == 0) {
error(2);
break;
}
} while (*s);
}
/* ----------- expect a comma next ---------- */
static void expect_comma(cp)
char **cp;
{
skip_white(cp);
if (*(*cp)++ != ',')
error(3);
}
/* --------- terminate schema program ------------- */
static void depart(n)
int n;
{
int el;
for (el = 0; el < dectr; el++)
free(dc[el].demask);
exit(n);
}
#if COMPILER == WIZARD
/* --- strncmp function to replace non-standard version --- */
int strncmp(s1, s2, n)
char *s1, *s2;
{
int i;
while (n--)
if (i = (*s1++ - *s2++))
return i;
return 0;
}
#endif
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/