xref: /plan9/sys/src/cmd/awk/main.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1*7dd7cddfSDavid du Colombier /****************************************************************
2*7dd7cddfSDavid du Colombier Copyright (C) Lucent Technologies 1997
33e12c5d1SDavid du Colombier All Rights Reserved
43e12c5d1SDavid du Colombier 
5*7dd7cddfSDavid du Colombier Permission to use, copy, modify, and distribute this software and
6*7dd7cddfSDavid du Colombier its documentation for any purpose and without fee is hereby
7*7dd7cddfSDavid du Colombier granted, provided that the above copyright notice appear in all
8*7dd7cddfSDavid du Colombier copies and that both that the copyright notice and this
9*7dd7cddfSDavid du Colombier permission notice and warranty disclaimer appear in supporting
10*7dd7cddfSDavid du Colombier documentation, and that the name Lucent Technologies or any of
11*7dd7cddfSDavid du Colombier its entities not be used in advertising or publicity pertaining
12*7dd7cddfSDavid du Colombier to distribution of the software without specific, written prior
13*7dd7cddfSDavid du Colombier permission.
143e12c5d1SDavid du Colombier 
15*7dd7cddfSDavid du Colombier LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16*7dd7cddfSDavid du Colombier INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17*7dd7cddfSDavid du Colombier IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18*7dd7cddfSDavid du Colombier SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19*7dd7cddfSDavid du Colombier WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20*7dd7cddfSDavid du Colombier IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21*7dd7cddfSDavid du Colombier ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22*7dd7cddfSDavid du Colombier THIS SOFTWARE.
23*7dd7cddfSDavid du Colombier ****************************************************************/
243e12c5d1SDavid du Colombier 
25*7dd7cddfSDavid du Colombier char	*version = "version 19990602";
263e12c5d1SDavid du Colombier 
273e12c5d1SDavid du Colombier #define DEBUG
283e12c5d1SDavid du Colombier #include <stdio.h>
293e12c5d1SDavid du Colombier #include <ctype.h>
303e12c5d1SDavid du Colombier #include <stdlib.h>
313e12c5d1SDavid du Colombier #include <string.h>
323e12c5d1SDavid du Colombier #include <signal.h>
333e12c5d1SDavid du Colombier #include "awk.h"
343e12c5d1SDavid du Colombier #include "y.tab.h"
353e12c5d1SDavid du Colombier 
363e12c5d1SDavid du Colombier extern	char	**environ;
37219b2ee8SDavid du Colombier extern	int	nfields;
383e12c5d1SDavid du Colombier 
393e12c5d1SDavid du Colombier int	dbg	= 0;
40*7dd7cddfSDavid du Colombier char	*cmdname;	/* gets argv[0] for error messages */
413e12c5d1SDavid du Colombier extern	FILE	*yyin;	/* lex input file */
42*7dd7cddfSDavid du Colombier char	*lexprog;	/* points to program argument if it exists */
433e12c5d1SDavid du Colombier extern	int errorflag;	/* non-zero if any syntax errors; set by yyerror */
443e12c5d1SDavid du Colombier int	compile_time = 2;	/* for error printing: */
453e12c5d1SDavid du Colombier 				/* 2 = cmdline, 1 = compile, 0 = running */
463e12c5d1SDavid du Colombier 
47*7dd7cddfSDavid du Colombier char	*pfile[20];	/* program filenames from -f's */
483e12c5d1SDavid du Colombier int	npfile = 0;	/* number of filenames */
493e12c5d1SDavid du Colombier int	curpfile = 0;	/* current filename */
503e12c5d1SDavid du Colombier 
51*7dd7cddfSDavid du Colombier int	safe	= 0;	/* 1 => "safe" mode */
523e12c5d1SDavid du Colombier 
53*7dd7cddfSDavid du Colombier int main(int argc, char *argv[])
543e12c5d1SDavid du Colombier {
55*7dd7cddfSDavid du Colombier 	char *fs = NULL, *marg;
56219b2ee8SDavid du Colombier 	int temp;
573e12c5d1SDavid du Colombier 
583e12c5d1SDavid du Colombier 	cmdname = argv[0];
593e12c5d1SDavid du Colombier 	if (argc == 1) {
60*7dd7cddfSDavid du Colombier 		fprintf(stderr, "Usage: %s [-f programfile | 'program'] [-Ffieldsep] [-v var=value] [files]\n", cmdname);
613e12c5d1SDavid du Colombier 		exit(1);
623e12c5d1SDavid du Colombier 	}
633e12c5d1SDavid du Colombier 	signal(SIGFPE, fpecatch);
643e12c5d1SDavid du Colombier 	yyin = NULL;
65219b2ee8SDavid du Colombier 	symtab = makesymtab(NSYMTAB);
663e12c5d1SDavid du Colombier 	while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
67*7dd7cddfSDavid du Colombier 		if (strcmp(argv[1], "--") == 0) {	/* explicit end of args */
683e12c5d1SDavid du Colombier 			argc--;
693e12c5d1SDavid du Colombier 			argv++;
703e12c5d1SDavid du Colombier 			break;
713e12c5d1SDavid du Colombier 		}
723e12c5d1SDavid du Colombier 		switch (argv[1][1]) {
73*7dd7cddfSDavid du Colombier 		case 's':
74*7dd7cddfSDavid du Colombier 			if (strcmp(argv[1], "-safe") == 0)
75*7dd7cddfSDavid du Colombier 				safe = 1;
76*7dd7cddfSDavid du Colombier 			break;
773e12c5d1SDavid du Colombier 		case 'f':	/* next argument is program filename */
783e12c5d1SDavid du Colombier 			argc--;
793e12c5d1SDavid du Colombier 			argv++;
803e12c5d1SDavid du Colombier 			if (argc <= 1)
81*7dd7cddfSDavid du Colombier 				FATAL("no program filename");
823e12c5d1SDavid du Colombier 			pfile[npfile++] = argv[1];
833e12c5d1SDavid du Colombier 			break;
843e12c5d1SDavid du Colombier 		case 'F':	/* set field separator */
853e12c5d1SDavid du Colombier 			if (argv[1][2] != 0) {	/* arg is -Fsomething */
863e12c5d1SDavid du Colombier 				if (argv[1][2] == 't' && argv[1][3] == 0)	/* wart: t=>\t */
87*7dd7cddfSDavid du Colombier 					fs = "\t";
883e12c5d1SDavid du Colombier 				else if (argv[1][2] != 0)
893e12c5d1SDavid du Colombier 					fs = &argv[1][2];
903e12c5d1SDavid du Colombier 			} else {		/* arg is -F something */
913e12c5d1SDavid du Colombier 				argc--; argv++;
923e12c5d1SDavid du Colombier 				if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0)	/* wart: t=>\t */
93*7dd7cddfSDavid du Colombier 					fs = "\t";
943e12c5d1SDavid du Colombier 				else if (argc > 1 && argv[1][0] != 0)
953e12c5d1SDavid du Colombier 					fs = &argv[1][0];
963e12c5d1SDavid du Colombier 			}
973e12c5d1SDavid du Colombier 			if (fs == NULL || *fs == '\0')
98*7dd7cddfSDavid du Colombier 				WARNING("field separator FS is empty");
993e12c5d1SDavid du Colombier 			break;
1003e12c5d1SDavid du Colombier 		case 'v':	/* -v a=1 to be done NOW.  one -v for each */
1013e12c5d1SDavid du Colombier 			if (argv[1][2] == '\0' && --argc > 1 && isclvar((++argv)[1]))
1023e12c5d1SDavid du Colombier 				setclvar(argv[1]);
1033e12c5d1SDavid du Colombier 			break;
104219b2ee8SDavid du Colombier 		case 'm':	/* more memory: -mr=record, -mf=fields */
105*7dd7cddfSDavid du Colombier 				/* no longer needed */
106219b2ee8SDavid du Colombier 			marg = argv[1];
107219b2ee8SDavid du Colombier 			if (argv[1][3])
108219b2ee8SDavid du Colombier 				temp = atoi(&argv[1][3]);
109219b2ee8SDavid du Colombier 			else {
110219b2ee8SDavid du Colombier 				argv++; argc--;
111219b2ee8SDavid du Colombier 				temp = atoi(&argv[1][0]);
112219b2ee8SDavid du Colombier 			}
113219b2ee8SDavid du Colombier 			switch (marg[2]) {
114219b2ee8SDavid du Colombier 			case 'r':	recsize = temp; break;
115219b2ee8SDavid du Colombier 			case 'f':	nfields = temp; break;
116*7dd7cddfSDavid du Colombier 			default: FATAL("unknown option %s\n", marg);
117219b2ee8SDavid du Colombier 			}
118219b2ee8SDavid du Colombier 			break;
1193e12c5d1SDavid du Colombier 		case 'd':
1203e12c5d1SDavid du Colombier 			dbg = atoi(&argv[1][2]);
1213e12c5d1SDavid du Colombier 			if (dbg == 0)
1223e12c5d1SDavid du Colombier 				dbg = 1;
1233e12c5d1SDavid du Colombier 			printf("awk %s\n", version);
1243e12c5d1SDavid du Colombier 			break;
125*7dd7cddfSDavid du Colombier 		case 'V':	/* added for exptools "standard" */
126*7dd7cddfSDavid du Colombier 			printf("awk %s\n", version);
127*7dd7cddfSDavid du Colombier 			exit(0);
128*7dd7cddfSDavid du Colombier 			break;
1293e12c5d1SDavid du Colombier 		default:
130*7dd7cddfSDavid du Colombier 			WARNING("unknown option %s ignored", argv[1]);
1313e12c5d1SDavid du Colombier 			break;
1323e12c5d1SDavid du Colombier 		}
1333e12c5d1SDavid du Colombier 		argc--;
1343e12c5d1SDavid du Colombier 		argv++;
1353e12c5d1SDavid du Colombier 	}
1363e12c5d1SDavid du Colombier 	/* argv[1] is now the first argument */
1373e12c5d1SDavid du Colombier 	if (npfile == 0) {	/* no -f; first argument is program */
138219b2ee8SDavid du Colombier 		if (argc <= 1) {
139219b2ee8SDavid du Colombier 			if (dbg)
140219b2ee8SDavid du Colombier 				exit(0);
141*7dd7cddfSDavid du Colombier 			FATAL("no program given");
142219b2ee8SDavid du Colombier 		}
1433e12c5d1SDavid du Colombier 		   dprintf( ("program = |%s|\n", argv[1]) );
1443e12c5d1SDavid du Colombier 		lexprog = argv[1];
1453e12c5d1SDavid du Colombier 		argc--;
1463e12c5d1SDavid du Colombier 		argv++;
1473e12c5d1SDavid du Colombier 	}
148219b2ee8SDavid du Colombier 	recinit(recsize);
149219b2ee8SDavid du Colombier 	syminit();
1503e12c5d1SDavid du Colombier 	compile_time = 1;
1513e12c5d1SDavid du Colombier 	argv[0] = cmdname;	/* put prog name at front of arglist */
1523e12c5d1SDavid du Colombier 	   dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
1533e12c5d1SDavid du Colombier 	arginit(argc, argv);
154*7dd7cddfSDavid du Colombier 	if (!safe)
1553e12c5d1SDavid du Colombier 		envinit(environ);
1563e12c5d1SDavid du Colombier 	yyparse();
1573e12c5d1SDavid du Colombier 	if (fs)
158*7dd7cddfSDavid du Colombier 		*FS = qstring(fs, '\0');
1593e12c5d1SDavid du Colombier 	   dprintf( ("errorflag=%d\n", errorflag) );
1603e12c5d1SDavid du Colombier 	if (errorflag == 0) {
1613e12c5d1SDavid du Colombier 		compile_time = 0;
1623e12c5d1SDavid du Colombier 		run(winner);
1633e12c5d1SDavid du Colombier 	} else
1643e12c5d1SDavid du Colombier 		bracecheck();
1653e12c5d1SDavid du Colombier 	return(errorflag);
1663e12c5d1SDavid du Colombier }
1673e12c5d1SDavid du Colombier 
168*7dd7cddfSDavid du Colombier int pgetc(void)		/* get 1 character from awk program */
1693e12c5d1SDavid du Colombier {
1703e12c5d1SDavid du Colombier 	int c;
1713e12c5d1SDavid du Colombier 
1723e12c5d1SDavid du Colombier 	for (;;) {
1733e12c5d1SDavid du Colombier 		if (yyin == NULL) {
1743e12c5d1SDavid du Colombier 			if (curpfile >= npfile)
1753e12c5d1SDavid du Colombier 				return EOF;
176*7dd7cddfSDavid du Colombier 			if (strcmp(pfile[curpfile], "-") == 0)
1773e12c5d1SDavid du Colombier 				yyin = stdin;
178*7dd7cddfSDavid du Colombier 			else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
179*7dd7cddfSDavid du Colombier 				FATAL("can't open file %s", pfile[curpfile]);
180*7dd7cddfSDavid du Colombier 			lineno = 1;
1813e12c5d1SDavid du Colombier 		}
1823e12c5d1SDavid du Colombier 		if ((c = getc(yyin)) != EOF)
1833e12c5d1SDavid du Colombier 			return c;
184219b2ee8SDavid du Colombier 		if (yyin != stdin)
1853e12c5d1SDavid du Colombier 			fclose(yyin);
1863e12c5d1SDavid du Colombier 		yyin = NULL;
1873e12c5d1SDavid du Colombier 		curpfile++;
1883e12c5d1SDavid du Colombier 	}
1893e12c5d1SDavid du Colombier }
190*7dd7cddfSDavid du Colombier 
191*7dd7cddfSDavid du Colombier char *cursource(void)	/* current source file name */
192*7dd7cddfSDavid du Colombier {
193*7dd7cddfSDavid du Colombier 	if (npfile > 0)
194*7dd7cddfSDavid du Colombier 		return pfile[curpfile];
195*7dd7cddfSDavid du Colombier 	else
196*7dd7cddfSDavid du Colombier 		return NULL;
197*7dd7cddfSDavid du Colombier }
198