xref: /freebsd/contrib/one-true-awk/main.c (revision 7cc42f6d)
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 #include <sys/cdefs.h>
26 __FBSDID("$FreeBSD$");
27 const char	*version = "version 20190529 (FreeBSD)";
28 
29 #define DEBUG
30 #include <stdio.h>
31 #include <ctype.h>
32 #include <locale.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <signal.h>
36 #include "awk.h"
37 #include "ytab.h"
38 
39 extern	char	**environ;
40 extern	int	nfields;
41 
42 int	dbg	= 0;
43 Awkfloat	srand_seed = 1;
44 char	*cmdname;	/* gets argv[0] for error messages */
45 extern	FILE	*yyin;	/* lex input file */
46 char	*lexprog;	/* points to program argument if it exists */
47 extern	int errorflag;	/* non-zero if any syntax errors; set by yyerror */
48 int	compile_time = 2;	/* for error printing: */
49 				/* 2 = cmdline, 1 = compile, 0 = running */
50 
51 #define	MAX_PFILE	20	/* max number of -f's */
52 
53 char	*pfile[MAX_PFILE];	/* program filenames from -f's */
54 int	npfile = 0;	/* number of filenames */
55 int	curpfile = 0;	/* current filename */
56 
57 int	safe	= 0;	/* 1 => "safe" mode */
58 
59 /* Can this work with recursive calls?  I don't think so.
60 void segvcatch(int n)
61 {
62 	FATAL("segfault.  Do you have an unbounded recursive call?", n);
63 }
64 */
65 
66 int main(int argc, char *argv[])
67 {
68 	const char *fs = NULL;
69 
70 	setlocale(LC_CTYPE, "");
71 	setlocale(LC_COLLATE, "");
72 	setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
73 	cmdname = argv[0];
74 	if (argc == 1) {
75 		fprintf(stderr,
76 		  "usage: %s [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]\n",
77 		  cmdname);
78 		exit(1);
79 	}
80 	signal(SIGFPE, fpecatch);
81 	/*signal(SIGSEGV, segvcatch); experiment */
82 
83 	srand_seed = 1;
84 	srandom((unsigned long) srand_seed);
85 
86 	yyin = NULL;
87 	symtab = makesymtab(NSYMTAB/NSYMTAB);
88 	while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
89 		if (strcmp(argv[1],"-version") == 0 || strcmp(argv[1],"--version") == 0) {
90 			printf("awk %s\n", version);
91 			exit(0);
92 			break;
93 		}
94 		if (strcmp(argv[1], "--") == 0) {	/* explicit end of args */
95 			argc--;
96 			argv++;
97 			break;
98 		}
99 		switch (argv[1][1]) {
100 		case 's':
101 			if (strcmp(argv[1], "-safe") == 0)
102 				safe = 1;
103 			break;
104 		case 'f':	/* next argument is program filename */
105 			if (argv[1][2] != 0) {  /* arg is -fsomething */
106 				if (npfile >= MAX_PFILE - 1)
107 					FATAL("too many -f options");
108 				pfile[npfile++] = &argv[1][2];
109 			} else {		/* arg is -f something */
110 				argc--; argv++;
111 				if (argc <= 1)
112 					FATAL("no program filename");
113 				if (npfile >= MAX_PFILE - 1)
114 					FATAL("too many -f options");
115 				pfile[npfile++] = argv[1];
116 			}
117 			break;
118 		case 'F':	/* set field separator */
119 			if (argv[1][2] != 0) {	/* arg is -Fsomething */
120 				if (argv[1][2] == 't' && argv[1][3] == 0)	/* wart: t=>\t */
121 					fs = "\t";
122 				else if (argv[1][2] != 0)
123 					fs = &argv[1][2];
124 			} else {		/* arg is -F something */
125 				argc--; argv++;
126 				if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0)	/* wart: t=>\t */
127 					fs = "\t";
128 				else if (argc > 1 && argv[1][0] != 0)
129 					fs = &argv[1][0];
130 			}
131 			if (fs == NULL || *fs == '\0')
132 				WARNING("field separator FS is empty");
133 			break;
134 		case 'v':	/* -v a=1 to be done NOW.  one -v for each */
135 			if (argv[1][2] != 0) {  /* arg is -vsomething */
136 				if (isclvar(&argv[1][2]))
137 					setclvar(&argv[1][2]);
138 				else
139 					FATAL("invalid -v option argument: %s", &argv[1][2]);
140 			} else {		/* arg is -v something */
141 				argc--; argv++;
142 				if (argc <= 1)
143 					FATAL("no variable name");
144 				if (isclvar(argv[1]))
145 					setclvar(argv[1]);
146 				else
147 					FATAL("invalid -v option argument: %s", argv[1]);
148 			}
149 			break;
150 		case 'd':
151 			dbg = atoi(&argv[1][2]);
152 			if (dbg == 0)
153 				dbg = 1;
154 			printf("awk %s\n", version);
155 			break;
156 		default:
157 			WARNING("unknown option %s ignored", argv[1]);
158 			break;
159 		}
160 		argc--;
161 		argv++;
162 	}
163 	/* argv[1] is now the first argument */
164 	if (npfile == 0) {	/* no -f; first argument is program */
165 		if (argc <= 1) {
166 			if (dbg)
167 				exit(0);
168 			FATAL("no program given");
169 		}
170 		   dprintf( ("program = |%s|\n", argv[1]) );
171 		lexprog = argv[1];
172 		argc--;
173 		argv++;
174 	}
175 	recinit(recsize);
176 	syminit();
177 	compile_time = 1;
178 	argv[0] = cmdname;	/* put prog name at front of arglist */
179 	   dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
180 	arginit(argc, argv);
181 	if (!safe)
182 		envinit(environ);
183 	yyparse();
184 	setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
185 	if (fs)
186 		*FS = qstring(fs, '\0');
187 	   dprintf( ("errorflag=%d\n", errorflag) );
188 	if (errorflag == 0) {
189 		compile_time = 0;
190 		run(winner);
191 	} else
192 		bracecheck();
193 	return(errorflag);
194 }
195 
196 int pgetc(void)		/* get 1 character from awk program */
197 {
198 	int c;
199 
200 	for (;;) {
201 		if (yyin == NULL) {
202 			if (curpfile >= npfile)
203 				return EOF;
204 			if (strcmp(pfile[curpfile], "-") == 0)
205 				yyin = stdin;
206 			else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
207 				FATAL("can't open file %s", pfile[curpfile]);
208 			lineno = 1;
209 		}
210 		if ((c = getc(yyin)) != EOF)
211 			return c;
212 		if (yyin != stdin)
213 			fclose(yyin);
214 		yyin = NULL;
215 		curpfile++;
216 	}
217 }
218 
219 char *cursource(void)	/* current source file name */
220 {
221 	if (npfile > 0)
222 		return pfile[curpfile];
223 	else
224 		return NULL;
225 }
226