File:  [MW Coherent from dump] / coherent / d / usr / lib / scn / lex.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

/*
 * Lexer and mainline for new screen builder.
 */
#include <scnbld.h>
#include <y.tab.h>
#include <string.h>
#include <ctype.h>

FILE *ifp, *ofp, *ohp;
int line = 1;
int fieldDesig = '!';
static int errors;
static char *name;

#ifdef TRACE
#define RET(val) { printf("%d: trace %d\n", __LINE__, val); return(val); }
#else
#define RET(val) return(val);
#endif
#define POINT printf("%d: trace point\n", __LINE__);

/*
 * Fatal error.
 */
void
fatal(s)
char *s;
{
	printf("%d: %r\n%d error%s detected\n",
		line, &s, (errors + 1), (errors ? "s": ""));
	exit(1);
}

/*
 * Nonfatal error.
 */
yyerror(s)
char *s;
{
	printf("%d: %r\n", line, &s);
	errors++;
}

main(argc, argv)
char *argv[];
{
	char *p, *q, *fileName;
	char file[20];

	if (NULL == (fileName = argv[1]))
		fatal("No work.");

	ifp = xopen(fileName, "r");

	/* Turn file name into .c and .h version in current dir */
	if (NULL == (p = strrchr(fileName, '/')))
		p = fileName;
	else
		p++;

	if (NULL != (q = strrchr(p, '.')))
		*q = '\0';

	sprintf(file, "%s.c", p);
	ofp = xopen(file, "w");

	sprintf(file, "%s.h", p);
	ohp = xopen(file, "w");

	name = newcpy(p);

	if(NULL != q)
		*q = '.';

	fprintf(ofp, "/*\n");
	fprintf(ofp, " * Screen definition file\n");
	fprintf(ofp, " * This file generated from %s\n", fileName);
	fprintf(ofp, " */\n");
	fprintf(ofp, "#include <%s>\n\n", file);

	fprintf(ohp, "/*\n");
	fprintf(ohp, " * Screen definition header\n");
	fprintf(ohp, " * This file generated from %s\n", fileName);
	fprintf(ohp, " */\n");
	fprintf(ohp, "#include <scn.h>\n\n");
	fprintf(ohp, "extern backGrnd %s_data[];\n", name);
	fprintf(ohp, "extern loc %s_locs[];\n", name);

	yyparse();

	finish();
}

typedef enum state state;
enum state { start, inname, innum, instr, bsl, incomm, pct, pctEnd };

struct sym {
	char *name;
	int  ytype;
} table[] = {
	"external",	EXT,
	"readonly",	RONLY,
	"long",		LONG,
	"default",	DEFAULT,
	"skip",		SKIP,
	"group",	GROUP,
	"help",		HELP,
	"verify",	VERIFY,
	"designator",	DESIG,
	"do",		DO,
	"done",		DONE,
	NULL
};

yylex()
{
	register int c;
	register struct sym *tp;
	state st, pst;
	char buf[80], *p;
	
	for (pst = st = start; ; ) {
		if (EOF == (c = fgetc(ifp)))
			fatal("unexpected EOF");

		switch (st) {
		case pctEnd:
			if ('\n' == c) {
				line++;
				RET(EOF)
			}
			continue;

		case pct:
			if ('%' != c) {
				yyerror("Lex error %%%c", c);
				st = start;
				continue;
			}
			st = pctEnd;
			continue;

		case bsl:
			if (start == pst) {
				if ('\n' == c) {
					line++;
					st = start;
					continue;
				}
				yyerror("%c after \\ outside of string");
				st = start;
				continue;
			}
			*p++ = c;
			st = pst;
			continue;

		case instr:
			switch (c) {
			case '\\':
				pst = st;
				st = bsl;
				*p++ = c;
				continue;
			case '\n':
				yyerror("new line in string");
			case '"':
				*p++ = '"';
				*p = 0;
				yylval.string = newcpy(buf);
				RET(STRING)
			default:
				*p++ = c;
				continue;
			}
		case inname:
			if (isalnum(c)) {
				*p++ = c;
				continue;
			}
			st = start;
			ungetc(c, ifp);
			*p = '\0';

			for (tp = table; tp->name != NULL; tp++)
				if (!strcmp(tp->name, buf))
					RET(tp->ytype)

			yylval.string = newcpy(buf);
			RET(NAME)

		case innum:
			if (isdigit(c)) {
				*p++ = c;
				continue;
			}
			st = start;
			ungetc(c, ifp);
			*p = '\0';
			yylval.val = atoi(buf);
			RET(NUMBER)

		case incomm:
			switch (c) {
			case '\\':
				pst = start;
				break;
			case '\n':
				line++;
				st = start;
			}
			continue;
			
		case start:
			switch (c) {
			case '#':
				st = incomm;
				continue;
			case '%':
				st = pct;
				continue;
			case '\n':
				line++;
				RET(NL)
			case '\\':
				pst = st;
				st = bsl;
				continue;
			case '"':
				st = instr;
				p = buf;
				*p++ = c;
				continue;
			default:
				if (isspace(c))
					continue;

				if (isdigit(c)) {
					st = innum;
					p = buf;
					*p++ = c;
					continue;
				}

				if (isalpha(c)) {
					st = inname;
					p = buf;
					*p++ = c;
					continue;
				}
				yyerror("Lexical error %c", c);
			}
		}
	}
}

typedef struct namelist namelist;
struct namelist {
	namelist *next;
	char *name;
};

/*
 * output extern for verify routine.
 */
void
outExtern(n)
char *n;
{
	static namelist *root = NULL;
	register namelist *p;

	for (p = root; p != NULL; p = p->next)
		if (!strcmp(p->name, n))
			return;

	p = alloc(sizeof(*p));
	p->next = root;
	p->name = n;
	root = p;
	fprintf(ohp, "extern int %s();\n", n);
}

/*
 * finish processing the scn tables.
 */
finish()
{
	int c;
	clump *cp;
	loc *lp;
	int times, count, toOut;
	int row, col, started;
	char *p, buf[80];

	fprintf(ofp, "backGrnd %s_data[] = {\n", name);

	for (row = col = started = times = count = 0, lp = locs, cp = clumps;
	     EOF != (c = fgetc(ifp)); ) {
		if (c == fieldDesig) {
			c = ' ';
			if (NULL == lp) {
				yyerror("To few fields defined");
				break;
			}

			if (NULL != cp && (cp->from == lp)  && !times) {
				times = cp->times;
				count = cp->count;
			}
			if (count) {
				if (NULL == lp->these)
					lp->these = alloc(sizeof(pair) * times);
				lp->these[times - 1].row = row;
				lp->these[times - 1].col = col;
			}
			else {
				lp->row = row;
				lp->col = col;
			}
			lp = lp->next;
			if (count && !--count) {	/* last in group */
				if (--times) {		/* go around again */
					count = cp->count;
					lp = cp->from;
				}
				else			/* next group */
					cp = cp->next;
			}
		}
		if (!started) {	/* No chars output for this line yet */
			switch (c) {
			case '\n':
				row++;
				col = 0;
				continue;
			case '\t':
				col |= 7;
			case ' ':
				col++;
				continue;
			}
			started++;
			toOut = col;
			p = buf;
			fputc('"', ofp);
		}
		switch (c) {
		case '\t':
			col |= 7;
			col++;
			*p++ = '\\';
			*p++ = 't';
			continue;
		case '\n':
			fprintf(ofp, "\",\n\t%d, %d,\n", row, toOut);
			row++;
			col = 0;
			started = 0;
			continue;
		case ' ':
			*p++ = c;
			col++;
			continue;
		}
		col++;
		if (buf != p) {	/* we have saved some whitespace */
			*p = 0;
			fprintf(ofp, "%s", buf);
			p = buf;
		}
		switch (c) { /* we are putting stuff into c strings */
		case '\\':
		case '"':
			fputc('\\', ofp);
		}
		fputc(c, ofp);
	}
	fprintf(ofp, "\tNULL\n};\n");
	if (NULL != lp)
		yyerror("To many fields defined");

	/*
	 * Output field descriptors.
	 */
	for (times = count = 0, cp = clumps, lp = locs;
	     lp != NULL;
	     lp = lp->next) {
		if (NULL != cp && (cp->from == lp)) {
			count = cp->count;
			times = cp->times;
		}
		if (count) {
			if(lp->flags & LONGFIELD) {
				if (!(lp->flags & EXTERNAL))
					fprintf(ofp, "char *%s[%d];\n",
						lp->field, times);
				fprintf(ohp, "extern char *%s[%d];\n",
					lp->field, times);
			}
			else {
				if (!(lp->flags & EXTERNAL))
					fprintf(ofp, "char %s[%d][%d];\n",
						lp->field, times, lp->len + 1);
				fprintf(ohp, "extern char %s[%d][%d];\n",
					lp->field, times, lp->len + 1);
			}
			if(!--count)
				cp = cp->next;
		}
		else {
			if(lp->flags & LONGFIELD) {
				if (!(lp->flags & EXTERNAL))
					fprintf(ofp, "char *%s;\n", lp->field);
				fprintf(ohp, "extern char *%s;\n", lp->field);
			}
			else {
				if (!(lp->flags & EXTERNAL))
					fprintf(ofp, "char %s[%d];\n",
						lp->field, lp->len + 1);
				fprintf(ohp, "extern char %s[%d];\n",
					lp->field, lp->len + 1);
			}
		}
		if (NULL == lp->verify)
			lp->verify = "noVerify";
		outExtern(lp->verify);
	}
	fprintf(ofp, "\n");

	/*
	 * Output loc table.
	 */
	fprintf(ofp, "loc %s_locs[] = {\n", name);

	for (times = count = 0, cp = clumps, lp = locs; lp != NULL;) {
		if (NULL != cp && (cp->from == lp)  && !times) {
			times = cp->times;
			count = cp->count;
			toOut = (times * count);
		}

		if (count) {
			toOut--;
			lp->row = lp->these[times - 1].row;
			lp->col = lp->these[times - 1].col;

			if(lp->flags & LONGFIELD)
				sprintf(buf, "%s + %d",
					lp->field, cp->times - times);
			else
				sprintf(buf, "%s[%d]",
					lp->field, cp->times - times);
		}
		else {
			if(lp->flags & LONGFIELD)
				sprintf(buf, "&%s", lp->field);
			else
				sprintf(buf, "%s", lp->field);
		}

		fprintf(ofp, "\t{ %s, %d, %s, %s, %d, %d, %d, %d, %s },\n",
			buf,
			lp->len,
			((NULL == lp->Default) ? buf : lp->Default),
			lp->verify,
			lp->flags & (LONGFIELD|READONLY),
			lp->row,
			lp->col,
			((255 == lp->skipf) ? toOut : lp->skipf),
			((NULL == lp->help) ? "NULL" : lp->help));

		lp = lp->next;
		if (count && !--count) {	/* last in group */
			if (--times) {		/* go around again */
				count = cp->count;
				lp = cp->from;
			}
			else
				cp = cp->next;	/* next group */
		}
	}
	fprintf(ofp, "\tNULL\n};\n");
	if(errors) {
		printf("%d error%s detected\n",
			errors, ((1 == errors) ? "s": ""));
		exit(1);
	}
}

unix.superglobalmegacorp.com

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