xref: /openbsd/usr.bin/awk/main.c (revision 28f4856a)
16ab05f83Stholo /****************************************************************
26ab05f83Stholo Copyright (C) AT&T and Lucent Technologies 1996
36ab05f83Stholo All Rights Reserved
46ab05f83Stholo 
56ab05f83Stholo Permission to use, copy, modify, and distribute this software and
66ab05f83Stholo its documentation for any purpose and without fee is hereby
76ab05f83Stholo granted, provided that the above copyright notice appear in all
86ab05f83Stholo copies and that both that the copyright notice and this
96ab05f83Stholo permission notice and warranty disclaimer appear in supporting
106ab05f83Stholo documentation, and that the names of AT&T or Lucent Technologies
116ab05f83Stholo or any of their entities not be used in advertising or publicity
126ab05f83Stholo pertaining to distribution of the software without specific,
136ab05f83Stholo written prior permission.
146ab05f83Stholo 
156ab05f83Stholo AT&T AND LUCENT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
166ab05f83Stholo SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
176ab05f83Stholo FITNESS. IN NO EVENT SHALL AT&T OR LUCENT OR ANY OF THEIR
186ab05f83Stholo ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
196ab05f83Stholo DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
206ab05f83Stholo DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
216ab05f83Stholo OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
226ab05f83Stholo USE OR PERFORMANCE OF THIS SOFTWARE.
236ab05f83Stholo ****************************************************************/
246ab05f83Stholo 
256ab05f83Stholo char	*version = "version May 27, 1996";
266ab05f83Stholo 
276ab05f83Stholo #define DEBUG
286ab05f83Stholo #include <stdio.h>
296ab05f83Stholo #include <ctype.h>
306ab05f83Stholo #include <stdlib.h>
316ab05f83Stholo #include <string.h>
326ab05f83Stholo #include <signal.h>
33*28f4856aStholo #include <locale.h>
346ab05f83Stholo #include "awk.h"
356ab05f83Stholo #include "awkgram.h"
366ab05f83Stholo 
376ab05f83Stholo extern	char	**environ;
386ab05f83Stholo extern	int	nfields;
396ab05f83Stholo 
406ab05f83Stholo int	dbg	= 0;
416ab05f83Stholo char	*cmdname;	/* gets argv[0] for error messages */
426ab05f83Stholo extern	FILE	*yyin;	/* lex input file */
436ab05f83Stholo char	*lexprog;	/* points to program argument if it exists */
446ab05f83Stholo extern	int errorflag;	/* non-zero if any syntax errors; set by yyerror */
456ab05f83Stholo int	compile_time = 2;	/* for error printing: */
466ab05f83Stholo 				/* 2 = cmdline, 1 = compile, 0 = running */
476ab05f83Stholo 
486ab05f83Stholo char	*pfile[20];	/* program filenames from -f's */
496ab05f83Stholo int	npfile = 0;	/* number of filenames */
506ab05f83Stholo int	curpfile = 0;	/* current filename */
516ab05f83Stholo 
526ab05f83Stholo int main(int argc, char *argv[])
536ab05f83Stholo {
546ab05f83Stholo 	char *fs = NULL, *marg;
556ab05f83Stholo 	int temp;
566ab05f83Stholo 
57*28f4856aStholo 	setlocale(LC_ALL, "");
58*28f4856aStholo 
596ab05f83Stholo 	if ((cmdname = strrchr(argv[0], '/')) != NULL)
606ab05f83Stholo 		cmdname++;
616ab05f83Stholo 	else
626ab05f83Stholo 		cmdname = argv[0];
636ab05f83Stholo 	if (argc == 1) {
646ab05f83Stholo 		fprintf(stderr, "Usage: %s [-f programfile | 'program'] [-Ffieldsep] [-v var=value] [-mf n] [-mr n] [files]\n", cmdname);
656ab05f83Stholo 		exit(1);
666ab05f83Stholo 	}
676ab05f83Stholo 	gs = newGstring();	/* for lex */
686ab05f83Stholo 	signal(SIGFPE, fpecatch);
696ab05f83Stholo 	yyin = NULL;
706ab05f83Stholo 	symtab = makesymtab(NSYMTAB);
716ab05f83Stholo 	while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
726ab05f83Stholo 		if (strcmp((char *) argv[1], "--") == 0) {	/* explicit end of args */
736ab05f83Stholo 			argc--;
746ab05f83Stholo 			argv++;
756ab05f83Stholo 			break;
766ab05f83Stholo 		}
776ab05f83Stholo 		switch (argv[1][1]) {
786ab05f83Stholo 		case 'f':	/* next argument is program filename */
796ab05f83Stholo 			argc--;
806ab05f83Stholo 			argv++;
816ab05f83Stholo 			if (argc <= 1)
826ab05f83Stholo 				ERROR "no program filename" FATAL;
836ab05f83Stholo 			pfile[npfile++] = argv[1];
846ab05f83Stholo 			break;
856ab05f83Stholo 		case 'F':	/* set field separator */
866ab05f83Stholo 			if (argv[1][2] != 0) {	/* arg is -Fsomething */
876ab05f83Stholo 				if (argv[1][2] == 't' && argv[1][3] == 0)	/* wart: t=>\t */
886ab05f83Stholo 					fs = (char *) "\t";
896ab05f83Stholo 				else if (argv[1][2] != 0)
906ab05f83Stholo 					fs = &argv[1][2];
916ab05f83Stholo 			} else {		/* arg is -F something */
926ab05f83Stholo 				argc--; argv++;
936ab05f83Stholo 				if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0)	/* wart: t=>\t */
946ab05f83Stholo 					fs = (char *) "\t";
956ab05f83Stholo 				else if (argc > 1 && argv[1][0] != 0)
966ab05f83Stholo 					fs = &argv[1][0];
976ab05f83Stholo 			}
986ab05f83Stholo 			if (fs == NULL || *fs == '\0')
996ab05f83Stholo 				ERROR "field separator FS is empty" WARNING;
1006ab05f83Stholo 			break;
1016ab05f83Stholo 		case 'v':	/* -v a=1 to be done NOW.  one -v for each */
1026ab05f83Stholo 			if (argv[1][2] == '\0' && --argc > 1 && isclvar((++argv)[1]))
1036ab05f83Stholo 				setclvar(argv[1]);
1046ab05f83Stholo 			break;
1056ab05f83Stholo 		case 'm':	/* more memory: -mr=record, -mf=fields */
1066ab05f83Stholo 			marg = argv[1];
1076ab05f83Stholo 			if (argv[1][3])
1086ab05f83Stholo 				temp = atoi(&argv[1][3]);
1096ab05f83Stholo 			else {
1106ab05f83Stholo 				argv++; argc--;
1116ab05f83Stholo 				temp = atoi(&argv[1][0]);
1126ab05f83Stholo 			}
1136ab05f83Stholo 			switch (marg[2]) {
1146ab05f83Stholo 			case 'r':	recsize = temp; break;
1156ab05f83Stholo 			case 'f':	nfields = temp; break;
1166ab05f83Stholo 			default: ERROR "unknown option %s\n", marg FATAL;
1176ab05f83Stholo 			}
1186ab05f83Stholo 			break;
1196ab05f83Stholo 		case 'd':
1206ab05f83Stholo 			dbg = atoi(&argv[1][2]);
1216ab05f83Stholo 			if (dbg == 0)
1226ab05f83Stholo 				dbg = 1;
1236ab05f83Stholo 			printf("awk %s\n", version);
1246ab05f83Stholo 			break;
1256ab05f83Stholo 		default:
1266ab05f83Stholo 			ERROR "unknown option %s ignored", argv[1] WARNING;
1276ab05f83Stholo 			break;
1286ab05f83Stholo 		}
1296ab05f83Stholo 		argc--;
1306ab05f83Stholo 		argv++;
1316ab05f83Stholo 	}
1326ab05f83Stholo 	/* argv[1] is now the first argument */
1336ab05f83Stholo 	if (npfile == 0) {	/* no -f; first argument is program */
1346ab05f83Stholo 		if (argc <= 1) {
1356ab05f83Stholo 			if (dbg)
1366ab05f83Stholo 				exit(0);
1376ab05f83Stholo 			ERROR "no program given" FATAL;
1386ab05f83Stholo 		}
1396ab05f83Stholo 		dprintf( ("program = |%s|\n", argv[1]) );
1406ab05f83Stholo 		lexprog = argv[1];
1416ab05f83Stholo 		argc--;
1426ab05f83Stholo 		argv++;
1436ab05f83Stholo 	}
1446ab05f83Stholo 	recinit(recsize);
1456ab05f83Stholo 	syminit();
1466ab05f83Stholo 	compile_time = 1;
1476ab05f83Stholo 	argv[0] = cmdname;	/* put prog name at front of arglist */
1486ab05f83Stholo 	dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
1496ab05f83Stholo 	arginit(argc, argv);
1506ab05f83Stholo 	envinit(environ);
1516ab05f83Stholo 	yyparse();
1526ab05f83Stholo 	if (fs)
1536ab05f83Stholo 		*FS = tostring(qstring(fs, '\0'));
1546ab05f83Stholo 	dprintf( ("errorflag=%d\n", errorflag) );
1556ab05f83Stholo 	if (errorflag == 0) {
1566ab05f83Stholo 		compile_time = 0;
1576ab05f83Stholo 		run(winner);
1586ab05f83Stholo 	} else
1596ab05f83Stholo 		bracecheck();
1606ab05f83Stholo 	return(errorflag);
1616ab05f83Stholo }
1626ab05f83Stholo 
1636ab05f83Stholo int pgetc(void)		/* get 1 character from awk program */
1646ab05f83Stholo {
1656ab05f83Stholo 	int c;
1666ab05f83Stholo 
1676ab05f83Stholo 	for (;;) {
1686ab05f83Stholo 		if (yyin == NULL) {
1696ab05f83Stholo 			if (curpfile >= npfile)
1706ab05f83Stholo 				return EOF;
1716ab05f83Stholo 			if (strcmp((char *) pfile[curpfile], "-") == 0)
1726ab05f83Stholo 				yyin = stdin;
1736ab05f83Stholo 			else if ((yyin = fopen((char *) pfile[curpfile], "r")) == NULL)
1746ab05f83Stholo 				ERROR "can't open file %s", pfile[curpfile] FATAL;
1756ab05f83Stholo 		}
1766ab05f83Stholo 		if ((c = getc(yyin)) != EOF)
1776ab05f83Stholo 			return c;
1786ab05f83Stholo 		if (yyin != stdin)
1796ab05f83Stholo 			fclose(yyin);
1806ab05f83Stholo 		yyin = NULL;
1816ab05f83Stholo 		curpfile++;
1826ab05f83Stholo 	}
1836ab05f83Stholo }
184