blob: e19a1b435dc4890c19051a8c0ffbd3b510d82d9a [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
Martijn Dekker5b602ca2019-07-26 10:46:58 +020025const char *version = "version 20190726";
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 */
46int compile_time = 2; /* for error printing: */
47 /* 2 = cmdline, 1 = compile, 0 = running */
48
49#define MAX_PFILE 20 /* max number of -f's */
50
51char *pfile[MAX_PFILE]; /* program filenames from -f's */
52int npfile = 0; /* number of filenames */
53int curpfile = 0; /* current filename */
54
55int safe = 0; /* 1 => "safe" mode */
56
Brian Kernighan3ed9e242018-08-15 10:45:03 -040057/* Can this work with recursive calls? I don't think so.
58void segvcatch(int n)
59{
60 FATAL("segfault. Do you have an unbounded recursive call?", n);
61}
62*/
63
Brian Kernighan87b94932012-12-22 10:35:39 -050064int main(int argc, char *argv[])
65{
66 const char *fs = NULL;
67
68 setlocale(LC_CTYPE, "");
69 setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
70 cmdname = argv[0];
71 if (argc == 1) {
Arnold D. Robbins795a06b2019-07-28 05:51:52 -060072 fprintf(stderr,
73 "usage: %s [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]\n",
Brian Kernighan87b94932012-12-22 10:35:39 -050074 cmdname);
75 exit(1);
76 }
77 signal(SIGFPE, fpecatch);
Brian Kernighan3ed9e242018-08-15 10:45:03 -040078 /*signal(SIGSEGV, segvcatch); experiment */
Brian Kernighan87b94932012-12-22 10:35:39 -050079
80 srand_seed = 1;
pfgc70b9fe2014-09-19 18:24:02 +000081 srandom((unsigned long) srand_seed);
Brian Kernighan87b94932012-12-22 10:35:39 -050082
83 yyin = NULL;
84 symtab = makesymtab(NSYMTAB/NSYMTAB);
85 while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
86 if (strcmp(argv[1],"-version") == 0 || strcmp(argv[1],"--version") == 0) {
87 printf("awk %s\n", version);
88 exit(0);
89 break;
90 }
Cody Peter Mello9b093ea2018-10-09 11:46:57 -070091 if (strcmp(argv[1], "--") == 0) { /* explicit end of args */
Brian Kernighan87b94932012-12-22 10:35:39 -050092 argc--;
93 argv++;
94 break;
95 }
96 switch (argv[1][1]) {
97 case 's':
98 if (strcmp(argv[1], "-safe") == 0)
99 safe = 1;
100 break;
101 case 'f': /* next argument is program filename */
102 if (argv[1][2] != 0) { /* arg is -fsomething */
103 if (npfile >= MAX_PFILE - 1)
Arnold D. Robbins795a06b2019-07-28 05:51:52 -0600104 FATAL("too many -f options");
Brian Kernighan87b94932012-12-22 10:35:39 -0500105 pfile[npfile++] = &argv[1][2];
106 } else { /* arg is -f something */
107 argc--; argv++;
108 if (argc <= 1)
109 FATAL("no program filename");
110 if (npfile >= MAX_PFILE - 1)
Arnold D. Robbins795a06b2019-07-28 05:51:52 -0600111 FATAL("too many -f options");
Brian Kernighan87b94932012-12-22 10:35:39 -0500112 pfile[npfile++] = argv[1];
113 }
114 break;
115 case 'F': /* set field separator */
116 if (argv[1][2] != 0) { /* arg is -Fsomething */
117 if (argv[1][2] == 't' && argv[1][3] == 0) /* wart: t=>\t */
118 fs = "\t";
119 else if (argv[1][2] != 0)
120 fs = &argv[1][2];
121 } else { /* arg is -F something */
122 argc--; argv++;
123 if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0) /* wart: t=>\t */
124 fs = "\t";
125 else if (argc > 1 && argv[1][0] != 0)
126 fs = &argv[1][0];
127 }
128 if (fs == NULL || *fs == '\0')
129 WARNING("field separator FS is empty");
130 break;
131 case 'v': /* -v a=1 to be done NOW. one -v for each */
132 if (argv[1][2] != 0) { /* arg is -vsomething */
133 if (isclvar(&argv[1][2]))
134 setclvar(&argv[1][2]);
135 else
136 FATAL("invalid -v option argument: %s", &argv[1][2]);
137 } else { /* arg is -v something */
138 argc--; argv++;
139 if (argc <= 1)
140 FATAL("no variable name");
141 if (isclvar(argv[1]))
142 setclvar(argv[1]);
143 else
144 FATAL("invalid -v option argument: %s", argv[1]);
145 }
146 break;
147 case 'd':
148 dbg = atoi(&argv[1][2]);
149 if (dbg == 0)
150 dbg = 1;
151 printf("awk %s\n", version);
152 break;
153 default:
154 WARNING("unknown option %s ignored", argv[1]);
155 break;
156 }
157 argc--;
158 argv++;
159 }
160 /* argv[1] is now the first argument */
161 if (npfile == 0) { /* no -f; first argument is program */
162 if (argc <= 1) {
163 if (dbg)
164 exit(0);
165 FATAL("no program given");
166 }
167 dprintf( ("program = |%s|\n", argv[1]) );
168 lexprog = argv[1];
169 argc--;
170 argv++;
171 }
172 recinit(recsize);
173 syminit();
174 compile_time = 1;
175 argv[0] = cmdname; /* put prog name at front of arglist */
176 dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
177 arginit(argc, argv);
178 if (!safe)
179 envinit(environ);
180 yyparse();
181 setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
182 if (fs)
183 *FS = qstring(fs, '\0');
184 dprintf( ("errorflag=%d\n", errorflag) );
185 if (errorflag == 0) {
186 compile_time = 0;
187 run(winner);
188 } else
189 bracecheck();
190 return(errorflag);
191}
192
193int pgetc(void) /* get 1 character from awk program */
194{
195 int c;
196
197 for (;;) {
198 if (yyin == NULL) {
199 if (curpfile >= npfile)
200 return EOF;
201 if (strcmp(pfile[curpfile], "-") == 0)
202 yyin = stdin;
203 else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
204 FATAL("can't open file %s", pfile[curpfile]);
205 lineno = 1;
206 }
207 if ((c = getc(yyin)) != EOF)
208 return c;
209 if (yyin != stdin)
210 fclose(yyin);
211 yyin = NULL;
212 curpfile++;
213 }
214}
215
216char *cursource(void) /* current source file name */
217{
218 if (npfile > 0)
219 return pfile[curpfile];
220 else
221 return NULL;
222}