]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/one-true-awk/main.c
MFV r357712: file 5.38.
[FreeBSD/FreeBSD.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 #include <sys/cdefs.h>
26 __FBSDID("$FreeBSD$");
27 const char      *version = "version 20190529 (FreeBSD)";
28
29 #define DEBUG
30 #include <stdio.h>
31 #include <ctype.h>
32 #include <locale.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <signal.h>
36 #include "awk.h"
37 #include "ytab.h"
38
39 extern  char    **environ;
40 extern  int     nfields;
41
42 int     dbg     = 0;
43 Awkfloat        srand_seed = 1;
44 char    *cmdname;       /* gets argv[0] for error messages */
45 extern  FILE    *yyin;  /* lex input file */
46 char    *lexprog;       /* points to program argument if it exists */
47 extern  int errorflag;  /* non-zero if any syntax errors; set by yyerror */
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
59 /* Can this work with recursive calls?  I don't think so.
60 void segvcatch(int n)
61 {
62         FATAL("segfault.  Do you have an unbounded recursive call?", n);
63 }
64 */
65
66 int main(int argc, char *argv[])
67 {
68         const char *fs = NULL;
69
70         setlocale(LC_CTYPE, "");
71         setlocale(LC_COLLATE, "");
72         setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
73         cmdname = argv[0];
74         if (argc == 1) {
75                 fprintf(stderr, 
76                   "usage: %s [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]\n", 
77                   cmdname);
78                 exit(1);
79         }
80         signal(SIGFPE, fpecatch);
81         /*signal(SIGSEGV, segvcatch); experiment */
82
83         srand_seed = 1;
84         srandom((unsigned long) srand_seed);
85
86         yyin = NULL;
87         symtab = makesymtab(NSYMTAB/NSYMTAB);
88         while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
89                 if (strcmp(argv[1],"-version") == 0 || strcmp(argv[1],"--version") == 0) {
90                         printf("awk %s\n", version);
91                         exit(0);
92                         break;
93                 }
94                 if (strcmp(argv[1], "--") == 0) {       /* explicit end of args */
95                         argc--;
96                         argv++;
97                         break;
98                 }
99                 switch (argv[1][1]) {
100                 case 's':
101                         if (strcmp(argv[1], "-safe") == 0)
102                                 safe = 1;
103                         break;
104                 case 'f':       /* next argument is program filename */
105                         if (argv[1][2] != 0) {  /* arg is -fsomething */
106                                 if (npfile >= MAX_PFILE - 1)
107                                         FATAL("too many -f options"); 
108                                 pfile[npfile++] = &argv[1][2];
109                         } else {                /* arg is -f something */
110                                 argc--; argv++;
111                                 if (argc <= 1)
112                                         FATAL("no program filename");
113                                 if (npfile >= MAX_PFILE - 1)
114                                         FATAL("too many -f options"); 
115                                 pfile[npfile++] = argv[1];
116                         }
117                         break;
118                 case 'F':       /* set field separator */
119                         if (argv[1][2] != 0) {  /* arg is -Fsomething */
120                                 if (argv[1][2] == 't' && argv[1][3] == 0)       /* wart: t=>\t */
121                                         fs = "\t";
122                                 else if (argv[1][2] != 0)
123                                         fs = &argv[1][2];
124                         } else {                /* arg is -F something */
125                                 argc--; argv++;
126                                 if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0)   /* wart: t=>\t */
127                                         fs = "\t";
128                                 else if (argc > 1 && argv[1][0] != 0)
129                                         fs = &argv[1][0];
130                         }
131                         if (fs == NULL || *fs == '\0')
132                                 WARNING("field separator FS is empty");
133                         break;
134                 case 'v':       /* -v a=1 to be done NOW.  one -v for each */
135                         if (argv[1][2] != 0) {  /* arg is -vsomething */
136                                 if (isclvar(&argv[1][2]))
137                                         setclvar(&argv[1][2]);
138                                 else
139                                         FATAL("invalid -v option argument: %s", &argv[1][2]);
140                         } else {                /* arg is -v something */
141                                 argc--; argv++;
142                                 if (argc <= 1)
143                                         FATAL("no variable name");
144                                 if (isclvar(argv[1]))
145                                         setclvar(argv[1]);
146                                 else
147                                         FATAL("invalid -v option argument: %s", argv[1]);
148                         }
149                         break;
150                 case 'd':
151                         dbg = atoi(&argv[1][2]);
152                         if (dbg == 0)
153                                 dbg = 1;
154                         printf("awk %s\n", version);
155                         break;
156                 default:
157                         WARNING("unknown option %s ignored", argv[1]);
158                         break;
159                 }
160                 argc--;
161                 argv++;
162         }
163         /* argv[1] is now the first argument */
164         if (npfile == 0) {      /* no -f; first argument is program */
165                 if (argc <= 1) {
166                         if (dbg)
167                                 exit(0);
168                         FATAL("no program given");
169                 }
170                    dprintf( ("program = |%s|\n", argv[1]) );
171                 lexprog = argv[1];
172                 argc--;
173                 argv++;
174         }
175         recinit(recsize);
176         syminit();
177         compile_time = 1;
178         argv[0] = cmdname;      /* put prog name at front of arglist */
179            dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
180         arginit(argc, argv);
181         if (!safe)
182                 envinit(environ);
183         yyparse();
184         setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
185         if (fs)
186                 *FS = qstring(fs, '\0');
187            dprintf( ("errorflag=%d\n", errorflag) );
188         if (errorflag == 0) {
189                 compile_time = 0;
190                 run(winner);
191         } else
192                 bracecheck();
193         return(errorflag);
194 }
195
196 int pgetc(void)         /* get 1 character from awk program */
197 {
198         int c;
199
200         for (;;) {
201                 if (yyin == NULL) {
202                         if (curpfile >= npfile)
203                                 return EOF;
204                         if (strcmp(pfile[curpfile], "-") == 0)
205                                 yyin = stdin;
206                         else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
207                                 FATAL("can't open file %s", pfile[curpfile]);
208                         lineno = 1;
209                 }
210                 if ((c = getc(yyin)) != EOF)
211                         return c;
212                 if (yyin != stdin)
213                         fclose(yyin);
214                 yyin = NULL;
215                 curpfile++;
216         }
217 }
218
219 char *cursource(void)   /* current source file name */
220 {
221         if (npfile > 0)
222                 return pfile[curpfile];
223         else
224                 return NULL;
225 }