diff --git a/contrib/one-true-awk/FIXES b/contrib/one-true-awk/FIXES index 89826ccd6e1b..e511394204f1 100644 --- a/contrib/one-true-awk/FIXES +++ b/contrib/one-true-awk/FIXES @@ -25,6 +25,43 @@ THIS SOFTWARE. This file lists all bug fixes, changes, etc., made since the AWK book was sent to the printers in August, 1987. +Nov 29, 2002: + modified b.c (with tiny changes in main and run) to support + locales, using strcoll and iswhatever tests for posix character + classes. thanks to ruslan ermilov (ru@freebsd.org) for code. + the function isblank doesn't seem to have propagated to any + header file near me, so it's there explicitly. not properly + tested on non-ascii character sets by me. + +Jun 28, 2002: + modified run/format() and tran/getsval() to do a slightly better + job on using OFMT for output from print and CONVFMT for other + number->string conversions, as promised by posix and done by + gawk and mawk. there are still places where it doesn't work + right if CONVFMT is changed; by then the STR attribute of the + variable has been irrevocably set. thanks to arnold robbins for + code and examples. + + fixed subtle bug in format that could get core dump. thanks to + Jaromir Dolecek for finding and fixing. + minor cleanup in run.c / format() at the same time. + + added some tests for null pointers to debugging printf's, which + were never intended for external consumption. thanks to dave + kerns (dkerns@lucent.com) for pointing this out. + + GNU compatibility: an empty regexp matches anything (thanks to + dag-erling smorgrav, des@ofug.org). subject to reversion if + this does more harm than good. + + pervasive small changes to make things more const-correct, as + reported by gcc's -Wwrite-strings. as it says in the gcc manual, + this may be more nuisance than useful. provoked by a suggestion + and code from arnaud desitter, arnaud@nimbus.geog.ox.ac.uk + + minor documentation changes to note that this now compiles out + of the box on Mac OS X. + Feb 10, 2002: changed types in posix chars structure to quiet solaris cc. diff --git a/contrib/one-true-awk/README b/contrib/one-true-awk/README index dc27a6be451b..8fbf30b0c665 100644 --- a/contrib/one-true-awk/README +++ b/contrib/one-true-awk/README @@ -40,18 +40,18 @@ which should produce a sequence of messages roughly like this: conflicts: 43 shift/reduce, 85 reduce/reduce mv y.tab.c ytab.c mv y.tab.h ytab.h - cc -O -c ytab.c - cc -O -c b.c - cc -O -c main.c - cc -O -c parse.c - cc -O maketab.c -o maketab + cc -c ytab.c + cc -c b.c + cc -c main.c + cc -c parse.c + cc maketab.c -o maketab ./maketab >proctab.c - cc -O -c proctab.c - cc -O -c tran.c - cc -O -c lib.c - cc -O -c run.c - cc -O -c lex.c - cc -O ytab.o b.o main.o parse.o proctab.o tran.o lib.o run.o lex.o -lm + cc -c proctab.c + cc -c tran.c + cc -c lib.c + cc -c run.c + cc -c lex.c + cc ytab.o b.o main.o parse.o proctab.o tran.o lib.o run.o lex.o -lm This produces an executable a.out; you will eventually want to move this to some place like /usr/bin/awk. @@ -75,9 +75,14 @@ with, though the underlying support has mysterious properties, the symptom of which can be truncated pipe output. Beware. The file makefile.win gives hints on how to proceed. -This is also said to compile on Macintosh systems, using the +This compiles without change on Macintosh OS X using gcc and +the standard developer tools. + +This is also said to compile on Macintosh OS 9 systems, using the file "buildmac" provided by Dan Allen (danallen@microsoft.com), to whom many thanks. The version of malloc that comes with some systems is sometimes astonishly slow. If awk seems slow, you might try fixing that. +More generally, turning on optimization can significantly improve +awk's speed, perhaps by 1/3 for highest levels. diff --git a/contrib/one-true-awk/awk.h b/contrib/one-true-awk/awk.h index 25fed1448f71..4b2cb8fb78f1 100644 --- a/contrib/one-true-awk/awk.h +++ b/contrib/one-true-awk/awk.h @@ -30,6 +30,8 @@ typedef unsigned char uschar; #define xfree(a) { if ((a) != NULL) { free((char *) a); a = NULL; } } +#define NN(p) ((p) ? (p) : "(null)") /* guaranteed non-null for dprintf +*/ #define DEBUG #ifdef DEBUG /* uses have to be doubly parenthesized */ diff --git a/contrib/one-true-awk/b.c b/contrib/one-true-awk/b.c index a9f01bf72485..1adb6c27570a 100644 --- a/contrib/one-true-awk/b.c +++ b/contrib/one-true-awk/b.c @@ -75,7 +75,7 @@ int patlen; fa *fatab[NFA]; int nfatab = 0; /* entries in fatab */ -fa *makedfa(char *s, int anchor) /* returns dfa for reg expr s */ +fa *makedfa(const char *s, int anchor) /* returns dfa for reg expr s */ { int i, use, nuse; fa *pfa; @@ -117,7 +117,7 @@ fa *makedfa(char *s, int anchor) /* returns dfa for reg expr s */ return pfa; } -fa *mkdfa(char *s, int anchor) /* does the real work of making a dfa */ +fa *mkdfa(const char *s, int anchor) /* does the real work of making a dfa */ /* anchor = 1 for anchored matches, else 0 */ { Node *p, *p1; @@ -282,9 +282,24 @@ int quoted(char **pp) /* pick up next thing after a \\ */ return c; } -char *cclenter(char *argp) /* add a character class */ +static int collate_range_cmp(int a, int b) +{ + int r; + static char s[2][2]; + + if ((uschar)a == (uschar)b) + return 0; + s[0][0] = a; + s[1][0] = b; + if ((r = strcoll(s[0], s[1])) == 0) + r = (uschar)a - (uschar)b; + return r; +} + +char *cclenter(const char *argp) /* add a character class */ { int i, c, c2; + int j; uschar *p = (uschar *) argp; uschar *op, *bp; static uschar *buf = 0; @@ -303,15 +318,18 @@ char *cclenter(char *argp) /* add a character class */ c2 = *p++; if (c2 == '\\') c2 = quoted((char **) &p); - if (c > c2) { /* empty; ignore */ + if (collate_range_cmp(c, c2) > 0) { /* empty; ignore */ bp--; i--; continue; } - while (c < c2) { + for (j = 0; j < NCHARS; j++) { + if ((collate_range_cmp(c, j) > 0) || + collate_range_cmp(j, c2) > 0) + continue; if (!adjbuf((char **) &buf, &bufsz, bp-buf+2, 100, (char **) &bp, 0)) FATAL("out of space for character class [%.10s...] 2", p); - *bp++ = ++c; + *bp++ = j; i++; } continue; @@ -328,7 +346,7 @@ char *cclenter(char *argp) /* add a character class */ return (char *) tostring((char *) buf); } -void overflo(char *s) +void overflo(const char *s) { FATAL("regular expression too big: %.30s...", s); } @@ -446,7 +464,7 @@ void follow(Node *v) /* collects leaves that can follow v into setvec */ } } -int member(int c, char *sarg) /* is c in s? */ +int member(int c, const char *sarg) /* is c in s? */ { uschar *s = (uschar *) sarg; @@ -456,7 +474,7 @@ int member(int c, char *sarg) /* is c in s? */ return(0); } -int match(fa *f, char *p0) /* shortest match ? */ +int match(fa *f, const char *p0) /* shortest match ? */ { int s, ns; uschar *p = (uschar *) p0; @@ -475,7 +493,7 @@ int match(fa *f, char *p0) /* shortest match ? */ return(0); } -int pmatch(fa *f, char *p0) /* longest match, for sub */ +int pmatch(fa *f, const char *p0) /* longest match, for sub */ { int s, ns; uschar *p = (uschar *) p0; @@ -528,7 +546,7 @@ int pmatch(fa *f, char *p0) /* longest match, for sub */ return (0); } -int nematch(fa *f, char *p0) /* non-empty match, for sub */ +int nematch(fa *f, const char *p0) /* non-empty match, for sub */ { int s, ns; uschar *p = (uschar *) p0; @@ -580,15 +598,17 @@ int nematch(fa *f, char *p0) /* non-empty match, for sub */ return (0); } -Node *reparse(char *p) /* parses regular expression pointed to by p */ +Node *reparse(const char *p) /* parses regular expression pointed to by p */ { /* uses relex() to scan regular expression */ Node *np; dprintf( ("reparse <%s>\n", p) ); lastre = prestr = (uschar *) p; /* prestr points to string to be parsed */ rtok = relex(); + /* GNU compatibility: an empty regexp matches anything */ if (rtok == '\0') - FATAL("empty regular expression"); + /* FATAL("empty regular expression"); previous */ + return(op2(ALL, NIL, NIL)); np = regexp(); if (rtok != '\0') FATAL("syntax error in regular expression %s at %s", lastre, prestr); @@ -693,23 +713,24 @@ Node *unary(Node *np) * relex(), the expanded character class (prior to range expansion) * must be less than twice the size of their full name. */ + struct charclass { const char *cc_name; int cc_namelen; - const char *cc_expand; + int (*cc_func)(int); } charclasses[] = { - { "alnum", 5, "0-9A-Za-z" }, - { "alpha", 5, "A-Za-z" }, - { "blank", 5, " \t" }, - { "cntrl", 5, "\000-\037\177" }, - { "digit", 5, "0-9" }, - { "graph", 5, "\041-\176" }, - { "lower", 5, "a-z" }, - { "print", 5, " \041-\176" }, - { "punct", 5, "\041-\057\072-\100\133-\140\173-\176" }, - { "space", 5, " \f\n\r\t\v" }, - { "upper", 5, "A-Z" }, - { "xdigit", 6, "0-9A-Fa-f" }, + { "alnum", 5, isalnum }, + { "alpha", 5, isalpha }, + { "blank", 5, isblank }, + { "cntrl", 5, iscntrl }, + { "digit", 5, isdigit }, + { "graph", 5, isgraph }, + { "lower", 5, islower }, + { "print", 5, isprint }, + { "punct", 5, ispunct }, + { "space", 5, isspace }, + { "upper", 5, isupper }, + { "xdigit", 6, isxdigit }, { NULL, 0, NULL }, }; @@ -722,7 +743,7 @@ int relex(void) /* lexical analyzer for reparse */ static int bufsz = 100; uschar *bp; struct charclass *cc; - const uschar *p; + int i; switch (c = *prestr++) { case '|': return OR; @@ -771,8 +792,14 @@ int relex(void) /* lexical analyzer for reparse */ if (cc->cc_name != NULL && prestr[1 + cc->cc_namelen] == ':' && prestr[2 + cc->cc_namelen] == ']') { prestr += cc->cc_namelen + 3; - for (p = (const uschar *) cc->cc_expand; *p; p++) - *bp++ = *p; + for (i = 0; i < NCHARS; i++) { + if (!adjbuf((char **) &buf, &bufsz, bp-buf+1, 100, (char **) &bp, 0)) + FATAL("out of space for reg expr %.10s...", lastre); + if (cc->cc_func(i)) { + *bp++ = i; + n++; + } + } } else *bp++ = c; } else if (c == '\0') { diff --git a/contrib/one-true-awk/lex.c b/contrib/one-true-awk/lex.c index 2b16b25fe6ab..e4b1fd374412 100644 --- a/contrib/one-true-awk/lex.c +++ b/contrib/one-true-awk/lex.c @@ -38,7 +38,7 @@ int brackcnt = 0; int parencnt = 0; typedef struct Keyword { - char *word; + const char *word; int sub; int type; } Keyword; @@ -499,7 +499,7 @@ int word(char *w) } } -void startreg(void) /* next call to yyles will return a regular expression */ +void startreg(void) /* next call to yylex will return a regular expression */ { reg = 1; } @@ -574,7 +574,7 @@ void unput(int c) /* put lexical character back on input */ ep = ebuf + sizeof(ebuf) - 1; } -void unputstr(char *s) /* put a string back on input */ +void unputstr(const char *s) /* put a string back on input */ { int i; diff --git a/contrib/one-true-awk/lib.c b/contrib/one-true-awk/lib.c index a44466f10add..630bbceb7dad 100644 --- a/contrib/one-true-awk/lib.c +++ b/contrib/one-true-awk/lib.c @@ -390,7 +390,7 @@ void growfldtab(int n) /* make new fields up to at least $n */ nfields = nf; } -int refldbld(char *rec, char *fs) /* build fields from reg expr in FS */ +int refldbld(const char *rec, const char *fs) /* build fields from reg expr in FS */ { /* this relies on having fields[] the same length as $0 */ /* the fields are all stored in this one array with \0's */ @@ -475,12 +475,12 @@ void recbld(void) /* create $0 from $1..$NF if necessary */ int errorflag = 0; -void yyerror(char *s) +void yyerror(const char *s) { SYNTAX(s); } -void SYNTAX(char *fmt, ...) +void SYNTAX(const char *fmt, ...) { extern char *cmdname, *curfname; static int been_here = 0; @@ -535,7 +535,7 @@ void bcheck2(int n, int c1, int c2) fprintf(stderr, "\t%d extra %c's\n", -n, c2); } -void FATAL(char *fmt, ...) +void FATAL(const char *fmt, ...) { extern char *cmdname; va_list varg; @@ -551,7 +551,7 @@ void FATAL(char *fmt, ...) exit(2); } -void WARNING(char *fmt, ...) +void WARNING(const char *fmt, ...) { extern char *cmdname; va_list varg; @@ -633,7 +633,7 @@ void bclass(int c) } } -double errcheck(double x, char *s) +double errcheck(double x, const char *s) { if (errno == EDOM) { @@ -648,9 +648,9 @@ double errcheck(double x, char *s) return x; } -int isclvar(char *s) /* is s of form var=something ? */ +int isclvar(const char *s) /* is s of form var=something ? */ { - char *os = s; + const char *os = s; if (!isalpha((uschar) *s) && *s != '_') return 0; @@ -665,7 +665,7 @@ int isclvar(char *s) /* is s of form var=something ? */ /* wrong: violates 4.10.1.4 of ansi C standard */ #include -int is_number(char *s) +int is_number(const char *s) { double r; char *ep; diff --git a/contrib/one-true-awk/mac.code b/contrib/one-true-awk/mac.code index 269d21053f9a..af47b17fb085 100644 --- a/contrib/one-true-awk/mac.code +++ b/contrib/one-true-awk/mac.code @@ -1,6 +1,14 @@ -This file contains a make shell script and a version -of the file missing95.c for the Mac, courtesy of -Dan Allen. +Note added June, 2002: + +With the advent of OS X, life is simpler: if you have the developer +tools installed, the standard awk makefile and gcc works fine, and +you can ignore the rest of this file, which is now hereby deprecated. + + + + +This file contains a make shell script and a version of the file +missing95.c for the Mac, courtesy of Dan Allen. make shell script: diff --git a/contrib/one-true-awk/main.c b/contrib/one-true-awk/main.c index 5d2be4be0b3c..491f1dcc52a3 100644 --- a/contrib/one-true-awk/main.c +++ b/contrib/one-true-awk/main.c @@ -22,11 +22,12 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ****************************************************************/ -char *version = "version 20020210"; +const char *version = "version 20021129"; #define DEBUG #include #include +#include #include #include #include @@ -52,8 +53,9 @@ int safe = 0; /* 1 => "safe" mode */ int main(int argc, char *argv[]) { - char *fs = NULL; + const char *fs = NULL; + setlocale(LC_ALL, ""); cmdname = argv[0]; if (argc == 1) { fprintf(stderr, "Usage: %s [-f programfile | 'program'] [-Ffieldsep] [-v var=value] [files]\n", cmdname); diff --git a/contrib/one-true-awk/makefile b/contrib/one-true-awk/makefile index 8f69bdacf962..b0222c2a1286 100644 --- a/contrib/one-true-awk/makefile +++ b/contrib/one-true-awk/makefile @@ -26,6 +26,7 @@ CFLAGS = -g CFLAGS = -O2 CFLAGS = +CC = gcc -Wall -g -Wwrite-strings CC = gcc -Wall -g CC = /opt/SUNWspro/bin/cc CC = /opt/pure/purify/purify cc @@ -37,11 +38,14 @@ YFLAGS = -d OFILES = b.o main.o parse.o proctab.o tran.o lib.o run.o lex.o -SOURCE = awk.h ytab.c ytab.h proto.h awkgram.y lex.c b.c main.c maketab.c parse.c lib.c run.c tran.c proctab.c missing95.c +SOURCE = awk.h ytab.c ytab.h proto.h awkgram.y lex.c b.c main.c \ + maketab.c parse.c lib.c run.c tran.c proctab.c missing95.c -LISTING = awk.h proto.h awkgram.y lex.c b.c main.c maketab.c parse.c lib.c run.c tran.c missing95.c +LISTING = awk.h proto.h awkgram.y lex.c b.c main.c maketab.c parse.c \ + lib.c run.c tran.c missing95.c -SHIP = README FIXES $(SOURCE) ytab[ch].bak makefile makefile.win buildwin.bat mac.code awk.1 +SHIP = README FIXES $(SOURCE) ytab[ch].bak makefile makefile.win \ + buildwin.bat mac.code awk.1 a.out: ytab.o $(OFILES) $(CC) $(CFLAGS) ytab.o $(OFILES) $(ALLOC) -lm diff --git a/contrib/one-true-awk/maketab.c b/contrib/one-true-awk/maketab.c index 10a038c4bc52..a35214008974 100644 --- a/contrib/one-true-awk/maketab.c +++ b/contrib/one-true-awk/maketab.c @@ -36,8 +36,8 @@ THIS SOFTWARE. struct xx { int token; - char *name; - char *pname; + const char *name; + const char *pname; } proc[] = { { PROGRAM, "program", NULL }, { BOR, "boolop", " || " }, @@ -107,12 +107,12 @@ struct xx }; #define SIZE (LASTTOKEN - FIRSTTOKEN + 1) -char *table[SIZE]; +const char *table[SIZE]; char *names[SIZE]; int main(int argc, char *argv[]) { - struct xx *p; + const struct xx *p; int i, n, tok; char c; FILE *fp; diff --git a/contrib/one-true-awk/parse.c b/contrib/one-true-awk/parse.c index ec7faca86912..8304ded837ba 100644 --- a/contrib/one-true-awk/parse.c +++ b/contrib/one-true-awk/parse.c @@ -253,7 +253,7 @@ void defn(Cell *v, Node *vl, Node *st) /* turn on FCN bit in definition, */ dprintf( ("defining func %s (%d args)\n", v->nval, n) ); } -int isarg(char *s) /* is s in argument list for current function? */ +int isarg(const char *s) /* is s in argument list for current function? */ { /* return -1 if not, otherwise arg # */ extern Node *arglist; Node *p = arglist; diff --git a/contrib/one-true-awk/proto.h b/contrib/one-true-awk/proto.h index 45f2908d96f7..adda07108c8c 100644 --- a/contrib/one-true-awk/proto.h +++ b/contrib/one-true-awk/proto.h @@ -33,28 +33,28 @@ extern int yylex(void); extern void startreg(void); extern int input(void); extern void unput(int); -extern void unputstr(char *); +extern void unputstr(const char *); extern int yylook(void); extern int yyback(int *, int); extern int yyinput(void); -extern fa *makedfa(char *, int); -extern fa *mkdfa(char *, int); +extern fa *makedfa(const char *, int); +extern fa *mkdfa(const char *, int); extern int makeinit(fa *, int); extern void penter(Node *); extern void freetr(Node *); extern int hexstr(char **); extern int quoted(char **); -extern char *cclenter(char *); -extern void overflo(char *); +extern char *cclenter(const char *); +extern void overflo(const char *); extern void cfoll(fa *, Node *); extern int first(Node *); extern void follow(Node *); -extern int member(int, char *); -extern int match(fa *, char *); -extern int pmatch(fa *, char *); -extern int nematch(fa *, char *); -extern Node *reparse(char *); +extern int member(int, const char *); +extern int match(fa *, const char *); +extern int pmatch(fa *, const char *); +extern int nematch(fa *, const char *); +extern Node *reparse(const char *); extern Node *regexp(void); extern Node *primary(void); extern Node *concat(Node *); @@ -87,7 +87,7 @@ extern Node *makearr(Node *); extern Node *pa2stat(Node *, Node *, Node *); extern Node *linkum(Node *, Node *); extern void defn(Cell *, Node *, Node *); -extern int isarg(char *); +extern int isarg(const char *); extern char *tokname(int); extern Cell *(*proctab[])(Node **, int); extern int ptoi(void *); @@ -98,18 +98,19 @@ extern void arginit(int, char **); extern void envinit(char **); extern Array *makesymtab(int); extern void freesymtab(Cell *); -extern void freeelem(Cell *, char *); -extern Cell *setsymtab(char *, char *, double, unsigned int, Array *); -extern int hash(char *, int); +extern void freeelem(Cell *, const char *); +extern Cell *setsymtab(const char *, const char *, double, unsigned int, Array *); +extern int hash(const char *, int); extern void rehash(Array *); -extern Cell *lookup(char *, Array *); +extern Cell *lookup(const char *, Array *); extern double setfval(Cell *, double); -extern void funnyvar(Cell *, char *); -extern char *setsval(Cell *, char *); +extern void funnyvar(Cell *, const char *); +extern char *setsval(Cell *, const char *); extern double getfval(Cell *); extern char *getsval(Cell *); -extern char *tostring(char *); -extern char *qstring(char *, int); +extern char *getpssval(Cell *); /* for print */ +extern char *tostring(const char *); +extern char *qstring(const char *, int); extern void recinit(unsigned int); extern void initgetrec(void); @@ -123,24 +124,24 @@ extern void setclvar(char *); extern void fldbld(void); extern void cleanfld(int, int); extern void newfld(int); -extern int refldbld(char *, char *); +extern int refldbld(const char *, const char *); extern void recbld(void); extern Cell *fieldadr(int); -extern void yyerror(char *); +extern void yyerror(const char *); extern void fpecatch(int); extern void bracecheck(void); extern void bcheck2(int, int, int); -extern void SYNTAX(char *, ...); -extern void FATAL(char *, ...); -extern void WARNING(char *, ...); +extern void SYNTAX(const char *, ...); +extern void FATAL(const char *, ...); +extern void WARNING(const char *, ...); extern void error(void); extern void eprint(void); extern void bclass(int); -extern double errcheck(double, char *); -extern int isclvar(char *); -extern int is_number(char *); +extern double errcheck(double, const char *); +extern int isclvar(const char *); +extern int is_number(const char *); -extern int adjbuf(char **pb, int *sz, int min, int q, char **pbp, char *what); +extern int adjbuf(char **pb, int *sz, int min, int q, char **pbp, const char *what); extern void run(Node *); extern Cell *execute(Node *); extern Cell *program(Node **, int); @@ -162,7 +163,7 @@ extern Cell *field(Node **, int); extern Cell *indirect(Node **, int); extern Cell *substr(Node **, int); extern Cell *sindex(Node **, int); -extern int format(char **, int *, char *, Node *); +extern int format(char **, int *, const char *, Node *); extern Cell *awksprintf(Node **, int); extern Cell *awkprintf(Node **, int); extern Cell *arith(Node **, int); @@ -183,8 +184,8 @@ extern Cell *bltin(Node **, int); extern Cell *printstat(Node **, int); extern Cell *nullproc(Node **, int); extern FILE *redirect(int, Node *); -extern FILE *openfile(int, char *); -extern char *filename(FILE *); +extern FILE *openfile(int, const char *); +extern const char *filename(FILE *); extern Cell *closefile(Node **, int); extern void closeall(void); extern Cell *sub(Node **, int); diff --git a/contrib/one-true-awk/run.c b/contrib/one-true-awk/run.c index 2f60a37638b8..617ac7d822fd 100644 --- a/contrib/one-true-awk/run.c +++ b/contrib/one-true-awk/run.c @@ -90,7 +90,7 @@ Node *curnode = NULL; /* the node being executed, for debugging */ /* buffer memory management */ int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr, - char *whatrtn) + const char *whatrtn) /* pbuf: address of pointer to buffer being managed * psiz: address of buffer size variable * minlen: minimum length of buffer needed @@ -247,7 +247,7 @@ Cell *call(Node **a, int n) /* function call. very kludgy and fragile */ y = execute(x); oargs[i] = y; dprintf( ("args[%d]: %s %f <%s>, t=%o\n", - i, y->nval, y->fval, isarr(y) ? "(array)" : y->sval, y->tval) ); + i, NN(y->nval), y->fval, isarr(y) ? "(array)" : NN(y->sval), y->tval) ); if (isfcn(y)) FATAL("can't use function %s as argument in %s", y->nval, s); if (isarr(y)) @@ -463,7 +463,7 @@ Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ tempfree(y); } if (!isarr(x)) { - dprintf( ("making %s into an array\n", x->nval) ); + dprintf( ("making %s into an array\n", NN(x->nval)) ); if (freeable(x)) xfree(x->sval); x->tval &= ~(STR|NUM|DONTFREE); @@ -564,7 +564,7 @@ Cell *matchop(Node **a, int n) /* ~ and match() */ char *s, *t; int i; fa *pfa; - int (*mf)(fa *, char *) = match, mode = 0; + int (*mf)(fa *, const char *) = match, mode = 0; if (n == MATCHFCN) { mf = pmatch; @@ -669,7 +669,7 @@ Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */ void tfree(Cell *a) /* free a tempcell */ { if (freeable(a)) { - dprintf( ("freeing %s %s %o\n", a->nval, a->sval, a->tval) ); + dprintf( ("freeing %s %s %o\n", NN(a->nval), NN(a->sval), a->tval) ); xfree(a->sval); } if (a == tmps) @@ -790,10 +790,11 @@ Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */ #define MAXNUMSIZE 50 -int format(char **pbuf, int *pbufsize, char *s, Node *a) /* printf-like conversions */ +int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like conversions */ { char *fmt; - char *p, *t, *os; + char *p, *t; + const char *os; Cell *x; int flag = 0, n; int fmtwd; /* format width */ @@ -844,27 +845,27 @@ int format(char **pbuf, int *pbufsize, char *s, Node *a) /* printf-like conversi switch (*s) { case 'f': case 'e': case 'g': case 'E': case 'G': - flag = 1; + flag = 'f'; break; case 'd': case 'i': - flag = 2; + flag = 'd'; if(*(s-1) == 'l') break; *(t-1) = 'l'; *t = 'd'; *++t = '\0'; break; case 'o': case 'x': case 'X': case 'u': - flag = *(s-1) == 'l' ? 2 : 3; + flag = *(s-1) == 'l' ? 'd' : 'u'; break; case 's': - flag = 4; + flag = 's'; break; case 'c': - flag = 5; + flag = 'c'; break; default: WARNING("weird printf conversion %s", fmt); - flag = 0; + flag = '?'; break; } if (a == NULL) @@ -876,7 +877,7 @@ int format(char **pbuf, int *pbufsize, char *s, Node *a) /* printf-like conversi n = fmtwd; adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format"); switch (flag) { - case 0: sprintf(p, "%s", fmt); /* unknown, so dump it too */ + case '?': sprintf(p, "%s", fmt); /* unknown, so dump it too */ t = getsval(x); n = strlen(t); if (fmtwd > n) @@ -885,10 +886,10 @@ int format(char **pbuf, int *pbufsize, char *s, Node *a) /* printf-like conversi p += strlen(p); sprintf(p, "%s", t); break; - case 1: sprintf(p, fmt, getfval(x)); break; - case 2: sprintf(p, fmt, (long) getfval(x)); break; - case 3: sprintf(p, fmt, (int) getfval(x)); break; - case 4: + case 'f': sprintf(p, fmt, getfval(x)); break; + case 'd': sprintf(p, fmt, (long) getfval(x)); break; + case 'u': sprintf(p, fmt, (int) getfval(x)); break; + case 's': t = getsval(x); n = strlen(t); if (fmtwd > n) @@ -897,15 +898,19 @@ int format(char **pbuf, int *pbufsize, char *s, Node *a) /* printf-like conversi FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t); sprintf(p, fmt, t); break; - case 5: + case 'c': if (isnum(x)) { if (getfval(x)) sprintf(p, fmt, (int) getfval(x)); - else - *p++ = '\0'; + else { + *p++ = '\0'; /* explicit null byte */ + *p = '\0'; /* next output will start here */ + } } else sprintf(p, fmt, getsval(x)[0]); break; + default: + FATAL("can't happen: bad conversion %c in format()", flag); } tempfree(x); p += strlen(p); @@ -1210,7 +1215,7 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ sep = *fs; ap = execute(a[1]); /* array name */ freesymtab(ap); - dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs) ); + dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs) ); ap->tval &= ~STR; ap->tval |= ARR; ap->sval = (char *) makesymtab(NSYMTAB); @@ -1504,11 +1509,11 @@ Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg lis if (t == FTOUPPER) { for (p = buf; *p; p++) if (islower((uschar) *p)) - *p = toupper(*p); + *p = toupper((uschar)*p); } else { for (p = buf; *p; p++) if (isupper((uschar) *p)) - *p = tolower(*p); + *p = tolower((uschar)*p); } tempfree(x); x = gettemp(); @@ -1551,7 +1556,7 @@ Cell *printstat(Node **a, int n) /* print a[0] */ fp = redirect(ptoi(a[1]), a[2]); for (x = a[0]; x != NULL; x = x->nnext) { y = execute(x); - fputs(getsval(y), fp); + fputs(getpssval(y), fp); tempfree(y); if (x->nnext == NULL) fputs(*ORS, fp); @@ -1590,7 +1595,7 @@ FILE *redirect(int a, Node *b) /* set up all i/o redirections */ struct files { FILE *fp; - char *fname; + const char *fname; int mode; /* '|', 'a', 'w' => LE/LT, GT */ } files[FOPEN_MAX] ={ { NULL, "/dev/stdin", LT }, /* watch out: don't free this! */ @@ -1605,9 +1610,9 @@ void stdinit(void) /* in case stdin, etc., are not constants */ files[2].fp = stderr; } -FILE *openfile(int a, char *us) +FILE *openfile(int a, const char *us) { - char *s = us; + const char *s = us; int i, m; FILE *fp = 0; @@ -1651,7 +1656,7 @@ FILE *openfile(int a, char *us) return fp; } -char *filename(FILE *fp) +const char *filename(FILE *fp) { int i; diff --git a/contrib/one-true-awk/tran.c b/contrib/one-true-awk/tran.c index a44d5720df0f..ba603ab3c675 100644 --- a/contrib/one-true-awk/tran.c +++ b/contrib/one-true-awk/tran.c @@ -180,7 +180,7 @@ void freesymtab(Cell *ap) /* free a symbol table */ free(tp); } -void freeelem(Cell *ap, char *s) /* free elem s from ap (i.e., ap["s"] */ +void freeelem(Cell *ap, const char *s) /* free elem s from ap (i.e., ap["s"] */ { Array *tp; Cell *p, *prev = NULL; @@ -203,14 +203,14 @@ void freeelem(Cell *ap, char *s) /* free elem s from ap (i.e., ap["s"] */ } } -Cell *setsymtab(char *n, char *s, Awkfloat f, unsigned t, Array *tp) +Cell *setsymtab(const char *n, const char *s, Awkfloat f, unsigned t, Array *tp) { int h; Cell *p; if (n != NULL && (p = lookup(n, tp)) != NULL) { dprintf( ("setsymtab found %p: n=%s s=\"%s\" f=%g t=%o\n", - p, p->nval, p->sval, p->fval, p->tval) ); + p, NN(p->nval), NN(p->sval), p->fval, p->tval) ); return(p); } p = (Cell *) malloc(sizeof(Cell)); @@ -233,7 +233,7 @@ Cell *setsymtab(char *n, char *s, Awkfloat f, unsigned t, Array *tp) return(p); } -int hash(char *s, int n) /* form hash value for string s */ +int hash(const char *s, int n) /* form hash value for string s */ { unsigned hashval; @@ -264,7 +264,7 @@ void rehash(Array *tp) /* rehash items in small table into big one */ tp->size = nsz; } -Cell *lookup(char *s, Array *tp) /* look for s in tp */ +Cell *lookup(const char *s, Array *tp) /* look for s in tp */ { Cell *p; int h; @@ -296,11 +296,11 @@ Awkfloat setfval(Cell *vp, Awkfloat f) /* set float val of a Cell */ xfree(vp->sval); /* free any previous string */ vp->tval &= ~STR; /* mark string invalid */ vp->tval |= NUM; /* mark number ok */ - dprintf( ("setfval %p: %s = %g, t=%o\n", vp, vp->nval, f, vp->tval) ); + dprintf( ("setfval %p: %s = %g, t=%o\n", vp, NN(vp->nval), f, vp->tval) ); return vp->fval = f; } -void funnyvar(Cell *vp, char *rw) +void funnyvar(Cell *vp, const char *rw) { if (isarr(vp)) FATAL("can't %s %s; it's an array name.", rw, vp->nval); @@ -310,12 +310,12 @@ void funnyvar(Cell *vp, char *rw) vp, vp->nval, vp->sval, vp->fval, vp->tval); } -char *setsval(Cell *vp, char *s) /* set string val of a Cell */ +char *setsval(Cell *vp, const char *s) /* set string val of a Cell */ { char *t; int fldno; - dprintf( ("starting setsval %p: %s = \"%s\", t=%o\n", vp, vp->nval, s, vp->tval) ); + dprintf( ("starting setsval %p: %s = \"%s\", t=%o\n", vp, NN(vp->nval), s, vp->tval) ); if ((vp->tval & (NUM | STR)) == 0) funnyvar(vp, "assign to"); if (isfld(vp)) { @@ -334,7 +334,7 @@ char *setsval(Cell *vp, char *s) /* set string val of a Cell */ if (freeable(vp)) xfree(vp->sval); vp->tval &= ~DONTFREE; - dprintf( ("setsval %p: %s = \"%s (%p)\", t=%o\n", vp, vp->nval, t,t, vp->tval) ); + dprintf( ("setsval %p: %s = \"%s (%p)\", t=%o\n", vp, NN(vp->nval), t,t, vp->tval) ); return(vp->sval = t); } @@ -351,11 +351,12 @@ Awkfloat getfval(Cell *vp) /* get float val of a Cell */ if (is_number(vp->sval) && !(vp->tval&CON)) vp->tval |= NUM; /* make NUM only sparingly */ } - dprintf( ("getfval %p: %s = %g, t=%o\n", vp, vp->nval, vp->fval, vp->tval) ); + dprintf( ("getfval %p: %s = %g, t=%o\n", vp, NN(vp->nval), vp->fval, vp->tval) ); return(vp->fval); } -char *getsval(Cell *vp) /* get string val of a Cell */ + static char *get_str_val(Cell *vp, char **fmt) /* get string val of a Cell */ + { char s[100]; /* BUG: unchecked */ double dtemp; @@ -372,16 +373,27 @@ char *getsval(Cell *vp) /* get string val of a Cell */ if (modf(vp->fval, &dtemp) == 0) /* it's integral */ sprintf(s, "%.30g", vp->fval); else - sprintf(s, *CONVFMT, vp->fval); + sprintf(s, *fmt, vp->fval); vp->sval = tostring(s); vp->tval &= ~DONTFREE; vp->tval |= STR; } - dprintf( ("getsval %p: %s = \"%s (%p)\", t=%o\n", vp, vp->nval, vp->sval, vp->sval, vp->tval) ); + dprintf( ("getsval %p: %s = \"%s (%p)\", t=%o\n", vp, NN(vp->nval), vp->sval, vp->sval, vp->tval) ); return(vp->sval); } -char *tostring(char *s) /* make a copy of string s */ +char *getsval(Cell *vp) /* get string val of a Cell */ +{ + return get_str_val(vp, CONVFMT); +} + +char *getpssval(Cell *vp) /* get string val of a Cell for print */ +{ + return get_str_val(vp, OFMT); +} + + +char *tostring(const char *s) /* make a copy of string s */ { char *p; @@ -392,9 +404,9 @@ char *tostring(char *s) /* make a copy of string s */ return(p); } -char *qstring(char *is, int delim) /* collect string up to next delim */ +char *qstring(const char *is, int delim) /* collect string up to next delim */ { - char *os = is; + const char *os = is; int c, n; uschar *s = (uschar *) is; uschar *buf, *bp;