xref: /openbsd-src/usr.bin/awk/main.c (revision db3296cf5c1dd9058ceecc3a29fe4aaa0bd26000)
1 /*	$OpenBSD: main.c,v 1.12 2002/12/19 21:24:28 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 20021213";
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 	const char *fs = NULL;
61 
62 	setlocale(LC_ALL, "");
63 
64 	cmdname = __progname;
65 	if (argc == 1) {
66 		fprintf(stderr, "usage: %s [-F fs] [-v var=value] [-safe] "
67 		    "[-mr n] [-mf n] [prog | -f progfile] file ...\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 			pfile[npfile++] = argv[1];
93 			break;
94 		case 'F':	/* set field separator */
95 			if (argv[1][2] != 0) {	/* arg is -Fsomething */
96 				if (argv[1][2] == 't' && argv[1][3] == 0)	/* wart: t=>\t */
97 					fs = "\t";
98 				else if (argv[1][2] != 0)
99 					fs = &argv[1][2];
100 			} else {		/* arg is -F something */
101 				argc--; argv++;
102 				if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0)	/* wart: t=>\t */
103 					fs = "\t";
104 				else if (argc > 1 && argv[1][0] != 0)
105 					fs = &argv[1][0];
106 			}
107 			if (fs == NULL || *fs == '\0')
108 				WARNING("field separator FS is empty");
109 			break;
110 		case 'v':	/* -v a=1 to be done NOW.  one -v for each */
111 			if (argv[1][2] == '\0' && --argc > 1 && isclvar((++argv)[1]))
112 				setclvar(argv[1]);
113 			break;
114 		case 'm':	/* more memory: -mr=record, -mf=fields */
115 				/* no longer supported */
116 			WARNING("obsolete option %s ignored", argv[1]);
117 			break;
118 		case 'd':
119 			dbg = atoi(&argv[1][2]);
120 			if (dbg == 0)
121 				dbg = 1;
122 			printf("awk %s\n", version);
123 			break;
124 		case 'V':	/* added for exptools "standard" */
125 			printf("awk %s\n", version);
126 			exit(0);
127 			break;
128 		default:
129 			WARNING("unknown option %s ignored", argv[1]);
130 			break;
131 		}
132 		argc--;
133 		argv++;
134 	}
135 	/* argv[1] is now the first argument */
136 	if (npfile == 0) {	/* no -f; first argument is program */
137 		if (argc <= 1) {
138 			if (dbg)
139 				exit(0);
140 			FATAL("no program given");
141 		}
142 		   dprintf( ("program = |%s|\n", argv[1]) );
143 		lexprog = argv[1];
144 		argc--;
145 		argv++;
146 	}
147 	recinit(recsize);
148 	syminit();
149 	compile_time = 1;
150 	argv[0] = cmdname;	/* put prog name at front of arglist */
151 	   dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
152 	arginit(argc, argv);
153 	if (!safe)
154 		envinit(environ);
155 	yyparse();
156 	if (fs)
157 		*FS = qstring(fs, '\0');
158 	   dprintf( ("errorflag=%d\n", errorflag) );
159 	if (errorflag == 0) {
160 		compile_time = 0;
161 		run(winner);
162 	} else
163 		bracecheck();
164 	return(errorflag);
165 }
166 
167 int pgetc(void)		/* get 1 character from awk program */
168 {
169 	int c;
170 
171 	for (;;) {
172 		if (yyin == NULL) {
173 			if (curpfile >= npfile)
174 				return EOF;
175 			if (strcmp(pfile[curpfile], "-") == 0)
176 				yyin = stdin;
177 			else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
178 				FATAL("can't open file %s", pfile[curpfile]);
179 			lineno = 1;
180 		}
181 		if ((c = getc(yyin)) != EOF)
182 			return c;
183 		if (yyin != stdin)
184 			fclose(yyin);
185 		yyin = NULL;
186 		curpfile++;
187 	}
188 }
189 
190 char *cursource(void)	/* current source file name */
191 {
192 	if (npfile > 0)
193 		return pfile[curpfile];
194 	else
195 		return NULL;
196 }
197