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 20100523"; 26 27 #if HAVE_NBTOOL_CONFIG_H 28 #include "nbtool_config.h" 29 #endif 30 31 #define DEBUG 32 #include <stdio.h> 33 #include <ctype.h> 34 #include <locale.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <signal.h> 38 #include "awk.h" 39 #include "awkgram.h" 40 41 extern char **environ; 42 extern int nfields; 43 44 int dbg = 0; 45 char *cmdname; /* gets argv[0] for error messages */ 46 extern FILE *yyin; /* lex input file */ 47 char *lexprog; /* points to program argument if it exists */ 48 extern int errorflag; /* non-zero if any syntax errors; set by yyerror */ 49 int compile_time = 2; /* for error printing: */ 50 /* 2 = cmdline, 1 = compile, 0 = running */ 51 52 static char **pfile = NULL; /* program filenames from -f's */ 53 static size_t maxpfile = 0; /* max program filenames */ 54 static size_t npfile = 0; /* number of filenames */ 55 static size_t curpfile = 0; /* current filename */ 56 57 int safe = 0; /* 1 => "safe" mode */ 58 59 static char * 60 setfs(char *p) 61 { 62 #ifdef notdef 63 /* wart: t=>\t */ 64 if (p[0] == 't' && p[1] == 0) 65 return "\t"; 66 else 67 #endif 68 if (p[0] != 0) 69 return p; 70 return NULL; 71 } 72 73 static void fpecatch(int n 74 #ifdef SA_SIGINFO 75 , siginfo_t *si, void *uc 76 #endif 77 ) 78 { 79 #ifdef SA_SIGINFO 80 static const char *emsg[] = { 81 "Unknown error", 82 "Integer divide by zero", 83 "Integer overflow", 84 "Floating point divide by zero", 85 "Floating point overflow", 86 "Floating point underflow", 87 "Floating point inexact result", 88 "Invalid Floating point operation", 89 "Subscript out of range", 90 }; 91 #endif 92 FATAL("floating point exception" 93 #ifdef SA_SIGINFO 94 ": %s\n", emsg[si->si_code >= 1 && si->si_code <= 8 ? 95 si->si_code : 0] 96 #endif 97 ); 98 } 99 100 int main(int argc, char *argv[]) 101 { 102 const char *fs = NULL; 103 104 setlocale(LC_ALL, ""); 105 setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */ 106 cmdname = argv[0]; 107 if (argc == 1) { 108 fprintf(stderr, 109 "usage: %s [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]\n", 110 cmdname); 111 exit(1); 112 } 113 114 #ifdef SA_SIGINFO 115 { 116 struct sigaction sa; 117 sa.sa_sigaction = fpecatch; 118 sa.sa_flags = SA_SIGINFO; 119 sigemptyset(&sa.sa_mask); 120 (void)sigaction(SIGFPE, &sa, NULL); 121 } 122 #else 123 (void)signal(SIGFPE, fpecatch); 124 #endif 125 yyin = NULL; 126 symtab = makesymtab(NSYMTAB/NSYMTAB); 127 while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') { 128 if (strcmp(argv[1],"-version") == 0 || strcmp(argv[1],"--version") == 0) { 129 printf("awk %s\n", version); 130 exit(0); 131 break; 132 } 133 if (strncmp(argv[1], "--", 2) == 0) { /* explicit end of args */ 134 argc--; 135 argv++; 136 break; 137 } 138 switch (argv[1][1]) { 139 case 's': 140 if (strcmp(argv[1], "-safe") == 0) 141 safe = 1; 142 break; 143 case 'f': /* next argument is program filename */ 144 argc--; 145 argv++; 146 if (argc <= 1) 147 FATAL("no program filename"); 148 if (npfile >= maxpfile) { 149 maxpfile += 20; 150 pfile = realloc(pfile, 151 maxpfile * sizeof(*pfile)); 152 if (pfile == NULL) 153 FATAL("error allocating space for " 154 "-f options"); 155 } 156 pfile[npfile++] = argv[1]; 157 break; 158 case 'F': /* set field separator */ 159 if (argv[1][2] != 0) { /* arg is -Fsomething */ 160 fs = setfs(argv[1] + 2); 161 } else { /* arg is -F something */ 162 argc--; argv++; 163 if (argc > 1) 164 fs = setfs(argv[1]); 165 } 166 if (fs == NULL || *fs == '\0') 167 WARNING("field separator FS is empty"); 168 break; 169 case 'v': /* -v a=1 to be done NOW. one -v for each */ 170 if (argv[1][2] == '\0' && --argc > 1 && isclvar((++argv)[1])) 171 setclvar(argv[1]); 172 else if (argv[1][2] != '\0') 173 setclvar(&argv[1][2]); 174 break; 175 case 'd': 176 dbg = atoi(&argv[1][2]); 177 if (dbg == 0) 178 dbg = 1; 179 printf("awk %s\n", version); 180 break; 181 default: 182 WARNING("unknown option %s ignored", argv[1]); 183 break; 184 } 185 argc--; 186 argv++; 187 } 188 /* argv[1] is now the first argument */ 189 if (npfile == 0) { /* no -f; first argument is program */ 190 if (argc <= 1) { 191 if (dbg) 192 exit(0); 193 FATAL("no program given"); 194 } 195 dprintf( ("program = |%s|\n", argv[1]) ); 196 lexprog = argv[1]; 197 argc--; 198 argv++; 199 } 200 recinit(recsize); 201 syminit(); 202 compile_time = 1; 203 argv[0] = cmdname; /* put prog name at front of arglist */ 204 dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) ); 205 arginit(argc, argv); 206 if (!safe) 207 envinit(environ); 208 yyparse(); 209 setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */ 210 if (fs) 211 *FS = qstring(fs, '\0'); 212 dprintf( ("errorflag=%d\n", errorflag) ); 213 if (errorflag == 0) { 214 compile_time = 0; 215 run(winner); 216 } else 217 bracecheck(); 218 return(errorflag); 219 } 220 221 int pgetc(void) /* get 1 character from awk program */ 222 { 223 int c; 224 225 for (;;) { 226 if (yyin == NULL) { 227 if (curpfile >= npfile) 228 return EOF; 229 if (strcmp(pfile[curpfile], "-") == 0) 230 yyin = stdin; 231 else if ((yyin = fopen(pfile[curpfile], "r")) == NULL) 232 FATAL("can't open file %s", pfile[curpfile]); 233 lineno = 1; 234 } 235 if ((c = getc(yyin)) != EOF) 236 return c; 237 if (yyin != stdin) 238 fclose(yyin); 239 yyin = NULL; 240 curpfile++; 241 } 242 } 243 244 char *cursource(void) /* current source file name */ 245 { 246 if (npfile > 0) 247 return pfile[curpfile]; 248 else 249 return NULL; 250 } 251