1 /* $OpenBSD: main.c,v 1.17 2011/09/28 19:27:18 millert Exp $ */
2 /****************************************************************
3 Copyright (C) Lucent Technologies 1997
4 All Rights Reserved
5
6 Permission to use, copy, modify, and distribute this software and
7 its documentation for any purpose and without fee is hereby
8 granted, provided that the above copyright notice appear in all
9 copies and that both that the copyright notice and this
10 permission notice and warranty disclaimer appear in supporting
11 documentation, and that the name Lucent Technologies or any of
12 its entities not be used in advertising or publicity pertaining
13 to distribution of the software without specific, written prior
14 permission.
15
16 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
18 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
19 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
21 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
22 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
23 THIS SOFTWARE.
24 ****************************************************************/
25
26 const char *version = "version 20110810";
27
28 #define DEBUG
29 #include <stdio.h>
30 #include <ctype.h>
31 #include <locale.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <signal.h>
35 #include "awk.h"
36 #include "awkgram.h"
37
38 __RCSID("$MirOS: src/usr.bin/awk/main.c,v 1.5 2014/03/23 20:18:27 tg Exp $");
39
40 extern char **environ;
41 extern int nfields;
42 extern char *__progname;
43
44 int dbg = 0;
45 char *cmdname; /* gets argv[0] for error messages */
46 extern FILE *yyin; /* lex input file */
47 char *lexprog; /* points to program argument if it exists */
48 int compile_time = 2; /* for error printing: */
49 /* 2 = cmdline, 1 = compile, 0 = running */
50
51 #define MAX_PFILE 20 /* max number of -f's */
52
53 char *pfile[MAX_PFILE]; /* program filenames from -f's */
54 int npfile = 0; /* number of filenames */
55 int curpfile = 0; /* current filename */
56
57 int safe = 0; /* 1 => "safe" mode */
58
main(int argc,char * argv[])59 int main(int argc, char *argv[])
60 {
61 const char *fs = NULL;
62
63 #ifndef __MirBSD__
64 setlocale(LC_ALL, "");
65 setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
66 #endif
67 cmdname = __progname;
68 if (argc == 1) {
69 fprintf(stderr, "usage: %s [-safe] [-V] [-d[n]] [-F fs] "
70 "[-v var=value] [prog | -f progfile]\n\tfile ...\n",
71 cmdname);
72 exit(1);
73 }
74 signal(SIGFPE, fpecatch);
75
76 yyin = NULL;
77 symtab = makesymtab(NSYMTAB);
78 while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
79 if (strcmp(argv[1], "--") == 0) { /* explicit end of args */
80 argc--;
81 argv++;
82 break;
83 }
84 switch (argv[1][1]) {
85 case 's':
86 if (strcmp(argv[1], "-safe") == 0)
87 safe = 1;
88 break;
89 case 'f': /* next argument is program filename */
90 if (argv[1][2] != 0) { /* arg is -fsomething */
91 if (npfile >= MAX_PFILE - 1)
92 FATAL("too many -f options");
93 pfile[npfile++] = &argv[1][2];
94 } else { /* arg is -f something */
95 argc--; argv++;
96 if (argc <= 1)
97 FATAL("no program filename");
98 if (npfile >= MAX_PFILE - 1)
99 FATAL("too many -f options");
100 pfile[npfile++] = argv[1];
101 }
102 break;
103 case 'F': /* set field separator */
104 if (argv[1][2] != 0) { /* arg is -Fsomething */
105 if (argv[1][2] == 't' && argv[1][3] == 0) /* wart: t=>\t */
106 fs = "\t";
107 else if (argv[1][2] != 0)
108 fs = &argv[1][2];
109 } else { /* arg is -F something */
110 argc--; argv++;
111 if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0) /* wart: t=>\t */
112 fs = "\t";
113 else if (argc > 1 && argv[1][0] != 0)
114 fs = &argv[1][0];
115 }
116 if (fs == NULL || *fs == '\0')
117 WARNING("field separator FS is empty");
118 break;
119 case 'v': /* -v a=1 to be done NOW. one -v for each */
120 if (argv[1][2] != 0) { /* arg is -vsomething */
121 if (isclvar(&argv[1][2]))
122 setclvar(&argv[1][2]);
123 else
124 FATAL("invalid -v option argument: %s", &argv[1][2]);
125 } else { /* arg is -v something */
126 argc--; argv++;
127 if (argc <= 1)
128 FATAL("no variable name");
129 if (isclvar(argv[1]))
130 setclvar(argv[1]);
131 else
132 FATAL("invalid -v option argument: %s", argv[1]);
133 }
134 break;
135 case 'd':
136 dbg = atoi(&argv[1][2]);
137 if (dbg == 0)
138 dbg = 1;
139 printf("awk %s\n", version);
140 break;
141 case 'V': /* added for exptools "standard" */
142 printf("awk %s\n", version);
143 exit(0);
144 break;
145 default:
146 WARNING("unknown option %s ignored", argv[1]);
147 break;
148 }
149 argc--;
150 argv++;
151 }
152 /* argv[1] is now the first argument */
153 if (npfile == 0) { /* no -f; first argument is program */
154 if (argc <= 1) {
155 if (dbg)
156 exit(0);
157 FATAL("no program given");
158 }
159 dprintf( ("program = |%s|\n", argv[1]) );
160 lexprog = argv[1];
161 argc--;
162 argv++;
163 }
164 recinit(recsize);
165 syminit();
166 compile_time = 1;
167 argv[0] = cmdname; /* put prog name at front of arglist */
168 dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
169 arginit(argc, argv);
170 if (!safe)
171 envinit(environ);
172 yyparse();
173 #ifndef __MirBSD__
174 setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
175 #endif
176 if (fs)
177 *FS = qstring(fs, '\0');
178 dprintf( ("errorflag=%d\n", errorflag) );
179 if (errorflag == 0) {
180 compile_time = 0;
181 run(winner);
182 } else
183 bracecheck();
184 return(errorflag);
185 }
186
pgetc(void)187 int pgetc(void) /* get 1 character from awk program */
188 {
189 int c;
190
191 for (;;) {
192 if (yyin == NULL) {
193 if (curpfile >= npfile)
194 return EOF;
195 if (strcmp(pfile[curpfile], "-") == 0)
196 yyin = stdin;
197 else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
198 FATAL("can't open file %s", pfile[curpfile]);
199 lineno = 1;
200 }
201 if ((c = getc(yyin)) != EOF)
202 return c;
203 if (yyin != stdin)
204 fclose(yyin);
205 yyin = NULL;
206 curpfile++;
207 }
208 }
209
cursource(void)210 char *cursource(void) /* current source file name */
211 {
212 if (npfile > 0)
213 return pfile[curpfile];
214 else
215 return NULL;
216 }
217