xref: /openbsd-src/usr.bin/awk/main.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: main.c,v 1.10 2000/11/21 14:08:22 aaron 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 char	*version = "version 19990620";
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 #define	MAX_PFILE	20
39 
40 extern	char	**environ;
41 extern	int	nfields;
42 extern	char	*__progname;
43 
44 int	dbg	= 0;
45 char	*cmdname;	/* gets argv[0] for error messages */
46 extern	FILE	*yyin;	/* lex input file */
47 char	*lexprog;	/* points to program argument if it exists */
48 extern	int errorflag;	/* non-zero if any syntax errors; set by yyerror */
49 int	compile_time = 2;	/* for error printing: */
50 				/* 2 = cmdline, 1 = compile, 0 = running */
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 	char *fs = NULL, *marg;
61 	int temp;
62 
63 	setlocale(LC_ALL, "");
64 
65 	cmdname = __progname;
66 	if (argc == 1) {
67 		fprintf(stderr, "usage: %s [-F fs] [-v var=value] [-safe] "
68 		    "[-mr n] [-mf n] [prog | -f progfile] file ...\n",
69 		    cmdname);
70 		exit(1);
71 	}
72 	signal(SIGFPE, fpecatch);
73 	yyin = NULL;
74 	symtab = makesymtab(NSYMTAB);
75 	while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
76 		if (strcmp(argv[1], "--") == 0) {	/* explicit end of args */
77 			argc--;
78 			argv++;
79 			break;
80 		}
81 		switch (argv[1][1]) {
82 		case 's':
83 			if (strcmp(argv[1], "-safe") == 0)
84 				safe = 1;
85 			break;
86 		case 'f':	/* next argument is program filename */
87 			argc--;
88 			argv++;
89 			if (npfile >= MAX_PFILE - 1)
90 				FATAL("too many -f options");
91 			if (argc <= 1)
92 				FATAL("no program filename");
93 			pfile[npfile++] = argv[1];
94 			break;
95 		case 'F':	/* set field separator */
96 			if (argv[1][2] != 0) {	/* arg is -Fsomething */
97 				if (argv[1][2] == 't' && argv[1][3] == 0)	/* wart: t=>\t */
98 					fs = "\t";
99 				else if (argv[1][2] != 0)
100 					fs = &argv[1][2];
101 			} else {		/* arg is -F something */
102 				argc--; argv++;
103 				if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0)	/* wart: t=>\t */
104 					fs = "\t";
105 				else if (argc > 1 && argv[1][0] != 0)
106 					fs = &argv[1][0];
107 			}
108 			if (fs == NULL || *fs == '\0')
109 				WARNING("field separator FS is empty");
110 			break;
111 		case 'v':	/* -v a=1 to be done NOW.  one -v for each */
112 			if (argv[1][2] == '\0' && --argc > 1 && isclvar((++argv)[1]))
113 				setclvar(argv[1]);
114 			break;
115 		case 'm':	/* more memory: -mr=record, -mf=fields */
116 				/* no longer needed */
117 			marg = argv[1];
118 			if (argv[1][3])
119 				temp = atoi(&argv[1][3]);
120 			else {
121 				argv++; argc--;
122 				temp = atoi(&argv[1][0]);
123 			}
124 			switch (marg[2]) {
125 			case 'r':	recsize = temp; break;
126 			case 'f':	nfields = temp; break;
127 			default: FATAL("unknown option %s\n", marg);
128 			}
129 			break;
130 		case 'd':
131 			dbg = atoi(&argv[1][2]);
132 			if (dbg == 0)
133 				dbg = 1;
134 			printf("awk %s\n", version);
135 			break;
136 		case 'V':	/* added for exptools "standard" */
137 			printf("awk %s\n", version);
138 			exit(0);
139 			break;
140 		default:
141 			WARNING("unknown option %s ignored", argv[1]);
142 			break;
143 		}
144 		argc--;
145 		argv++;
146 	}
147 	/* argv[1] is now the first argument */
148 	if (npfile == 0) {	/* no -f; first argument is program */
149 		if (argc <= 1) {
150 			if (dbg)
151 				exit(0);
152 			FATAL("no program given");
153 		}
154 		   dprintf( ("program = |%s|\n", argv[1]) );
155 		lexprog = argv[1];
156 		argc--;
157 		argv++;
158 	}
159 	recinit(recsize);
160 	syminit();
161 	compile_time = 1;
162 	argv[0] = cmdname;	/* put prog name at front of arglist */
163 	   dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
164 	arginit(argc, argv);
165 	if (!safe)
166 		envinit(environ);
167 	yyparse();
168 	if (fs)
169 		*FS = qstring(fs, '\0');
170 	   dprintf( ("errorflag=%d\n", errorflag) );
171 	if (errorflag == 0) {
172 		compile_time = 0;
173 		run(winner);
174 	} else
175 		bracecheck();
176 	return(errorflag);
177 }
178 
179 int pgetc(void)		/* get 1 character from awk program */
180 {
181 	int c;
182 
183 	for (;;) {
184 		if (yyin == NULL) {
185 			if (curpfile >= npfile)
186 				return EOF;
187 			if (strcmp(pfile[curpfile], "-") == 0)
188 				yyin = stdin;
189 			else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
190 				FATAL("can't open file %s", pfile[curpfile]);
191 			lineno = 1;
192 		}
193 		if ((c = getc(yyin)) != EOF)
194 			return c;
195 		if (yyin != stdin)
196 			fclose(yyin);
197 		yyin = NULL;
198 		curpfile++;
199 	}
200 }
201 
202 char *cursource(void)	/* current source file name */
203 {
204 	if (npfile > 0)
205 		return pfile[curpfile];
206 	else
207 		return NULL;
208 }
209