xref: /netbsd-src/external/historical/nawk/dist/main.c (revision 56bb44cae5b13a6b74792381ba1e6d930b26aa67)
1 /****************************************************************
2 Copyright (C) Lucent Technologies 1997
3 All Rights Reserved
4 
5 Permission to use, copy, modify, and distribute this software and
6 its documentation for any purpose and without fee is hereby
7 granted, provided that the above copyright notice appear in all
8 copies and that both that the copyright notice and this
9 permission notice and warranty disclaimer appear in supporting
10 documentation, and that the name Lucent Technologies or any of
11 its entities not be used in advertising or publicity pertaining
12 to distribution of the software without specific, written prior
13 permission.
14 
15 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22 THIS SOFTWARE.
23 ****************************************************************/
24 
25 const char	*version = "version 20100523";
26 
27 #if HAVE_NBTOOL_CONFIG_H
28 #include "nbtool_config.h"
29 #endif
30 
31 #define DEBUG
32 #include <stdio.h>
33 #include <ctype.h>
34 #include <locale.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <signal.h>
38 #include "awk.h"
39 #include "awkgram.h"
40 
41 extern	char	**environ;
42 extern	int	nfields;
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 static char	**pfile = NULL;	/* program filenames from -f's */
53 static size_t 	maxpfile = 0;	/* max program filenames */
54 static size_t	npfile = 0;	/* number of filenames */
55 static size_t	curpfile = 0;	/* current filename */
56 
57 int	safe	= 0;	/* 1 => "safe" mode */
58 
59 static char *
60 setfs(char *p)
61 {
62 #ifdef notdef
63 	/* wart: t=>\t */
64 	if (p[0] == 't' && p[1] == 0)
65 		return "\t";
66 	else
67 #endif
68 	if (p[0] != 0)
69 		return p;
70 	return NULL;
71 }
72 
73 static void fpecatch(int n
74 #ifdef SA_SIGINFO
75 	, siginfo_t *si, void *uc
76 #endif
77 )
78 {
79 #ifdef SA_SIGINFO
80 	static const char *emsg[] = {
81 	    "Unknown error",
82 	    "Integer divide by zero",
83 	    "Integer overflow",
84 	    "Floating point divide by zero",
85 	    "Floating point overflow",
86 	    "Floating point underflow",
87 	    "Floating point inexact result",
88 	    "Invalid Floating point operation",
89 	    "Subscript out of range",
90 	};
91 #endif
92 	FATAL("floating point exception"
93 #ifdef SA_SIGINFO
94 	    ": %s\n", emsg[si->si_code >= 1 && si->si_code <= 8 ?
95 	    si->si_code : 0]
96 #endif
97 	    );
98 }
99 
100 int main(int argc, char *argv[])
101 {
102 	const char *fs = NULL;
103 
104 	setlocale(LC_ALL, "");
105 	setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
106 	cmdname = argv[0];
107 	if (argc == 1) {
108 		fprintf(stderr,
109 		  "usage: %s [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]\n",
110 		  cmdname);
111 		exit(1);
112 	}
113 
114 #ifdef SA_SIGINFO
115 	{
116 		struct sigaction sa;
117 		sa.sa_sigaction = fpecatch;
118 		sa.sa_flags = SA_SIGINFO;
119 		sigemptyset(&sa.sa_mask);
120 		(void)sigaction(SIGFPE, &sa, NULL);
121 	}
122 #else
123 	(void)signal(SIGFPE, fpecatch);
124 #endif
125 	yyin = NULL;
126 	symtab = makesymtab(NSYMTAB/NSYMTAB);
127 	while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
128 		if (strcmp(argv[1],"-version") == 0 || strcmp(argv[1],"--version") == 0) {
129 			printf("awk %s\n", version);
130 			exit(0);
131 			break;
132 		}
133 		if (strncmp(argv[1], "--", 2) == 0) {	/* explicit end of args */
134 			argc--;
135 			argv++;
136 			break;
137 		}
138 		switch (argv[1][1]) {
139 		case 's':
140 			if (strcmp(argv[1], "-safe") == 0)
141 				safe = 1;
142 			break;
143 		case 'f':	/* next argument is program filename */
144 			argc--;
145 			argv++;
146 			if (argc <= 1)
147 				FATAL("no program filename");
148 			if (npfile >= maxpfile) {
149 				maxpfile += 20;
150 				pfile = realloc(pfile,
151 				    maxpfile * sizeof(*pfile));
152 				if (pfile == NULL)
153 					FATAL("error allocating space for "
154 					    "-f options");
155 			}
156 			pfile[npfile++] = argv[1];
157 			break;
158 		case 'F':	/* set field separator */
159 			if (argv[1][2] != 0) {	/* arg is -Fsomething */
160 				fs = setfs(argv[1] + 2);
161 			} else {		/* arg is -F something */
162 				argc--; argv++;
163 				if (argc > 1)
164 					fs = setfs(argv[1]);
165 			}
166 			if (fs == NULL || *fs == '\0')
167 				WARNING("field separator FS is empty");
168 			break;
169 		case 'v':	/* -v a=1 to be done NOW.  one -v for each */
170 			if (argv[1][2] == '\0' && --argc > 1 && isclvar((++argv)[1]))
171 				setclvar(argv[1]);
172 			else if (argv[1][2] != '\0')
173 				setclvar(&argv[1][2]);
174 			break;
175 		case 'd':
176 			dbg = atoi(&argv[1][2]);
177 			if (dbg == 0)
178 				dbg = 1;
179 			printf("awk %s\n", version);
180 			break;
181 		default:
182 			WARNING("unknown option %s ignored", argv[1]);
183 			break;
184 		}
185 		argc--;
186 		argv++;
187 	}
188 	/* argv[1] is now the first argument */
189 	if (npfile == 0) {	/* no -f; first argument is program */
190 		if (argc <= 1) {
191 			if (dbg)
192 				exit(0);
193 			FATAL("no program given");
194 		}
195 		   dprintf( ("program = |%s|\n", argv[1]) );
196 		lexprog = argv[1];
197 		argc--;
198 		argv++;
199 	}
200 	recinit(recsize);
201 	syminit();
202 	compile_time = 1;
203 	argv[0] = cmdname;	/* put prog name at front of arglist */
204 	   dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
205 	arginit(argc, argv);
206 	if (!safe)
207 		envinit(environ);
208 	yyparse();
209 	setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
210 	if (fs)
211 		*FS = qstring(fs, '\0');
212 	   dprintf( ("errorflag=%d\n", errorflag) );
213 	if (errorflag == 0) {
214 		compile_time = 0;
215 		run(winner);
216 	} else
217 		bracecheck();
218 	return(errorflag);
219 }
220 
221 int pgetc(void)		/* get 1 character from awk program */
222 {
223 	int c;
224 
225 	for (;;) {
226 		if (yyin == NULL) {
227 			if (curpfile >= npfile)
228 				return EOF;
229 			if (strcmp(pfile[curpfile], "-") == 0)
230 				yyin = stdin;
231 			else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
232 				FATAL("can't open file %s", pfile[curpfile]);
233 			lineno = 1;
234 		}
235 		if ((c = getc(yyin)) != EOF)
236 			return c;
237 		if (yyin != stdin)
238 			fclose(yyin);
239 		yyin = NULL;
240 		curpfile++;
241 	}
242 }
243 
244 char *cursource(void)	/* current source file name */
245 {
246 	if (npfile > 0)
247 		return pfile[curpfile];
248 	else
249 		return NULL;
250 }
251