]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/one-true-awk/main.c
Rename smmu pmap functions
[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 const char      *version = "version 20210724";
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
36 extern  char    **environ;
37 extern  int     nfields;
38
39 int     dbg     = 0;
40 Awkfloat        srand_seed = 1;
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 enum compile_states     compile_time = ERROR_PRINTING;
46
47 static char     **pfile;        /* program filenames from -f's */
48 static size_t   maxpfile;       /* max program filename */
49 static size_t   npfile;         /* number of filenames */
50 static size_t   curpfile;       /* current filename */
51
52 bool    safe = false;   /* true => "safe" mode */
53
54 static noreturn void fpecatch(int n
55 #ifdef SA_SIGINFO
56         , siginfo_t *si, void *uc
57 #endif
58 )
59 {
60 #ifdef SA_SIGINFO
61         static const char *emsg[] = {
62                 [0] = "Unknown error",
63                 [FPE_INTDIV] = "Integer divide by zero",
64                 [FPE_INTOVF] = "Integer overflow",
65                 [FPE_FLTDIV] = "Floating point divide by zero",
66                 [FPE_FLTOVF] = "Floating point overflow",
67                 [FPE_FLTUND] = "Floating point underflow",
68                 [FPE_FLTRES] = "Floating point inexact result",
69                 [FPE_FLTINV] = "Invalid Floating point operation",
70                 [FPE_FLTSUB] = "Subscript out of range",
71         };
72 #endif
73         FATAL("floating point exception"
74 #ifdef SA_SIGINFO
75                 ": %s", (size_t)si->si_code < sizeof(emsg) / sizeof(emsg[0]) &&
76                 emsg[si->si_code] ? emsg[si->si_code] : emsg[0]
77 #endif
78             );
79 }
80
81 /* Can this work with recursive calls?  I don't think so.
82 void segvcatch(int n)
83 {
84         FATAL("segfault.  Do you have an unbounded recursive call?", n);
85 }
86 */
87
88 static const char *
89 setfs(char *p)
90 {
91         /* wart: t=>\t */
92         if (p[0] == 't' && p[1] == '\0') {
93                 WARNING("-Ft to imply tab separator is deprecated behavior.");
94                 return "\t";
95         }
96         return p;
97 }
98
99 static char *
100 getarg(int *argc, char ***argv, const char *msg)
101 {
102         if ((*argv)[1][2] != '\0') {    /* arg is -fsomething */
103                 return &(*argv)[1][2];
104         } else {                        /* arg is -f something */
105                 (*argc)--; (*argv)++;
106                 if (*argc <= 1)
107                         FATAL("%s", msg);
108                 return (*argv)[1];
109         }
110 }
111
112 int main(int argc, char *argv[])
113 {
114         const char *fs = NULL;
115         char *fn, *vn;
116
117         setlocale(LC_CTYPE, "");
118         setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
119         cmdname = argv[0];
120         if (argc == 1) {
121                 fprintf(stderr,
122                   "usage: %s [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]\n",
123                   cmdname);
124                 exit(1);
125         }
126 #ifdef SA_SIGINFO
127         {
128                 struct sigaction sa;
129                 sa.sa_sigaction = fpecatch;
130                 sa.sa_flags = SA_SIGINFO;
131                 sigemptyset(&sa.sa_mask);
132                 (void)sigaction(SIGFPE, &sa, NULL);
133         }
134 #else
135         (void)signal(SIGFPE, fpecatch);
136 #endif
137         /*signal(SIGSEGV, segvcatch); experiment */
138
139         /* Set and keep track of the random seed */
140         srand_seed = 1;
141         srandom((unsigned long) srand_seed);
142
143         yyin = NULL;
144         symtab = makesymtab(NSYMTAB/NSYMTAB);
145         while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
146                 if (strcmp(argv[1], "-version") == 0 || strcmp(argv[1], "--version") == 0) {
147                         printf("awk %s\n", version);
148                         return 0;
149                 }
150                 if (strcmp(argv[1], "--") == 0) {       /* explicit end of args */
151                         argc--;
152                         argv++;
153                         break;
154                 }
155                 switch (argv[1][1]) {
156                 case 's':
157                         if (strcmp(argv[1], "-safe") == 0)
158                                 safe = true;
159                         break;
160                 case 'f':       /* next argument is program filename */
161                         fn = getarg(&argc, &argv, "no program filename");
162                         if (npfile >= maxpfile) {
163                                 maxpfile += 20;
164                                 pfile = (char **) realloc(pfile, maxpfile * sizeof(*pfile));
165                                 if (pfile == NULL)
166                                         FATAL("error allocating space for -f options");
167                         }
168                         pfile[npfile++] = fn;
169                         break;
170                 case 'F':       /* set field separator */
171                         fs = setfs(getarg(&argc, &argv, "no field separator"));
172                         break;
173                 case 'v':       /* -v a=1 to be done NOW.  one -v for each */
174                         vn = getarg(&argc, &argv, "no variable name");
175                         if (isclvar(vn))
176                                 setclvar(vn);
177                         else
178                                 FATAL("invalid -v option argument: %s", vn);
179                         break;
180                 case 'd':
181                         dbg = atoi(&argv[1][2]);
182                         if (dbg == 0)
183                                 dbg = 1;
184                         printf("awk %s\n", version);
185                         break;
186                 default:
187                         WARNING("unknown option %s ignored", argv[1]);
188                         break;
189                 }
190                 argc--;
191                 argv++;
192         }
193         /* argv[1] is now the first argument */
194         if (npfile == 0) {      /* no -f; first argument is program */
195                 if (argc <= 1) {
196                         if (dbg)
197                                 exit(0);
198                         FATAL("no program given");
199                 }
200                 DPRINTF("program = |%s|\n", argv[1]);
201                 lexprog = argv[1];
202                 argc--;
203                 argv++;
204         }
205         recinit(recsize);
206         syminit();
207         compile_time = COMPILING;
208         argv[0] = cmdname;      /* put prog name at front of arglist */
209         DPRINTF("argc=%d, argv[0]=%s\n", argc, argv[0]);
210         arginit(argc, argv);
211         if (!safe)
212                 envinit(environ);
213         yyparse();
214 #if 0
215         // Doing this would comply with POSIX, but is not compatible with
216         // other awks and with what most users expect. So comment it out.
217         setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
218 #endif
219         if (fs)
220                 *FS = qstring(fs, '\0');
221         DPRINTF("errorflag=%d\n", errorflag);
222         if (errorflag == 0) {
223                 compile_time = RUNNING;
224                 run(winner);
225         } else
226                 bracecheck();
227         return(errorflag);
228 }
229
230 int pgetc(void)         /* get 1 character from awk program */
231 {
232         int c;
233
234         for (;;) {
235                 if (yyin == NULL) {
236                         if (curpfile >= npfile)
237                                 return EOF;
238                         if (strcmp(pfile[curpfile], "-") == 0)
239                                 yyin = stdin;
240                         else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
241                                 FATAL("can't open file %s", pfile[curpfile]);
242                         lineno = 1;
243                 }
244                 if ((c = getc(yyin)) != EOF)
245                         return c;
246                 if (yyin != stdin)
247                         fclose(yyin);
248                 yyin = NULL;
249                 curpfile++;
250         }
251 }
252
253 char *cursource(void)   /* current source file name */
254 {
255         if (npfile > 0)
256                 return pfile[curpfile < npfile ? curpfile : curpfile - 1];
257         else
258                 return NULL;
259 }