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