xref: /openbsd-src/usr.bin/awk/main.c (revision daf88648c0e349d5c02e1504293082072c981640)
1 /*	$OpenBSD: main.c,v 1.13 2004/12/30 01:52:48 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 20041222";
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 	setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
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 	setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
157 	if (fs)
158 		*FS = qstring(fs, '\0');
159 	   dprintf( ("errorflag=%d\n", errorflag) );
160 	if (errorflag == 0) {
161 		compile_time = 0;
162 		run(winner);
163 	} else
164 		bracecheck();
165 	return(errorflag);
166 }
167 
168 int pgetc(void)		/* get 1 character from awk program */
169 {
170 	int c;
171 
172 	for (;;) {
173 		if (yyin == NULL) {
174 			if (curpfile >= npfile)
175 				return EOF;
176 			if (strcmp(pfile[curpfile], "-") == 0)
177 				yyin = stdin;
178 			else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
179 				FATAL("can't open file %s", pfile[curpfile]);
180 			lineno = 1;
181 		}
182 		if ((c = getc(yyin)) != EOF)
183 			return c;
184 		if (yyin != stdin)
185 			fclose(yyin);
186 		yyin = NULL;
187 		curpfile++;
188 	}
189 }
190 
191 char *cursource(void)	/* current source file name */
192 {
193 	if (npfile > 0)
194 		return pfile[curpfile];
195 	else
196 		return NULL;
197 }
198