xref: /freebsd/contrib/one-true-awk/main.c (revision 884a2a699669ec61e2366e3e358342dbc94be24a)
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 20110506 (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 	srand(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' && --argc > 1 && isclvar((++argv)[1]))
129 				setclvar(argv[1]);
130 			else if (argv[1][2] != '\0')
131 				setclvar(&argv[1][2]);
132 			break;
133 		case 'd':
134 			dbg = atoi(&argv[1][2]);
135 			if (dbg == 0)
136 				dbg = 1;
137 			printf("awk %s\n", version);
138 			break;
139 		default:
140 			WARNING("unknown option %s ignored", argv[1]);
141 			break;
142 		}
143 		argc--;
144 		argv++;
145 	}
146 	/* argv[1] is now the first argument */
147 	if (npfile == 0) {	/* no -f; first argument is program */
148 		if (argc <= 1) {
149 			if (dbg)
150 				exit(0);
151 			FATAL("no program given");
152 		}
153 		   dprintf( ("program = |%s|\n", argv[1]) );
154 		lexprog = argv[1];
155 		argc--;
156 		argv++;
157 	}
158 	recinit(recsize);
159 	syminit();
160 	compile_time = 1;
161 	argv[0] = cmdname;	/* put prog name at front of arglist */
162 	   dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
163 	arginit(argc, argv);
164 	if (!safe)
165 		envinit(environ);
166 	yyparse();
167 	setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
168 	if (fs)
169 		*FS = qstring(fs, '\0');
170 	   dprintf( ("errorflag=%d\n", errorflag) );
171 	if (errorflag == 0) {
172 		compile_time = 0;
173 		run(winner);
174 	} else
175 		bracecheck();
176 	return(errorflag);
177 }
178 
179 int pgetc(void)		/* get 1 character from awk program */
180 {
181 	int c;
182 
183 	for (;;) {
184 		if (yyin == NULL) {
185 			if (curpfile >= npfile)
186 				return EOF;
187 			if (strcmp(pfile[curpfile], "-") == 0)
188 				yyin = stdin;
189 			else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
190 				FATAL("can't open file %s", pfile[curpfile]);
191 			lineno = 1;
192 		}
193 		if ((c = getc(yyin)) != EOF)
194 			return c;
195 		if (yyin != stdin)
196 			fclose(yyin);
197 		yyin = NULL;
198 		curpfile++;
199 	}
200 }
201 
202 char *cursource(void)	/* current source file name */
203 {
204 	if (npfile > 0)
205 		return pfile[curpfile];
206 	else
207 		return NULL;
208 }
209