diff options
Diffstat (limited to 'usr.bin/awk')
-rw-r--r-- | usr.bin/awk/FIXES | 27 | ||||
-rw-r--r-- | usr.bin/awk/awk.1 | 17 | ||||
-rw-r--r-- | usr.bin/awk/awk.h | 5 | ||||
-rw-r--r-- | usr.bin/awk/awkgram.y | 4 | ||||
-rw-r--r-- | usr.bin/awk/b.c | 20 | ||||
-rw-r--r-- | usr.bin/awk/lex.c | 16 | ||||
-rw-r--r-- | usr.bin/awk/lib.c | 31 | ||||
-rw-r--r-- | usr.bin/awk/main.c | 4 | ||||
-rw-r--r-- | usr.bin/awk/maketab.c | 10 | ||||
-rw-r--r-- | usr.bin/awk/run.c | 32 | ||||
-rw-r--r-- | usr.bin/awk/tran.c | 8 |
11 files changed, 120 insertions, 54 deletions
diff --git a/usr.bin/awk/FIXES b/usr.bin/awk/FIXES index d1c3217d28d..04c201fd60b 100644 --- a/usr.bin/awk/FIXES +++ b/usr.bin/awk/FIXES @@ -1,4 +1,4 @@ -/* $OpenBSD: FIXES,v 1.30 2020/06/10 21:04:40 millert Exp $ */ +/* $OpenBSD: FIXES,v 1.31 2020/06/10 21:05:02 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -26,6 +26,25 @@ THIS SOFTWARE. This file lists all bug fixes, changes, etc., made since the AWK book was sent to the printers in August, 1987. +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). 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 <martijn@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 @@ -64,13 +83,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 @@ -78,7 +97,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: diff --git a/usr.bin/awk/awk.1 b/usr.bin/awk/awk.1 index 770f558d1b5..84e4f057e73 100644 --- a/usr.bin/awk/awk.1 +++ b/usr.bin/awk/awk.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: awk.1,v 1.49 2020/06/10 21:02:53 millert Exp $ +.\" $OpenBSD: awk.1,v 1.50 2020/06/10 21:05:02 millert Exp $ .\" .\" Copyright (C) Lucent Technologies 1997 .\" All Rights Reserved @@ -726,6 +726,14 @@ Returns integer argument x shifted by n bits to the left. .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 @@ -792,7 +800,12 @@ The .Nm utility is compliant with the .St -p1003.1-2008 -specification. +specification except that consecutive backslashes in the replacement +string argument for +.Fn sub +and +.Fn gsub +are not collapsed. .Pp The flags .Op Fl \&dV diff --git a/usr.bin/awk/awk.h b/usr.bin/awk/awk.h index ba604cae6a6..e010dd7184d 100644 --- a/usr.bin/awk/awk.h +++ b/usr.bin/awk/awk.h @@ -1,4 +1,4 @@ -/* $OpenBSD: awk.h,v 1.21 2020/06/10 21:03:56 millert Exp $ */ +/* $OpenBSD: awk.h,v 1.22 2020/06/10 21:05:02 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -61,6 +61,7 @@ extern bool safe; /* false => unsafe, true => safe */ #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; @@ -79,8 +80,6 @@ extern int lineno; /* line number in awk program */ 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 */ diff --git a/usr.bin/awk/awkgram.y b/usr.bin/awk/awkgram.y index 9a59fc785aa..85034770f07 100644 --- a/usr.bin/awk/awkgram.y +++ b/usr.bin/awk/awkgram.y @@ -1,4 +1,4 @@ -/* $OpenBSD: awkgram.y,v 1.12 2020/06/10 21:03:56 millert Exp $ */ +/* $OpenBSD: awkgram.y,v 1.13 2020/06/10 21:05:02 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -51,7 +51,7 @@ Node *arglist = 0; /* list of args for current function */ %token <i> NL ',' '{' '(' '|' ';' '/' ')' '}' '[' ']' %token <i> ARRAY %token <i> MATCH NOTMATCH MATCHOP -%token <i> FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS EMPTYRE +%token <i> FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS EMPTYRE ZERO %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 diff --git a/usr.bin/awk/b.c b/usr.bin/awk/b.c index 97719cf1132..687ff5015f8 100644 --- a/usr.bin/awk/b.c +++ b/usr.bin/awk/b.c @@ -1,4 +1,4 @@ -/* $OpenBSD: b.c,v 1.30 2020/06/10 21:04:40 millert Exp $ */ +/* $OpenBSD: b.c,v 1.31 2020/06/10 21:05:02 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -271,6 +271,8 @@ void penter(Node *p) /* set up parent pointers and leaf indices */ 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; @@ -285,6 +287,7 @@ void freetr(Node *p) /* free parse tree */ xfree(p); break; UNARY + case ZERO: freetr(left(p)); xfree(p); break; @@ -444,6 +447,8 @@ void cfoll(fa *f, Node *v) /* enter follow set of each leaf of vertex v into lfo 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)); } @@ -487,6 +492,8 @@ int first(Node *p) /* collects initially active leaves of p into setvec */ 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); @@ -846,6 +853,9 @@ 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); } @@ -880,7 +890,7 @@ int (xisblank)(int c) #endif -struct charclass { +static const struct charclass { const char *cc_name; int cc_namelen; int (*cc_func)(int); @@ -916,7 +926,7 @@ replace_repeat(const uschar *reptok, int reptoklen, const uschar *atom, int i, j; uschar *buf = NULL; int ret = 1; - bool init_q = (firstnum == 0); /* first added char will be ? */ + int 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 */ @@ -1024,7 +1034,7 @@ int relex(void) /* lexical analyzer for reparse */ static uschar *buf = NULL; static int bufsz = 100; uschar *bp; - struct charclass *cc; + const struct charclass *cc; int i; int num, m; bool commafound, digitfound; @@ -1198,7 +1208,7 @@ rescan: if (repeat(starttok, prestr-starttok, lastatom, startreptok - lastatom, n, m) > 0) { if (n == 0 && m == 0) { - return EMPTYRE; + return ZERO; } /* must rescan input for next token */ goto rescan; diff --git a/usr.bin/awk/lex.c b/usr.bin/awk/lex.c index 9861c7d25b4..4e7a546d019 100644 --- a/usr.bin/awk/lex.c +++ b/usr.bin/awk/lex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lex.c,v 1.17 2020/06/10 21:04:40 millert Exp $ */ +/* $OpenBSD: lex.c,v 1.18 2020/06/10 21:05:02 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -44,7 +44,7 @@ typedef struct Keyword { int type; } Keyword; -Keyword keywords[] ={ /* keep sorted: binary searched */ +const Keyword keywords[] = { /* keep sorted: binary searched */ { "BEGIN", XBEGIN, XBEGIN }, { "END", XEND, XEND }, { "NF", VARNF, VARNF }, @@ -102,14 +102,14 @@ int peek(void); int gettok(char **, int *); int binsearch(char *, Keyword *, int); -int peek(void) +static int peek(void) { int c = input(); unput(c); return c; } -int gettok(char **pbuf, int *psz) /* get next input token */ +static int gettok(char **pbuf, int *psz) /* get next input token */ { int c, retc; char *buf = *pbuf; @@ -401,7 +401,7 @@ int string(void) case 'r': *bp++ = '\r'; break; case 'b': *bp++ = '\b'; break; case 'v': *bp++ = '\v'; break; - case 'a': *bp++ = '\007'; break; + case 'a': *bp++ = '\a'; break; case '\\': *bp++ = '\\'; break; case '0': case '1': case '2': /* octal: \d \dd \ddd */ @@ -451,7 +451,7 @@ int string(void) } -int binsearch(char *w, Keyword *kp, int n) +static int binsearch(char *w, const Keyword *kp, int n) { int cond, low, mid, high; @@ -471,7 +471,7 @@ int binsearch(char *w, Keyword *kp, int n) int word(char *w) { - Keyword *kp; + const Keyword *kp; int c, n; n = binsearch(w, keywords, sizeof(keywords)/sizeof(keywords[0])); @@ -587,6 +587,8 @@ int input(void) /* get next lexical input character */ 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; diff --git a/usr.bin/awk/lib.c b/usr.bin/awk/lib.c index ee3e187aa77..f00a5ec856b 100644 --- a/usr.bin/awk/lib.c +++ b/usr.bin/awk/lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lib.c,v 1.32 2020/06/10 21:03:56 millert Exp $ */ +/* $OpenBSD: lib.c,v 1.33 2020/06/10 21:05:02 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -31,18 +31,21 @@ THIS SOFTWARE. #include <stdlib.h> #include <unistd.h> #include <stdarg.h> +#include <limits.h> #include "awk.h" #include "ytab.h" +char EMPTY[] = { '\0' }; FILE *infile = NULL; -char *file = ""; +char *file = EMPTY; char *record; int recsize = RECSIZE; char *fields; int fieldssize = RECSIZE; Cell **fldtab; /* pointers to Cells */ -char inputFS[100] = " "; +static size_t len_inputFS = 0; +static char *inputFS = NULL; /* FS at time of input, for field splitting */ #define MAXFLD 2 int nfields = MAXFLD; /* last allocated slot for $i */ @@ -54,8 +57,8 @@ int lastfld = 0; /* last used field */ int argno = 1; /* current input argument number */ extern Awkfloat *ARGC; -static Cell dollar0 = { OCELL, CFLD, NULL, "", 0.0, REC|STR|DONTFREE }; -static Cell dollar1 = { OCELL, CFLD, NULL, "", 0.0, FLD|STR|DONTFREE }; +static Cell dollar0 = { OCELL, CFLD, NULL, EMPTY, 0.0, REC|STR|DONTFREE }; +static Cell dollar1 = { OCELL, CFLD, NULL, EMPTY, 0.0, FLD|STR|DONTFREE }; void recinit(unsigned int n) { @@ -118,9 +121,17 @@ void initgetrec(void) */ void savefs(void) { - if (strlen(getsval(fsloc)) >= sizeof (inputFS)) + 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) FATAL("field separator %.10s... is too long", *FS); - strlcpy(inputFS, *FS, sizeof(inputFS)); + memcpy(inputFS, *FS, len_inputFS); } static bool firsttime = true; @@ -335,14 +346,14 @@ void fldbld(void) /* create fields from current record */ *fr = 0; } else if ((sep = *inputFS) == 0) { /* new: FS="" => 1 char/field */ for (i = 0; *r != '\0'; r += n) { - char buf[MB_CUR_MAX + 1]; + char buf[MB_LEN_MAX + 1]; i++; if (i > nfields) growfldtab(i); if (freeable(fldtab[i])) xfree(fldtab[i]->sval); - n = mblen(r, MB_CUR_MAX); + n = mblen(r, MB_LEN_MAX); if (n < 0) n = 1; memcpy(buf, r, n); @@ -406,7 +417,7 @@ void cleanfld(int n1, int n2) /* clean out fields n1 .. n2 inclusive */ p = fldtab[i]; if (freeable(p)) xfree(p->sval); - p->sval = ""; + p->sval = EMPTY, p->tval = FLD | STR | DONTFREE; } } diff --git a/usr.bin/awk/main.c b/usr.bin/awk/main.c index cb23a884667..9c4e47874a9 100644 --- a/usr.bin/awk/main.c +++ b/usr.bin/awk/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.35 2020/06/10 21:04:40 millert Exp $ */ +/* $OpenBSD: main.c,v 1.36 2020/06/10 21:05:02 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -23,7 +23,7 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ****************************************************************/ -const char *version = "version 20200105"; +const char *version = "version 20200131"; #define DEBUG #include <stdio.h> diff --git a/usr.bin/awk/maketab.c b/usr.bin/awk/maketab.c index a488d7ed187..6c25233503a 100644 --- a/usr.bin/awk/maketab.c +++ b/usr.bin/awk/maketab.c @@ -1,4 +1,4 @@ -/* $OpenBSD: maketab.c,v 1.16 2020/06/10 21:03:36 millert Exp $ */ +/* $OpenBSD: maketab.c,v 1.17 2020/06/10 21:05:02 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -123,8 +123,6 @@ int main(int argc, char *argv[]) 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"); @@ -161,10 +159,8 @@ 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++) - if (table[i]==NULL) - printf("\tnullproc,\t/* %s */\n", names[i]); - else - printf("\t%s,\t/* %s */\n", table[i], names[i]); + printf("\t%s,\t/* %s */\n", + table[i] ? table[i] : "nullproc", names[i] ? names[i] : ""); printf("};\n\n"); printf("const char *tokname(int n)\n"); /* print a tokname() function */ diff --git a/usr.bin/awk/run.c b/usr.bin/awk/run.c index 605b71e47f6..c4a4254de64 100644 --- a/usr.bin/awk/run.c +++ b/usr.bin/awk/run.c @@ -1,4 +1,4 @@ -/* $OpenBSD: run.c,v 1.55 2020/06/10 21:04:40 millert Exp $ */ +/* $OpenBSD: run.c,v 1.56 2020/06/10 21:05:02 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -27,6 +27,7 @@ THIS SOFTWARE. #include <stdio.h> #include <ctype.h> #include <errno.h> +#include <fcntl.h> #include <setjmp.h> #include <limits.h> #include <math.h> @@ -91,7 +92,7 @@ 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 }; Cell *jret = &retcell; -static Cell tempcell ={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE, NULL }; +static Cell tempcell ={ OCELL, CTEMP, 0, EMPTY, 0.0, NUM|STR|DONTFREE, NULL }; Node *curnode = NULL; /* the node being executed, for debugging */ @@ -226,7 +227,7 @@ struct Frame *fp = NULL; /* frame pointer. bottom level unused */ Cell *call(Node **a, int n) /* function call. very kludgy and fragile */ { - static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE, NULL }; + static Cell newcopycell = { OCELL, CCOPY, 0, EMPTY, 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; @@ -1254,7 +1255,8 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ { Cell *x = NULL, *y, *ap; const char *s, *origs, *t; - char *fs = NULL, *origfs = NULL; + const char *fs = NULL; + char *origfs = NULL; int sep; char temp, num[50]; int n, tempstat, arg3type; @@ -1268,7 +1270,7 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ fs = getsval(fsloc); else if (arg3type == STRING) { /* split(str,arr,"string") */ x = execute(a[2]); - origfs = fs = strdup(getsval(x)); + fs = origfs = strdup(getsval(x)); if (fs == NULL) FATAL("out of space in split"); tempfree(x); @@ -1820,6 +1822,8 @@ FILE *openfile(int a, const char *us) files[i].fname = tostring(s); files[i].fp = fp; files[i].mode = m; + if (fp != stdin && fp != stdout && fp != stderr) + (void) fcntl(fileno(fp), F_SETFD, FD_CLOEXEC); } return fp; } @@ -1845,13 +1849,13 @@ Cell *closefile(Node **a, int n) 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 ); + FATAL( "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 ); + 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 */ @@ -1871,13 +1875,13 @@ void closeall(void) 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 ); + FATAL( "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 ); + FATAL( "i/o error occurred while closing %s", files[i].fname ); } } } @@ -2059,6 +2063,13 @@ void backsub(char **pb_ptr, const char **sptr_ptr) /* handle \\& variations */ { /* 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] == '&') { /* \\\& -> \& */ @@ -2068,6 +2079,9 @@ void backsub(char **pb_ptr, const char **sptr_ptr) /* handle \\& variations */ } else if (sptr[2] == '&') { /* \\& -> \ + matched */ *pb++ = '\\'; sptr += 2; + } else if (do_posix) { /* \\x -> \x */ + sptr++; + *pb++ = *sptr++; } else { /* \\x -> \\x */ *pb++ = *sptr++; *pb++ = *sptr++; diff --git a/usr.bin/awk/tran.c b/usr.bin/awk/tran.c index 0318be0c57d..8e8b755f9bb 100644 --- a/usr.bin/awk/tran.c +++ b/usr.bin/awk/tran.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tran.c,v 1.25 2020/06/10 21:04:40 millert Exp $ */ +/* $OpenBSD: tran.c,v 1.26 2020/06/10 21:05:02 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -529,12 +529,14 @@ Cell *catstr(Cell *a, Cell *b) /* concatenate a and b */ if (p == NULL) FATAL("out of space concatenating %s and %s", sa, sb); snprintf(p, l, "%s%s", sa, sb); - char *newbuf = malloc(strlen(p) + 2); + + l++; // add room for ' ' + char *newbuf = malloc(l); 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 ". - sprintf(newbuf, "%s ", p); + snprintf(newbuf, l, "%s ", p); c = setsymtab(newbuf, p, 0.0, CON|STR|DONTFREE, symtab); free(p); free(newbuf); |