[BACK]Return to main.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / awk

Annotation of src/usr.bin/awk/main.c, Revision 1.62

1.62    ! millert     1: /*     $OpenBSD: main.c,v 1.61 2023/09/18 19:32:19 millert Exp $       */
1.1       tholo       2: /****************************************************************
1.4       kstailey    3: Copyright (C) Lucent Technologies 1997
1.1       tholo       4: All Rights Reserved
                      5:
                      6: Permission to use, copy, modify, and distribute this software and
                      7: its documentation for any purpose and without fee is hereby
                      8: granted, provided that the above copyright notice appear in all
                      9: copies and that both that the copyright notice and this
                     10: permission notice and warranty disclaimer appear in supporting
1.4       kstailey   11: documentation, and that the name Lucent Technologies or any of
                     12: its entities not be used in advertising or publicity pertaining
                     13: to distribution of the software without specific, written prior
                     14: permission.
                     15:
                     16: LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
                     17: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
                     18: IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
                     19: SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     20: WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
                     21: IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
                     22: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
                     23: THIS SOFTWARE.
1.1       tholo      24: ****************************************************************/
                     25:
1.59      millert    26: const char     *version = "version 20230913";
1.1       tholo      27:
                     28: #define DEBUG
                     29: #include <stdio.h>
                     30: #include <ctype.h>
1.3       millert    31: #include <locale.h>
1.1       tholo      32: #include <stdlib.h>
                     33: #include <string.h>
                     34: #include <signal.h>
1.18      doug       35: #include <unistd.h>
1.1       tholo      36: #include "awk.h"
                     37:
                     38: extern char    **environ;
                     39: extern int     nfields;
1.6       millert    40: extern char    *__progname;
1.1       tholo      41:
                     42: int    dbg     = 0;
1.17      millert    43: Awkfloat       srand_seed = 1;
1.1       tholo      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 */
1.34      millert    48: enum compile_states    compile_time = ERROR_PRINTING;
1.1       tholo      49:
1.37      millert    50: static char    **pfile;        /* program filenames from -f's */
                     51: static size_t  maxpfile;       /* max program filename */
                     52: static size_t  npfile;         /* number of filenames */
                     53: static size_t  curpfile;       /* current filename */
1.15      millert    54:
1.59      millert    55: bool   CSV = false;            /* true for csv input */
1.40      millert    56: bool   safe = false;           /* true => "safe" mode */
                     57: bool   do_posix = false;       /* true => POSIX mode */
1.37      millert    58:
1.61      millert    59: size_t awk_mb_cur_max = 1;
                     60:
1.38      millert    61: static noreturn void fpecatch(int n
1.37      millert    62: #ifdef SA_SIGINFO
                     63:        , siginfo_t *si, void *uc
                     64: #endif
                     65: )
                     66: {
                     67:        extern Node *curnode;
                     68: #ifdef SA_SIGINFO
                     69:        static const char *emsg[] = {
                     70:                [0] = "Unknown error",
                     71:                [FPE_INTDIV] = "Integer divide by zero",
                     72:                [FPE_INTOVF] = "Integer overflow",
                     73:                [FPE_FLTDIV] = "Floating point divide by zero",
                     74:                [FPE_FLTOVF] = "Floating point overflow",
                     75:                [FPE_FLTUND] = "Floating point underflow",
                     76:                [FPE_FLTRES] = "Floating point inexact result",
                     77:                [FPE_FLTINV] = "Invalid Floating point operation",
                     78:                [FPE_FLTSUB] = "Subscript out of range",
                     79:        };
                     80: #endif
                     81:        dprintf(STDERR_FILENO, "floating point exception%s%s\n",
                     82: #ifdef SA_SIGINFO
                     83:                ": ", (size_t)si->si_code < sizeof(emsg) / sizeof(emsg[0]) &&
                     84:                emsg[si->si_code] ? emsg[si->si_code] : emsg[0]
                     85: #else
                     86:                "", ""
                     87: #endif
                     88:            );
                     89:
                     90:        if (compile_time != 2 && NR && *NR > 0) {
                     91:                dprintf(STDERR_FILENO, " input record number %d", (int) (*FNR));
                     92:                if (strcmp(*FILENAME, "-") != 0) {
                     93:                        dprintf(STDERR_FILENO, ", file %s", *FILENAME);
                     94:                }
                     95:                dprintf(STDERR_FILENO, "\n");
                     96:        }
                     97:        if (compile_time != 2 && curnode) {
                     98:                dprintf(STDERR_FILENO, " source line number %d", curnode->lineno);
                     99:        } else if (compile_time != 2 && lineno) {
                    100:                dprintf(STDERR_FILENO, " source line number %d", lineno);
                    101:        }
                    102:        if (compile_time == 1 && cursource() != NULL) {
                    103:                dprintf(STDERR_FILENO, " source file %s", cursource());
                    104:        }
                    105:        dprintf(STDERR_FILENO, "\n");
                    106:        if (dbg > 1)            /* core dump if serious debugging on */
                    107:                abort();
                    108:        _exit(2);
                    109: }
1.1       tholo     110:
1.37      millert   111: static const char *
                    112: setfs(char *p)
                    113: {
                    114:        /* wart: t=>\t */
                    115:        if (p[0] == 't' && p[1] == '\0')
                    116:                return "\t";
1.48      millert   117:        return p;
1.37      millert   118: }
                    119:
                    120: static char *
                    121: getarg(int *argc, char ***argv, const char *msg)
                    122: {
                    123:        if ((*argv)[1][2] != '\0') {    /* arg is -fsomething */
                    124:                return &(*argv)[1][2];
                    125:        } else {                        /* arg is -f something */
                    126:                (*argc)--; (*argv)++;
                    127:                if (*argc <= 1)
                    128:                        FATAL("%s", msg);
                    129:                return (*argv)[1];
                    130:        }
                    131: }
1.4       kstailey  132:
1.1       tholo     133: int main(int argc, char *argv[])
                    134: {
1.12      millert   135:        const char *fs = NULL;
1.37      millert   136:        char *fn, *vn;
1.2       tholo     137:
1.39      millert   138:        setlocale(LC_CTYPE, "");
1.19      deraadt   139:        setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
1.61      millert   140:        awk_mb_cur_max = MB_CUR_MAX;
1.19      deraadt   141:
1.20      tb        142:        cmdname = __progname;
1.18      doug      143:        if (pledge("stdio rpath wpath cpath proc exec", NULL) == -1) {
                    144:                fprintf(stderr, "%s: pledge: incorrect arguments\n",
                    145:                    cmdname);
                    146:                exit(1);
                    147:        }
                    148:
1.1       tholo     149:        if (argc == 1) {
1.60      jmc       150:                fprintf(stderr, "usage: %s [-safe] [-V] [-d[n]] "
                    151:                    "[-f fs | --csv] [-v var=value]\n"
                    152:                    "\t   [prog | -f progfile] file ...\n",
1.10      aaron     153:                    cmdname);
1.1       tholo     154:                exit(1);
                    155:        }
1.37      millert   156: #ifdef SA_SIGINFO
                    157:        {
                    158:                struct sigaction sa;
                    159:                sa.sa_sigaction = fpecatch;
                    160:                sa.sa_flags = SA_SIGINFO;
                    161:                sigemptyset(&sa.sa_mask);
                    162:                (void)sigaction(SIGFPE, &sa, NULL);
                    163:        }
                    164: #else
                    165:        (void)signal(SIGFPE, fpecatch);
                    166: #endif
1.40      millert   167:
                    168:        do_posix = (getenv("POSIXLY_CORRECT") != NULL);
1.17      millert   169:
1.1       tholo     170:        yyin = NULL;
                    171:        symtab = makesymtab(NSYMTAB);
                    172:        while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
1.62    ! millert   173:                if (strcmp(argv[1], "--version") == 0) {
        !           174:                        printf("awk %s\n", version);
        !           175:                        return 0;
        !           176:                }
1.4       kstailey  177:                if (strcmp(argv[1], "--") == 0) {       /* explicit end of args */
1.1       tholo     178:                        argc--;
                    179:                        argv++;
                    180:                        break;
                    181:                }
1.59      millert   182:                if (strcmp(argv[1], "--csv") == 0) {    /* turn on csv input processing */
                    183:                        CSV = true;
                    184:                        argc--;
                    185:                        argv++;
                    186:                        continue;
                    187:                }
1.1       tholo     188:                switch (argv[1][1]) {
1.4       kstailey  189:                case 's':
                    190:                        if (strcmp(argv[1], "-safe") == 0)
1.34      millert   191:                                safe = true;
1.4       kstailey  192:                        break;
1.1       tholo     193:                case 'f':       /* next argument is program filename */
1.37      millert   194:                        fn = getarg(&argc, &argv, "no program filename");
                    195:                        if (npfile >= maxpfile) {
                    196:                                maxpfile += 20;
1.59      millert   197:                                pfile = (char **) reallocarray(pfile, maxpfile, sizeof(*pfile));
1.37      millert   198:                                if (pfile == NULL)
                    199:                                        FATAL("error allocating space for -f options");
                    200:                        }
                    201:                        pfile[npfile++] = fn;
                    202:                        break;
1.1       tholo     203:                case 'F':       /* set field separator */
1.37      millert   204:                        fs = setfs(getarg(&argc, &argv, "no field separator"));
1.1       tholo     205:                        break;
                    206:                case 'v':       /* -v a=1 to be done NOW.  one -v for each */
1.37      millert   207:                        vn = getarg(&argc, &argv, "no variable name");
                    208:                        if (isclvar(vn))
                    209:                                setclvar(vn);
                    210:                        else
                    211:                                FATAL("invalid -v option argument: %s", vn);
1.1       tholo     212:                        break;
                    213:                case 'd':
                    214:                        dbg = atoi(&argv[1][2]);
                    215:                        if (dbg == 0)
                    216:                                dbg = 1;
                    217:                        printf("awk %s\n", version);
1.6       millert   218:                        break;
                    219:                case 'V':       /* added for exptools "standard" */
                    220:                        printf("awk %s\n", version);
1.62    ! millert   221:                        return 0;
1.1       tholo     222:                default:
1.9       millert   223:                        WARNING("unknown option %s ignored", argv[1]);
1.1       tholo     224:                        break;
                    225:                }
                    226:                argc--;
                    227:                argv++;
                    228:        }
1.18      doug      229:
                    230:        if (safe) {
                    231:                if (pledge("stdio rpath", NULL) == -1) {
                    232:                        fprintf(stderr, "%s: pledge: incorrect arguments\n",
                    233:                            cmdname);
                    234:                        exit(1);
                    235:                }
                    236:        }
                    237:
1.1       tholo     238:        /* argv[1] is now the first argument */
                    239:        if (npfile == 0) {      /* no -f; first argument is program */
                    240:                if (argc <= 1) {
                    241:                        if (dbg)
                    242:                                exit(0);
1.9       millert   243:                        FATAL("no program given");
1.1       tholo     244:                }
1.42      millert   245:                DPRINTF("program = |%s|\n", argv[1]);
1.1       tholo     246:                lexprog = argv[1];
                    247:                argc--;
                    248:                argv++;
                    249:        }
                    250:        recinit(recsize);
                    251:        syminit();
1.34      millert   252:        compile_time = COMPILING;
1.1       tholo     253:        argv[0] = cmdname;      /* put prog name at front of arglist */
1.42      millert   254:        DPRINTF("argc=%d, argv[0]=%s\n", argc, argv[0]);
1.1       tholo     255:        arginit(argc, argv);
1.4       kstailey  256:        if (!safe)
                    257:                envinit(environ);
1.1       tholo     258:        yyparse();
1.37      millert   259: #if 0
                    260:        // Doing this would comply with POSIX, but is not compatible with
                    261:        // other awks and with what most users expect. So comment it out.
1.13      millert   262:        setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
1.37      millert   263: #endif
1.1       tholo     264:        if (fs)
1.4       kstailey  265:                *FS = qstring(fs, '\0');
1.42      millert   266:        DPRINTF("errorflag=%d\n", errorflag);
1.1       tholo     267:        if (errorflag == 0) {
1.34      millert   268:                compile_time = RUNNING;
1.1       tholo     269:                run(winner);
                    270:        } else
                    271:                bracecheck();
                    272:        return(errorflag);
                    273: }
                    274:
                    275: int pgetc(void)                /* get 1 character from awk program */
                    276: {
                    277:        int c;
                    278:
                    279:        for (;;) {
                    280:                if (yyin == NULL) {
                    281:                        if (curpfile >= npfile)
                    282:                                return EOF;
1.4       kstailey  283:                        if (strcmp(pfile[curpfile], "-") == 0)
1.1       tholo     284:                                yyin = stdin;
1.4       kstailey  285:                        else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
1.9       millert   286:                                FATAL("can't open file %s", pfile[curpfile]);
1.7       millert   287:                        lineno = 1;
1.1       tholo     288:                }
                    289:                if ((c = getc(yyin)) != EOF)
                    290:                        return c;
                    291:                if (yyin != stdin)
                    292:                        fclose(yyin);
                    293:                yyin = NULL;
                    294:                curpfile++;
                    295:        }
1.7       millert   296: }
                    297:
                    298: char *cursource(void)  /* current source file name */
                    299: {
                    300:        if (npfile > 0)
1.44      millert   301:                return pfile[curpfile < npfile ? curpfile : curpfile - 1];
1.7       millert   302:        else
                    303:                return NULL;
1.1       tholo     304: }