Import awk-20110506.
[dragonfly.git] / contrib / 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 const char      *version = "version 20110506";
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 int main(int argc, char *argv[])
58 {
59         const char *fs = NULL;
60
61         setlocale(LC_CTYPE, "");
62         setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
63         cmdname = argv[0];
64         if (argc == 1) {
65                 fprintf(stderr, 
66                   "usage: %s [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]\n", 
67                   cmdname);
68                 exit(1);
69         }
70         signal(SIGFPE, fpecatch);
71
72         srand_seed = 1;
73         srand(srand_seed);
74
75         yyin = NULL;
76         symtab = makesymtab(NSYMTAB/NSYMTAB);
77         while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
78                 if (strcmp(argv[1],"-version") == 0 || strcmp(argv[1],"--version") == 0) {
79                         printf("awk %s\n", version);
80                         exit(0);
81                         break;
82                 }
83                 if (strncmp(argv[1], "--", 2) == 0) {   /* explicit end of args */
84                         argc--;
85                         argv++;
86                         break;
87                 }
88                 switch (argv[1][1]) {
89                 case 's':
90                         if (strcmp(argv[1], "-safe") == 0)
91                                 safe = 1;
92                         break;
93                 case 'f':       /* next argument is program filename */
94                         if (argv[1][2] != 0) {  /* arg is -fsomething */
95                                 if (npfile >= MAX_PFILE - 1)
96                                         FATAL("too many -f options"); 
97                                 pfile[npfile++] = &argv[1][2];
98                         } else {                /* arg is -f something */
99                                 argc--; argv++;
100                                 if (argc <= 1)
101                                         FATAL("no program filename");
102                                 if (npfile >= MAX_PFILE - 1)
103                                         FATAL("too many -f options"); 
104                                 pfile[npfile++] = argv[1];
105                         }
106                         break;
107                 case 'F':       /* set field separator */
108                         if (argv[1][2] != 0) {  /* arg is -Fsomething */
109                                 if (argv[1][2] == 't' && argv[1][3] == 0)       /* wart: t=>\t */
110                                         fs = "\t";
111                                 else if (argv[1][2] != 0)
112                                         fs = &argv[1][2];
113                         } else {                /* arg is -F something */
114                                 argc--; argv++;
115                                 if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0)   /* wart: t=>\t */
116                                         fs = "\t";
117                                 else if (argc > 1 && argv[1][0] != 0)
118                                         fs = &argv[1][0];
119                         }
120                         if (fs == NULL || *fs == '\0')
121                                 WARNING("field separator FS is empty");
122                         break;
123                 case 'v':       /* -v a=1 to be done NOW.  one -v for each */
124                         if (argv[1][2] == '\0' && --argc > 1 && isclvar((++argv)[1]))
125                                 setclvar(argv[1]);
126                         else if (argv[1][2] != '\0')
127                                 setclvar(&argv[1][2]);
128                         break;
129                 case 'd':
130                         dbg = atoi(&argv[1][2]);
131                         if (dbg == 0)
132                                 dbg = 1;
133                         printf("awk %s\n", version);
134                         break;
135                 default:
136                         WARNING("unknown option %s ignored", argv[1]);
137                         break;
138                 }
139                 argc--;
140                 argv++;
141         }
142         /* argv[1] is now the first argument */
143         if (npfile == 0) {      /* no -f; first argument is program */
144                 if (argc <= 1) {
145                         if (dbg)
146                                 exit(0);
147                         FATAL("no program given");
148                 }
149                    dprintf( ("program = |%s|\n", argv[1]) );
150                 lexprog = argv[1];
151                 argc--;
152                 argv++;
153         }
154         recinit(recsize);
155         syminit();
156         compile_time = 1;
157         argv[0] = cmdname;      /* put prog name at front of arglist */
158            dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
159         arginit(argc, argv);
160         if (!safe)
161                 envinit(environ);
162         yyparse();
163         setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
164         if (fs)
165                 *FS = qstring(fs, '\0');
166            dprintf( ("errorflag=%d\n", errorflag) );
167         if (errorflag == 0) {
168                 compile_time = 0;
169                 run(winner);
170         } else
171                 bracecheck();
172         return(errorflag);
173 }
174
175 int pgetc(void)         /* get 1 character from awk program */
176 {
177         int c;
178
179         for (;;) {
180                 if (yyin == NULL) {
181                         if (curpfile >= npfile)
182                                 return EOF;
183                         if (strcmp(pfile[curpfile], "-") == 0)
184                                 yyin = stdin;
185                         else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
186                                 FATAL("can't open file %s", pfile[curpfile]);
187                         lineno = 1;
188                 }
189                 if ((c = getc(yyin)) != EOF)
190                         return c;
191                 if (yyin != stdin)
192                         fclose(yyin);
193                 yyin = NULL;
194                 curpfile++;
195         }
196 }
197
198 char *cursource(void)   /* current source file name */
199 {
200         if (npfile > 0)
201                 return pfile[curpfile];
202         else
203                 return NULL;
204 }