[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.42

1.42    ! millert     1: /*     $OpenBSD: main.c,v 1.41 2020/06/26 15:50:06 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.42    ! millert    26: const char     *version = "version 20200625";
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"
1.4       kstailey   37: #include "ytab.h"
1.1       tholo      38:
                     39: extern char    **environ;
                     40: extern int     nfields;
1.6       millert    41: extern char    *__progname;
1.1       tholo      42:
                     43: int    dbg     = 0;
1.17      millert    44: Awkfloat       srand_seed = 1;
1.1       tholo      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 */
1.34      millert    49: enum compile_states    compile_time = ERROR_PRINTING;
1.1       tholo      50:
1.37      millert    51: static char    **pfile;        /* program filenames from -f's */
                     52: static size_t  maxpfile;       /* max program filename */
                     53: static size_t  npfile;         /* number of filenames */
                     54: static size_t  curpfile;       /* current filename */
1.15      millert    55:
1.40      millert    56: bool   safe = false;           /* true => "safe" mode */
                     57: bool   do_posix = false;       /* true => POSIX mode */
1.37      millert    58:
1.38      millert    59: static noreturn void fpecatch(int n
1.37      millert    60: #ifdef SA_SIGINFO
                     61:        , siginfo_t *si, void *uc
                     62: #endif
                     63: )
                     64: {
                     65:        extern Node *curnode;
                     66: #ifdef SA_SIGINFO
                     67:        static const char *emsg[] = {
                     68:                [0] = "Unknown error",
                     69:                [FPE_INTDIV] = "Integer divide by zero",
                     70:                [FPE_INTOVF] = "Integer overflow",
                     71:                [FPE_FLTDIV] = "Floating point divide by zero",
                     72:                [FPE_FLTOVF] = "Floating point overflow",
                     73:                [FPE_FLTUND] = "Floating point underflow",
                     74:                [FPE_FLTRES] = "Floating point inexact result",
                     75:                [FPE_FLTINV] = "Invalid Floating point operation",
                     76:                [FPE_FLTSUB] = "Subscript out of range",
                     77:        };
                     78: #endif
                     79:        dprintf(STDERR_FILENO, "floating point exception%s%s\n",
                     80: #ifdef SA_SIGINFO
                     81:                ": ", (size_t)si->si_code < sizeof(emsg) / sizeof(emsg[0]) &&
                     82:                emsg[si->si_code] ? emsg[si->si_code] : emsg[0]
                     83: #else
                     84:                "", ""
                     85: #endif
                     86:            );
                     87:
                     88:        if (compile_time != 2 && NR && *NR > 0) {
                     89:                dprintf(STDERR_FILENO, " input record number %d", (int) (*FNR));
                     90:                if (strcmp(*FILENAME, "-") != 0) {
                     91:                        dprintf(STDERR_FILENO, ", file %s", *FILENAME);
                     92:                }
                     93:                dprintf(STDERR_FILENO, "\n");
                     94:        }
                     95:        if (compile_time != 2 && curnode) {
                     96:                dprintf(STDERR_FILENO, " source line number %d", curnode->lineno);
                     97:        } else if (compile_time != 2 && lineno) {
                     98:                dprintf(STDERR_FILENO, " source line number %d", lineno);
                     99:        }
                    100:        if (compile_time == 1 && cursource() != NULL) {
                    101:                dprintf(STDERR_FILENO, " source file %s", cursource());
                    102:        }
                    103:        dprintf(STDERR_FILENO, "\n");
                    104:        if (dbg > 1)            /* core dump if serious debugging on */
                    105:                abort();
                    106:        _exit(2);
                    107: }
1.1       tholo     108:
1.37      millert   109: static const char *
                    110: setfs(char *p)
                    111: {
                    112:        /* wart: t=>\t */
                    113:        if (p[0] == 't' && p[1] == '\0')
                    114:                return "\t";
                    115:        else if (p[0] != '\0')
                    116:                return p;
                    117:        return NULL;
                    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 */
                    140:
1.20      tb        141:        cmdname = __progname;
1.18      doug      142:        if (pledge("stdio rpath wpath cpath proc exec", NULL) == -1) {
                    143:                fprintf(stderr, "%s: pledge: incorrect arguments\n",
                    144:                    cmdname);
                    145:                exit(1);
                    146:        }
                    147:
1.1       tholo     148:        if (argc == 1) {
1.14      jmc       149:                fprintf(stderr, "usage: %s [-safe] [-V] [-d[n]] [-F fs] "
                    150:                    "[-v var=value] [prog | -f progfile]\n\tfile ...\n",
1.10      aaron     151:                    cmdname);
1.1       tholo     152:                exit(1);
                    153:        }
1.37      millert   154: #ifdef SA_SIGINFO
                    155:        {
                    156:                struct sigaction sa;
                    157:                sa.sa_sigaction = fpecatch;
                    158:                sa.sa_flags = SA_SIGINFO;
                    159:                sigemptyset(&sa.sa_mask);
                    160:                (void)sigaction(SIGFPE, &sa, NULL);
                    161:        }
                    162: #else
                    163:        (void)signal(SIGFPE, fpecatch);
                    164: #endif
1.40      millert   165:
                    166:        do_posix = (getenv("POSIXLY_CORRECT") != NULL);
1.17      millert   167:
1.1       tholo     168:        yyin = NULL;
                    169:        symtab = makesymtab(NSYMTAB);
                    170:        while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
1.4       kstailey  171:                if (strcmp(argv[1], "--") == 0) {       /* explicit end of args */
1.1       tholo     172:                        argc--;
                    173:                        argv++;
                    174:                        break;
                    175:                }
                    176:                switch (argv[1][1]) {
1.4       kstailey  177:                case 's':
                    178:                        if (strcmp(argv[1], "-safe") == 0)
1.34      millert   179:                                safe = true;
1.4       kstailey  180:                        break;
1.1       tholo     181:                case 'f':       /* next argument is program filename */
1.37      millert   182:                        fn = getarg(&argc, &argv, "no program filename");
                    183:                        if (npfile >= maxpfile) {
                    184:                                maxpfile += 20;
                    185:                                pfile = realloc(pfile, maxpfile * sizeof(*pfile));
                    186:                                if (pfile == NULL)
                    187:                                        FATAL("error allocating space for -f options");
                    188:                        }
                    189:                        pfile[npfile++] = fn;
                    190:                        break;
1.1       tholo     191:                case 'F':       /* set field separator */
1.37      millert   192:                        fs = setfs(getarg(&argc, &argv, "no field separator"));
                    193:                        if (fs == NULL)
1.9       millert   194:                                WARNING("field separator FS is empty");
1.1       tholo     195:                        break;
                    196:                case 'v':       /* -v a=1 to be done NOW.  one -v for each */
1.37      millert   197:                        vn = getarg(&argc, &argv, "no variable name");
                    198:                        if (isclvar(vn))
                    199:                                setclvar(vn);
                    200:                        else
                    201:                                FATAL("invalid -v option argument: %s", vn);
1.1       tholo     202:                        break;
                    203:                case 'd':
                    204:                        dbg = atoi(&argv[1][2]);
                    205:                        if (dbg == 0)
                    206:                                dbg = 1;
                    207:                        printf("awk %s\n", version);
1.6       millert   208:                        break;
                    209:                case 'V':       /* added for exptools "standard" */
                    210:                        printf("awk %s\n", version);
                    211:                        exit(0);
1.1       tholo     212:                        break;
                    213:                default:
1.9       millert   214:                        WARNING("unknown option %s ignored", argv[1]);
1.1       tholo     215:                        break;
                    216:                }
                    217:                argc--;
                    218:                argv++;
                    219:        }
1.18      doug      220:
                    221:        if (safe) {
                    222:                if (pledge("stdio rpath", NULL) == -1) {
                    223:                        fprintf(stderr, "%s: pledge: incorrect arguments\n",
                    224:                            cmdname);
                    225:                        exit(1);
                    226:                }
                    227:        }
                    228:
1.1       tholo     229:        /* argv[1] is now the first argument */
                    230:        if (npfile == 0) {      /* no -f; first argument is program */
                    231:                if (argc <= 1) {
                    232:                        if (dbg)
                    233:                                exit(0);
1.9       millert   234:                        FATAL("no program given");
1.1       tholo     235:                }
1.42    ! millert   236:                DPRINTF("program = |%s|\n", argv[1]);
1.1       tholo     237:                lexprog = argv[1];
                    238:                argc--;
                    239:                argv++;
                    240:        }
                    241:        recinit(recsize);
                    242:        syminit();
1.34      millert   243:        compile_time = COMPILING;
1.1       tholo     244:        argv[0] = cmdname;      /* put prog name at front of arglist */
1.42    ! millert   245:        DPRINTF("argc=%d, argv[0]=%s\n", argc, argv[0]);
1.1       tholo     246:        arginit(argc, argv);
1.4       kstailey  247:        if (!safe)
                    248:                envinit(environ);
1.1       tholo     249:        yyparse();
1.37      millert   250: #if 0
                    251:        // Doing this would comply with POSIX, but is not compatible with
                    252:        // other awks and with what most users expect. So comment it out.
1.13      millert   253:        setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
1.37      millert   254: #endif
1.1       tholo     255:        if (fs)
1.4       kstailey  256:                *FS = qstring(fs, '\0');
1.42    ! millert   257:        DPRINTF("errorflag=%d\n", errorflag);
1.1       tholo     258:        if (errorflag == 0) {
1.34      millert   259:                compile_time = RUNNING;
1.1       tholo     260:                run(winner);
                    261:        } else
                    262:                bracecheck();
                    263:        return(errorflag);
                    264: }
                    265:
                    266: int pgetc(void)                /* get 1 character from awk program */
                    267: {
                    268:        int c;
                    269:
                    270:        for (;;) {
                    271:                if (yyin == NULL) {
                    272:                        if (curpfile >= npfile)
                    273:                                return EOF;
1.4       kstailey  274:                        if (strcmp(pfile[curpfile], "-") == 0)
1.1       tholo     275:                                yyin = stdin;
1.4       kstailey  276:                        else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
1.9       millert   277:                                FATAL("can't open file %s", pfile[curpfile]);
1.7       millert   278:                        lineno = 1;
1.1       tholo     279:                }
                    280:                if ((c = getc(yyin)) != EOF)
                    281:                        return c;
                    282:                if (yyin != stdin)
                    283:                        fclose(yyin);
                    284:                yyin = NULL;
                    285:                curpfile++;
                    286:        }
1.7       millert   287: }
                    288:
                    289: char *cursource(void)  /* current source file name */
                    290: {
                    291:        if (npfile > 0)
                    292:                return pfile[curpfile];
                    293:        else
                    294:                return NULL;
1.1       tholo     295: }