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 20190125";
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 int 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
51 char *pfile[MAX_PFILE]; /* program filenames from -f's */
52 int npfile = 0; /* number of filenames */
53 int curpfile = 0; /* current filename */
54
55 int safe = 0; /* 1 => "safe" mode */
56
57 /* Can this work with recursive calls? I don't think so.
58 void segvcatch(int n)
59 {
60 FATAL("segfault. Do you have an unbounded recursive call?", n);
61 }
62 */
63
main(int argc,char * argv[])64 int 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) {
72 fprintf(stderr,
73 "usage: %s [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]\n",
74 cmdname);
75 exit(1);
76 }
77 signal(SIGFPE, fpecatch);
78 /*signal(SIGSEGV, segvcatch); experiment */
79
80 srand_seed = 1;
81 srand(srand_seed);
82
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 }
91 if (strcmp(argv[1], "--") == 0) { /* explicit end of args */
92 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)
104 FATAL("too many -f options");
105 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)
111 FATAL("too many -f options");
112 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
pgetc(void)193 int 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
cursource(void)216 char *cursource(void) /* current source file name */
217 {
218 if (npfile > 0)
219 return pfile[curpfile];
220 else
221 return NULL;
222 }
223