The base/count bounds checking was insufficient, leading to a kernel memory
[dragonfly.git] / contrib / one-true-awk / main.c
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 char    *version = "version 20020210";
26
27 #define DEBUG
28 #include <stdio.h>
29 #include <ctype.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <signal.h>
33 #include "awk.h"
34 #include "ytab.h"
35
36 extern  char    **environ;
37 extern  int     nfields;
38
39 int     dbg     = 0;
40 char    *cmdname;       /* gets argv[0] for error messages */
41 extern  FILE    *yyin;  /* lex input file */
42 char    *lexprog;       /* points to program argument if it exists */
43 extern  int errorflag;  /* non-zero if any syntax errors; set by yyerror */
44 int     compile_time = 2;       /* for error printing: */
45                                 /* 2 = cmdline, 1 = compile, 0 = running */
46
47 char    *pfile[20];     /* program filenames from -f's */
48 int     npfile = 0;     /* number of filenames */
49 int     curpfile = 0;   /* current filename */
50
51 int     safe    = 0;    /* 1 => "safe" mode */
52
53 int main(int argc, char *argv[])
54 {
55         char *fs = NULL;
56
57         cmdname = argv[0];
58         if (argc == 1) {
59                 fprintf(stderr, "Usage: %s [-f programfile | 'program'] [-Ffieldsep] [-v var=value] [files]\n", cmdname);
60                 exit(1);
61         }
62         signal(SIGFPE, fpecatch);
63         yyin = NULL;
64         symtab = makesymtab(NSYMTAB);
65         while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
66                 if (strcmp(argv[1], "--") == 0) {       /* explicit end of args */
67                         argc--;
68                         argv++;
69                         break;
70                 }
71                 switch (argv[1][1]) {
72                 case 's':
73                         if (strcmp(argv[1], "-safe") == 0)
74                                 safe = 1;
75                         break;
76                 case 'f':       /* next argument is program filename */
77                         argc--;
78                         argv++;
79                         if (argc <= 1)
80                                 FATAL("no program filename");
81                         pfile[npfile++] = argv[1];
82                         break;
83                 case 'F':       /* set field separator */
84                         if (argv[1][2] != 0) {  /* arg is -Fsomething */
85                                 if (argv[1][2] == 't' && argv[1][3] == 0)       /* wart: t=>\t */
86                                         fs = "\t";
87                                 else if (argv[1][2] != 0)
88                                         fs = &argv[1][2];
89                         } else {                /* arg is -F something */
90                                 argc--; argv++;
91                                 if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0)   /* wart: t=>\t */
92                                         fs = "\t";
93                                 else if (argc > 1 && argv[1][0] != 0)
94                                         fs = &argv[1][0];
95                         }
96                         if (fs == NULL || *fs == '\0')
97                                 WARNING("field separator FS is empty");
98                         break;
99                 case 'v':       /* -v a=1 to be done NOW.  one -v for each */
100                         if (argv[1][2] == '\0' && --argc > 1 && isclvar((++argv)[1]))
101                                 setclvar(argv[1]);
102                         break;
103                 case 'm':       /* more memory: -mr=record, -mf=fields */
104                                 /* no longer supported */
105                         WARNING("obsolete option %s ignored", argv[1]);
106                         break;
107                 case 'd':
108                         dbg = atoi(&argv[1][2]);
109                         if (dbg == 0)
110                                 dbg = 1;
111                         printf("awk %s\n", version);
112                         break;
113                 case 'V':       /* added for exptools "standard" */
114                         printf("awk %s\n", version);
115                         exit(0);
116                         break;
117                 default:
118                         WARNING("unknown option %s ignored", argv[1]);
119                         break;
120                 }
121                 argc--;
122                 argv++;
123         }
124         /* argv[1] is now the first argument */
125         if (npfile == 0) {      /* no -f; first argument is program */
126                 if (argc <= 1) {
127                         if (dbg)
128                                 exit(0);
129                         FATAL("no program given");
130                 }
131                    dprintf( ("program = |%s|\n", argv[1]) );
132                 lexprog = argv[1];
133                 argc--;
134                 argv++;
135         }
136         recinit(recsize);
137         syminit();
138         compile_time = 1;
139         argv[0] = cmdname;      /* put prog name at front of arglist */
140            dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
141         arginit(argc, argv);
142         if (!safe)
143                 envinit(environ);
144         yyparse();
145         if (fs)
146                 *FS = qstring(fs, '\0');
147            dprintf( ("errorflag=%d\n", errorflag) );
148         if (errorflag == 0) {
149                 compile_time = 0;
150                 run(winner);
151         } else
152                 bracecheck();
153         return(errorflag);
154 }
155
156 int pgetc(void)         /* get 1 character from awk program */
157 {
158         int c;
159
160         for (;;) {
161                 if (yyin == NULL) {
162                         if (curpfile >= npfile)
163                                 return EOF;
164                         if (strcmp(pfile[curpfile], "-") == 0)
165                                 yyin = stdin;
166                         else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
167                                 FATAL("can't open file %s", pfile[curpfile]);
168                         lineno = 1;
169                 }
170                 if ((c = getc(yyin)) != EOF)
171                         return c;
172                 if (yyin != stdin)
173                         fclose(yyin);
174                 yyin = NULL;
175                 curpfile++;
176         }
177 }
178
179 char *cursource(void)   /* current source file name */
180 {
181         if (npfile > 0)
182                 return pfile[curpfile];
183         else
184                 return NULL;
185 }