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