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