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