xref: /openbsd-src/usr.bin/awk/main.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: main.c,v 1.15 2008/10/06 20:38:33 millert Exp $	*/
2 /****************************************************************
3 Copyright (C) Lucent Technologies 1997
4 All Rights Reserved
5 
6 Permission to use, copy, modify, and distribute this software and
7 its documentation for any purpose and without fee is hereby
8 granted, provided that the above copyright notice appear in all
9 copies and that both that the copyright notice and this
10 permission notice and warranty disclaimer appear in supporting
11 documentation, and that the name Lucent Technologies or any of
12 its entities not be used in advertising or publicity pertaining
13 to distribution of the software without specific, written prior
14 permission.
15 
16 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
18 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
19 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
21 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
22 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
23 THIS SOFTWARE.
24 ****************************************************************/
25 
26 const char	*version = "version 20071023";
27 
28 #define DEBUG
29 #include <stdio.h>
30 #include <ctype.h>
31 #include <locale.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <signal.h>
35 #include "awk.h"
36 #include "ytab.h"
37 
38 extern	char	**environ;
39 extern	int	nfields;
40 extern	char	*__progname;
41 
42 int	dbg	= 0;
43 char	*cmdname;	/* gets argv[0] for error messages */
44 extern	FILE	*yyin;	/* lex input file */
45 char	*lexprog;	/* points to program argument if it exists */
46 extern	int errorflag;	/* non-zero if any syntax errors; set by yyerror */
47 int	compile_time = 2;	/* for error printing: */
48 				/* 2 = cmdline, 1 = compile, 0 = running */
49 
50 #define	MAX_PFILE	20	/* max number of -f's */
51 
52 char	*pfile[MAX_PFILE];	/* program filenames from -f's */
53 int	npfile = 0;	/* number of filenames */
54 int	curpfile = 0;	/* current filename */
55 
56 int	safe	= 0;	/* 1 => "safe" mode */
57 
58 int main(int argc, char *argv[])
59 {
60 	const char *fs = NULL;
61 
62 	setlocale(LC_ALL, "");
63 	setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
64 	cmdname = __progname;
65 	if (argc == 1) {
66 		fprintf(stderr, "usage: %s [-safe] [-V] [-d[n]] [-F fs] "
67 		    "[-v var=value] [prog | -f progfile]\n\tfile ...\n",
68 		    cmdname);
69 		exit(1);
70 	}
71 	signal(SIGFPE, fpecatch);
72 	yyin = NULL;
73 	symtab = makesymtab(NSYMTAB);
74 	while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
75 		if (strcmp(argv[1], "--") == 0) {	/* explicit end of args */
76 			argc--;
77 			argv++;
78 			break;
79 		}
80 		switch (argv[1][1]) {
81 		case 's':
82 			if (strcmp(argv[1], "-safe") == 0)
83 				safe = 1;
84 			break;
85 		case 'f':	/* next argument is program filename */
86 			argc--;
87 			argv++;
88 			if (npfile >= MAX_PFILE - 1)
89 				FATAL("too many -f options");
90 			if (argc <= 1)
91 				FATAL("no program filename");
92 			if (npfile >= MAX_PFILE - 1)
93 				FATAL("too many -f options");
94 			pfile[npfile++] = argv[1];
95 			break;
96 		case 'F':	/* set field separator */
97 			if (argv[1][2] != 0) {	/* arg is -Fsomething */
98 				if (argv[1][2] == 't' && argv[1][3] == 0)	/* wart: t=>\t */
99 					fs = "\t";
100 				else if (argv[1][2] != 0)
101 					fs = &argv[1][2];
102 			} else {		/* arg is -F something */
103 				argc--; argv++;
104 				if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0)	/* wart: t=>\t */
105 					fs = "\t";
106 				else if (argc > 1 && argv[1][0] != 0)
107 					fs = &argv[1][0];
108 			}
109 			if (fs == NULL || *fs == '\0')
110 				WARNING("field separator FS is empty");
111 			break;
112 		case 'v':	/* -v a=1 to be done NOW.  one -v for each */
113 			if (argv[1][2] == '\0' && --argc > 1 && isclvar((++argv)[1]))
114 				setclvar(argv[1]);
115 			break;
116 		case 'd':
117 			dbg = atoi(&argv[1][2]);
118 			if (dbg == 0)
119 				dbg = 1;
120 			printf("awk %s\n", version);
121 			break;
122 		case 'V':	/* added for exptools "standard" */
123 			printf("awk %s\n", version);
124 			exit(0);
125 			break;
126 		default:
127 			WARNING("unknown option %s ignored", argv[1]);
128 			break;
129 		}
130 		argc--;
131 		argv++;
132 	}
133 	/* argv[1] is now the first argument */
134 	if (npfile == 0) {	/* no -f; first argument is program */
135 		if (argc <= 1) {
136 			if (dbg)
137 				exit(0);
138 			FATAL("no program given");
139 		}
140 		   dprintf( ("program = |%s|\n", argv[1]) );
141 		lexprog = argv[1];
142 		argc--;
143 		argv++;
144 	}
145 	recinit(recsize);
146 	syminit();
147 	compile_time = 1;
148 	argv[0] = cmdname;	/* put prog name at front of arglist */
149 	   dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
150 	arginit(argc, argv);
151 	if (!safe)
152 		envinit(environ);
153 	yyparse();
154 	setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
155 	if (fs)
156 		*FS = qstring(fs, '\0');
157 	   dprintf( ("errorflag=%d\n", errorflag) );
158 	if (errorflag == 0) {
159 		compile_time = 0;
160 		run(winner);
161 	} else
162 		bracecheck();
163 	return(errorflag);
164 }
165 
166 int pgetc(void)		/* get 1 character from awk program */
167 {
168 	int c;
169 
170 	for (;;) {
171 		if (yyin == NULL) {
172 			if (curpfile >= npfile)
173 				return EOF;
174 			if (strcmp(pfile[curpfile], "-") == 0)
175 				yyin = stdin;
176 			else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
177 				FATAL("can't open file %s", pfile[curpfile]);
178 			lineno = 1;
179 		}
180 		if ((c = getc(yyin)) != EOF)
181 			return c;
182 		if (yyin != stdin)
183 			fclose(yyin);
184 		yyin = NULL;
185 		curpfile++;
186 	}
187 }
188 
189 char *cursource(void)	/* current source file name */
190 {
191 	if (npfile > 0)
192 		return pfile[curpfile];
193 	else
194 		return NULL;
195 }
196