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 20200206";
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 Awkfloat srand_seed = 1;
42 char *cmdname; /* gets argv[0] for error messages */
43 extern FILE *yyin; /* lex input file */
44 char *lexprog; /* points to program argument if it exists */
45 extern int errorflag; /* non-zero if any syntax errors; set by yyerror */
46 enum compile_states compile_time = ERROR_PRINTING;
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 bool safe = false; /* true => "safe" mode */
55
56 /* Can this work with recursive calls? I don't think so.
57 void segvcatch(int n)
58 {
59 FATAL("segfault. Do you have an unbounded recursive call?", n);
60 }
61 */
62
main(int argc,char * argv[])63 int 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) {
71 fprintf(stderr,
72 "usage: %s [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]\n",
73 cmdname);
74 exit(1);
75 }
76 signal(SIGFPE, fpecatch);
77 /*signal(SIGSEGV, segvcatch); experiment */
78
79 srand_seed = 1;
80 srandom((unsigned long) srand_seed);
81
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 }
90 if (strcmp(argv[1], "--") == 0) { /* explicit end of args */
91 argc--;
92 argv++;
93 break;
94 }
95 switch (argv[1][1]) {
96 case 's':
97 if (strcmp(argv[1], "-safe") == 0)
98 safe = true;
99 break;
100 case 'f': /* next argument is program filename */
101 if (argv[1][2] != 0) { /* arg is -fsomething */
102 if (npfile >= MAX_PFILE - 1)
103 FATAL("too many -f options");
104 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)
110 FATAL("too many -f options");
111 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();
173 compile_time = COMPILING;
174 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) {
185 compile_time = RUNNING;
186 run(winner);
187 } else
188 bracecheck();
189 return(errorflag);
190 }
191
pgetc(void)192 int 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
cursource(void)215 char *cursource(void) /* current source file name */
216 {
217 if (npfile > 0)
218 return pfile[curpfile];
219 else
220 return NULL;
221 }
222