blob: 986f1a386ad16ef7e916fc6e18076fd62dbca8d3 [file] [log] [blame]
Brian Kernighan87b94932012-12-22 10:35:39 -05001/****************************************************************
2Copyright (C) Lucent Technologies 1997
3All Rights Reserved
4
5Permission to use, copy, modify, and distribute this software and
6its documentation for any purpose and without fee is hereby
7granted, provided that the above copyright notice appear in all
8copies and that both that the copyright notice and this
9permission notice and warranty disclaimer appear in supporting
10documentation, and that the name Lucent Technologies or any of
11its entities not be used in advertising or publicity pertaining
12to distribution of the software without specific, written prior
13permission.
14
15LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22THIS SOFTWARE.
23****************************************************************/
24
Miguel Pineiro Jr99f6a432021-12-08 21:37:28 -050025const char *version = "version 20211208";
Brian Kernighan87b94932012-12-22 10:35:39 -050026
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"
Brian Kernighan87b94932012-12-22 10:35:39 -050035
36extern char **environ;
37extern int nfields;
38
39int dbg = 0;
40Awkfloat srand_seed = 1;
41char *cmdname; /* gets argv[0] for error messages */
42extern FILE *yyin; /* lex input file */
43char *lexprog; /* points to program argument if it exists */
44extern int errorflag; /* non-zero if any syntax errors; set by yyerror */
Arnold D. Robbins108224b2019-11-10 21:19:18 +020045enum compile_states compile_time = ERROR_PRINTING;
Brian Kernighan87b94932012-12-22 10:35:39 -050046
zoulasc94e4c042020-02-18 14:20:27 -050047static char **pfile; /* program filenames from -f's */
48static size_t maxpfile; /* max program filename */
49static size_t npfile; /* number of filenames */
50static size_t curpfile; /* current filename */
Brian Kernighan87b94932012-12-22 10:35:39 -050051
Arnold D. Robbins108224b2019-11-10 21:19:18 +020052bool safe = false; /* true => "safe" mode */
Brian Kernighan87b94932012-12-22 10:35:39 -050053
awkfan77bb538fe2020-04-05 19:10:52 +010054static noreturn void fpecatch(int n
zoulasc94e4c042020-02-18 14:20:27 -050055#ifdef SA_SIGINFO
56 , siginfo_t *si, void *uc
57#endif
58)
Arnold D. Robbinsed6ff8c2020-02-18 21:26:24 +020059{
zoulasc94e4c042020-02-18 14:20:27 -050060#ifdef SA_SIGINFO
61 static const char *emsg[] = {
Arnold D. Robbinsed6ff8c2020-02-18 21:26:24 +020062 [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",
zoulasc94e4c042020-02-18 14:20:27 -050071 };
72#endif
73 FATAL("floating point exception"
74#ifdef SA_SIGINFO
Arnold D. Robbinsed6ff8c2020-02-18 21:26:24 +020075 ": %s", (size_t)si->si_code < sizeof(emsg) / sizeof(emsg[0]) &&
76 emsg[si->si_code] ? emsg[si->si_code] : emsg[0]
zoulasc94e4c042020-02-18 14:20:27 -050077#endif
78 );
79}
80
Brian Kernighan3ed9e242018-08-15 10:45:03 -040081/* Can this work with recursive calls? I don't think so.
82void segvcatch(int n)
83{
84 FATAL("segfault. Do you have an unbounded recursive call?", n);
85}
86*/
87
zoulasc94e4c042020-02-18 14:20:27 -050088static const char *
89setfs(char *p)
90{
91 /* wart: t=>\t */
92 if (p[0] == 't' && p[1] == '\0')
93 return "\t";
Warner Losh45dab2a2021-07-19 22:47:30 -060094 return p;
zoulasc94e4c042020-02-18 14:20:27 -050095}
96
97static char *
98getarg(int *argc, char ***argv, const char *msg)
99{
100 if ((*argv)[1][2] != '\0') { /* arg is -fsomething */
101 return &(*argv)[1][2];
102 } else { /* arg is -f something */
103 (*argc)--; (*argv)++;
104 if (*argc <= 1)
105 FATAL("%s", msg);
106 return (*argv)[1];
107 }
108}
109
Brian Kernighan87b94932012-12-22 10:35:39 -0500110int main(int argc, char *argv[])
111{
112 const char *fs = NULL;
zoulasc94e4c042020-02-18 14:20:27 -0500113 char *fn, *vn;
Brian Kernighan87b94932012-12-22 10:35:39 -0500114
115 setlocale(LC_CTYPE, "");
116 setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
117 cmdname = argv[0];
118 if (argc == 1) {
Arnold D. Robbins795a06b2019-07-28 05:51:52 -0600119 fprintf(stderr,
120 "usage: %s [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]\n",
Brian Kernighan87b94932012-12-22 10:35:39 -0500121 cmdname);
122 exit(1);
123 }
zoulasc94e4c042020-02-18 14:20:27 -0500124#ifdef SA_SIGINFO
125 {
126 struct sigaction sa;
127 sa.sa_sigaction = fpecatch;
128 sa.sa_flags = SA_SIGINFO;
129 sigemptyset(&sa.sa_mask);
130 (void)sigaction(SIGFPE, &sa, NULL);
131 }
132#else
133 (void)signal(SIGFPE, fpecatch);
134#endif
Brian Kernighan3ed9e242018-08-15 10:45:03 -0400135 /*signal(SIGSEGV, segvcatch); experiment */
Brian Kernighan87b94932012-12-22 10:35:39 -0500136
zoulasc94e4c042020-02-18 14:20:27 -0500137 /* Set and keep track of the random seed */
Brian Kernighan87b94932012-12-22 10:35:39 -0500138 srand_seed = 1;
pfgc70b9fe2014-09-19 18:24:02 +0000139 srandom((unsigned long) srand_seed);
Brian Kernighan87b94932012-12-22 10:35:39 -0500140
141 yyin = NULL;
142 symtab = makesymtab(NSYMTAB/NSYMTAB);
143 while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
Arnold D. Robbinsed6ff8c2020-02-18 21:26:24 +0200144 if (strcmp(argv[1], "-version") == 0 || strcmp(argv[1], "--version") == 0) {
Brian Kernighan87b94932012-12-22 10:35:39 -0500145 printf("awk %s\n", version);
zoulasc94e4c042020-02-18 14:20:27 -0500146 return 0;
Brian Kernighan87b94932012-12-22 10:35:39 -0500147 }
Cody Peter Mello9b093ea2018-10-09 11:46:57 -0700148 if (strcmp(argv[1], "--") == 0) { /* explicit end of args */
Brian Kernighan87b94932012-12-22 10:35:39 -0500149 argc--;
150 argv++;
151 break;
152 }
153 switch (argv[1][1]) {
154 case 's':
155 if (strcmp(argv[1], "-safe") == 0)
Arnold D. Robbins108224b2019-11-10 21:19:18 +0200156 safe = true;
Brian Kernighan87b94932012-12-22 10:35:39 -0500157 break;
158 case 'f': /* next argument is program filename */
zoulasc94e4c042020-02-18 14:20:27 -0500159 fn = getarg(&argc, &argv, "no program filename");
160 if (npfile >= maxpfile) {
161 maxpfile += 20;
Arnold D. Robbins3b42cfa2020-10-13 20:52:43 +0300162 pfile = (char **) realloc(pfile, maxpfile * sizeof(*pfile));
zoulasc94e4c042020-02-18 14:20:27 -0500163 if (pfile == NULL)
Arnold D. Robbinsed6ff8c2020-02-18 21:26:24 +0200164 FATAL("error allocating space for -f options");
zoulasc94e4c042020-02-18 14:20:27 -0500165 }
166 pfile[npfile++] = fn;
167 break;
Brian Kernighan87b94932012-12-22 10:35:39 -0500168 case 'F': /* set field separator */
zoulasc94e4c042020-02-18 14:20:27 -0500169 fs = setfs(getarg(&argc, &argv, "no field separator"));
Brian Kernighan87b94932012-12-22 10:35:39 -0500170 break;
171 case 'v': /* -v a=1 to be done NOW. one -v for each */
zoulasc94e4c042020-02-18 14:20:27 -0500172 vn = getarg(&argc, &argv, "no variable name");
173 if (isclvar(vn))
174 setclvar(vn);
175 else
176 FATAL("invalid -v option argument: %s", vn);
Brian Kernighan87b94932012-12-22 10:35:39 -0500177 break;
178 case 'd':
179 dbg = atoi(&argv[1][2]);
180 if (dbg == 0)
181 dbg = 1;
182 printf("awk %s\n", version);
183 break;
184 default:
185 WARNING("unknown option %s ignored", argv[1]);
186 break;
187 }
188 argc--;
189 argv++;
190 }
191 /* argv[1] is now the first argument */
192 if (npfile == 0) { /* no -f; first argument is program */
193 if (argc <= 1) {
194 if (dbg)
195 exit(0);
196 FATAL("no program given");
197 }
Todd C. Miller292d39f2020-06-25 12:32:34 -0600198 DPRINTF("program = |%s|\n", argv[1]);
Brian Kernighan87b94932012-12-22 10:35:39 -0500199 lexprog = argv[1];
200 argc--;
201 argv++;
202 }
203 recinit(recsize);
204 syminit();
Arnold D. Robbins108224b2019-11-10 21:19:18 +0200205 compile_time = COMPILING;
Brian Kernighan87b94932012-12-22 10:35:39 -0500206 argv[0] = cmdname; /* put prog name at front of arglist */
Todd C. Miller292d39f2020-06-25 12:32:34 -0600207 DPRINTF("argc=%d, argv[0]=%s\n", argc, argv[0]);
Brian Kernighan87b94932012-12-22 10:35:39 -0500208 arginit(argc, argv);
209 if (!safe)
210 envinit(environ);
211 yyparse();
Arnold D. Robbins2017c2e2020-02-28 13:47:42 +0200212#if 0
213 // Doing this would comply with POSIX, but is not compatible with
214 // other awks and with what most users expect. So comment it out.
215 setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
216#endif
Brian Kernighan87b94932012-12-22 10:35:39 -0500217 if (fs)
218 *FS = qstring(fs, '\0');
Todd C. Miller292d39f2020-06-25 12:32:34 -0600219 DPRINTF("errorflag=%d\n", errorflag);
Brian Kernighan87b94932012-12-22 10:35:39 -0500220 if (errorflag == 0) {
Arnold D. Robbins108224b2019-11-10 21:19:18 +0200221 compile_time = RUNNING;
Brian Kernighan87b94932012-12-22 10:35:39 -0500222 run(winner);
223 } else
224 bracecheck();
225 return(errorflag);
226}
227
228int pgetc(void) /* get 1 character from awk program */
229{
230 int c;
231
232 for (;;) {
233 if (yyin == NULL) {
234 if (curpfile >= npfile)
235 return EOF;
236 if (strcmp(pfile[curpfile], "-") == 0)
237 yyin = stdin;
238 else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
239 FATAL("can't open file %s", pfile[curpfile]);
240 lineno = 1;
241 }
242 if ((c = getc(yyin)) != EOF)
243 return c;
244 if (yyin != stdin)
245 fclose(yyin);
246 yyin = NULL;
247 curpfile++;
248 }
249}
250
251char *cursource(void) /* current source file name */
252{
253 if (npfile > 0)
Todd C. Miller453ce862020-07-29 12:31:29 -0600254 return pfile[curpfile < npfile ? curpfile : curpfile - 1];
Brian Kernighan87b94932012-12-22 10:35:39 -0500255 else
256 return NULL;
257}