DataMuseum.dk

Presents historical artifacts from the history of:

Commodore CBM-900

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Commodore CBM-900

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦57c7373c2⟧ TextFile

    Length: 8469 (0x2115)
    Types: TextFile
    Notes: UNIX file
    Names: »awk1.c«

Derivation

└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
    └─⟦f4b8d8c84⟧ UNIX V7 Filesystem
        └─ ⟦this⟧ »cmd/awk/awk1.c« 

TextFile

/*
 * AWK
 * Main routine.
 * Lexical analysis of input.
 * Program input routines.
 * Error message routines.
 */

#include "awk.h"
#include "y.tab.h"

YYSTYPE	yylval;

char	*readclass();
NODE	*instring();
NODE	*innumber();

/*
 * Main routine of AWK.
 */
main(argc, argv)
int argc;
char *argv[];
{
	register int i;
	register char *ap;
	register FILE *fp;
	register char *prog = NULL;
	register char *progfile;
	NODE *yyparse();

	awkinit();
	while (argc>1 && *argv[1]=='-') {
		if (argv[1][1] == '\0')
			break;		/* - is stdin */
		switch (argv[1][1]) {
		case 'F':
			sassign(FSp, &argv[1][2]);
			break;

		case 'f':
			if (argc < 2)
				usage();
			if ((pfp = fopen(argv[2], "r")) == NULL)
				awkerr("Cannot open %s", argv[2]);
			setbuf(pfp, inbuf);
			progfile = argv[2];
			argv++;
			argc--;
			break;

		case 'y':
			yflag++;
			break;

		default:
			usage();
		}
		argv++;
		argc--;
	}
	if (argc>1 && pfp==NULL) {
		prog = argv[1];
		argv++;
		argc--;
	}
	if (pfp==NULL && prog==NULL)
		usage();
	while (argc>1 && parameter(argv[1])) {
		argv++;
		argc--;
	}
	pgetinit(prog);
	if (pfp != NULL) {
		lineno = 1;
		sassign(FILENAMEp, progfile);
	}
	yyparse();
	if (pfp != NULL)
		fclose(pfp);
	fsmapinit(FS);
	runflag = 1;
	beginflag = 1;
	if (setjmp(nextenv) == 0)
		awk(codep, NULL, SNULL);
	beginflag = 0;
	if (argc > 1) {
		for (i=1; i<argc; i++) {
			ap = argv[i];
			if (ap[0]=='-' && ap[1]=='\0')
				fp = stdin;
			else if ((fp = fopen(ap, "r")) == NULL) {
				fprintf(stderr, "awk: cannot open %s\n", ap);
				exit(1);
			}
			awk(codep, fp, ap);
		}
	} else
		awk(codep, stdin, SNULL);
	awkexit(0);
}

/*
 * Read a parameter from the command line.
 * Return non-zero if the string is a parameter.
 * We have to fudge a bit to make sure `yylex'
 * is properly reset.
 */
parameter(s)
char *s;
{
	register char *cp;
	register int c;
	NODE *left, *right;

	cp = s;
	if (!isalpha(*cp))
		return (0);
	for (; (c = *cp)!='='; cp++) {
		if (c == '\0')
			return (0);
		if (isspace(c)) {
			*cp = '\0';
			continue;
		}
		if (!(isalpha(c) || isdigit(c)))
			return (0);
	}
	*cp++ = '\0';
	left = lookup(s);
	while (isspace(c = *cp++))
		;
	pgetinit(cp);
	if (c == '"')
		right = instring(c);
	else if (isdigit(c) || c=='.')
		right = innumber(c);
	else
		awkerr("non-constant assignment to parameter `%s'", s);
	xassign(left, right);
	return (1);
}

/*
 * Leave awk and run the
 * cleanup (`END') phase.
 */
awkexit(s)
int s;
{
	register OFILE *ofp;

	beginflag = 0;
	endflag = 1;
	exitflag = 1;
	if (setjmp(nextenv) == 0)
		awk(codep, NULL, SNULL);
	for (ofp = files; ofp < endof(files); ofp++)
		if (ofp->of_fp != NULL) {
			if (ofp->of_flag & OFPIPE)
				pclose(ofp->of_fp); else
				fclose(ofp->of_fp);
		}
	exit(s);
}

/*
 * Lexical analyser.
 * This must have flags to
 * determine when certain
 * types of characters are
 * special (e.g. reading regular
 * expressions)
 * Delete multiple newlines.
 */
yylex()
{
	static int nlf = 1;
	static int prev, next;
	register char *cp;
	register int c;
	register int t;
	register NODE *np;

	if (lexre)
		return (relex());
again:
	if (next) {
		t = next;
		next = 0;
	} else if ((t = c = pgetc()) == EOF)
		;
	else if (!isascii(c))
		awkerr("%o is an illegal character", c);
	else if (isdigit(c) || c=='.') {
		yylval.u_node = innumber(c);
		t = NUMBER_;
	} else if (isalpha(c)) {
		cp = wordbuf;
		do {
			*cp++ = c;
			c = pgetc();
		} while (isalpha(c) || isdigit(c));
		pungetc(c);
		*cp = '\0';
		np = lookup(wordbuf);
		if (np->t_op == AKEYW)
			t = np->t_INT;
		else if (np->t_op == AFUNC) {
			t = FUNCTION_;
			yylval.u_node = np;
		} else {
			t = ID_;
			yylval.u_node = np;
		}
	} else switch (c) {

	case '"':
		yylval.u_node = instring(c);
		t = STRING_;
		break;

	case '#':
		while ((c = pgetc())!=EOF && c!='\n')
			;
		goto again;

	case '{':
		brlevel++;
		break;

	case '}':
		if (--brlevel < 0) {
			awkerr("Unbalanced braces");
			brlevel = 0;
		}
		next = '}';
		t = ';';
		break;

	case '!':
		if (checkop('~'))
			t = NMATCH_;
		else if (checkop('='))
			t = NE_;
		break;

	case '|':
		if (checkop('|'))
			t = OROR_;
		break;

	case '&':
		if (checkop('&'))
			t = ANDAND_;
		break;

	case '+':
		if (checkop('='))
			t = ASADD_;
		else if (checkop('+'))
			t = INC_;
		break;

	case '-':
		if (checkop('='))
			t = ASSUB_;
		else if (checkop('-'))
			t = DEC_;
		break;

	case '*':
		if (checkop('='))
			t = ASMUL_;
		break;

	case '/':
		if (checkop('='))
			t = ASDIV_;
		break;

	case '%':
		if (checkop('='))
			t = ASDIV_;
		break;

	case '>':
		if (checkop('='))
			t = GE_;
		else if (checkop('>'))
			t = FAPPEND_;
		else if (outflag)
			t = FOUT_;
		break;

	case '<':
		if (checkop('='))
			t = LE_;
		break;

	case '=':
		if (checkop('='))
			t = EQ_;
		break;

	case '\n':
		if (nlf || nlskip)
			goto again;
		if (brlevel)
			t = ';';
		break;

	case ' ':
	case '\t':
		goto again;
	}
	nlf = nlskip = 0;
	if (t==ELSE_ && prev!=';' && prev!='\n' && prev!='}') {
		next = t;
		t = ';';
	} else if (t == '\n')
		nlf++;
	if (t==';') {
		outflag = 0;
		if (prev == ';')
			goto again;
	}
	return (prev = t);
}

/*
 * Part of lexical analyser
 * for reading regular expressions.
 */
relex()
{
	register int c;
	register int n, max;

	switch (c = pgetc()) {
	case '?':
		return (REZOCL_);

	case '*':
		return (RECLOS_);

	case '+':
		return (RENECL_);

	case '^':
		return (REBOL_);

	case '$':
		return (REEOL_);

	case '.':
		return (REANY_);

	case '|':
		return (REOR_);

	case '(':
	case ')':
	case '/':
		return (c);

	case '[':
		yylval.u_charp = readclass();
		return (RECLASS_);

	case EOF:
	case '\n':
		awkerr("Non-terminated regular expression");

	case '\\':
		c = pgetc();
		if (c>='0' && c<='7') {
			n = 0;
			max = 3;
			do {
				n = (n<<3) + c - '0';
				if ((c=pgetc())<'0' || c>'7')
					break;
			} while (--max);
			pungetc(c);
			c = n;
		}
	default:
		yylval.u_char = c;
		return (RECHAR_);
	}
}

/*
 * Check for dual-character operators.
 * such as `+=' and return 1 if so.
 * This looks for a match on the next
 * character `nc'.
 */
checkop(nc)
int nc;
{
	register int c;

	if ((c = pgetc()) == nc)
		return (1);
	pungetc(c);
	return (0);
}

/*
 * Read in a character class from
 * a regular expression (called from relex).
 */
char *
readclass()
{
	register char *cc;
	register c, i, pc;
	int comp;

	cc = xalloc(NCLASS);
	for (i=0; i<NCLASS; i++)
		cc[i] = 0;
	if ((c = pgetc()) != '^') {
		comp = 0;
		pungetc(c);
	} else
		comp = 1;
	pc = EOF;
	while ((c = pgetc()) != ']') {
		if (c==EOF || c=='\n')
			awkerr("Non-terminated character class");
		if (c=='-' && pc!=EOF) {
			if ((c = pgetc()) == ']')
				break;
			for (i=pc; i<=c; i++)
				cc[i/NBPC] |= 1<<(i%NBPC);
			pc = EOF;
		} else {
			cc[c/NBPC] |= 1<<(c%NBPC);
			pc = c;
		}
	}
	if (comp)
		for (i=0; i<NCLASS; i++)
			cc[i] ^= -1;
	return (cc);
}

/*
 * Return a string read from
 * the program file.
 * The string is to be terminated
 * with `ec'.
 */
NODE *
instring(ec)
register int ec;
{
	register char *cp;
	register int c;
	register int octal, nc;

	cp = wordbuf;
	while ((c = pgetc()) != ec) {
		if (c=='\n' || c==EOF)
			awkerr("%s in string", c==EOF ? "EOF" : "Newline");
		if (c == '\\') {
			switch (c = pgetc()) {
			case 'r':
				c = '\r';
				break;

			case 'n':
				c = '\n';
				break;

			case 'b':
				c = '\b';
				break;

			case 't':
				c = '\t';
				break;

			default:
				if (c>='0' && c<='7') {
					octal = 0;
					nc = 3;
					for (;;) {
						octal = octal*8 + c - '0';
						if (--nc <= 0)
							break;
						c = pgetc();
						if (c==ec || c<'0' || c>'7') {
							pungetc(c);
							break;
						}
					}
					c = octal;
				}
			}
		}
		if (cp < &wordbuf[NWORD-1])
			*cp++ = c;
		else {
			awkerr("Character string too long");
			break;
		}
	}
	*cp = '\0';
	cp = xalloc(strlen(wordbuf)+sizeof(char));
	strcpy(cp, wordbuf);
	return (snode(cp, T_ALLOC));
}

/*
 * Read a number from the
 * program file.
 */
NODE *
innumber(c)
register int c;
{
	register char *np;
	register int floatflag = 0;

	np = wordbuf;
	for (;;) {
		if (c == '.')
			floatflag++;
		*np++ = c;
		c = pgetc();
		if (c=='e' || c=='E') {
			floatflag++;
			*np++ = c;
			if ((c = pgetc())=='-' || c=='+') {
				*np++ = c;
				c = pgetc();
			}
			do {
				*np++ = c;
				c = pgetc();
			} while (c>='0' && c<='9');
			break;
		}
		if (c!='.' && !(c>='0' && c<='9'))
			break;
	}
	pungetc(c);
	*np = '\0';
	return (floatflag ? fnode(stof(wordbuf)) : inode(stoi(wordbuf)));
}