1 /****************************************************************
2 Copyright (C) Lucent Technologies 1997
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
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
23 ****************************************************************/
25 const char *version = "version 20210215";
36 extern char **environ;
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;
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 */
52 bool safe = false; /* true => "safe" mode */
54 static noreturn void fpecatch(int n
56 , siginfo_t *si, void *uc
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",
73 FATAL("floating point exception"
75 ": %s", (size_t)si->si_code < sizeof(emsg) / sizeof(emsg[0]) &&
76 emsg[si->si_code] ? emsg[si->si_code] : emsg[0]
81 /* Can this work with recursive calls? I don't think so.
84 FATAL("segfault. Do you have an unbounded recursive call?", n);
92 if (p[0] == 't' && p[1] == '\0')
98 getarg(int *argc, char ***argv, const char *msg)
100 if ((*argv)[1][2] != '\0') { /* arg is -fsomething */
101 return &(*argv)[1][2];
102 } else { /* arg is -f something */
103 (*argc)--; (*argv)++;
110 int main(int argc, char *argv[])
112 const char *fs = NULL;
115 setlocale(LC_CTYPE, "");
116 setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
120 "usage: %s [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]\n",
127 sa.sa_sigaction = fpecatch;
128 sa.sa_flags = SA_SIGINFO;
129 sigemptyset(&sa.sa_mask);
130 (void)sigaction(SIGFPE, &sa, NULL);
133 (void)signal(SIGFPE, fpecatch);
135 /*signal(SIGSEGV, segvcatch); experiment */
137 /* Set and keep track of the random seed */
139 srandom((unsigned long) srand_seed);
142 symtab = makesymtab(NSYMTAB/NSYMTAB);
143 while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
144 if (strcmp(argv[1], "-version") == 0 || strcmp(argv[1], "--version") == 0) {
145 printf("awk %s\n", version);
148 if (strcmp(argv[1], "--") == 0) { /* explicit end of args */
153 switch (argv[1][1]) {
155 if (strcmp(argv[1], "-safe") == 0)
158 case 'f': /* next argument is program filename */
159 fn = getarg(&argc, &argv, "no program filename");
160 if (npfile >= maxpfile) {
162 pfile = (char **) realloc(pfile, maxpfile * sizeof(*pfile));
164 FATAL("error allocating space for -f options");
166 pfile[npfile++] = fn;
168 case 'F': /* set field separator */
169 fs = setfs(getarg(&argc, &argv, "no field separator"));
171 case 'v': /* -v a=1 to be done NOW. one -v for each */
172 vn = getarg(&argc, &argv, "no variable name");
176 FATAL("invalid -v option argument: %s", vn);
179 dbg = atoi(&argv[1][2]);
182 printf("awk %s\n", version);
185 WARNING("unknown option %s ignored", argv[1]);
191 /* argv[1] is now the first argument */
192 if (npfile == 0) { /* no -f; first argument is program */
196 FATAL("no program given");
198 DPRINTF("program = |%s|\n", argv[1]);
205 compile_time = COMPILING;
206 argv[0] = cmdname; /* put prog name at front of arglist */
207 DPRINTF("argc=%d, argv[0]=%s\n", argc, argv[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 */
218 *FS = qstring(fs, '\0');
219 DPRINTF("errorflag=%d\n", errorflag);
220 if (errorflag == 0) {
221 compile_time = RUNNING;
228 int pgetc(void) /* get 1 character from awk program */
234 if (curpfile >= npfile)
236 if (strcmp(pfile[curpfile], "-") == 0)
238 else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
239 FATAL("can't open file %s", pfile[curpfile]);
242 if ((c = getc(yyin)) != EOF)
251 char *cursource(void) /* current source file name */
254 return pfile[curpfile < npfile ? curpfile : curpfile - 1];