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

1.51    ! millert     1: /*     $OpenBSD: main.c,v 1.50 2021/11/12 15:16:58 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.51    ! millert    26: const char     *version = "version 20211208";
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";
1.48      millert   114:        return p;
1.37      millert   115: }
                    116:
                    117: static char *
                    118: getarg(int *argc, char ***argv, const char *msg)
                    119: {
                    120:        if ((*argv)[1][2] != '\0') {    /* arg is -fsomething */
                    121:                return &(*argv)[1][2];
                    122:        } else {                        /* arg is -f something */
                    123:                (*argc)--; (*argv)++;
                    124:                if (*argc <= 1)
                    125:                        FATAL("%s", msg);
                    126:                return (*argv)[1];
                    127:        }
                    128: }
1.4       kstailey  129:
1.1       tholo     130: int main(int argc, char *argv[])
                    131: {
1.12      millert   132:        const char *fs = NULL;
1.37      millert   133:        char *fn, *vn;
1.2       tholo     134:
1.39      millert   135:        setlocale(LC_CTYPE, "");
1.19      deraadt   136:        setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
                    137:
1.20      tb        138:        cmdname = __progname;
1.18      doug      139:        if (pledge("stdio rpath wpath cpath proc exec", NULL) == -1) {
                    140:                fprintf(stderr, "%s: pledge: incorrect arguments\n",
                    141:                    cmdname);
                    142:                exit(1);
                    143:        }
                    144:
1.1       tholo     145:        if (argc == 1) {
1.14      jmc       146:                fprintf(stderr, "usage: %s [-safe] [-V] [-d[n]] [-F fs] "
                    147:                    "[-v var=value] [prog | -f progfile]\n\tfile ...\n",
1.10      aaron     148:                    cmdname);
1.1       tholo     149:                exit(1);
                    150:        }
1.37      millert   151: #ifdef SA_SIGINFO
                    152:        {
                    153:                struct sigaction sa;
                    154:                sa.sa_sigaction = fpecatch;
                    155:                sa.sa_flags = SA_SIGINFO;
                    156:                sigemptyset(&sa.sa_mask);
                    157:                (void)sigaction(SIGFPE, &sa, NULL);
                    158:        }
                    159: #else
                    160:        (void)signal(SIGFPE, fpecatch);
                    161: #endif
1.40      millert   162:
                    163:        do_posix = (getenv("POSIXLY_CORRECT") != NULL);
1.17      millert   164:
1.1       tholo     165:        yyin = NULL;
                    166:        symtab = makesymtab(NSYMTAB);
                    167:        while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
1.4       kstailey  168:                if (strcmp(argv[1], "--") == 0) {       /* explicit end of args */
1.1       tholo     169:                        argc--;
                    170:                        argv++;
                    171:                        break;
                    172:                }
                    173:                switch (argv[1][1]) {
1.4       kstailey  174:                case 's':
                    175:                        if (strcmp(argv[1], "-safe") == 0)
1.34      millert   176:                                safe = true;
1.4       kstailey  177:                        break;
1.1       tholo     178:                case 'f':       /* next argument is program filename */
1.37      millert   179:                        fn = getarg(&argc, &argv, "no program filename");
                    180:                        if (npfile >= maxpfile) {
                    181:                                maxpfile += 20;
1.46      millert   182:                                pfile = (char **) realloc(pfile, maxpfile * sizeof(*pfile));
1.37      millert   183:                                if (pfile == NULL)
                    184:                                        FATAL("error allocating space for -f options");
                    185:                        }
                    186:                        pfile[npfile++] = fn;
                    187:                        break;
1.1       tholo     188:                case 'F':       /* set field separator */
1.37      millert   189:                        fs = setfs(getarg(&argc, &argv, "no field separator"));
1.1       tholo     190:                        break;
                    191:                case 'v':       /* -v a=1 to be done NOW.  one -v for each */
1.37      millert   192:                        vn = getarg(&argc, &argv, "no variable name");
                    193:                        if (isclvar(vn))
                    194:                                setclvar(vn);
                    195:                        else
                    196:                                FATAL("invalid -v option argument: %s", vn);
1.1       tholo     197:                        break;
                    198:                case 'd':
                    199:                        dbg = atoi(&argv[1][2]);
                    200:                        if (dbg == 0)
                    201:                                dbg = 1;
                    202:                        printf("awk %s\n", version);
1.6       millert   203:                        break;
                    204:                case 'V':       /* added for exptools "standard" */
                    205:                        printf("awk %s\n", version);
                    206:                        exit(0);
1.1       tholo     207:                        break;
                    208:                default:
1.9       millert   209:                        WARNING("unknown option %s ignored", argv[1]);
1.1       tholo     210:                        break;
                    211:                }
                    212:                argc--;
                    213:                argv++;
                    214:        }
1.18      doug      215:
                    216:        if (safe) {
                    217:                if (pledge("stdio rpath", NULL) == -1) {
                    218:                        fprintf(stderr, "%s: pledge: incorrect arguments\n",
                    219:                            cmdname);
                    220:                        exit(1);
                    221:                }
                    222:        }
                    223:
1.1       tholo     224:        /* argv[1] is now the first argument */
                    225:        if (npfile == 0) {      /* no -f; first argument is program */
                    226:                if (argc <= 1) {
                    227:                        if (dbg)
                    228:                                exit(0);
1.9       millert   229:                        FATAL("no program given");
1.1       tholo     230:                }
1.42      millert   231:                DPRINTF("program = |%s|\n", argv[1]);
1.1       tholo     232:                lexprog = argv[1];
                    233:                argc--;
                    234:                argv++;
                    235:        }
                    236:        recinit(recsize);
                    237:        syminit();
1.34      millert   238:        compile_time = COMPILING;
1.1       tholo     239:        argv[0] = cmdname;      /* put prog name at front of arglist */
1.42      millert   240:        DPRINTF("argc=%d, argv[0]=%s\n", argc, argv[0]);
1.1       tholo     241:        arginit(argc, argv);
1.4       kstailey  242:        if (!safe)
                    243:                envinit(environ);
1.1       tholo     244:        yyparse();
1.37      millert   245: #if 0
                    246:        // Doing this would comply with POSIX, but is not compatible with
                    247:        // other awks and with what most users expect. So comment it out.
1.13      millert   248:        setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
1.37      millert   249: #endif
1.1       tholo     250:        if (fs)
1.4       kstailey  251:                *FS = qstring(fs, '\0');
1.42      millert   252:        DPRINTF("errorflag=%d\n", errorflag);
1.1       tholo     253:        if (errorflag == 0) {
1.34      millert   254:                compile_time = RUNNING;
1.1       tholo     255:                run(winner);
                    256:        } else
                    257:                bracecheck();
                    258:        return(errorflag);
                    259: }
                    260:
                    261: int pgetc(void)                /* get 1 character from awk program */
                    262: {
                    263:        int c;
                    264:
                    265:        for (;;) {
                    266:                if (yyin == NULL) {
                    267:                        if (curpfile >= npfile)
                    268:                                return EOF;
1.4       kstailey  269:                        if (strcmp(pfile[curpfile], "-") == 0)
1.1       tholo     270:                                yyin = stdin;
1.4       kstailey  271:                        else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
1.9       millert   272:                                FATAL("can't open file %s", pfile[curpfile]);
1.7       millert   273:                        lineno = 1;
1.1       tholo     274:                }
                    275:                if ((c = getc(yyin)) != EOF)
                    276:                        return c;
                    277:                if (yyin != stdin)
                    278:                        fclose(yyin);
                    279:                yyin = NULL;
                    280:                curpfile++;
                    281:        }
1.7       millert   282: }
                    283:
                    284: char *cursource(void)  /* current source file name */
                    285: {
                    286:        if (npfile > 0)
1.44      millert   287:                return pfile[curpfile < npfile ? curpfile : curpfile - 1];
1.7       millert   288:        else
                    289:                return NULL;
1.1       tholo     290: }