|
|
coherent
/*
* Quick and dirty screen builder.
* by Charles Fiterman on 2-6-90
*
* pass 1 count lines with data and field start chars.
* allocate tables.
* pass 2 build data.
* pass 3 output data to .c file.
*/
#include <misc.h>
#include <scn.h>
#include <ctype.h>
extern char *strrchr();
extern char *strchr();
extern char *strcpy();
static char *fileName = NULL;
static char *outFile;
static char fieldDesig = '!';
static int errCt = 0, line = 1;
static int backCnt, locCnt;
static loc *locTab;
static long filePos;
static FILE *ifp, *ofp, *hfp;
static char *buf;
#define MAXTOKEN 5
/*
* Usage message documents program usage.
*/
void
Usage()
{
fprintf(stderr, "Usage: scn [-fc] filename\n");
fprintf(stderr, "\t-fc sets field designator to c\n");
exit(1);
}
/*
* Read into buff.
*/
qread()
{
return (NULL != (buf = getline(ifp, &line)));
}
/*
* this routine breaks command_string into individual tokens, putting
* pointers to these tokens into the array tokenlist.
* no more than maxtoken tokens will be found.
* Note that the string is modified to place '\0' over
* token separators. The tokenlist points into the string.
* Tokens are separated by spaces, tabs and commas.
*/
void
tokenize(s, tokenlist, maxtoken)
register char *s;
char *tokenlist[];
int maxtoken;
{
register int state, i;
for (i = 0; i < maxtoken; i++)
tokenlist[i] = NULL;
for (i = state = 0; ; s++) {
switch (*s) {
case ' ':
case '\t':
*s = state = 0;
continue;
case ',':
*s = state = 0;
if (maxtoken > ++i)
continue;
fprintf(stderr, "Too many tokens in line %d\n", line);
errCt++;
case 0:
return;
}
if (!state) { /* was in whitespace */
tokenlist[i] = s;
state = 1; /* in token */
}
}
}
/*
* Count lines and fields allocate space.
*/
void
pass1()
{
register char *p, c;
int sw, pos, nameCt, nlines, repits;
fprintf(ofp, "/*\n");
fprintf(ofp, " * This file generated by scn from %s\n", fileName);
fprintf(ofp, " */\n");
for (nlines = repits = nameCt = 0; qread(); ) {
char *token[MAXTOKEN]; /* name len default verifyProc */
int len;
if ('%' == buf[0]) { /* control statemnet */
switch (buf[1]) {
case '%': /* done with preface */
filePos = ftell(ifp);
break;
case 'h': /* help line */
continue;
case ' ': /* group line */
case 'g':
if (2 == sscanf(buf + 2, "%d %d",
&nlines, &repits))
continue;
default:
fatal("Improper control line line %d", line);
}
break;
}
tokenize(buf, token, MAXTOKEN);
if (token[0] != NULL) {
if (!(len = abs(atoi(token[1]))))
len = abs(atoi(token[2]));
len++;
if (nlines) {
nlines--;
nameCt += repits;
fprintf(hfp,
"extern char %s[%d][%d];\n",
token[0],
repits,
len);
fprintf(ofp,
"char %s[%d][%d];\n",
token[0],
repits,
len);
}
else {
nameCt++;
fprintf(hfp, "extern char %s[%d];\n",
token[0], len);
fprintf(ofp, "char %s[%d];\n",
token[0], len);
}
}
else {
errCt++;
fprintf(stderr, "No field in line %d\n", line);
}
if (NULL != token[3])
fprintf(ofp, "extern int (*%s)();\n", token[3]);
if ((NULL != token[2]) && (NULL != token[1]) &&
((len = atoi(token[1])) > 0) &&
(strlen(token[2]) > len)) {
errCt++;
fprintf(stderr, "default %s greater then %d line %d\n",
token[2], len, line);
}
}
fprintf(ofp, "/* C tables for the screen:\n");
while (qread()) {
pos = sw = 0;
for (p = buf; c = *p; p++, pos++) {
if (c == fieldDesig)
locCnt++;
else if (!isspace(c))
sw = 1;
else if ('\t' == c)
pos |= 7;
}
backCnt += sw;
if (pos > 80) {
errCt++;
fprintf(stderr, "Line %d too long", line);
continue;
}
for (p = buf; c = *p++; sw = c) {
if ((('/' == c) && ('*' == sw)) ||
(('/' == sw) && ('*' == c)))
c = '?';
fputc(c, ofp);
}
fputc('\n', ofp);
}
fprintf(ofp, " */\n\n");
if (nameCt != locCnt)
fatal("%d field names but %d fileds", nameCt, locCnt);
if (errCt)
exit(1);
if (locCnt)
locTab = alloc(locCnt * sizeof(loc));
}
/*
* Put together tables.
*/
void
pass2()
{
int dataLine, row, lc;
fseek(ifp, filePos, 0); /* pass %% */
fprintf(ofp, "/*\n");
fprintf(ofp, " * Screen background data.\n");
fprintf(ofp, " */\n");
fprintf(ofp, "#include <scn.h>\n\n");
fprintf(ofp, "struct backGrnd %s_data[] = {\n", fileName);
for (lc = row = dataLine = 0; qread(); row++) {
register char *p, c, *p1;
int spos, pos;
for ((p1 = NULL), (p = buf), (pos = 0); c = *p; pos++, p++) {
if (c == fieldDesig) {
locTab[lc].row = row;
locTab[lc].col = pos;
*p = ' ';
lc++;
continue;
}
switch (c) {
case '\t':
pos |= 7;
case ' ':
continue;
}
if (NULL == p1) { /* mark start of line */
spos = pos;
p1 = p;
}
}
if (NULL == p1) /* no printable data on line */
continue;
for (p--; isspace(*p); p--) /* trim line */
*p = '\0';
fputc('"', ofp);
for (pos = spos; c = *p1; p1++) {
switch (c) {
case '\t': /* raw mode ignores tabs */
do { /* make them spaces */
fputc(' ', ofp);
} while (++pos & 7);
continue;
case '\\':
case '"':
fputc('\\', ofp);
default:
fputc(c, ofp);
}
pos++;
}
fprintf(ofp, "\",\n\t %d, %d,\n", row, spos);
}
fprintf(ofp, "NULL\n");
fprintf(ofp, "};\n\n");
}
#define nc(t, x) ((NULL != t) ? t : x)
void
pass3()
{
register int i;
int nlines, skipout;
rewind(ifp);
fprintf(ofp, "/*\n");
fprintf(ofp, " * Screen data location table.\n");
fprintf(ofp, " */\n");
fprintf(ofp, "struct loc %s_locs[] = {\n", fileName);
for (skipout = nlines = i = 0; i < locCnt; i++) {
char *token[MAXTOKEN]; /* name len default verifyProc */
char helpMsg[80];
int skip, len, slines, j, repits;
helpMsg[0] = 0;
for (qread(); '%' == buf[0]; qread()) {
switch (buf[1]) {
case ' ':
case 'g':
sscanf(buf + 2, "%d %d", &nlines, &repits);
j = 0;
slines = nlines;
skipout = nlines * repits;
filePos = ftell(ifp);
break;
case 'h':
strcpy(helpMsg, buf + 3);
}
}
tokenize(buf, token, MAXTOKEN);
if (NULL == token[1]) /* no length given */
len = 79 - locTab[i].col;
else
len = atoi(token[1]);
if (skipout)
skipout--;
skip = 0;
if (NULL != token[4]) {
if (strcmp(token[4], "group"))
skip = atoi(token[4]);
else
skip = skipout;
}
else if (!len)
skip = atoi(token[2]);
if (nlines) {
if (len <= 0)
fprintf(ofp, /* field is default */
"\t%s[%d], %d, %s[%d], %s, %d, %d, %d,",
token[0], j,
-len,
((len && NULL != token[2]) ?
token[2] : token[0]),
j,
nc(token[3], "NULL"),
locTab[i].row,
locTab[i].col,
skip);
else
fprintf(ofp,
"\t%s[%d], %d, \"%s\", %s, %d, %d, %d,",
token[0], j,
len,
nc(token[2], ""),
nc(token[3], "NULL"),
locTab[i].row,
locTab[i].col,
skip);
if (!--nlines && (++j != repits)) {
fseek(ifp, filePos, 0);
nlines = slines;
}
}
else {
if (len <= 0)
fprintf(ofp,
"\t%s, %d, %s, %s, %d, %d, %d,",
token[0],
-len,
((len && NULL != token[2]) ?
token[2] : token[0]),
nc(token[3], "NULL"),
locTab[i].row,
locTab[i].col,
skip);
else
fprintf(ofp,
"\t%s, %d, \"%s\", %s, %d, %d, %d,",
token[0],
len,
nc(token[2], ""),
nc(token[3], "NULL"),
locTab[i].row,
locTab[i].col,
skip);
}
if (helpMsg[0])
fprintf(ofp, "\n\t\"%s\",\n", helpMsg);
else
fprintf(ofp, " NULL,\n");
}
fprintf(ofp, "\tNULL\n};\n");
}
/*
* Process args and call phases.
*/
main(argc, argv)
char **argv;
{
register char *arg;
while (NULL != (arg = *++argv)) {
if ('-' == *arg) {
switch (*++arg) {
case 'f':
fieldDesig = *++arg;
break;
default:
Usage();
}
continue;
}
fileName = arg;
}
if (NULL == fileName)
Usage();
ifp = xopen(fileName, "r");
if (NULL != (arg = strrchr(fileName, '/')))
fileName = arg + 1;
if (NULL != (arg = strrchr(fileName, '.')))
*arg = '\0';
outFile = alloc(strlen(fileName) + 3);
sprintf(outFile, "%s.c", fileName);
ofp = xopen(outFile, "w");
sprintf(outFile, "%s.h", fileName);
hfp = xopen(outFile, "w");
fprintf(hfp, "/*\n");
fprintf(hfp, " * This file generated by scn from %s\n", fileName);
fprintf(hfp, " */\n");
fprintf(hfp, "#include <scn.h>\n\n");
fprintf(hfp, "extern loc %s_locs[];\n", fileName);
fprintf(hfp, "extern backGrnd %s_data[];\n", fileName);
pass1();
pass2();
pass3();
exit(0);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.