blob: 832d971ba2d75720cc37e9a95fecc8559eb62da1 [file] [log] [blame]
Brian Kernighan87b94932012-12-22 10:35:39 -05001/****************************************************************
2Copyright (C) Lucent Technologies 1997
3All Rights Reserved
4
5Permission to use, copy, modify, and distribute this software and
6its documentation for any purpose and without fee is hereby
7granted, provided that the above copyright notice appear in all
8copies and that both that the copyright notice and this
9permission notice and warranty disclaimer appear in supporting
10documentation, and that the name Lucent Technologies or any of
11its entities not be used in advertising or publicity pertaining
12to distribution of the software without specific, written prior
13permission.
14
15LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22THIS SOFTWARE.
23****************************************************************/
24
Arnold D. Robbins5068d202020-02-06 22:27:31 +020025const char *version = "version 20200206";
Brian Kernighan87b94932012-12-22 10:35:39 -050026
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
37extern char **environ;
38extern int nfields;
39
40int dbg = 0;
41Awkfloat srand_seed = 1;
42char *cmdname; /* gets argv[0] for error messages */
43extern FILE *yyin; /* lex input file */
44char *lexprog; /* points to program argument if it exists */
45extern int errorflag; /* non-zero if any syntax errors; set by yyerror */
Arnold D. Robbins108224b2019-11-10 21:19:18 +020046enum compile_states compile_time = ERROR_PRINTING;
Brian Kernighan87b94932012-12-22 10:35:39 -050047
48#define MAX_PFILE 20 /* max number of -f's */
49
50char *pfile[MAX_PFILE]; /* program filenames from -f's */
51int npfile = 0; /* number of filenames */
52int curpfile = 0; /* current filename */
53
Arnold D. Robbins108224b2019-11-10 21:19:18 +020054bool safe = false; /* true => "safe" mode */
Brian Kernighan87b94932012-12-22 10:35:39 -050055
Brian Kernighan3ed9e242018-08-15 10:45:03 -040056/* Can this work with recursive calls? I don't think so.
57void segvcatch(int n)
58{
59 FATAL("segfault. Do you have an unbounded recursive call?", n);
60}
61*/
62
Brian Kernighan87b94932012-12-22 10:35:39 -050063int main(int argc, char *argv[])
64{
65 const char *fs = NULL;
66
67 setlocale(LC_CTYPE, "");
68 setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
69 cmdname = argv[0];
70 if (argc == 1) {
Arnold D. Robbins795a06b2019-07-28 05:51:52 -060071 fprintf(stderr,
72 "usage: %s [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]\n",
Brian Kernighan87b94932012-12-22 10:35:39 -050073 cmdname);
74 exit(1);
75 }
76 signal(SIGFPE, fpecatch);
Brian Kernighan3ed9e242018-08-15 10:45:03 -040077 /*signal(SIGSEGV, segvcatch); experiment */
Brian Kernighan87b94932012-12-22 10:35:39 -050078
79 srand_seed = 1;
pfgc70b9fe2014-09-19 18:24:02 +000080 srandom((unsigned long) srand_seed);
Brian Kernighan87b94932012-12-22 10:35:39 -050081
82 yyin = NULL;
83 symtab = makesymtab(NSYMTAB/NSYMTAB);
84 while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
85 if (strcmp(argv[1],"-version") == 0 || strcmp(argv[1],"--version") == 0) {
86 printf("awk %s\n", version);
87 exit(0);
88 break;
89 }
Cody Peter Mello9b093ea2018-10-09 11:46:57 -070090 if (strcmp(argv[1], "--") == 0) { /* explicit end of args */
Brian Kernighan87b94932012-12-22 10:35:39 -050091 argc--;
92 argv++;
93 break;
94 }
95 switch (argv[1][1]) {
96 case 's':
97 if (strcmp(argv[1], "-safe") == 0)
Arnold D. Robbins108224b2019-11-10 21:19:18 +020098 safe = true;
Brian Kernighan87b94932012-12-22 10:35:39 -050099 break;
100 case 'f': /* next argument is program filename */
101 if (argv[1][2] != 0) { /* arg is -fsomething */
102 if (npfile >= MAX_PFILE - 1)
Arnold D. Robbins795a06b2019-07-28 05:51:52 -0600103 FATAL("too many -f options");
Brian Kernighan87b94932012-12-22 10:35:39 -0500104 pfile[npfile++] = &argv[1][2];
105 } else { /* arg is -f something */
106 argc--; argv++;
107 if (argc <= 1)
108 FATAL("no program filename");
109 if (npfile >= MAX_PFILE - 1)
Arnold D. Robbins795a06b2019-07-28 05:51:52 -0600110 FATAL("too many -f options");
Brian Kernighan87b94932012-12-22 10:35:39 -0500111 pfile[npfile++] = argv[1];
112 }
113 break;
114 case 'F': /* set field separator */
115 if (argv[1][2] != 0) { /* arg is -Fsomething */
116 if (argv[1][2] == 't' && argv[1][3] == 0) /* wart: t=>\t */
117 fs = "\t";
118 else if (argv[1][2] != 0)
119 fs = &argv[1][2];
120 } else { /* arg is -F something */
121 argc--; argv++;
122 if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0) /* wart: t=>\t */
123 fs = "\t";
124 else if (argc > 1 && argv[1][0] != 0)
125 fs = &argv[1][0];
126 }
127 if (fs == NULL || *fs == '\0')
128 WARNING("field separator FS is empty");
129 break;
130 case 'v': /* -v a=1 to be done NOW. one -v for each */
131 if (argv[1][2] != 0) { /* arg is -vsomething */
132 if (isclvar(&argv[1][2]))
133 setclvar(&argv[1][2]);
134 else
135 FATAL("invalid -v option argument: %s", &argv[1][2]);
136 } else { /* arg is -v something */
137 argc--; argv++;
138 if (argc <= 1)
139 FATAL("no variable name");
140 if (isclvar(argv[1]))
141 setclvar(argv[1]);
142 else
143 FATAL("invalid -v option argument: %s", argv[1]);
144 }
145 break;
146 case 'd':
147 dbg = atoi(&argv[1][2]);
148 if (dbg == 0)
149 dbg = 1;
150 printf("awk %s\n", version);
151 break;
152 default:
153 WARNING("unknown option %s ignored", argv[1]);
154 break;
155 }
156 argc--;
157 argv++;
158 }
159 /* argv[1] is now the first argument */
160 if (npfile == 0) { /* no -f; first argument is program */
161 if (argc <= 1) {
162 if (dbg)
163 exit(0);
164 FATAL("no program given");
165 }
166 dprintf( ("program = |%s|\n", argv[1]) );
167 lexprog = argv[1];
168 argc--;
169 argv++;
170 }
171 recinit(recsize);
172 syminit();
Arnold D. Robbins108224b2019-11-10 21:19:18 +0200173 compile_time = COMPILING;
Brian Kernighan87b94932012-12-22 10:35:39 -0500174 argv[0] = cmdname; /* put prog name at front of arglist */
175 dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
176 arginit(argc, argv);
177 if (!safe)
178 envinit(environ);
179 yyparse();
180 setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
181 if (fs)
182 *FS = qstring(fs, '\0');
183 dprintf( ("errorflag=%d\n", errorflag) );
184 if (errorflag == 0) {
Arnold D. Robbins108224b2019-11-10 21:19:18 +0200185 compile_time = RUNNING;
Brian Kernighan87b94932012-12-22 10:35:39 -0500186 run(winner);
187 } else
188 bracecheck();
189 return(errorflag);
190}
191
192int pgetc(void) /* get 1 character from awk program */
193{
194 int c;
195
196 for (;;) {
197 if (yyin == NULL) {
198 if (curpfile >= npfile)
199 return EOF;
200 if (strcmp(pfile[curpfile], "-") == 0)
201 yyin = stdin;
202 else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
203 FATAL("can't open file %s", pfile[curpfile]);
204 lineno = 1;
205 }
206 if ((c = getc(yyin)) != EOF)
207 return c;
208 if (yyin != stdin)
209 fclose(yyin);
210 yyin = NULL;
211 curpfile++;
212 }
213}
214
215char *cursource(void) /* current source file name */
216{
217 if (npfile > 0)
218 return pfile[curpfile];
219 else
220 return NULL;
221}