File:  [MW Coherent from dump] / coherent / d / usr / lib / scn / scn.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:38 2019 UTC (7 years, 2 months ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
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);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.