See attached test case extracted from libgpg-error, it fails on i386 but works on amd64. (ports/lang/gcc failed too, I forgot to save the build directory).
TZ=GMT cvs up -D '2020/06/10 21:05:00' January 5, 2020 works as expected TZ=GMT cvs up -D '2020/06/10 21:05:10' January 31, 2020 building awk fails TZ=GMT cvs up -D '2020/06/10 21:05:50' February 28, 2020 building awk works, test case fails $ cc -E -P _mkerrcodes.h | grep GPG_ERR_ | awk -f ./mkerrcodes.awk > /dev/null awk: nonterminated character class [ input record number 2, file source line number 93 *** Error 2 in /tmp/awk-problem (Makefile:4 'all') I am going to start a ports build with the January 5 version, i.e. the following backout: Index: FIXES =================================================================== RCS file: /cvs/src/usr.bin/awk/FIXES,v retrieving revision 1.33 diff -u -p -r1.33 FIXES --- FIXES 10 Jun 2020 21:06:09 -0000 1.33 +++ FIXES 11 Jun 2020 11:02:48 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: FIXES,v 1.33 2020/06/10 21:06:09 millert Exp $ */ +/* $OpenBSD: FIXES,v 1.30 2020/06/10 21:04:40 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -26,60 +26,6 @@ THIS SOFTWARE. This file lists all bug fixes, changes, etc., made since the AWK book was sent to the printers in August, 1987. -June 5, 2020: - In fldbld(), make sure that inputFS is set before trying to - use it. Thanks to Steffen Nurpmeso <stef...@sdaoden.eu> - for the report. - -May 5, 2020: - Fix checks for compilers that can handle noreturn. Thanks to - GitHub user enh-google for pointing it out. Closes Issue #79. - -April 16, 2020: - Handle old compilers that don't support C11 (for noreturn). - Thanks to Arnold Robbins. - -April 5, 2020: - Use <stdnoreturn.h> and noreturn instead of GCC attributes. - Thanks to GitHub user awkfan77. Closes PR #77. - -February 28, 2020: - More cleanups from Christos Zoulas: notably backslash continuation - inside strings removes the newline and a fix for RS = "^a". - Fix for address sanitizer-found problem. Thanks to GitHub user - enh-google. - -February 19, 2020: - More small cleanups from Christos Zoulas. - -February 18, 2020: - Additional cleanups from Christos Zoulas. It's no longer necessary - to use the -y flag to bison. - -February 6, 2020: - Additional small cleanups from Christos Zoulas. awk is now - a little more robust about reporting I/O errors upon exit. - -January 31, 2020: - Merge PR #70, which avoids use of variable length arrays. Thanks - to GitHub user michaelforney. Fix issue #60 ({0} in interval - expressions doesn't work). Also get all tests working again. - Thanks to Arnold Robbins. - -January 24, 2020: - A number of small cleanups from Christos Zoulas. Add the close - on exec flag to files/pipes opened for redirection; courtesy of - Arnold Robbins. - -January 19, 2020: - If POSIXLY_CORRECT is set in the environment, then sub and gsub - use POSIX rules for multiple backslashes. This fixes Issue #66, - while maintaining backwards compatibility. - -January 9, 2020: - Input/output errors on closing files are now fatal instead of - mere warnings. Thanks to Martijn Dekker <mart...@inlv.org>. - January 5, 2020: Fix a bug in the concatentation of two string constants into one done in the grammar. Fixes GitHub issue #61. Thanks @@ -118,13 +64,13 @@ October 25, 2019: October 24, 2019: Import second round of code cleanups from NetBSD. Much thanks - to Christos Zoulas (GitHub user zoulasc). Merges PR 53. + to Christos Zoulas (Github user zoulasc). Merges PR 53. Add an optimization for string concatenation, also from Christos. October 17, 2019: Import code cleanups from NetBSD. Much thanks to Christos - Zoulas (GitHub user zoulasc). Merges PR 51. + Zoulas (Github user zoulasc). Merges PR 51. October 6, 2019: Import code from NetBSD awk that implements RS as a regular @@ -132,7 +78,7 @@ October 6, 2019: September 10, 2019: Fixes for various array / memory overruns found via gcc's - -fsanitize=unknown. Thanks to Alexander Richardson (GitHub + -fsanitize=unknown. Thanks to Alexander Richardson (Github user arichardson). Merges PRs 47 and 48. July 28, 2019: Index: README.md =================================================================== RCS file: /cvs/src/usr.bin/awk/README.md,v retrieving revision 1.2 diff -u -p -r1.2 README.md --- README.md 10 Jun 2020 21:05:50 -0000 1.2 +++ README.md 11 Jun 2020 11:02:48 -0000 @@ -1,4 +1,4 @@ -$OpenBSD: README.md,v 1.2 2020/06/10 21:05:50 millert Exp $ +$OpenBSD: README.md,v 1.1 2020/06/10 21:04:40 millert Exp $ # The One True Awk @@ -44,19 +44,7 @@ Thanks. ## Submitting Pull Requests -Pull requests are welcome. Some guidelines: - -* Please do not use functions or facilities that are not standard (e.g., -`strlcpy()`, `fpurge()`). - -* Please run the test suite and make sure that your changes pass before -posting the pull request. To do so: - - 1. Save the previous version of `awk` somewhere in your path. Call it `nawk` (for example). - 1. Run `oldawk=nawk make check > check.out 2>&1`. - 1. Search for `BAD` or `error` in the result. In general, look over it manually to make sure there are no errors. - -* Please create the pull request with a request +Pull requests are welcome. However, please create them with a request to merge into the `staging` branch instead of into the `master` branch. This allows us to do testing, and to make any additional edits or changes after the merge but before merging to `master`. Index: awk.1 =================================================================== RCS file: /cvs/src/usr.bin/awk/awk.1,v retrieving revision 1.50 diff -u -p -r1.50 awk.1 --- awk.1 10 Jun 2020 21:05:02 -0000 1.50 +++ awk.1 11 Jun 2020 11:02:48 -0000 @@ -1,4 +1,4 @@ -.\" $OpenBSD: awk.1,v 1.50 2020/06/10 21:05:02 millert Exp $ +.\" $OpenBSD: awk.1,v 1.49 2020/06/10 21:02:53 millert Exp $ .\" .\" Copyright (C) Lucent Technologies 1997 .\" All Rights Reserved @@ -726,14 +726,6 @@ Returns integer argument x shifted by n .It Fn rshift x n Returns integer argument x shifted by n bits to the right. .El -.Sh ENVIRONMENT -The following environment variables affect the execution of -.Nm : -.Bl -tag -width POSIXLY_CORRECT -.It Ev POSIXLY_CORRECT -When set, behave in accordance with the standard, even when it conflicts -with historical behavior. -.El .Sh EXIT STATUS .Ex -std awk .Pp @@ -800,12 +792,7 @@ The .Nm utility is compliant with the .St -p1003.1-2008 -specification except that consecutive backslashes in the replacement -string argument for -.Fn sub -and -.Fn gsub -are not collapsed. +specification. .Pp The flags .Op Fl \&dV Index: awk.h =================================================================== RCS file: /cvs/src/usr.bin/awk/awk.h,v retrieving revision 1.23 diff -u -p -r1.23 awk.h --- awk.h 10 Jun 2020 21:06:09 -0000 1.23 +++ awk.h 11 Jun 2020 11:02:48 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: awk.h,v 1.23 2020/06/10 21:06:09 millert Exp $ */ +/* $OpenBSD: awk.h,v 1.21 2020/06/10 21:03:56 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -26,11 +26,6 @@ THIS SOFTWARE. #include <assert.h> #include <stdint.h> #include <stdbool.h> -#if __STDC_VERSION__ <= 199901L -#define noreturn __dead -#else -#include <stdnoreturn.h> -#endif typedef double Awkfloat; @@ -66,7 +61,6 @@ extern bool safe; /* false => unsafe, t #define RECSIZE (8 * 1024) /* sets limit on records, fields, etc., etc. */ extern int recsize; /* size of current record, orig RECSIZE */ -extern char EMPTY[]; /* this avoid -Wwritable-strings issues */ extern char **FS; extern char **RS; extern char **ORS; @@ -85,6 +79,8 @@ extern int lineno; /* line number in aw extern int errorflag; /* 1 if error has occurred */ extern bool donefld; /* true if record broken into fields */ extern bool donerec; /* true if record is valid (no fld has changed */ +extern char inputFS[]; /* FS at time of input, for field splitting */ + extern int dbg; extern const char *patbeg; /* beginning of pattern matched */ Index: awkgram.y =================================================================== RCS file: /cvs/src/usr.bin/awk/awkgram.y,v retrieving revision 1.13 diff -u -p -r1.13 awkgram.y --- awkgram.y 10 Jun 2020 21:05:02 -0000 1.13 +++ awkgram.y 11 Jun 2020 11:02:48 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: awkgram.y,v 1.13 2020/06/10 21:05:02 millert Exp $ */ +/* $OpenBSD: awkgram.y,v 1.12 2020/06/10 21:03:56 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -51,7 +51,7 @@ Node *arglist = 0; /* list of args for c %token <i> NL ',' '{' '(' '|' ';' '/' ')' '}' '[' ']' %token <i> ARRAY %token <i> MATCH NOTMATCH MATCHOP -%token <i> FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS EMPTYRE ZERO +%token <i> FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS EMPTYRE %token <i> AND BOR APPEND EQ GE GT LE LT NE IN %token <i> ARG BLTIN BREAK CLOSE CONTINUE DELETE DO EXIT FOR FUNC %token <i> SUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT NEXTFILE Index: b.c =================================================================== RCS file: /cvs/src/usr.bin/awk/b.c,v retrieving revision 1.31 diff -u -p -r1.31 b.c --- b.c 10 Jun 2020 21:05:02 -0000 1.31 +++ b.c 11 Jun 2020 11:02:48 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: b.c,v 1.31 2020/06/10 21:05:02 millert Exp $ */ +/* $OpenBSD: b.c,v 1.30 2020/06/10 21:04:40 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -271,8 +271,6 @@ void penter(Node *p) /* set up parent po parent(left(p)) = p; parent(right(p)) = p; break; - case ZERO: - break; default: /* can't happen */ FATAL("can't happen: unknown type %d in penter", type(p)); break; @@ -287,7 +285,6 @@ void freetr(Node *p) /* free parse tree xfree(p); break; UNARY - case ZERO: freetr(left(p)); xfree(p); break; @@ -447,8 +444,6 @@ void cfoll(fa *f, Node *v) /* enter foll cfoll(f,left(v)); cfoll(f,right(v)); break; - case ZERO: - break; default: /* can't happen */ FATAL("can't happen: unknown type %d in cfoll", type(v)); } @@ -492,8 +487,6 @@ int first(Node *p) /* collects initially b = first(right(p)); if (first(left(p)) == 0 || b == 0) return(0); return(1); - case ZERO: - return 0; } FATAL("can't happen: unknown type %d in first", type(p)); /* can't happen */ return(-1); @@ -853,9 +846,6 @@ Node *unary(Node *np) case QUEST: rtok = relex(); return (unary(op2(QUEST, np, NIL))); - case ZERO: - rtok = relex(); - return (unary(op2(ZERO, np, NIL))); default: return (np); } @@ -890,7 +880,7 @@ int (xisblank)(int c) #endif -static const struct charclass { +struct charclass { const char *cc_name; int cc_namelen; int (*cc_func)(int); @@ -926,7 +916,7 @@ replace_repeat(const uschar *reptok, int int i, j; uschar *buf = NULL; int ret = 1; - int init_q = (firstnum == 0); /* first added char will be ? */ + bool init_q = (firstnum == 0); /* first added char will be ? */ int n_q_reps = secondnum-firstnum; /* m>n, so reduce until {1,m-n} left */ int prefix_length = reptok - basestr; /* prefix includes first rep */ int suffix_length = strlen((const char *) reptok) - reptoklen; /* string after rep specifier */ @@ -1034,7 +1024,7 @@ int relex(void) /* lexical analyzer for static uschar *buf = NULL; static int bufsz = 100; uschar *bp; - const struct charclass *cc; + struct charclass *cc; int i; int num, m; bool commafound, digitfound; @@ -1208,7 +1198,7 @@ rescan: if (repeat(starttok, prestr-starttok, lastatom, startreptok - lastatom, n, m) > 0) { if (n == 0 && m == 0) { - return ZERO; + return EMPTYRE; } /* must rescan input for next token */ goto rescan; Index: lex.c =================================================================== RCS file: /cvs/src/usr.bin/awk/lex.c,v retrieving revision 1.19 diff -u -p -r1.19 lex.c --- lex.c 10 Jun 2020 21:05:50 -0000 1.19 +++ lex.c 11 Jun 2020 11:02:48 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: lex.c,v 1.19 2020/06/10 21:05:50 millert Exp $ */ +/* $OpenBSD: lex.c,v 1.17 2020/06/10 21:04:40 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -31,7 +31,7 @@ THIS SOFTWARE. #include "ytab.h" extern YYSTYPE yylval; -extern bool infunc; +extern int infunc; int lineno = 1; int bracecnt = 0; @@ -44,7 +44,7 @@ typedef struct Keyword { int type; } Keyword; -const Keyword keywords[] = { /* keep sorted: binary searched */ +Keyword keywords[] ={ /* keep sorted: binary searched */ { "BEGIN", XBEGIN, XBEGIN }, { "END", XEND, XEND }, { "NF", VARNF, VARNF }, @@ -98,14 +98,18 @@ const Keyword keywords[] = { /* keep sor #define RET(x) { if(dbg)printf("lex %s\n", tokname(x)); return(x); } -static int peek(void) +int peek(void); +int gettok(char **, int *); +int binsearch(char *, Keyword *, int); + +int peek(void) { int c = input(); unput(c); return c; } -static int gettok(char **pbuf, int *psz) /* get next input token */ +int gettok(char **pbuf, int *psz) /* get next input token */ { int c, retc; char *buf = *pbuf; @@ -217,11 +221,6 @@ int yylex(void) while ((c = input()) != '\n' && c != 0) ; unput(c); - /* - * Next line is a hack, itcompensates for - * unput's treatment of \n. - */ - lineno++; break; case ';': RET(';'); @@ -395,7 +394,6 @@ int string(void) case '\\': c = input(); switch (c) { - case '\n': break; case '"': *bp++ = '"'; break; case 'n': *bp++ = '\n'; break; case 't': *bp++ = '\t'; break; @@ -403,7 +401,7 @@ int string(void) case 'r': *bp++ = '\r'; break; case 'b': *bp++ = '\b'; break; case 'v': *bp++ = '\v'; break; - case 'a': *bp++ = '\a'; break; + case 'a': *bp++ = '\007'; break; case '\\': *bp++ = '\\'; break; case '0': case '1': case '2': /* octal: \d \dd \ddd */ @@ -453,7 +451,7 @@ int string(void) } -static int binsearch(char *w, const Keyword *kp, int n) +int binsearch(char *w, Keyword *kp, int n) { int cond, low, mid, high; @@ -473,7 +471,7 @@ static int binsearch(char *w, const Keyw int word(char *w) { - const Keyword *kp; + Keyword *kp; int c, n; n = binsearch(w, keywords, sizeof(keywords)/sizeof(keywords[0])); @@ -589,8 +587,6 @@ int input(void) /* get next lexical inpu void unput(int c) /* put lexical character back on input */ { - if (c == '\n') - lineno--; if (yysptr >= yysbuf + sizeof(yysbuf)) FATAL("pushed back too much: %.20s...", yysbuf); *yysptr++ = c; Index: lib.c =================================================================== RCS file: /cvs/src/usr.bin/awk/lib.c,v retrieving revision 1.35 diff -u -p -r1.35 lib.c --- lib.c 10 Jun 2020 21:06:09 -0000 1.35 +++ lib.c 11 Jun 2020 11:02:48 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: lib.c,v 1.35 2020/06/10 21:06:09 millert Exp $ */ +/* $OpenBSD: lib.c,v 1.32 2020/06/10 21:03:56 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -29,23 +29,20 @@ THIS SOFTWARE. #include <ctype.h> #include <errno.h> #include <stdlib.h> +#include <unistd.h> #include <stdarg.h> -#include <limits.h> #include "awk.h" #include "ytab.h" -char EMPTY[] = { '\0' }; FILE *infile = NULL; -bool innew; /* true = infile has not been read by readrec */ -char *file = EMPTY; +char *file = ""; char *record; int recsize = RECSIZE; char *fields; int fieldssize = RECSIZE; Cell **fldtab; /* pointers to Cells */ -static size_t len_inputFS = 0; -static char *inputFS = NULL; /* FS at time of input, for field splitting */ +char inputFS[100] = " "; #define MAXFLD 2 int nfields = MAXFLD; /* last allocated slot for $i */ @@ -57,8 +54,8 @@ int lastfld = 0; /* last used field */ int argno = 1; /* current input argument number */ extern Awkfloat *ARGC; -static Cell dollar0 = { OCELL, CFLD, NULL, EMPTY, 0.0, REC|STR|DONTFREE, NULL, NULL }; -static Cell dollar1 = { OCELL, CFLD, NULL, EMPTY, 0.0, FLD|STR|DONTFREE, NULL, NULL }; +static Cell dollar0 = { OCELL, CFLD, NULL, "", 0.0, REC|STR|DONTFREE }; +static Cell dollar1 = { OCELL, CFLD, NULL, "", 0.0, FLD|STR|DONTFREE }; void recinit(unsigned int n) { @@ -108,7 +105,6 @@ void initgetrec(void) argno++; } infile = stdin; /* no filenames, so use stdin */ - innew = true; } /* @@ -122,17 +118,9 @@ void initgetrec(void) */ void savefs(void) { - size_t len; - if ((len = strlen(getsval(fsloc))) < len_inputFS) { - strlcpy(inputFS, *FS, sizeof(inputFS)); /* for subsequent field splitting */ - return; - } - - len_inputFS = len + 1; - inputFS = realloc(inputFS, len_inputFS); - if (inputFS == NULL) + if (strlen(getsval(fsloc)) >= sizeof (inputFS)) FATAL("field separator %.10s... is too long", *FS); - memcpy(inputFS, *FS, len_inputFS); + strlcpy(inputFS, *FS, sizeof(inputFS)); } static bool firsttime = true; @@ -178,9 +166,7 @@ int getrec(char **pbuf, int *pbufsize, b FATAL("can't open file %s", file); setfval(fnrloc, 0.0); } - c = readrec(&buf, &bufsize, infile, innew); - if (innew) - innew = false; + c = readrec(&buf, &bufsize, infile); if (c != 0 || buf[0] != '\0') { /* normal record */ if (isrecord) { if (freeable(fldtab[0])) @@ -218,7 +204,7 @@ void nextfile(void) argno++; } -int readrec(char **pbuf, int *pbufsize, FILE *inf, bool newflag) /* read one record into buf */ +int readrec(char **pbuf, int *pbufsize, FILE *inf) /* read one record into buf */ { int sep, c, isrec; char *rr, *buf = *pbuf; @@ -229,14 +215,7 @@ int readrec(char **pbuf, int *pbufsize, bool found; fa *pfa = makedfa(rs, 1); - if (newflag) - found = fnematch(pfa, inf, &buf, &bufsize, recsize); - else { - int tempstat = pfa->initstat; - pfa->initstat = 2; - found = fnematch(pfa, inf, &buf, &bufsize, recsize); - pfa->initstat = tempstat; - } + found = fnematch(pfa, inf, &buf, &bufsize, recsize); if (found) setptr(patbeg, '\0'); } else { @@ -333,8 +312,6 @@ void fldbld(void) /* create fields from } fr = fields; i = 0; /* number of fields accumulated here */ - if (inputFS == NULL) /* make sure we have a copy of FS */ - savefs(); if (strlen(inputFS) > 1) { /* it's a regular expression */ i = refldbld(r, inputFS); } else if ((sep = *inputFS) == ' ') { /* default whitespace */ @@ -358,14 +335,14 @@ void fldbld(void) /* create fields from *fr = 0; } else if ((sep = *inputFS) == 0) { /* new: FS="" => 1 char/field */ for (i = 0; *r != '\0'; r += n) { - char buf[MB_LEN_MAX + 1]; + char buf[MB_CUR_MAX + 1]; i++; if (i > nfields) growfldtab(i); if (freeable(fldtab[i])) xfree(fldtab[i]->sval); - n = mblen(r, MB_LEN_MAX); + n = mblen(r, MB_CUR_MAX); if (n < 0) n = 1; memcpy(buf, r, n); @@ -429,7 +406,7 @@ void cleanfld(int n1, int n2) /* clean o p = fldtab[i]; if (freeable(p)) xfree(p->sval); - p->sval = EMPTY, + p->sval = ""; p->tval = FLD | STR | DONTFREE; } } @@ -475,7 +452,7 @@ void growfldtab(int n) /* make new field if (n > nf) nf = n; s = (nf+1) * (sizeof (struct Cell *)); /* freebsd: how much do we need? */ - if (s / sizeof(struct Cell *) - 1 == (size_t)nf) /* didn't overflow */ + if (s / sizeof(struct Cell *) - 1 == nf) /* didn't overflow */ fldtab = realloc(fldtab, s); else /* overflow sizeof int */ xfree(fldtab); /* make it null */ @@ -598,6 +575,33 @@ void SYNTAX(const char *fmt, ...) eprint(); } +void fpecatch(int sig) +{ + extern Node *curnode; + + dprintf(STDERR_FILENO, "floating point exception\n"); + + if (compile_time != 2 && NR && *NR > 0) { + dprintf(STDERR_FILENO, " input record number %d", (int) (*FNR)); + if (strcmp(*FILENAME, "-") != 0) { + dprintf(STDERR_FILENO, ", file %s", *FILENAME); + } + dprintf(STDERR_FILENO, "\n"); + } + if (compile_time != 2 && curnode) { + dprintf(STDERR_FILENO, " source line number %d", curnode->lineno); + } else if (compile_time != 2 && lineno) { + dprintf(STDERR_FILENO, " source line number %d", lineno); + } + if (compile_time == 1 && cursource() != NULL) { + dprintf(STDERR_FILENO, " source file %s", cursource()); + } + dprintf(STDERR_FILENO, "\n"); + if (dbg > 1) /* core dump if serious debugging on */ + abort(); + _exit(1); +} + extern int bracecnt, brackcnt, parencnt; void bracecheck(void) @@ -626,7 +630,7 @@ void bcheck2(int n, int c1, int c2) fprintf(stderr, "\t%d extra %c's\n", -n, c2); } -void FATAL(const char *fmt, ...) +__dead void FATAL(const char *fmt, ...) { extern char *cmdname; va_list varg; Index: main.c =================================================================== RCS file: /cvs/src/usr.bin/awk/main.c,v retrieving revision 1.38 diff -u -p -r1.38 main.c --- main.c 10 Jun 2020 21:06:09 -0000 1.38 +++ main.c 11 Jun 2020 11:02:48 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.38 2020/06/10 21:06:09 millert Exp $ */ +/* $OpenBSD: main.c,v 1.35 2020/06/10 21:04:40 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -23,7 +23,7 @@ ARISING OUT OF OR IN CONNECTION WITH THE THIS SOFTWARE. ****************************************************************/ -const char *version = "version 20200605"; +const char *version = "version 20200105"; #define DEBUG #include <stdio.h> @@ -48,91 +48,17 @@ char *lexprog; /* points to program argu extern int errorflag; /* non-zero if any syntax errors; set by yyerror */ enum compile_states compile_time = ERROR_PRINTING; -static char **pfile; /* program filenames from -f's */ -static size_t maxpfile; /* max program filename */ -static size_t npfile; /* number of filenames */ -static size_t curpfile; /* current filename */ +#define MAX_PFILE 20 /* max number of -f's */ -bool safe = false; /* true => "safe" mode */ - -static noreturn void fpecatch(int n -#ifdef SA_SIGINFO - , siginfo_t *si, void *uc -#endif -) -{ - extern Node *curnode; -#ifdef SA_SIGINFO - static const char *emsg[] = { - [0] = "Unknown error", - [FPE_INTDIV] = "Integer divide by zero", - [FPE_INTOVF] = "Integer overflow", - [FPE_FLTDIV] = "Floating point divide by zero", - [FPE_FLTOVF] = "Floating point overflow", - [FPE_FLTUND] = "Floating point underflow", - [FPE_FLTRES] = "Floating point inexact result", - [FPE_FLTINV] = "Invalid Floating point operation", - [FPE_FLTSUB] = "Subscript out of range", - }; -#endif - dprintf(STDERR_FILENO, "floating point exception%s%s\n", -#ifdef SA_SIGINFO - ": ", (size_t)si->si_code < sizeof(emsg) / sizeof(emsg[0]) && - emsg[si->si_code] ? emsg[si->si_code] : emsg[0] -#else - "", "" -#endif - ); - - if (compile_time != 2 && NR && *NR > 0) { - dprintf(STDERR_FILENO, " input record number %d", (int) (*FNR)); - if (strcmp(*FILENAME, "-") != 0) { - dprintf(STDERR_FILENO, ", file %s", *FILENAME); - } - dprintf(STDERR_FILENO, "\n"); - } - if (compile_time != 2 && curnode) { - dprintf(STDERR_FILENO, " source line number %d", curnode->lineno); - } else if (compile_time != 2 && lineno) { - dprintf(STDERR_FILENO, " source line number %d", lineno); - } - if (compile_time == 1 && cursource() != NULL) { - dprintf(STDERR_FILENO, " source file %s", cursource()); - } - dprintf(STDERR_FILENO, "\n"); - if (dbg > 1) /* core dump if serious debugging on */ - abort(); - _exit(2); -} +char *pfile[MAX_PFILE]; /* program filenames from -f's */ +int npfile = 0; /* number of filenames */ +int curpfile = 0; /* current filename */ -static const char * -setfs(char *p) -{ - /* wart: t=>\t */ - if (p[0] == 't' && p[1] == '\0') - return "\t"; - else if (p[0] != '\0') - return p; - return NULL; -} - -static char * -getarg(int *argc, char ***argv, const char *msg) -{ - if ((*argv)[1][2] != '\0') { /* arg is -fsomething */ - return &(*argv)[1][2]; - } else { /* arg is -f something */ - (*argc)--; (*argv)++; - if (*argc <= 1) - FATAL("%s", msg); - return (*argv)[1]; - } -} +bool safe = false; /* true => "safe" mode */ int main(int argc, char *argv[]) { const char *fs = NULL; - char *fn, *vn; setlocale(LC_ALL, ""); setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */ @@ -150,17 +76,7 @@ int main(int argc, char *argv[]) cmdname); exit(1); } -#ifdef SA_SIGINFO - { - struct sigaction sa; - sa.sa_sigaction = fpecatch; - sa.sa_flags = SA_SIGINFO; - sigemptyset(&sa.sa_mask); - (void)sigaction(SIGFPE, &sa, NULL); - } -#else - (void)signal(SIGFPE, fpecatch); -#endif + signal(SIGFPE, fpecatch); yyin = NULL; symtab = makesymtab(NSYMTAB); @@ -176,26 +92,50 @@ int main(int argc, char *argv[]) safe = true; break; case 'f': /* next argument is program filename */ - fn = getarg(&argc, &argv, "no program filename"); - if (npfile >= maxpfile) { - maxpfile += 20; - pfile = realloc(pfile, maxpfile * sizeof(*pfile)); - if (pfile == NULL) - FATAL("error allocating space for -f options"); - } - pfile[npfile++] = fn; - break; + if (argv[1][2] != 0) { /* arg is -fsomething */ + if (npfile >= MAX_PFILE - 1) + FATAL("too many -f options"); + pfile[npfile++] = &argv[1][2]; + } else { /* arg is -f something */ + argc--; argv++; + if (argc <= 1) + FATAL("no program filename"); + if (npfile >= MAX_PFILE - 1) + FATAL("too many -f options"); + pfile[npfile++] = argv[1]; + } + break; case 'F': /* set field separator */ - fs = setfs(getarg(&argc, &argv, "no field separator")); - if (fs == NULL) + if (argv[1][2] != 0) { /* arg is -Fsomething */ + if (argv[1][2] == 't' && argv[1][3] == 0) /* wart: t=>\t */ + fs = "\t"; + else if (argv[1][2] != 0) + fs = &argv[1][2]; + } else { /* arg is -F something */ + argc--; argv++; + if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0) /* wart: t=>\t */ + fs = "\t"; + else if (argc > 1 && argv[1][0] != 0) + fs = &argv[1][0]; + } + if (fs == NULL || *fs == '\0') WARNING("field separator FS is empty"); break; case 'v': /* -v a=1 to be done NOW. one -v for each */ - vn = getarg(&argc, &argv, "no variable name"); - if (isclvar(vn)) - setclvar(vn); - else - FATAL("invalid -v option argument: %s", vn); + if (argv[1][2] != 0) { /* arg is -vsomething */ + if (isclvar(&argv[1][2])) + setclvar(&argv[1][2]); + else + FATAL("invalid -v option argument: %s", &argv[1][2]); + } else { /* arg is -v something */ + argc--; argv++; + if (argc <= 1) + FATAL("no variable name"); + if (isclvar(argv[1])) + setclvar(argv[1]); + else + FATAL("invalid -v option argument: %s", argv[1]); + } break; case 'd': dbg = atoi(&argv[1][2]); @@ -244,11 +184,7 @@ int main(int argc, char *argv[]) if (!safe) envinit(environ); yyparse(); -#if 0 - // Doing this would comply with POSIX, but is not compatible with - // other awks and with what most users expect. So comment it out. setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */ -#endif if (fs) *FS = qstring(fs, '\0'); DPRINTF( ("errorflag=%d\n", errorflag) ); Index: maketab.c =================================================================== RCS file: /cvs/src/usr.bin/awk/maketab.c,v retrieving revision 1.18 diff -u -p -r1.18 maketab.c --- maketab.c 10 Jun 2020 21:05:50 -0000 1.18 +++ maketab.c 11 Jun 2020 11:02:48 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: maketab.c,v 1.18 2020/06/10 21:05:50 millert Exp $ */ +/* $OpenBSD: maketab.c,v 1.16 2020/06/10 21:03:36 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -119,11 +119,12 @@ int main(int argc, char *argv[]) char c; FILE *fp; char buf[200], name[200], def[200]; - enum { TOK_UNKNOWN, TOK_ENUM, TOK_DEFINE } tokentype = TOK_UNKNOWN; printf("#include <stdio.h>\n"); printf("#include \"awk.h\"\n"); printf("#include \"ytab.h\"\n\n"); + for (i = SIZE; --i >= 0; ) + names[i] = ""; if (argc != 2) { fprintf(stderr, "usage: maketab YTAB_H\n"); @@ -137,28 +138,12 @@ int main(int argc, char *argv[]) i = 0; while (fgets(buf, sizeof buf, fp) != NULL) { // 199 is sizeof(def) - 1 - if (tokentype != TOK_ENUM) { - n = sscanf(buf, "%1c %199s %199s %d", &c, def, name, - &tok); - if (n == 4 && c == '#' && strcmp(def, "define") == 0) { - tokentype = TOK_DEFINE; - } else if (tokentype != TOK_UNKNOWN) { - continue; - } - } - if (tokentype != TOK_DEFINE) { - /* not a valid #define, bison uses enums now */ - n = sscanf(buf, "%199s = %d,\n", name, &tok); - if (n != 2) - continue; - tokentype = TOK_ENUM; - } - if (strcmp(name, "YYSTYPE_IS_DECLARED") == 0) { - tokentype = TOK_UNKNOWN; + n = sscanf(buf, "%1c %199s %199s %d", &c, def, name, &tok); + if (n != 4 || c != '#' || strcmp(def, "define") != 0) + continue; /* not a valid #define */ + if (strcmp(name, "YYSTYPE_IS_DECLARED") == 0) continue; - } if (tok < FIRSTTOKEN || tok > LASTTOKEN) { - tokentype = TOK_UNKNOWN; /* fprintf(stderr, "maketab: funny token %d %s ignored\n", tok, buf); */ continue; } @@ -176,8 +161,10 @@ int main(int argc, char *argv[]) table[p->token-FIRSTTOKEN] = p->name; printf("\nCell *(*proctab[%d])(Node **, int) = {\n", SIZE); for (i=0; i<SIZE; i++) - printf("\t%s,\t/* %s */\n", - table[i] ? table[i] : "nullproc", names[i] ? names[i] : ""); + if (table[i]==NULL) + printf("\tnullproc,\t/* %s */\n", names[i]); + else + printf("\t%s,\t/* %s */\n", table[i], names[i]); printf("};\n\n"); printf("const char *tokname(int n)\n"); /* print a tokname() function */ Index: proto.h =================================================================== RCS file: /cvs/src/usr.bin/awk/proto.h,v retrieving revision 1.18 diff -u -p -r1.18 proto.h --- proto.h 10 Jun 2020 21:06:09 -0000 1.18 +++ proto.h 11 Jun 2020 11:02:48 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: proto.h,v 1.18 2020/06/10 21:06:09 millert Exp $ */ +/* $OpenBSD: proto.h,v 1.16 2020/06/10 21:03:56 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -47,7 +47,7 @@ extern void freetr(Node *); extern int hexstr(const uschar **); extern int quoted(const uschar **); extern char *cclenter(const char *); -extern noreturn void overflo(const char *); +extern void overflo(const char *) __attribute__((__noreturn__)); extern void cfoll(fa *, Node *); extern int first(Node *); extern void follow(Node *); @@ -112,7 +112,6 @@ extern double getfval(Cell *); extern char *getsval(Cell *); extern char *getpssval(Cell *); /* for print */ extern char *tostring(const char *); -extern char *tostringN(const char *, size_t); extern char *qstring(const char *, int); extern Cell *catstr(Cell *, Cell *); @@ -123,7 +122,7 @@ extern void growfldtab(int n); extern void savefs(void); extern int getrec(char **, int *, bool); extern void nextfile(void); -extern int readrec(char **buf, int *bufsize, FILE *inf, bool isnew); +extern int readrec(char **buf, int *bufsize, FILE *inf); extern char *getargv(int); extern void setclvar(char *); extern void fldbld(void); @@ -134,14 +133,12 @@ extern int refldbld(const char *, const extern void recbld(void); extern Cell *fieldadr(int); extern void yyerror(const char *); +extern void fpecatch(int); extern void bracecheck(void); extern void bcheck2(int, int, int); -extern void SYNTAX(const char *, ...) - __attribute__((__format__(__printf__, 1, 2))); -extern noreturn void FATAL(const char *, ...) - __attribute__((__format__(__printf__, 1, 2))); -extern void WARNING(const char *, ...) - __attribute__((__format__(__printf__, 1, 2))); +extern void SYNTAX(const char *, ...); +extern void FATAL(const char *, ...) __attribute__((__noreturn__)); +extern void WARNING(const char *, ...); extern void error(void); extern void eprint(void); extern void bclass(int); @@ -192,7 +189,7 @@ extern Cell *bltin(Node **, int); extern Cell *printstat(Node **, int); extern Cell *nullproc(Node **, int); extern FILE *redirect(int, Node *); -extern FILE *openfile(int, const char *, bool *); +extern FILE *openfile(int, const char *); extern const char *filename(FILE *); extern Cell *closefile(Node **, int); extern void closeall(void); Index: run.c =================================================================== RCS file: /cvs/src/usr.bin/awk/run.c,v retrieving revision 1.57 diff -u -p -r1.57 run.c --- run.c 10 Jun 2020 21:05:50 -0000 1.57 +++ run.c 11 Jun 2020 11:02:48 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: run.c,v 1.57 2020/06/10 21:05:50 millert Exp $ */ +/* $OpenBSD: run.c,v 1.55 2020/06/10 21:04:40 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -26,10 +26,7 @@ THIS SOFTWARE. #define DEBUG #include <stdio.h> #include <ctype.h> -#include <wchar.h> -#include <wctype.h> #include <errno.h> -#include <fcntl.h> #include <setjmp.h> #include <limits.h> #include <math.h> @@ -41,12 +38,11 @@ THIS SOFTWARE. #include "awk.h" #include "ytab.h" -static void stdinit(void); -static void flush_all(void); +#define tempfree(x) if (istemp(x)) tfree(x); else + +/* +#undef tempfree -#if 1 -#define tempfree(x) do { if (istemp(x)) tfree(x); } while (/*CONSTCOND*/0) -#else void tempfree(Cell *p) { if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) { WARNING("bad csub %d in Cell %d %s", @@ -55,7 +51,7 @@ void tempfree(Cell *p) { if (istemp(p)) tfree(p); } -#endif +*/ /* do we really need these? */ /* #ifdef _NFILE */ @@ -79,26 +75,29 @@ extern Awkfloat srand_seed; Node *winner = NULL; /* root of parse tree */ Cell *tmps; /* free temporary cells for execution */ -static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM, NULL, NULL }; +static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM, NULL }; Cell *True = &truecell; -static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM, NULL, NULL }; +static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM, NULL }; Cell *False = &falsecell; -static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM, NULL, NULL }; +static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM, NULL }; Cell *jbreak = &breakcell; -static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM, NULL, NULL }; +static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM, NULL }; Cell *jcont = &contcell; -static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM, NULL, NULL }; +static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM, NULL }; Cell *jnext = &nextcell; -static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM, NULL, NULL }; +static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM, NULL }; Cell *jnextfile = &nextfilecell; -static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM, NULL, NULL }; +static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM, NULL }; Cell *jexit = &exitcell; -static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM, NULL, NULL }; +static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM, NULL }; Cell *jret = &retcell; -static Cell tempcell ={ OCELL, CTEMP, 0, EMPTY, 0.0, NUM|STR|DONTFREE, NULL, NULL }; +static Cell tempcell ={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE, NULL }; Node *curnode = NULL; /* the node being executed, for debugging */ +void stdinit(void); +void flush_all(void); + /* buffer memory management */ int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr, const char *whatrtn) @@ -223,11 +222,11 @@ struct Frame { /* stack frame for awk fu struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */ int nframe = 0; /* number of frames allocated */ -struct Frame *frp = NULL; /* frame pointer. bottom level unused */ +struct Frame *fp = NULL; /* frame pointer. bottom level unused */ Cell *call(Node **a, int n) /* function call. very kludgy and fragile */ { - static const Cell newcopycell = { OCELL, CCOPY, 0, EMPTY, 0.0, NUM|STR|DONTFREE, NULL, NULL }; + static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE, NULL }; int i, ncall, ndef; int freed = 0; /* handles potential double freeing when fcn & param share a tempcell */ Node *x; @@ -240,21 +239,21 @@ Cell *call(Node **a, int n) /* function if (!isfcn(fcn)) FATAL("calling undefined function %s", s); if (frame == NULL) { - frp = frame = calloc(nframe += 100, sizeof(*frame)); + fp = frame = calloc(nframe += 100, sizeof(*frame)); if (frame == NULL) FATAL("out of space for stack frames calling %s", s); } for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */ ncall++; ndef = (int) fcn->fval; /* args in defn */ - DPRINTF( ("calling %s, %d args (%d in defn), frp=%d\n", s, ncall, ndef, (int) (frp-frame)) ); + DPRINTF( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) ); if (ncall > ndef) WARNING("function %s called with %d args, uses only %d", s, ncall, ndef); if (ncall + ndef > NARGS) FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS); for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */ - DPRINTF( ("evaluate args[%d], frp=%d:\n", i, (int) (frp-frame)) ); + DPRINTF( ("evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) ); y = execute(x); oargs[i] = y; DPRINTF( ("args[%d]: %s %f <%s>, t=%o\n", @@ -271,25 +270,26 @@ Cell *call(Node **a, int n) /* function args[i] = gettemp(); *args[i] = newcopycell; } - frp++; /* now ok to up frame */ - if (frp >= frame + nframe) { - int dfp = frp - frame; /* old index */ - frame = reallocarray(frame, (nframe += 100), sizeof(*frame)); + fp++; /* now ok to up frame */ + if (fp >= frame + nframe) { + int dfp = fp - frame; /* old index */ + frame = reallocarray(frame, (nframe += 100), + sizeof(*frame)); if (frame == NULL) FATAL("out of space for stack frames in %s", s); - frp = frame + dfp; + fp = frame + dfp; } - frp->fcncell = fcn; - frp->args = args; - frp->nargs = ndef; /* number defined with (excess are locals) */ - frp->retval = gettemp(); + fp->fcncell = fcn; + fp->args = args; + fp->nargs = ndef; /* number defined with (excess are locals) */ + fp->retval = gettemp(); - DPRINTF( ("start exec of %s, frp=%d\n", s, (int) (frp-frame)) ); + DPRINTF( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) ); y = execute((Node *)(fcn->sval)); /* execute body */ - DPRINTF( ("finished exec of %s, frp=%d\n", s, (int) (frp-frame)) ); + DPRINTF( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) ); for (i = 0; i < ndef; i++) { - Cell *t = frp->args[i]; + Cell *t = fp->args[i]; if (isarr(t)) { if (t->csub == CCOPY) { if (i >= ncall) { @@ -318,9 +318,9 @@ Cell *call(Node **a, int n) /* function if (freed == 0) { tempfree(y); /* don't free twice! */ } - z = frp->retval; /* return value */ + z = fp->retval; /* return value */ DPRINTF( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) ); - frp--; + fp--; return(z); } @@ -347,11 +347,11 @@ Cell *arg(Node **a, int n) /* nth argume { n = ptoi(a[0]); /* argument number, counting from 0 */ - DPRINTF( ("arg(%d), frp->nargs=%d\n", n, frp->nargs) ); - if (n+1 > frp->nargs) + DPRINTF( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) ); + if (n+1 > fp->nargs) FATAL("argument #%d of function %s was not supplied", - n+1, frp->fcncell->nval); - return frp->args[n]; + n+1, fp->fcncell->nval); + return fp->args[n]; } Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */ @@ -370,14 +370,14 @@ Cell *jump(Node **a, int n) /* break, co if (a[0] != NULL) { y = execute(a[0]); if ((y->tval & (STR|NUM)) == (STR|NUM)) { - setsval(frp->retval, getsval(y)); - frp->retval->fval = getfval(y); - frp->retval->tval |= NUM; + setsval(fp->retval, getsval(y)); + fp->retval->fval = getfval(y); + fp->retval->tval |= NUM; } else if (y->tval & STR) - setsval(frp->retval, getsval(y)); + setsval(fp->retval, getsval(y)); else if (y->tval & NUM) - setfval(frp->retval, getfval(y)); + setfval(fp->retval, getfval(y)); else /* can't happen */ FATAL("bad type variable %d", y->tval); tempfree(y); @@ -406,7 +406,6 @@ Cell *awkgetline(Node **a, int n) /* get char *buf; int bufsize = recsize; int mode; - bool newflag; if ((buf = malloc(bufsize)) == NULL) FATAL("out of memory in getline"); @@ -418,12 +417,12 @@ Cell *awkgetline(Node **a, int n) /* get mode = ptoi(a[1]); if (mode == '|') /* input pipe */ mode = LE; /* arbitrary flag */ - fp = openfile(mode, getsval(x), &newflag); + fp = openfile(mode, getsval(x)); tempfree(x); if (fp == NULL) n = -1; else - n = readrec(&buf, &bufsize, fp, newflag); + n = readrec(&buf, &bufsize, fp); if (n <= 0) { ; } else if (a[0] != NULL) { /* getline var <file */ @@ -797,8 +796,8 @@ Cell *sindex(Node **a, int nnn) /* inde z = gettemp(); for (p1 = s1; *p1 != '\0'; p1++) { - for (q = p1, p2 = s2; *p2 != '\0' && *q == *p2; q++, p2++) - continue; + for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++) + ; if (*p2 == '\0') { v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */ break; @@ -830,10 +829,10 @@ int format(char **pbuf, int *pbufsize, c static bool have_a_format = false; if (first) { - char xbuf[100]; + char buf[100]; - snprintf(xbuf, sizeof(xbuf), "%a", 42.0); - have_a_format = (strcmp(xbuf, "0x1.5p+5") == 0); + snprintf(buf, sizeof(buf), "%a", 42.0); + have_a_format = (strcmp(buf, "0x1.5p+5") == 0); first = false; } @@ -1069,7 +1068,7 @@ Cell *arith(Node **a, int n) /* a[0] + a case UMINUS: i = -i; break; - case UPLUS: /* handled by getfval(), above */ + case UPLUS: /* handled by getfval(), above */ break; case POWER: if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */ @@ -1255,8 +1254,7 @@ Cell *split(Node **a, int nnn) /* split( { Cell *x = NULL, *y, *ap; const char *s, *origs, *t; - const char *fs = NULL; - char *origfs = NULL; + char *fs = NULL, *origfs = NULL; int sep; char temp, num[50]; int n, tempstat, arg3type; @@ -1270,7 +1268,7 @@ Cell *split(Node **a, int nnn) /* split( fs = getsval(fsloc); else if (arg3type == STRING) { /* split(str,arr,"string") */ x = execute(a[2]); - fs = origfs = strdup(getsval(x)); + origfs = fs = strdup(getsval(x)); if (fs == NULL) FATAL("out of space in split"); tempfree(x); @@ -1314,7 +1312,7 @@ Cell *split(Node **a, int nnn) /* split( setsymtab(num, s, 0.0, STR, (Array *) ap->sval); setptr(patbeg, temp); s = patbeg + patlen; - if (*(patbeg+patlen-1) == '\0' || *s == '\0') { + if (*(patbeg+patlen-1) == 0 || *s == 0) { n++; snprintf(num, sizeof(num), "%d", n); setsymtab(num, "", 0.0, STR, (Array *) ap->sval); @@ -1335,16 +1333,15 @@ Cell *split(Node **a, int nnn) /* split( pfa = NULL; } else if (sep == ' ') { for (n = 0; ; ) { -#define ISWS(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') - while (ISWS(*s)) + while (*s == ' ' || *s == '\t' || *s == '\n') s++; - if (*s == '\0') + if (*s == 0) break; n++; t = s; do s++; - while (*s != '\0' && !ISWS(*s)); + while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0'); temp = *s; setptr(s, '\0'); snprintf(num, sizeof(num), "%d", n); @@ -1353,22 +1350,22 @@ Cell *split(Node **a, int nnn) /* split( else setsymtab(num, t, 0.0, STR, (Array *) ap->sval); setptr(s, temp); - if (*s != '\0') + if (*s != 0) s++; } } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */ - for (n = 0; *s != '\0'; s++) { + for (n = 0; *s != 0; s++) { char buf[2]; n++; snprintf(num, sizeof(num), "%d", n); buf[0] = *s; - buf[1] = '\0'; + buf[1] = 0; if (isdigit((uschar)buf[0])) setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval); else setsymtab(num, buf, 0.0, STR, (Array *) ap->sval); } - } else if (*s != '\0') { + } else if (*s != 0) { for (;;) { n++; t = s; @@ -1382,7 +1379,7 @@ Cell *split(Node **a, int nnn) /* split( else setsymtab(num, t, 0.0, STR, (Array *) ap->sval); setptr(s, temp); - if (*s++ == '\0') + if (*s++ == 0) break; } } @@ -1519,71 +1516,13 @@ Cell *instat(Node **a, int n) /* for (a[ return True; } -static char *nawk_convert(const char *s, int (*fun_c)(int), - wint_t (*fun_wc)(wint_t)) -{ - char *buf = NULL; - char *pbuf = NULL; - const char *ps = NULL; - size_t n = 0; - mbstate_t mbs, mbs2; - wchar_t wc; - size_t sz = MB_CUR_MAX; - - if (sz == 1) { - buf = tostring(s); - - for (pbuf = buf; *pbuf; pbuf++) - *pbuf = fun_c((uschar)*pbuf); - - return buf; - } else { - /* upper/lower character may be shorter/longer */ - buf = tostringN(s, strlen(s) * sz + 1); - - memset(&mbs, 0, sizeof(mbs)); - memset(&mbs2, 0, sizeof(mbs2)); - - ps = s; - pbuf = buf; - while (n = mbrtowc(&wc, ps, sz, &mbs), - n > 0 && n != (size_t)-1 && n != (size_t)-2) - { - ps += n; - - n = wcrtomb(pbuf, fun_wc(wc), &mbs2); - if (n == (size_t)-1) - FATAL("illegal wide character %s", s); - - pbuf += n; - } - - *pbuf = '\0'; - - if (n) - FATAL("illegal byte sequence %s", s); - - return buf; - } -} - -static char *nawk_toupper(const char *s) -{ - return nawk_convert(s, toupper, towupper); -} - -static char *nawk_tolower(const char *s) -{ - return nawk_convert(s, tolower, towlower); -} - Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */ { Cell *x, *y; Awkfloat u; int t; Awkfloat tmp; - char *buf; + char *p, *buf; Node *nextarg; FILE *fp; int status = 0; @@ -1720,10 +1659,16 @@ Cell *bltin(Node **a, int n) /* builtin break; case FTOUPPER: case FTOLOWER: - if (t == FTOUPPER) - buf = nawk_toupper(getsval(x)); - else - buf = nawk_tolower(getsval(x)); + buf = tostring(getsval(x)); + if (t == FTOUPPER) { + for (p = buf; *p; p++) + if (islower((uschar) *p)) + *p = toupper((uschar)*p); + } else { + for (p = buf; *p; p++) + if (isupper((uschar) *p)) + *p = tolower((uschar)*p); + } tempfree(x); x = gettemp(); setsval(x, buf); @@ -1733,7 +1678,7 @@ Cell *bltin(Node **a, int n) /* builtin if (isrec(x) || strlen(getsval(x)) == 0) { flush_all(); /* fflush() or fflush("") -> all */ u = 0; - } else if ((fp = openfile(FFLUSH, getsval(x), NULL)) == NULL) + } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL) u = EOF; else u = fflush(fp); @@ -1793,7 +1738,7 @@ FILE *redirect(int a, Node *b) /* set up x = execute(b); fname = getsval(x); - fp = openfile(a, fname, NULL); + fp = openfile(a, fname); if (fp == NULL) FATAL("can't open file %s", fname); tempfree(x); @@ -1806,14 +1751,14 @@ struct files { int mode; /* '|', 'a', 'w' => LE/LT, GT */ } *files; -size_t nfiles; +int nfiles; -static void stdinit(void) /* in case stdin, etc., are not constants */ +void stdinit(void) /* in case stdin, etc., are not constants */ { nfiles = FOPEN_MAX; files = calloc(nfiles, sizeof(*files)); if (files == NULL) - FATAL("can't allocate file memory for %zu files", nfiles); + FATAL("can't allocate file memory for %u files", nfiles); files[0].fp = stdin; files[0].fname = "/dev/stdin"; files[0].mode = LT; @@ -1825,35 +1770,33 @@ static void stdinit(void) /* in case std files[2].mode = GT; } -FILE *openfile(int a, const char *us, bool *pnewflag) +FILE *openfile(int a, const char *us) { const char *s = us; - size_t i; - int m; + int i, m; FILE *fp = NULL; if (*s == '\0') FATAL("null file name in print or getline"); - for (i = 0; i < nfiles; i++) - if (files[i].fname && strcmp(s, files[i].fname) == 0 && - (a == files[i].mode || (a==APPEND && files[i].mode==GT) || - a == FFLUSH)) { - if (pnewflag) - *pnewflag = false; - return files[i].fp; + for (i=0; i < nfiles; i++) + if (files[i].fname && strcmp(s, files[i].fname) == 0) { + if (a == files[i].mode || (a==APPEND && files[i].mode==GT)) + return files[i].fp; + if (a == FFLUSH) + return files[i].fp; } if (a == FFLUSH) /* didn't find it, so don't create it! */ return NULL; - for (i = 0; i < nfiles; i++) + for (i=0; i < nfiles; i++) if (files[i].fp == NULL) break; if (i >= nfiles) { struct files *nf; - size_t nnf = nfiles + FOPEN_MAX; + int nnf = nfiles + FOPEN_MAX; nf = reallocarray(files, nnf, sizeof(*nf)); if (nf == NULL) - FATAL("cannot grow files for %s and %zu files", s, nnf); + FATAL("cannot grow files for %s and %d files", s, nnf); memset(&nf[nfiles], 0, FOPEN_MAX * sizeof(*nf)); nfiles = nnf; files = nf; @@ -1877,17 +1820,13 @@ FILE *openfile(int a, const char *us, bo files[i].fname = tostring(s); files[i].fp = fp; files[i].mode = m; - if (pnewflag) - *pnewflag = true; - if (fp != stdin && fp != stdout && fp != stderr) - (void) fcntl(fileno(fp), F_SETFD, FD_CLOEXEC); } return fp; } const char *filename(FILE *fp) { - size_t i; + int i; for (i = 0; i < nfiles; i++) if (fp == files[i].fp) @@ -1895,59 +1834,57 @@ const char *filename(FILE *fp) return "???"; } - Cell *closefile(Node **a, int n) - { - Cell *x; - size_t i; - bool stat; - - x = execute(a[0]); - getsval(x); - stat = true; - for (i = 0; i < nfiles; i++) { - if (!files[i].fname || strcmp(x->sval, files[i].fname) != 0) - continue; - if (ferror(files[i].fp)) - FATAL("i/o error occurred on %s", files[i].fname); - if (files[i].mode == '|' || files[i].mode == LE) - stat = pclose(files[i].fp) == -1; - else - stat = fclose(files[i].fp) == EOF; - if (stat) - FATAL("i/o error occurred closing %s", files[i].fname); - if (i > 2) /* don't do /dev/std... */ - xfree(files[i].fname); - files[i].fname = NULL; /* watch out for ref thru this */ - files[i].fp = NULL; - } - tempfree(x); - x = gettemp(); - setfval(x, (Awkfloat) (stat ? -1 : 0)); - return(x); - } +Cell *closefile(Node **a, int n) +{ + Cell *x; + int i, stat; + + x = execute(a[0]); + getsval(x); + stat = -1; + for (i = 0; i < nfiles; i++) { + if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) { + if (ferror(files[i].fp)) + WARNING( "i/o error occurred on %s", files[i].fname ); + if (files[i].mode == '|' || files[i].mode == LE) + stat = pclose(files[i].fp); + else + stat = fclose(files[i].fp); + if (stat == EOF) + WARNING( "i/o error occurred closing %s", files[i].fname ); + if (i > 2) /* don't do /dev/std... */ + xfree(files[i].fname); + files[i].fname = NULL; /* watch out for ref thru this */ + files[i].fp = NULL; + } + } + tempfree(x); + x = gettemp(); + setfval(x, (Awkfloat) stat); + return(x); +} void closeall(void) { - size_t i; - bool stat = false; + int i, stat; - for (i = 0; i < nfiles; i++) { - if (! files[i].fp) - continue; - if (ferror(files[i].fp)) - FATAL( "i/o error occurred on %s", files[i].fname ); - if (files[i].mode == '|' || files[i].mode == LE) - stat = pclose(files[i].fp) == -1; - else - stat = fclose(files[i].fp) == EOF; - if (stat) - FATAL( "i/o error occurred while closing %s", files[i].fname ); + for (i = 0; i < FOPEN_MAX; i++) { + if (files[i].fp) { + if (ferror(files[i].fp)) + WARNING( "i/o error occurred on %s", files[i].fname ); + if (files[i].mode == '|' || files[i].mode == LE) + stat = pclose(files[i].fp); + else + stat = fclose(files[i].fp); + if (stat == EOF) + WARNING( "i/o error occurred while closing %s", files[i].fname ); + } } } -static void flush_all(void) +void flush_all(void) { - size_t i; + int i; for (i = 0; i < nfiles; i++) if (files[i].fp) @@ -1984,7 +1921,7 @@ Cell *sub(Node **a, int nnn) /* substitu while (sptr < patbeg) *pb++ = *sptr++; sptr = getsval(y); - while (*sptr != '\0') { + while (*sptr != 0) { adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub"); if (*sptr == '\\') { backsub(&pb, &sptr); @@ -2002,8 +1939,8 @@ Cell *sub(Node **a, int nnn) /* substitu sptr = patbeg + patlen; if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) { adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub"); - while ((*pb++ = *sptr++) != '\0') - continue; + while ((*pb++ = *sptr++) != 0) + ; } if (pb > buf + bufsz) FATAL("sub result2 %.30s too big; can't happen", buf); @@ -2046,11 +1983,11 @@ Cell *gsub(Node **a, int nnn) /* global pb = buf; rptr = getsval(y); do { - if (patlen == 0 && *patbeg != '\0') { /* matched empty string */ + if (patlen == 0 && *patbeg != 0) { /* matched empty string */ if (mflag == 0) { /* can replace empty */ num++; sptr = rptr; - while (*sptr != '\0') { + while (*sptr != 0) { adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); if (*sptr == '\\') { backsub(&pb, &sptr); @@ -2063,7 +2000,7 @@ Cell *gsub(Node **a, int nnn) /* global *pb++ = *sptr++; } } - if (*t == '\0') /* at end */ + if (*t == 0) /* at end */ goto done; adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub"); *pb++ = *t++; @@ -2078,7 +2015,7 @@ Cell *gsub(Node **a, int nnn) /* global while (sptr < patbeg) *pb++ = *sptr++; sptr = rptr; - while (*sptr != '\0') { + while (*sptr != 0) { adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); if (*sptr == '\\') { backsub(&pb, &sptr); @@ -2091,7 +2028,7 @@ Cell *gsub(Node **a, int nnn) /* global *pb++ = *sptr++; } t = patbeg + patlen; - if (patlen == 0 || *t == '\0' || *(t-1) == '\0') + if (patlen == 0 || *t == 0 || *(t-1) == 0) goto done; if (pb > buf + bufsz) FATAL("gsub result1 %.30s too big; can't happen", buf); @@ -2100,8 +2037,8 @@ Cell *gsub(Node **a, int nnn) /* global } while (pmatch(pfa,t)); sptr = t; adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub"); - while ((*pb++ = *sptr++) != '\0') - continue; + while ((*pb++ = *sptr++) != 0) + ; done: if (pb < buf + bufsz) *pb = '\0'; else if (*(pb-1) != '\0') @@ -2122,13 +2059,6 @@ void backsub(char **pb_ptr, const char * { /* sptr[0] == '\\' */ char *pb = *pb_ptr; const char *sptr = *sptr_ptr; - static bool first = true; - static bool do_posix = false; - - if (first) { - first = false; - do_posix = (getenv("POSIXLY_CORRECT") != NULL); - } if (sptr[1] == '\\') { if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */ @@ -2138,9 +2068,6 @@ void backsub(char **pb_ptr, const char * } else if (sptr[2] == '&') { /* \\& -> \ + matched */ *pb++ = '\\'; sptr += 2; - } else if (do_posix) { /* \\x -> \x */ - sptr++; - *pb++ = *sptr++; } else { /* \\x -> \\x */ *pb++ = *sptr++; *pb++ = *sptr++; Index: tran.c =================================================================== RCS file: /cvs/src/usr.bin/awk/tran.c,v retrieving revision 1.27 diff -u -p -r1.27 tran.c --- tran.c 10 Jun 2020 21:05:50 -0000 1.27 +++ tran.c 11 Jun 2020 11:02:48 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: tran.c,v 1.27 2020/06/10 21:05:50 millert Exp $ */ +/* $OpenBSD: tran.c,v 1.25 2020/06/10 21:04:40 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -345,7 +345,7 @@ void funnyvar(Cell *vp, const char *rw) if (vp->tval & FCN) FATAL("can't %s %s; it's a function.", rw, vp->nval); WARNING("funny variable %p: n=%s s=\"%s\" f=%g t=%o", - (void *)vp, vp->nval, vp->sval, vp->fval, vp->tval); + vp, vp->nval, vp->sval, vp->fval, vp->tval); } char *setsval(Cell *vp, const char *s) /* set string val of a Cell */ @@ -518,17 +518,6 @@ char *tostring(const char *s) /* make a return(p); } -char *tostringN(const char *s, size_t n) /* make a copy of string s */ -{ - char *p; - - p = malloc(n); - if (p == NULL) - FATAL("out of space in tostring on %s", s); - strlcpy(p, s, n); - return(p); -} - Cell *catstr(Cell *a, Cell *b) /* concatenate a and b */ { Cell *c; @@ -540,14 +529,12 @@ Cell *catstr(Cell *a, Cell *b) /* concat if (p == NULL) FATAL("out of space concatenating %s and %s", sa, sb); snprintf(p, l, "%s%s", sa, sb); - - l++; // add room for ' ' - char *newbuf = malloc(l); + char *newbuf = malloc(strlen(p) + 2); if (newbuf == NULL) FATAL("out of space concatenating %s and %s", sa, sb); // See string() in lex.c; a string "xx" is stored in the symbol // table as "xx ". - snprintf(newbuf, l, "%s ", p); + sprintf(newbuf, "%s ", p); c = setsymtab(newbuf, p, 0.0, CON|STR|DONTFREE, symtab); free(p); free(newbuf);
awk-problem.tgz
Description: application/tar-gz