xref: /openbsd/usr.bin/awk/main.c (revision 6ab0fc03)
1*6ab0fc03Stb /*	$OpenBSD: main.c,v 1.20 2017/10/08 12:40:37 tb Exp $	*/
26ab05f83Stholo /****************************************************************
307edfa4aSkstailey Copyright (C) Lucent Technologies 1997
46ab05f83Stholo All Rights Reserved
56ab05f83Stholo 
66ab05f83Stholo Permission to use, copy, modify, and distribute this software and
76ab05f83Stholo its documentation for any purpose and without fee is hereby
86ab05f83Stholo granted, provided that the above copyright notice appear in all
96ab05f83Stholo copies and that both that the copyright notice and this
106ab05f83Stholo permission notice and warranty disclaimer appear in supporting
1107edfa4aSkstailey documentation, and that the name Lucent Technologies or any of
1207edfa4aSkstailey its entities not be used in advertising or publicity pertaining
1307edfa4aSkstailey to distribution of the software without specific, written prior
1407edfa4aSkstailey permission.
156ab05f83Stholo 
1607edfa4aSkstailey LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1707edfa4aSkstailey INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
1807edfa4aSkstailey IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
1907edfa4aSkstailey SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
2007edfa4aSkstailey WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
2107edfa4aSkstailey IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2207edfa4aSkstailey ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
2307edfa4aSkstailey THIS SOFTWARE.
246ab05f83Stholo ****************************************************************/
256ab05f83Stholo 
26000399a4Smillert const char	*version = "version 20110810";
276ab05f83Stholo 
286ab05f83Stholo #define DEBUG
296ab05f83Stholo #include <stdio.h>
306ab05f83Stholo #include <ctype.h>
31b2698ba9Smillert #include <locale.h>
326ab05f83Stholo #include <stdlib.h>
336ab05f83Stholo #include <string.h>
346ab05f83Stholo #include <signal.h>
358ce597b3Sdoug #include <unistd.h>
366ab05f83Stholo #include "awk.h"
3707edfa4aSkstailey #include "ytab.h"
386ab05f83Stholo 
396ab05f83Stholo extern	char	**environ;
406ab05f83Stholo extern	int	nfields;
41a4fa8700Smillert extern	char	*__progname;
426ab05f83Stholo 
436ab05f83Stholo int	dbg	= 0;
44000399a4Smillert Awkfloat	srand_seed = 1;
456ab05f83Stholo char	*cmdname;	/* gets argv[0] for error messages */
466ab05f83Stholo extern	FILE	*yyin;	/* lex input file */
476ab05f83Stholo char	*lexprog;	/* points to program argument if it exists */
486ab05f83Stholo extern	int errorflag;	/* non-zero if any syntax errors; set by yyerror */
496ab05f83Stholo int	compile_time = 2;	/* for error printing: */
506ab05f83Stholo 				/* 2 = cmdline, 1 = compile, 0 = running */
516ab05f83Stholo 
5280b86fb0Smillert #define	MAX_PFILE	20	/* max number of -f's */
5380b86fb0Smillert 
54466ccf10Smillert char	*pfile[MAX_PFILE];	/* program filenames from -f's */
556ab05f83Stholo int	npfile = 0;	/* number of filenames */
566ab05f83Stholo int	curpfile = 0;	/* current filename */
576ab05f83Stholo 
5807edfa4aSkstailey int	safe	= 0;	/* 1 => "safe" mode */
5907edfa4aSkstailey 
606ab05f83Stholo int main(int argc, char *argv[])
616ab05f83Stholo {
629a69093aSmillert 	const char *fs = NULL;
636ab05f83Stholo 
642682ef6bSderaadt 	setlocale(LC_ALL, "");
652682ef6bSderaadt 	setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
662682ef6bSderaadt 
67*6ab0fc03Stb 	cmdname = __progname;
688ce597b3Sdoug 	if (pledge("stdio rpath wpath cpath proc exec", NULL) == -1) {
698ce597b3Sdoug 		fprintf(stderr, "%s: pledge: incorrect arguments\n",
708ce597b3Sdoug 		    cmdname);
718ce597b3Sdoug 		exit(1);
728ce597b3Sdoug 	}
738ce597b3Sdoug 
746ab05f83Stholo 	if (argc == 1) {
75f0b76118Sjmc 		fprintf(stderr, "usage: %s [-safe] [-V] [-d[n]] [-F fs] "
76f0b76118Sjmc 		    "[-v var=value] [prog | -f progfile]\n\tfile ...\n",
77a54e3325Saaron 		    cmdname);
786ab05f83Stholo 		exit(1);
796ab05f83Stholo 	}
806ab05f83Stholo 	signal(SIGFPE, fpecatch);
81000399a4Smillert 
826ab05f83Stholo 	yyin = NULL;
836ab05f83Stholo 	symtab = makesymtab(NSYMTAB);
846ab05f83Stholo 	while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
8507edfa4aSkstailey 		if (strcmp(argv[1], "--") == 0) {	/* explicit end of args */
866ab05f83Stholo 			argc--;
876ab05f83Stholo 			argv++;
886ab05f83Stholo 			break;
896ab05f83Stholo 		}
906ab05f83Stholo 		switch (argv[1][1]) {
9107edfa4aSkstailey 		case 's':
9207edfa4aSkstailey 			if (strcmp(argv[1], "-safe") == 0)
9307edfa4aSkstailey 				safe = 1;
9407edfa4aSkstailey 			break;
956ab05f83Stholo 		case 'f':	/* next argument is program filename */
96000399a4Smillert 			if (argv[1][2] != 0) {  /* arg is -fsomething */
97466ccf10Smillert 				if (npfile >= MAX_PFILE - 1)
987b11b857Smillert 					FATAL("too many -f options");
99000399a4Smillert 				pfile[npfile++] = &argv[1][2];
100000399a4Smillert 			} else {		/* arg is -f something */
101000399a4Smillert 				argc--; argv++;
1026ab05f83Stholo 				if (argc <= 1)
1037b11b857Smillert 					FATAL("no program filename");
10480b86fb0Smillert 				if (npfile >= MAX_PFILE - 1)
10580b86fb0Smillert 					FATAL("too many -f options");
1066ab05f83Stholo 				pfile[npfile++] = argv[1];
107000399a4Smillert 			}
1086ab05f83Stholo 			break;
1096ab05f83Stholo 		case 'F':	/* set field separator */
1106ab05f83Stholo 			if (argv[1][2] != 0) {	/* arg is -Fsomething */
1116ab05f83Stholo 				if (argv[1][2] == 't' && argv[1][3] == 0)	/* wart: t=>\t */
11207edfa4aSkstailey 					fs = "\t";
1136ab05f83Stholo 				else if (argv[1][2] != 0)
1146ab05f83Stholo 					fs = &argv[1][2];
1156ab05f83Stholo 			} else {		/* arg is -F something */
1166ab05f83Stholo 				argc--; argv++;
1176ab05f83Stholo 				if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0)	/* wart: t=>\t */
11807edfa4aSkstailey 					fs = "\t";
1196ab05f83Stholo 				else if (argc > 1 && argv[1][0] != 0)
1206ab05f83Stholo 					fs = &argv[1][0];
1216ab05f83Stholo 			}
1226ab05f83Stholo 			if (fs == NULL || *fs == '\0')
1237b11b857Smillert 				WARNING("field separator FS is empty");
1246ab05f83Stholo 			break;
1256ab05f83Stholo 		case 'v':	/* -v a=1 to be done NOW.  one -v for each */
126000399a4Smillert 			if (argv[1][2] != 0) {  /* arg is -vsomething */
127000399a4Smillert 				if (isclvar(&argv[1][2]))
128d6972635Smillert 					setclvar(&argv[1][2]);
129000399a4Smillert 				else
130000399a4Smillert 					FATAL("invalid -v option argument: %s", &argv[1][2]);
131000399a4Smillert 			} else {		/* arg is -v something */
132000399a4Smillert 				argc--; argv++;
133000399a4Smillert 				if (argc <= 1)
134000399a4Smillert 					FATAL("no variable name");
135000399a4Smillert 				if (isclvar(argv[1]))
136000399a4Smillert 					setclvar(argv[1]);
137000399a4Smillert 				else
138000399a4Smillert 					FATAL("invalid -v option argument: %s", argv[1]);
139000399a4Smillert 			}
1406ab05f83Stholo 			break;
1416ab05f83Stholo 		case 'd':
1426ab05f83Stholo 			dbg = atoi(&argv[1][2]);
1436ab05f83Stholo 			if (dbg == 0)
1446ab05f83Stholo 				dbg = 1;
1456ab05f83Stholo 			printf("awk %s\n", version);
1466ab05f83Stholo 			break;
147a4fa8700Smillert 		case 'V':	/* added for exptools "standard" */
148a4fa8700Smillert 			printf("awk %s\n", version);
149a4fa8700Smillert 			exit(0);
150a4fa8700Smillert 			break;
1516ab05f83Stholo 		default:
1527b11b857Smillert 			WARNING("unknown option %s ignored", argv[1]);
1536ab05f83Stholo 			break;
1546ab05f83Stholo 		}
1556ab05f83Stholo 		argc--;
1566ab05f83Stholo 		argv++;
1576ab05f83Stholo 	}
1588ce597b3Sdoug 
1598ce597b3Sdoug 	if (safe) {
1608ce597b3Sdoug 		if (pledge("stdio rpath", NULL) == -1) {
1618ce597b3Sdoug 			fprintf(stderr, "%s: pledge: incorrect arguments\n",
1628ce597b3Sdoug 			    cmdname);
1638ce597b3Sdoug 			exit(1);
1648ce597b3Sdoug 		}
1658ce597b3Sdoug 	}
1668ce597b3Sdoug 
1676ab05f83Stholo 	/* argv[1] is now the first argument */
1686ab05f83Stholo 	if (npfile == 0) {	/* no -f; first argument is program */
1696ab05f83Stholo 		if (argc <= 1) {
1706ab05f83Stholo 			if (dbg)
1716ab05f83Stholo 				exit(0);
1727b11b857Smillert 			FATAL("no program given");
1736ab05f83Stholo 		}
1746ab05f83Stholo 		   dprintf( ("program = |%s|\n", argv[1]) );
1756ab05f83Stholo 		lexprog = argv[1];
1766ab05f83Stholo 		argc--;
1776ab05f83Stholo 		argv++;
1786ab05f83Stholo 	}
1796ab05f83Stholo 	recinit(recsize);
1806ab05f83Stholo 	syminit();
1816ab05f83Stholo 	compile_time = 1;
1826ab05f83Stholo 	argv[0] = cmdname;	/* put prog name at front of arglist */
1836ab05f83Stholo 	   dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
1846ab05f83Stholo 	arginit(argc, argv);
18507edfa4aSkstailey 	if (!safe)
1866ab05f83Stholo 		envinit(environ);
1876ab05f83Stholo 	yyparse();
18823cb51abSmillert 	setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
1896ab05f83Stholo 	if (fs)
19007edfa4aSkstailey 		*FS = qstring(fs, '\0');
1916ab05f83Stholo 	   dprintf( ("errorflag=%d\n", errorflag) );
1926ab05f83Stholo 	if (errorflag == 0) {
1936ab05f83Stholo 		compile_time = 0;
1946ab05f83Stholo 		run(winner);
1956ab05f83Stholo 	} else
1966ab05f83Stholo 		bracecheck();
1976ab05f83Stholo 	return(errorflag);
1986ab05f83Stholo }
1996ab05f83Stholo 
2006ab05f83Stholo int pgetc(void)		/* get 1 character from awk program */
2016ab05f83Stholo {
2026ab05f83Stholo 	int c;
2036ab05f83Stholo 
2046ab05f83Stholo 	for (;;) {
2056ab05f83Stholo 		if (yyin == NULL) {
2066ab05f83Stholo 			if (curpfile >= npfile)
2076ab05f83Stholo 				return EOF;
20807edfa4aSkstailey 			if (strcmp(pfile[curpfile], "-") == 0)
2096ab05f83Stholo 				yyin = stdin;
21007edfa4aSkstailey 			else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
2117b11b857Smillert 				FATAL("can't open file %s", pfile[curpfile]);
212271018d0Smillert 			lineno = 1;
2136ab05f83Stholo 		}
2146ab05f83Stholo 		if ((c = getc(yyin)) != EOF)
2156ab05f83Stholo 			return c;
2166ab05f83Stholo 		if (yyin != stdin)
2176ab05f83Stholo 			fclose(yyin);
2186ab05f83Stholo 		yyin = NULL;
2196ab05f83Stholo 		curpfile++;
2206ab05f83Stholo 	}
2216ab05f83Stholo }
222271018d0Smillert 
223271018d0Smillert char *cursource(void)	/* current source file name */
224271018d0Smillert {
225271018d0Smillert 	if (npfile > 0)
226271018d0Smillert 		return pfile[curpfile];
227271018d0Smillert 	else
228271018d0Smillert 		return NULL;
229271018d0Smillert }
230