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