xref: /plan9/sys/src/cmd/awk/main.c (revision 4aeffbf5869a066cad266dfda04e87c99bacbc21)
17dd7cddfSDavid du Colombier /****************************************************************
27dd7cddfSDavid du Colombier Copyright (C) Lucent Technologies 1997
33e12c5d1SDavid du Colombier All Rights Reserved
43e12c5d1SDavid du Colombier 
57dd7cddfSDavid du Colombier Permission to use, copy, modify, and distribute this software and
67dd7cddfSDavid du Colombier its documentation for any purpose and without fee is hereby
77dd7cddfSDavid du Colombier granted, provided that the above copyright notice appear in all
87dd7cddfSDavid du Colombier copies and that both that the copyright notice and this
97dd7cddfSDavid du Colombier permission notice and warranty disclaimer appear in supporting
107dd7cddfSDavid du Colombier documentation, and that the name Lucent Technologies or any of
117dd7cddfSDavid du Colombier its entities not be used in advertising or publicity pertaining
127dd7cddfSDavid du Colombier to distribution of the software without specific, written prior
137dd7cddfSDavid du Colombier permission.
143e12c5d1SDavid du Colombier 
157dd7cddfSDavid du Colombier LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
167dd7cddfSDavid du Colombier INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
177dd7cddfSDavid du Colombier IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
187dd7cddfSDavid du Colombier SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
197dd7cddfSDavid du Colombier WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
207dd7cddfSDavid du Colombier IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
217dd7cddfSDavid du Colombier ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
227dd7cddfSDavid du Colombier THIS SOFTWARE.
237dd7cddfSDavid du Colombier ****************************************************************/
243e12c5d1SDavid du Colombier 
257dd7cddfSDavid 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;
407dd7cddfSDavid du Colombier char	*cmdname;	/* gets argv[0] for error messages */
413e12c5d1SDavid du Colombier extern	FILE	*yyin;	/* lex input file */
427dd7cddfSDavid 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 
477dd7cddfSDavid 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 
517dd7cddfSDavid du Colombier int	safe	= 0;	/* 1 => "safe" mode */
523e12c5d1SDavid du Colombier 
main(int argc,char * argv[])537dd7cddfSDavid du Colombier int main(int argc, char *argv[])
543e12c5d1SDavid du Colombier {
557dd7cddfSDavid 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*4aeffbf5SDavid du Colombier 		fprintf(stderr, "Usage: %s [-F fieldsep] [-mf n] [-mr n] [-v var=value] [-f programfile | 'program'] [file ...]\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') {
677dd7cddfSDavid 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]) {
737dd7cddfSDavid du Colombier 		case 's':
747dd7cddfSDavid du Colombier 			if (strcmp(argv[1], "-safe") == 0)
757dd7cddfSDavid du Colombier 				safe = 1;
767dd7cddfSDavid 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)
817dd7cddfSDavid 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 */
877dd7cddfSDavid 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 */
937dd7cddfSDavid 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')
987dd7cddfSDavid 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 */
1057dd7cddfSDavid 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;
1167dd7cddfSDavid 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;
1257dd7cddfSDavid du Colombier 		case 'V':	/* added for exptools "standard" */
1267dd7cddfSDavid du Colombier 			printf("awk %s\n", version);
1277dd7cddfSDavid du Colombier 			exit(0);
1287dd7cddfSDavid du Colombier 			break;
1293e12c5d1SDavid du Colombier 		default:
1307dd7cddfSDavid 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);
1417dd7cddfSDavid 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);
1547dd7cddfSDavid du Colombier 	if (!safe)
1553e12c5d1SDavid du Colombier 		envinit(environ);
1563e12c5d1SDavid du Colombier 	yyparse();
1573e12c5d1SDavid du Colombier 	if (fs)
1587dd7cddfSDavid 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 
pgetc(void)1687dd7cddfSDavid 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;
1767dd7cddfSDavid du Colombier 			if (strcmp(pfile[curpfile], "-") == 0)
1773e12c5d1SDavid du Colombier 				yyin = stdin;
1787dd7cddfSDavid du Colombier 			else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
1797dd7cddfSDavid du Colombier 				FATAL("can't open file %s", pfile[curpfile]);
1807dd7cddfSDavid 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 }
1907dd7cddfSDavid du Colombier 
cursource(void)1917dd7cddfSDavid du Colombier char *cursource(void)	/* current source file name */
1927dd7cddfSDavid du Colombier {
1937dd7cddfSDavid du Colombier 	if (npfile > 0)
1947dd7cddfSDavid du Colombier 		return pfile[curpfile];
1957dd7cddfSDavid du Colombier 	else
1967dd7cddfSDavid du Colombier 		return NULL;
1977dd7cddfSDavid du Colombier }
198