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

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