Apply all our changes including newer fixes to WARNS?=4

This commit is contained in:
christos 2010-08-26 14:55:19 +00:00
parent 35f471cb95
commit 5642d0040b
13 changed files with 1002 additions and 504 deletions

View File

@ -48,6 +48,7 @@ extern int safe; /* 0 => unsafe, 1 => safe */
#define RECSIZE (8 * 1024) /* sets limit on records, fields, etc., etc. */
extern int recsize; /* size of current record, orig RECSIZE */
extern char EMPTY[];
extern char **FS;
extern char **RS;
extern char **ORS;
@ -61,16 +62,15 @@ extern char **SUBSEP;
extern Awkfloat *RSTART;
extern Awkfloat *RLENGTH;
extern char *record; /* points to $0 */
extern uschar *record; /* points to $0 */
extern int lineno; /* line number in awk program */
extern int errorflag; /* 1 if error has occurred */
extern int donefld; /* 1 if record broken into fields */
extern int donerec; /* 1 if record is valid (no fld has changed */
extern char inputFS[]; /* FS at time of input, for field splitting */
extern int dbg;
extern char *patbeg; /* beginning of pattern matched */
extern uschar *patbeg; /* beginning of pattern matched */
extern int patlen; /* length of pattern matched. set in b.c */
/* Cell: all information about a variable or constant */
@ -126,6 +126,8 @@ extern Cell *rlengthloc; /* RLENGTH */
#define FTOUPPER 12
#define FTOLOWER 13
#define FFLUSH 14
#define FSYSTIME 15
#define FSTRFTIME 16
/* Node: parse tree is made of nodes, with Cell's at bottom */
@ -203,8 +205,6 @@ extern int pairstack[], paircnt;
#define NCHARS (256+3) /* 256 handles 8-bit chars; 128 does 7-bit */
/* watch out in match(), etc. */
#define NSTATES 32
typedef struct rrow {
long ltype; /* long avoids pointer warnings on 64-bit */
union {
@ -216,16 +216,16 @@ typedef struct rrow {
} rrow;
typedef struct fa {
uschar gototab[NSTATES][NCHARS];
uschar out[NSTATES];
unsigned int **gototab;
uschar *out;
uschar *restr;
int *posns[NSTATES];
int **posns;
int state_count;
int anchor;
int use;
int initstat;
int curstat;
int accept;
int reset;
struct rrow re[1]; /* variable: actual size set by calling malloc */
} fa;

View File

@ -23,6 +23,10 @@ THIS SOFTWARE.
****************************************************************/
%{
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <stdio.h>
#include <string.h>
#include "awk.h"
@ -80,7 +84,7 @@ Node *arglist = 0; /* list of args for current function */
%left GETLINE
%nonassoc APPEND EQ GE GT LE LT NE MATCHOP IN '|'
%left ARG BLTIN BREAK CALL CLOSE CONTINUE DELETE DO EXIT FOR FUNC
%left GSUB IF INDEX LSUBSTR MATCHFCN NEXT NUMBER
%left GENSUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT NUMBER
%left PRINT PRINTF RETURN SPLIT SPRINTF STRING SUB SUBSTR
%left REGEXPR VAR VARNF IVAR WHILE '('
%left CAT
@ -369,6 +373,22 @@ term:
| INCR var { $$ = op1(PREINCR, $2); }
| var DECR { $$ = op1(POSTDECR, $1); }
| var INCR { $$ = op1(POSTINCR, $1); }
| GENSUB '(' reg_expr comma pattern comma pattern ')'
{ $$ = op5(GENSUB, NIL, (Node*)makedfa($3, 1), $5, $7, rectonode()); }
| GENSUB '(' pattern comma pattern comma pattern ')'
{ if (constnode($3))
$$ = op5(GENSUB, NIL, (Node *)makedfa(strnode($3), 1), $5, $7, rectonode());
else
$$ = op5(GENSUB, (Node *)1, $3, $5, $7, rectonode());
}
| GENSUB '(' reg_expr comma pattern comma pattern comma pattern ')'
{ $$ = op5(GENSUB, NIL, (Node*)makedfa($3, 1), $5, $7, $9); }
| GENSUB '(' pattern comma pattern comma pattern comma pattern ')'
{ if (constnode($3))
$$ = op5(GENSUB, NIL, (Node *)makedfa(strnode($3),1), $5,$7,$9);
else
$$ = op5(GENSUB, (Node *)1, $3, $5, $7, $9);
}
| GETLINE var LT term { $$ = op3(GETLINE, $2, itonp($3), $4); }
| GETLINE LT term { $$ = op3(GETLINE, NIL, itonp($2), $3); }
| GETLINE var { $$ = op3(GETLINE, $2, NIL, NIL); }

View File

@ -24,14 +24,19 @@ THIS SOFTWARE.
/* lasciate ogne speranza, voi ch'intrate. */
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#define DEBUG
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "awk.h"
#include "ytab.h"
#include "awkgram.h"
#define HAT (NCHARS+2) /* matches ^ in regular expr */
/* NCHARS is 2**n */
@ -62,33 +67,80 @@ int maxsetvec = 0;
int rtok; /* next token in current re */
int rlxval;
static uschar *rlxstr;
static uschar *prestr; /* current position in current re */
static uschar *lastre; /* origin of last re */
static const uschar *rlxstr;
static const uschar *prestr; /* current position in current re */
static const uschar *lastre; /* origin of last re */
static int setcnt;
static int poscnt;
char *patbeg;
uschar *patbeg;
int patlen;
#define NFA 20 /* cache this many dynamic fa's */
#define NFA 128 /* cache this many dynamic fa's */
fa *fatab[NFA];
int nfatab = 0; /* entries in fatab */
static void
resizesetvec(const char *msg)
{
if (maxsetvec == 0)
maxsetvec = MAXLIN;
else
maxsetvec *= 4;
setvec = realloc(setvec, maxsetvec * sizeof(*setvec));
tmpset = realloc(tmpset, maxsetvec * sizeof(*tmpset));
if (setvec == 0 || tmpset == 0)
overflo(msg);
}
static void
resize_state(fa *f, int state)
{
void *p;
int i, new_count;
if (++state < f->state_count)
return;
new_count = state + 10; /* needs to be tuned */
p = realloc(f->gototab, new_count * sizeof(f->gototab[0]));
if (p == NULL)
goto out;
f->gototab = p;
p = realloc(f->out, new_count * sizeof(f->out[0]));
if (p == NULL)
goto out;
f->out = p;
p = realloc(f->posns, new_count * sizeof(f->posns[0]));
if (p == NULL)
goto out;
f->posns = p;
for (i = f->state_count; i < new_count; ++i) {
f->gototab[i] = calloc(1, NCHARS * sizeof (**f->gototab));
if (f->gototab[i] == NULL)
goto out;
f->out[i] = 0;
f->posns[i] = NULL;
}
f->state_count = new_count;
return;
out:
overflo("out of memory in resize_state");
}
fa *makedfa(const char *s, int anchor) /* returns dfa for reg expr s */
{
int i, use, nuse;
fa *pfa;
static int now = 1;
if (setvec == 0) { /* first time through any RE */
maxsetvec = MAXLIN;
setvec = (int *) malloc(maxsetvec * sizeof(int));
tmpset = (int *) malloc(maxsetvec * sizeof(int));
if (setvec == 0 || tmpset == 0)
overflo("out of space initializing makedfa");
}
if (setvec == 0) /* first time through any RE */
resizesetvec("out of space initializing makedfa");
if (compile_time) /* a constant for sure */
return mkdfa(s, anchor);
@ -132,14 +184,15 @@ fa *mkdfa(const char *s, int anchor) /* does the real work of making a dfa */
poscnt = 0;
penter(p1); /* enter parent pointers and leaf indices */
if ((f = (fa *) calloc(1, sizeof(fa) + poscnt*sizeof(rrow))) == NULL)
if ((f = calloc(1, sizeof(*f) + poscnt*sizeof(rrow))) == NULL)
overflo("out of space for fa");
f->accept = poscnt-1; /* penter has computed number of positions in re */
cfoll(f, p1); /* set up follow sets */
freetr(p1);
if ((f->posns[0] = (int *) calloc(1, *(f->re[0].lfollow)*sizeof(int))) == NULL)
resize_state(f, 1);
if ((f->posns[0] = calloc(1, *(f->re[0].lfollow)*sizeof(int))) == NULL)
overflo("out of space in makedfa");
if ((f->posns[1] = (int *) calloc(1, sizeof(int))) == NULL)
if ((f->posns[1] = calloc(1, sizeof(int))) == NULL)
overflo("out of space in makedfa");
*f->posns[1] = 0;
f->initstat = makeinit(f, anchor);
@ -152,12 +205,12 @@ int makeinit(fa *f, int anchor)
{
int i, k;
resize_state(f, 2);
f->curstat = 2;
f->out[2] = 0;
f->reset = 0;
k = *(f->re[0].lfollow);
xfree(f->posns[2]);
if ((f->posns[2] = (int *) calloc(1, (k+1)*sizeof(int))) == NULL)
if ((f->posns[2] = calloc(1, (k+1)*sizeof(int))) == NULL)
overflo("out of space in makeinit");
for (i=0; i <= k; i++) {
(f->posns[2])[i] = (f->re[0].lfollow)[i];
@ -174,9 +227,11 @@ int makeinit(fa *f, int anchor)
}
f->out[0] = f->out[2];
if (f->curstat != 2)
if (f->curstat != 2) {
resize_state(f, f->curstat);
--(*f->posns[f->curstat]);
}
}
return f->curstat;
}
@ -231,13 +286,13 @@ void freetr(Node *p) /* free parse tree */
/* in the parsing of regular expressions, metacharacters like . have */
/* to be seen literally; \056 is not a metacharacter. */
int hexstr(char **pp) /* find and eval hex string at pp, return new p */
int hexstr(const uschar **pp) /* find and eval hex string at pp, return new p */
{ /* only pick up one 8-bit byte (2 chars) */
uschar *p;
const uschar *p;
int n = 0;
int i;
for (i = 0, p = (uschar *) *pp; i < 2 && isxdigit(*p); i++, p++) {
for (i = 0, p = *pp; i < 2 && isxdigit(*p); i++, p++) {
if (isdigit(*p))
n = 16 * n + *p - '0';
else if (*p >= 'a' && *p <= 'f')
@ -245,16 +300,16 @@ int hexstr(char **pp) /* find and eval hex string at pp, return new p */
else if (*p >= 'A' && *p <= 'F')
n = 16 * n + *p - 'A' + 10;
}
*pp = (char *) p;
*pp = p;
return n;
}
#define isoctdigit(c) ((c) >= '0' && (c) <= '7') /* multiple use of arg */
int quoted(char **pp) /* pick up next thing after a \\ */
int quoted(const uschar **pp) /* pick up next thing after a \\ */
/* and increment *pp */
{
char *p = *pp;
const uschar *p = *pp;
int c;
if ((c = *p++) == 't')
@ -288,31 +343,32 @@ int quoted(char **pp) /* pick up next thing after a \\ */
char *cclenter(const char *argp) /* add a character class */
{
int i, c, c2;
uschar *p = (uschar *) argp;
uschar *op, *bp;
const uschar *p = (const uschar *) argp;
const uschar *op;
uschar *bp;
static uschar *buf = 0;
static int bufsz = 100;
op = p;
if (buf == 0 && (buf = (uschar *) malloc(bufsz)) == NULL)
if (buf == 0 && (buf = malloc(bufsz)) == NULL)
FATAL("out of space for character class [%.10s...] 1", p);
bp = buf;
for (i = 0; (c = *p++) != 0; ) {
if (c == '\\') {
c = quoted((char **) &p);
c = quoted(&p);
} else if (c == '-' && i > 0 && bp[-1] != 0) {
if (*p != 0) {
c = bp[-1];
c2 = *p++;
if (c2 == '\\')
c2 = quoted((char **) &p);
c2 = quoted(&p);
if (c > c2) { /* empty; ignore */
bp--;
i--;
continue;
}
while (c < c2) {
if (!adjbuf((char **) &buf, &bufsz, bp-buf+2, 100, (char **) &bp, "cclenter1"))
if (!adjbuf(&buf, &bufsz, bp-buf+2, 100, &bp, "cclenter1"))
FATAL("out of space for character class [%.10s...] 2", p);
*bp++ = ++c;
i++;
@ -320,14 +376,14 @@ char *cclenter(const char *argp) /* add a character class */
continue;
}
}
if (!adjbuf((char **) &buf, &bufsz, bp-buf+2, 100, (char **) &bp, "cclenter2"))
if (!adjbuf(&buf, &bufsz, bp-buf+2, 100, &bp, "cclenter2"))
FATAL("out of space for character class [%.10s...] 3", p);
*bp++ = c;
i++;
}
*bp = 0;
dprintf( ("cclenter: in = |%s|, out = |%s|\n", op, buf) );
xfree(op);
free(__UNCONST(op));
return (char *) tostring((char *) buf);
}
@ -346,18 +402,13 @@ void cfoll(fa *f, Node *v) /* enter follow set of each leaf of vertex v into lfo
LEAF
f->re[info(v)].ltype = type(v);
f->re[info(v)].lval.np = right(v);
while (f->accept >= maxsetvec) { /* guessing here! */
maxsetvec *= 4;
setvec = (int *) realloc(setvec, maxsetvec * sizeof(int));
tmpset = (int *) realloc(tmpset, maxsetvec * sizeof(int));
if (setvec == 0 || tmpset == 0)
overflo("out of space in cfoll()");
}
while (f->accept >= maxsetvec) /* guessing here! */
resizesetvec("out of space in cfoll()");
for (i = 0; i <= f->accept; i++)
setvec[i] = 0;
setcnt = 0;
follow(v); /* computes setvec and setcnt */
if ((p = (int *) calloc(1, (setcnt+1)*sizeof(int))) == NULL)
if ((p = calloc(1, (setcnt+1)*sizeof(int))) == NULL)
overflo("out of space building follow set");
f->re[info(v)].lfollow = p;
*p = setcnt;
@ -387,13 +438,8 @@ int first(Node *p) /* collects initially active leaves of p into setvec */
ELEAF
LEAF
lp = info(p); /* look for high-water mark of subscripts */
while (setcnt >= maxsetvec || lp >= maxsetvec) { /* guessing here! */
maxsetvec *= 4;
setvec = (int *) realloc(setvec, maxsetvec * sizeof(int));
tmpset = (int *) realloc(tmpset, maxsetvec * sizeof(int));
if (setvec == 0 || tmpset == 0)
overflo("out of space in first()");
}
while (setcnt >= maxsetvec || lp >= maxsetvec) /* guessing here! */
resizesetvec("out of space in first()");
if (type(p) == EMPTYRE) {
setvec[lp] = 0;
return(0);
@ -457,7 +503,7 @@ void follow(Node *v) /* collects leaves that can follow v into setvec */
int member(int c, const char *sarg) /* is c in s? */
{
uschar *s = (uschar *) sarg;
const uschar *s = (const uschar *) sarg;
while (*s)
if (c == *s++)
@ -468,9 +514,11 @@ int member(int c, const char *sarg) /* is c in s? */
int match(fa *f, const char *p0) /* shortest match ? */
{
int s, ns;
uschar *p = (uschar *) p0;
const uschar *p = (const uschar *) p0;
s = f->initstat;
assert (s < f->state_count);
s = f->reset ? makeinit(f,0) : f->initstat;
if (f->out[s])
return(1);
do {
@ -479,6 +527,9 @@ int match(fa *f, const char *p0) /* shortest match ? */
s = ns;
else
s = cgoto(f, s, *p);
assert (s < f->state_count);
if (f->out[s])
return(1);
} while (*p++ != 0);
@ -488,17 +539,12 @@ int match(fa *f, const char *p0) /* shortest match ? */
int pmatch(fa *f, const char *p0) /* longest match, for sub */
{
int s, ns;
uschar *p = (uschar *) p0;
uschar *p = __UNCONST(p0);
uschar *q;
int i, k;
/* s = f->reset ? makeinit(f,1) : f->initstat; */
if (f->reset) {
f->initstat = s = makeinit(f,1);
} else {
s = f->initstat;
}
patbeg = (char *) p;
assert(s < f->state_count);
patbeg = p;
patlen = -1;
do {
q = p;
@ -510,9 +556,12 @@ int pmatch(fa *f, const char *p0) /* longest match, for sub */
s = ns;
else
s = cgoto(f, s, *q);
assert(s < f->state_count);
if (s == 1) { /* no transition */
if (patlen >= 0) {
patbeg = (char *) p;
patbeg = p;
return(1);
}
else
@ -522,24 +571,11 @@ int pmatch(fa *f, const char *p0) /* longest match, for sub */
if (f->out[s])
patlen = q-p-1; /* don't count $ */
if (patlen >= 0) {
patbeg = (char *) p;
patbeg = p;
return(1);
}
nextin:
s = 2;
if (f->reset) {
for (i = 2; i <= f->curstat; i++)
xfree(f->posns[i]);
k = *f->posns[0];
if ((f->posns[2] = (int *) calloc(1, (k+1)*sizeof(int))) == NULL)
overflo("out of space in pmatch");
for (i = 0; i <= k; i++)
(f->posns[2])[i] = (f->posns[0])[i];
f->initstat = f->curstat = 2;
f->out[2] = f->out[0];
for (i = 0; i < NCHARS; i++)
f->gototab[2][i] = 0;
}
} while (*p++ != 0);
return (0);
}
@ -547,16 +583,12 @@ int pmatch(fa *f, const char *p0) /* longest match, for sub */
int nematch(fa *f, const char *p0) /* non-empty match, for sub */
{
int s, ns;
uschar *p = (uschar *) p0;
uschar *p = __UNCONST(p0);
uschar *q;
int i, k;
/* s = f->reset ? makeinit(f,1) : f->initstat; */
if (f->reset) {
f->initstat = s = makeinit(f,1);
} else {
s = f->initstat;
}
assert(s < f->state_count);
patlen = -1;
while (*p) {
q = p;
@ -568,9 +600,12 @@ int nematch(fa *f, const char *p0) /* non-empty match, for sub */
s = ns;
else
s = cgoto(f, s, *q);
assert(s < f->state_count);
if (s == 1) { /* no transition */
if (patlen > 0) {
patbeg = (char *) p;
patbeg = p;
return(1);
} else
goto nnextin; /* no nonempty match */
@ -579,24 +614,11 @@ int nematch(fa *f, const char *p0) /* non-empty match, for sub */
if (f->out[s])
patlen = q-p-1; /* don't count $ */
if (patlen > 0 ) {
patbeg = (char *) p;
patbeg = p;
return(1);
}
nnextin:
s = 2;
if (f->reset) {
for (i = 2; i <= f->curstat; i++)
xfree(f->posns[i]);
k = *f->posns[0];
if ((f->posns[2] = (int *) calloc(1, (k+1)*sizeof(int))) == NULL)
overflo("out of state space");
for (i = 0; i <= k; i++)
(f->posns[2])[i] = (f->posns[0])[i];
f->initstat = f->curstat = 2;
f->out[2] = f->out[0];
for (i = 0; i < NCHARS; i++)
f->gototab[2][i] = 0;
}
p++;
}
return (0);
@ -607,7 +629,7 @@ Node *reparse(const char *p) /* parses regular expression pointed to by p */
Node *np;
dprintf( ("reparse <%s>\n", p) );
lastre = prestr = (uschar *) p; /* prestr points to string to be parsed */
lastre = prestr = (const uschar *) p; /* prestr points to string to be parsed */
rtok = relex();
/* GNU compatibility: an empty regexp matches anything */
if (rtok == '\0') {
@ -644,11 +666,11 @@ Node *primary(void)
rtok = relex();
return (unary(op2(DOT, NIL, NIL)));
case CCL:
np = op2(CCL, NIL, (Node*) cclenter((char *) rlxstr));
np = op2(CCL, NIL, (Node*) cclenter((const char *) rlxstr));
rtok = relex();
return (unary(np));
case NCCL:
np = op2(NCCL, NIL, (Node *) cclenter((char *) rlxstr));
np = op2(NCCL, NIL, (Node *) cclenter((const char *) rlxstr));
rtok = relex();
return (unary(np));
case '^':
@ -732,23 +754,15 @@ Node *unary(Node *np)
*/
/* #define HAS_ISBLANK */
#ifndef HAS_ISBLANK
int (xisblank)(int c)
{
return c==' ' || c=='\t';
}
#endif
struct charclass {
static const struct charclass {
const char *cc_name;
int cc_namelen;
int (*cc_func)(int);
} charclasses[] = {
{ "alnum", 5, isalnum },
{ "alpha", 5, isalpha },
{ "blank", 5, isspace }, /* was isblank */
{ "blank", 5, isblank },
{ "cntrl", 5, iscntrl },
{ "digit", 5, isdigit },
{ "graph", 5, isgraph },
@ -769,7 +783,7 @@ int relex(void) /* lexical analyzer for reparse */
static uschar *buf = 0;
static int bufsz = 100;
uschar *bp;
struct charclass *cc;
const struct charclass *cc;
int i;
switch (c = *prestr++) {
@ -785,13 +799,13 @@ int relex(void) /* lexical analyzer for reparse */
case ')':
return c;
case '\\':
rlxval = quoted((char **) &prestr);
rlxval = quoted(&prestr);
return CHAR;
default:
rlxval = c;
return CHAR;
case '[':
if (buf == 0 && (buf = (uschar *) malloc(bufsz)) == NULL)
if (buf == 0 && (buf = malloc(bufsz)) == NULL)
FATAL("out of space in reg expr %.10s..", lastre);
bp = buf;
if (*prestr == '^') {
@ -801,7 +815,7 @@ int relex(void) /* lexical analyzer for reparse */
else
cflag = 0;
n = 2 * strlen((const char *) prestr)+1;
if (!adjbuf((char **) &buf, &bufsz, n, n, (char **) &bp, "relex1"))
if (!adjbuf(&buf, &bufsz, n, n, &bp, "relex1"))
FATAL("out of space for reg expr %.10s...", lastre);
for (; ; ) {
if ((c = *prestr++) == '\\') {
@ -819,8 +833,8 @@ 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 (i = 0; i < NCHARS; i++) {
if (!adjbuf((char **) &buf, &bufsz, bp-buf+1, 100, (char **) &bp, "relex2"))
for (i = 1; i < NCHARS; i++) {
if (!adjbuf(&buf, &bufsz, bp-buf+1, 100, &bp, "relex2"))
FATAL("out of space for reg expr %.10s...", lastre);
if (cc->cc_func(i)) {
*bp++ = i;
@ -852,16 +866,12 @@ int cgoto(fa *f, int s, int c)
int *p, *q;
assert(c == HAT || c < NCHARS);
while (f->accept >= maxsetvec) { /* guessing here! */
maxsetvec *= 4;
setvec = (int *) realloc(setvec, maxsetvec * sizeof(int));
tmpset = (int *) realloc(tmpset, maxsetvec * sizeof(int));
if (setvec == 0 || tmpset == 0)
overflo("out of space in cgoto()");
}
while (f->accept >= maxsetvec) /* guessing here! */
resizesetvec("out of space in cgoto()");
for (i = 0; i <= f->accept; i++)
setvec[i] = 0;
setcnt = 0;
resize_state(f, s);
/* compute positions of gototab[s,c] into setvec */
p = f->posns[s];
for (i = 1; i <= *p; i++) {
@ -874,13 +884,8 @@ int cgoto(fa *f, int s, int c)
|| (k == NCCL && !member(c, (char *) f->re[p[i]].lval.up) && c != 0 && c != HAT)) {
q = f->re[p[i]].lfollow;
for (j = 1; j <= *q; j++) {
if (q[j] >= maxsetvec) {
maxsetvec *= 4;
setvec = (int *) realloc(setvec, maxsetvec * sizeof(int));
tmpset = (int *) realloc(tmpset, maxsetvec * sizeof(int));
if (setvec == 0 || tmpset == 0)
overflo("cgoto overflow");
}
if (q[j] >= maxsetvec)
resizesetvec("cgoto overflow");
if (setvec[q[j]] == 0) {
setcnt++;
setvec[q[j]] = 1;
@ -896,6 +901,8 @@ int cgoto(fa *f, int s, int c)
if (setvec[i]) {
tmpset[j++] = i;
}
resize_state(f, f->curstat > s ? f->curstat : s);
/* tmpset == previous state? */
for (i = 1; i <= f->curstat; i++) {
p = f->posns[i];
@ -905,26 +912,23 @@ int cgoto(fa *f, int s, int c)
if (tmpset[j] != p[j])
goto different;
/* setvec is state i */
if (c != HAT)
f->gototab[s][c] = i;
return i;
different:;
}
/* add tmpset to current set of states */
if (f->curstat >= NSTATES-1) {
f->curstat = 2;
f->reset = 1;
for (i = 2; i < NSTATES; i++)
xfree(f->posns[i]);
} else
++(f->curstat);
resize_state(f, f->curstat);
for (i = 0; i < NCHARS; i++)
f->gototab[f->curstat][i] = 0;
xfree(f->posns[f->curstat]);
if ((p = (int *) calloc(1, (setcnt+1)*sizeof(int))) == NULL)
if ((p = calloc(1, (setcnt+1)*sizeof(int))) == NULL)
overflo("out of space in cgoto");
f->posns[f->curstat] = p;
if (c != HAT)
f->gototab[s][c] = f->curstat;
for (i = 0; i <= setcnt; i++)
p[i] = tmpset[i];
@ -942,13 +946,18 @@ void freefa(fa *f) /* free a finite automaton */
if (f == NULL)
return;
for (i = 0; i <= f->curstat; i++)
for (i = 0; i < f->state_count; i++) {
xfree(f->gototab[i])
xfree(f->posns[i]);
}
for (i = 0; i <= f->accept; i++) {
xfree(f->re[i].lfollow);
if (f->re[i].ltype == CCL || f->re[i].ltype == NCCL)
xfree((f->re[i].lval.np));
}
xfree(f->restr);
xfree(f->out);
xfree(f->posns);
xfree(f->gototab);
xfree(f);
}

View File

@ -22,12 +22,16 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
****************************************************************/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "awk.h"
#include "ytab.h"
#include "awkgram.h"
extern YYSTYPE yylval;
extern int infunc;
@ -43,7 +47,11 @@ typedef struct Keyword {
int type;
} Keyword;
Keyword keywords[] ={ /* keep sorted: binary searched */
int peek(void);
int gettok(char **, int *);
int binsearch(const char *, const Keyword *, int);
const Keyword keywords[] ={ /* keep sorted: binary searched */
{ "BEGIN", XBEGIN, XBEGIN },
{ "END", XEND, XEND },
{ "NF", VARNF, VARNF },
@ -61,6 +69,7 @@ Keyword keywords[] ={ /* keep sorted: binary searched */
{ "for", FOR, FOR },
{ "func", FUNC, FUNC },
{ "function", FUNC, FUNC },
{ "gensub", GENSUB, GENSUB },
{ "getline", GETLINE, GETLINE },
{ "gsub", GSUB, GSUB },
{ "if", IF, IF },
@ -81,9 +90,11 @@ Keyword keywords[] ={ /* keep sorted: binary searched */
{ "sprintf", SPRINTF, SPRINTF },
{ "sqrt", FSQRT, BLTIN },
{ "srand", FSRAND, BLTIN },
{ "strftime", FSTRFTIME, BLTIN },
{ "sub", SUB, SUB },
{ "substr", SUBSTR, SUBSTR },
{ "system", FSYSTEM, BLTIN },
{ "systime", FSYSTIME, BLTIN },
{ "tolower", FTOLOWER, BLTIN },
{ "toupper", FTOUPPER, BLTIN },
{ "while", WHILE, WHILE },
@ -101,9 +112,9 @@ int peek(void)
int gettok(char **pbuf, int *psz) /* get next input token */
{
int c, retc;
char *buf = *pbuf;
uschar *buf = (uschar *) *pbuf;
int sz = *psz;
char *bp = buf;
uschar *bp = buf;
c = input();
if (c == 0)
@ -146,7 +157,7 @@ int gettok(char **pbuf, int *psz) /* get next input token */
}
*bp = 0;
strtod(buf, &rem); /* parse the number */
if (rem == buf) { /* it wasn't a valid number at all */
if (rem == (char *)buf) { /* it wasn't a valid number at all */
buf[1] = 0; /* return one character as token */
retc = buf[0]; /* character is its own type */
unputstr(rem+1); /* put rest back for later */
@ -173,7 +184,7 @@ int yylex(void)
static char *buf = 0;
static int bufsize = 5; /* BUG: setting this small causes core dump! */
if (buf == 0 && (buf = (char *) malloc(bufsize)) == NULL)
if (buf == 0 && (buf = malloc(bufsize)) == NULL)
FATAL( "out of space in yylex" );
if (sc) {
sc = 0;
@ -357,11 +368,11 @@ int yylex(void)
int string(void)
{
int c, n;
char *s, *bp;
static char *buf = 0;
uschar *s, *bp;
static uschar *buf = 0;
static int bufsz = 500;
if (buf == 0 && (buf = (char *) malloc(bufsz)) == NULL)
if (buf == 0 && (buf = malloc(bufsz)) == NULL)
FATAL("out of space for strings");
for (bp = buf; (c = input()) != '"'; ) {
if (!adjbuf(&buf, &bufsz, bp-buf+2, 500, &bp, "string"))
@ -378,6 +389,7 @@ int string(void)
case '\\':
c = input();
switch (c) {
case '\n': break;
case '"': *bp++ = '"'; break;
case 'n': *bp++ = '\n'; break;
case 't': *bp++ = '\t'; break;
@ -417,6 +429,8 @@ int string(void)
}
default:
WARNING("warning: escape sequence `\\%c' "
"treated as plain `%c'", c, c);
*bp++ = c;
break;
}
@ -434,7 +448,7 @@ int string(void)
}
int binsearch(char *w, Keyword *kp, int n)
int binsearch(const char *w, const Keyword *kp, int n)
{
int cond, low, mid, high;
@ -454,7 +468,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]));
@ -504,11 +518,11 @@ void startreg(void) /* next call to yylex will return a regular expression */
int regexpr(void)
{
int c;
static char *buf = 0;
static uschar *buf = 0;
static int bufsz = 500;
char *bp;
uschar *bp;
if (buf == 0 && (buf = (char *) malloc(bufsz)) == NULL)
if (buf == 0 && (buf = malloc(bufsz)) == NULL)
FATAL("out of space for rex expr");
bp = buf;
for ( ; (c = input()) != '/' && c != 0; ) {

View File

@ -22,6 +22,10 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
****************************************************************/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#define DEBUG
#include <stdio.h>
#include <string.h>
@ -30,17 +34,20 @@ THIS SOFTWARE.
#include <stdlib.h>
#include <stdarg.h>
#include "awk.h"
#include "ytab.h"
#include "awkgram.h"
char EMPTY[] = { '\0' };
FILE *infile = NULL;
char *file = "";
char *record;
char *file = EMPTY;
uschar *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;
#define MAXFLD 2
int nfields = MAXFLD; /* last allocated slot for $i */
@ -52,15 +59,15 @@ 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, NULL };
static Cell dollar1 = { OCELL, CFLD, NULL, EMPTY, 0.0, FLD|STR|DONTFREE, NULL };
void recinit(unsigned int n)
{
if ( (record = (char *) malloc(n)) == NULL
|| (fields = (char *) malloc(n+1)) == NULL
|| (fldtab = (Cell **) malloc((nfields+1) * sizeof(Cell *))) == NULL
|| (fldtab[0] = (Cell *) malloc(sizeof(Cell))) == NULL )
if ( (record = malloc(n)) == NULL
|| (fields = malloc(n+1)) == NULL
|| (fldtab = malloc((nfields+1) * sizeof(*fldtab))) == NULL
|| (fldtab[0] = malloc(sizeof(**fldtab))) == NULL )
FATAL("out of space for $0 and fields");
*fldtab[0] = dollar0;
fldtab[0]->sval = record;
@ -74,11 +81,11 @@ void makefields(int n1, int n2) /* create $n1..$n2 inclusive */
int i;
for (i = n1; i <= n2; i++) {
fldtab[i] = (Cell *) malloc(sizeof (struct Cell));
fldtab[i] = malloc(sizeof(**fldtab));
if (fldtab[i] == NULL)
FATAL("out of space in makefields %d", i);
*fldtab[i] = dollar1;
sprintf(temp, "%d", i);
snprintf(temp, sizeof(temp), "%d", i);
fldtab[i]->nval = tostring(temp);
}
}
@ -101,10 +108,10 @@ void initgetrec(void)
static int firsttime = 1;
int getrec(char **pbuf, int *pbufsize, int isrecord) /* get next input record */
int getrec(uschar **pbuf, int *pbufsize, int isrecord) /* get next input record */
{ /* note: cares whether buf == record */
int c;
char *buf = *pbuf;
uschar *buf = *pbuf;
uschar saveb0;
int bufsize = *pbufsize, savebufsize = bufsize;
@ -179,38 +186,85 @@ void nextfile(void)
argno++;
}
int readrec(char **pbuf, int *pbufsize, FILE *inf) /* read one record into buf */
int readrec(uschar **pbuf, int *pbufsize, FILE *inf) /* read one record into buf */
{
int sep, c;
char *rr, *buf = *pbuf;
uschar *rr, *buf = *pbuf;
int bufsize = *pbufsize;
size_t len;
if (strlen(*FS) >= sizeof(inputFS))
FATAL("field separator %.10s... is too long", *FS);
if ((len = strlen(*FS)) < len_inputFS) {
strcpy(inputFS, *FS); /* for subsequent field splitting */
} else {
len_inputFS = len + 1;
inputFS = realloc(inputFS, len_inputFS);
if (inputFS == NULL)
FATAL("field separator %.10s... is too long", *FS);
memcpy(inputFS, *FS, len_inputFS);
}
if ((sep = **RS) == 0) {
sep = '\n';
while ((c=getc(inf)) == '\n' && c != EOF) /* skip leading \n's */
;
if (c != EOF)
ungetc(c, inf);
} else if ((*RS)[1]) {
fa *pfa = makedfa(*RS, 1);
int tempstat = pfa->initstat;
char *brr = buf;
char *rrr = NULL;
int x;
for (rr = buf; ; ) {
while ((c = getc(inf)) != EOF) {
if (rr-buf+3 > bufsize)
if (!adjbuf(&buf, &bufsize, 3+rr-buf,
recsize, &rr, "readrec 2"))
FATAL("input record `%.30s...'"
" too long", buf);
*rr++ = c;
*rr = '\0';
if (!(x = nematch(pfa, brr))) {
pfa->initstat = tempstat;
if (rrr) {
rr = rrr;
ungetc(c, inf);
break;
}
} else {
pfa->initstat = 2;
brr = rrr = rr = patbeg;
}
}
if (rrr || c == EOF)
break;
if ((c = getc(inf)) == '\n' || c == EOF)
/* 2 in a row */
break;
*rr++ = '\n';
*rr++ = c;
}
} else {
for (rr = buf; ; ) {
for (; (c=getc(inf)) != sep && c != EOF; ) {
if (rr-buf+1 > bufsize)
if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 1"))
FATAL("input record `%.30s...' too long", buf);
if (!adjbuf(&buf, &bufsize, 1+rr-buf,
recsize, &rr, "readrec 1"))
FATAL("input record `%.30s...'"
" too long", buf);
*rr++ = c;
}
if (**RS == sep || c == EOF)
break;
if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
if ((c = getc(inf)) == '\n' || c == EOF)
/* 2 in a row */
break;
if (!adjbuf(&buf, &bufsize, 2+rr-buf, recsize, &rr, "readrec 2"))
if (!adjbuf(&buf, &bufsize, 2+rr-buf, recsize, &rr,
"readrec 2"))
FATAL("input record `%.30s...' too long", buf);
*rr++ = '\n';
*rr++ = c;
}
}
if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 3"))
FATAL("input record `%.30s...' too long", buf);
*rr = 0;
@ -226,7 +280,7 @@ char *getargv(int n) /* get ARGV[n] */
char *s, temp[50];
extern Array *ARGVtab;
sprintf(temp, "%d", n);
snprintf(temp, sizeof(temp), "%d", n);
x = setsymtab(temp, "", 0.0, STR, ARGVtab);
s = getsval(x);
dprintf( ("getargv(%d) returns |%s|\n", n, s) );
@ -268,14 +322,13 @@ void fldbld(void) /* create fields from current record */
n = strlen(r);
if (n > fieldssize) {
xfree(fields);
if ((fields = (char *) malloc(n+1)) == NULL)
if ((fields = malloc(n+1)) == NULL)
FATAL("out of space for fields in fldbld %d", n);
fieldssize = n;
}
fr = fields;
i = 0; /* number of fields accumulated here */
strcpy(inputFS, *FS);
if (strlen(inputFS) > 1) { /* it's a regular expression */
if (inputFS[0] && inputFS[1]) { /* it's a regular expression */
i = refldbld(r, inputFS);
} else if ((sep = *inputFS) == ' ') { /* default whitespace */
for (i = 0; ; ) {
@ -364,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;
}
}
@ -395,8 +448,8 @@ void growfldtab(int n) /* make new fields up to at least $n */
if (n > nf)
nf = n;
s = (nf+1) * (sizeof (struct Cell *)); /* freebsd: how much do we need? */
if (s / sizeof(struct Cell *) - 1 == nf) /* didn't overflow */
fldtab = (Cell **) realloc(fldtab, s);
if (s / sizeof(struct Cell *) - 1 == (size_t)nf) /* didn't overflow */
fldtab = realloc(fldtab, s);
else /* overflow sizeof int */
xfree(fldtab); /* make it null */
if (fldtab == NULL)
@ -416,7 +469,7 @@ int refldbld(const char *rec, const char *fs) /* build fields from reg expr in F
n = strlen(rec);
if (n > fieldssize) {
xfree(fields);
if ((fields = (char *) malloc(n+1)) == NULL)
if ((fields = malloc(n+1)) == NULL)
FATAL("out of space for fields in refldbld %d", n);
fieldssize = n;
}
@ -438,8 +491,8 @@ int refldbld(const char *rec, const char *fs) /* build fields from reg expr in F
if (nematch(pfa, rec)) {
pfa->initstat = 2; /* horrible coupling to b.c */
dprintf( ("match %s (%d chars)\n", patbeg, patlen) );
strncpy(fr, rec, patbeg-rec);
fr += patbeg - rec + 1;
strncpy(fr, rec, ((const char*)patbeg)-rec);
fr += ((const char*)patbeg) - rec + 1;
*(fr-1) = '\0';
rec = patbeg + patlen;
} else {
@ -455,7 +508,8 @@ int refldbld(const char *rec, const char *fs) /* build fields from reg expr in F
void recbld(void) /* create $0 from $1..$NF if necessary */
{
int i;
char *r, *p;
uschar *r;
char *p;
if (donerec == 1)
return;
@ -517,11 +571,6 @@ void SYNTAX(const char *fmt, ...)
eprint();
}
void fpecatch(int n)
{
FATAL("floating point exception %d", n);
}
extern int bracecnt, brackcnt, parencnt;
void bracecheck(void)
@ -603,7 +652,6 @@ void error()
void eprint(void) /* try to print context around error */
{
char *p, *q;
int c;
static int been_here = 0;
extern char ebuf[], *ep;
@ -627,11 +675,25 @@ void eprint(void) /* try to print context around error */
if (*p)
putc(*p, stderr);
fprintf(stderr, " <<< ");
if (*ep)
#if 0
/*
* The following code was used to print the rest of the line of
* error context. It naively counts brackets, parens and braces in
* order to minimize the parsing effect of dropping the rest of the
* line but it does not work in all the cases. It is too much work
* to save the current program input point and restore it in all the
* cases just for the benefit of error printing so for now this
* code is disabled. In particular this code is confused if the
* [ { ( ) } ] is inside a quoted string or a pattern.
*/
if (*ep) {
int c;
while ((c = input()) != '\n' && c != '\0' && c != EOF) {
putc(c, stderr);
bclass(c);
}
}
#endif
putc('\n', stderr);
ep = ebuf;
}
@ -686,7 +748,9 @@ int is_number(const char *s)
char *ep;
errno = 0;
r = strtod(s, &ep);
if (ep == s || r == HUGE_VAL || errno == ERANGE)
if (ep == s || errno == ERANGE)
return 0;
if (ep - s >= 3 && strncasecmp(ep - 3, "nan", 3) == 0)
return 0;
while (*ep == ' ' || *ep == '\t' || *ep == '\n')
ep++;

View File

@ -24,6 +24,10 @@ THIS SOFTWARE.
const char *version = "version 20100523";
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#define DEBUG
#include <stdio.h>
#include <ctype.h>
@ -32,7 +36,7 @@ const char *version = "version 20100523";
#include <string.h>
#include <signal.h>
#include "awk.h"
#include "ytab.h"
#include "awkgram.h"
extern char **environ;
extern int nfields;
@ -53,11 +57,52 @@ int curpfile = 0; /* current filename */
int safe = 0; /* 1 => "safe" mode */
static char *
setfs(char *p)
{
#ifdef notdef
/* wart: t=>\t */
if (p[0] == 't' && p[1] == 0)
return "\t";
else
#endif
if (p[0] != 0)
return p;
return NULL;
}
static void fpecatch(int n
#ifdef SA_SIGINFO
, siginfo_t *si, void *uc
#endif
)
{
#ifdef SA_SIGINFO
static const char *emsg[] = {
"Unknown error",
"Integer divide by zero",
"Integer overflow",
"Floating point divide by zero",
"Floating point overflow",
"Floating point underflow",
"Floating point inexact result",
"Invalid Floating point operation",
"Subscript out of range",
};
#endif
FATAL("floating point exception"
#ifdef SA_SIGINFO
": %s\n", emsg[si->si_code >= 1 && si->si_code <= 8 ?
si->si_code : 0]
#endif
);
}
int main(int argc, char *argv[])
{
const char *fs = NULL;
setlocale(LC_CTYPE, "");
setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
cmdname = argv[0];
if (argc == 1) {
@ -66,7 +111,18 @@ int main(int argc, char *argv[])
cmdname);
exit(1);
}
signal(SIGFPE, fpecatch);
#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
yyin = NULL;
symtab = makesymtab(NSYMTAB/NSYMTAB);
while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
@ -96,16 +152,11 @@ int main(int argc, char *argv[])
break;
case 'F': /* set field separator */
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];
fs = setfs(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 (argc > 1)
fs = setfs(argv[1]);
}
if (fs == NULL || *fs == '\0')
WARNING("field separator FS is empty");

View File

@ -27,6 +27,8 @@ CFLAGS = -O2
CFLAGS =
CC = gcc -Wall -g
CC = /opt/SUNWspro/bin/cc
CC = /opt/pure/purify/purify cc
CC = cc
CC = gcc -Wall -g -Wwrite-strings
CC = gcc -fprofile-arcs -ftest-coverage # then gcov f1.c; cat f1.c.gcov
@ -83,4 +85,4 @@ names:
@echo $(LISTING)
clean:
rm -f a.out *.o *.obj maketab maketab.exe *.bb *.bbg *.da *.gcov *.gcno *.gcda # proctab.c
rm -f a.out *.o *.obj maketab maketab.exe ytab.[ch] *.bb *.bbg *.da *.gcov *.gcno *.gcda # proctab.c

View File

@ -28,11 +28,15 @@ THIS SOFTWARE.
* it finds the indices in ytab.h, produced by yacc.
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "awk.h"
#include "ytab.h"
#include "awkgram.h"
struct xx
{ int token;
@ -103,6 +107,7 @@ struct xx
{ ARG, "arg", "arg" },
{ VARNF, "getnf", "NF" },
{ GETLINE, "awkgetline", "getline" },
{ GENSUB, "gensub", "gensub" },
{ 0, "", "" },
};
@ -120,27 +125,30 @@ int main(int argc, char *argv[])
printf("#include <stdio.h>\n");
printf("#include \"awk.h\"\n");
printf("#include \"ytab.h\"\n\n");
printf("#include \"awkgram.h\"\n\n");
for (i = SIZE; --i >= 0; )
names[i] = "";
if ((fp = fopen("ytab.h", "r")) == NULL) {
fprintf(stderr, "maketab can't open ytab.h!\n");
if ((fp = fopen("awkgram.h", "r")) == NULL) {
fprintf(stderr, "maketab can't open awkgram.h!\n");
exit(1);
}
printf("static char *printname[%d] = {\n", SIZE);
printf("static const char * const printname[%d] = {\n", SIZE);
i = 0;
while (fgets(buf, sizeof buf, fp) != NULL) {
n = sscanf(buf, "%1c %s %s %d", &c, def, name, &tok);
n = sscanf(buf, "%1c %199s %199s %d", &c, def, name, &tok);
if (c != '#' || (n != 4 && strcmp(def,"define") != 0)) /* not a valid #define */
continue;
if (tok < FIRSTTOKEN || tok > LASTTOKEN) {
/* fprintf(stderr, "maketab funny token %d %s ignored\n", tok, buf); */
continue;
}
names[tok-FIRSTTOKEN] = (char *) malloc(strlen(name)+1);
strcpy(names[tok-FIRSTTOKEN], name);
printf("\t(char *) \"%s\",\t/* %d */\n", name, tok);
names[tok-FIRSTTOKEN] = strdup(name);
if (names[tok-FIRSTTOKEN] == NULL) {
fprintf(stderr, "maketab out of space copying %s", name);
continue;
}
printf("\t\"%s\",\t/* %d */\n", name, tok);
i++;
}
printf("};\n\n");
@ -155,11 +163,11 @@ int main(int argc, char *argv[])
printf("\t%s,\t/* %s */\n", table[i], names[i]);
printf("};\n\n");
printf("char *tokname(int n)\n"); /* print a tokname() function */
printf("const char *tokname(int n)\n"); /* print a tokname() function */
printf("{\n");
printf(" static char buf[100];\n\n");
printf(" if (n < FIRSTTOKEN || n > LASTTOKEN) {\n");
printf(" sprintf(buf, \"token %%d\", n);\n");
printf(" snprintf(buf, sizeof(buf), \"token %%d\", n);\n");
printf(" return buf;\n");
printf(" }\n");
printf(" return printname[n-FIRSTTOKEN];\n");

View File

@ -22,18 +22,22 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
****************************************************************/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#define DEBUG
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "awk.h"
#include "ytab.h"
#include "awkgram.h"
Node *nodealloc(int n)
{
Node *x;
x = (Node *) malloc(sizeof(Node) + (n-1)*sizeof(Node *));
x = malloc(sizeof(Node) + (n-1)*sizeof(Node *));
if (x == NULL)
FATAL("out of space in nodealloc");
x->nnext = NULL;
@ -93,6 +97,20 @@ Node *node4(int a, Node *b, Node *c, Node *d, Node *e)
return(x);
}
Node *node5(int a, Node *b, Node *c, Node *d, Node *e, Node *f)
{
Node *x;
x = nodealloc(5);
x->nobj = a;
x->narg[0] = b;
x->narg[1] = c;
x->narg[2] = d;
x->narg[3] = e;
x->narg[4] = f;
return(x);
}
Node *stat1(int a, Node *b)
{
Node *x;
@ -165,6 +183,15 @@ Node *op4(int a, Node *b, Node *c, Node *d, Node *e)
return(x);
}
Node *op5(int a, Node *b, Node *c, Node *d, Node *e, Node *f)
{
Node *x;
x = node5(a,b,c,d,e, f);
x->ntype = NEXPR;
return(x);
}
Node *celltonode(Cell *a, int b)
{
Node *x;

View File

@ -1,105 +1,110 @@
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <stdio.h>
#include "awk.h"
#include "ytab.h"
#include "awkgram.h"
static char *printname[93] = {
(char *) "FIRSTTOKEN", /* 258 */
(char *) "PROGRAM", /* 259 */
(char *) "PASTAT", /* 260 */
(char *) "PASTAT2", /* 261 */
(char *) "XBEGIN", /* 262 */
(char *) "XEND", /* 263 */
(char *) "NL", /* 264 */
(char *) "ARRAY", /* 265 */
(char *) "MATCH", /* 266 */
(char *) "NOTMATCH", /* 267 */
(char *) "MATCHOP", /* 268 */
(char *) "FINAL", /* 269 */
(char *) "DOT", /* 270 */
(char *) "ALL", /* 271 */
(char *) "CCL", /* 272 */
(char *) "NCCL", /* 273 */
(char *) "CHAR", /* 274 */
(char *) "OR", /* 275 */
(char *) "STAR", /* 276 */
(char *) "QUEST", /* 277 */
(char *) "PLUS", /* 278 */
(char *) "EMPTYRE", /* 279 */
(char *) "AND", /* 280 */
(char *) "BOR", /* 281 */
(char *) "APPEND", /* 282 */
(char *) "EQ", /* 283 */
(char *) "GE", /* 284 */
(char *) "GT", /* 285 */
(char *) "LE", /* 286 */
(char *) "LT", /* 287 */
(char *) "NE", /* 288 */
(char *) "IN", /* 289 */
(char *) "ARG", /* 290 */
(char *) "BLTIN", /* 291 */
(char *) "BREAK", /* 292 */
(char *) "CLOSE", /* 293 */
(char *) "CONTINUE", /* 294 */
(char *) "DELETE", /* 295 */
(char *) "DO", /* 296 */
(char *) "EXIT", /* 297 */
(char *) "FOR", /* 298 */
(char *) "FUNC", /* 299 */
(char *) "SUB", /* 300 */
(char *) "GSUB", /* 301 */
(char *) "IF", /* 302 */
(char *) "INDEX", /* 303 */
(char *) "LSUBSTR", /* 304 */
(char *) "MATCHFCN", /* 305 */
(char *) "NEXT", /* 306 */
(char *) "NEXTFILE", /* 307 */
(char *) "ADD", /* 308 */
(char *) "MINUS", /* 309 */
(char *) "MULT", /* 310 */
(char *) "DIVIDE", /* 311 */
(char *) "MOD", /* 312 */
(char *) "ASSIGN", /* 313 */
(char *) "ASGNOP", /* 314 */
(char *) "ADDEQ", /* 315 */
(char *) "SUBEQ", /* 316 */
(char *) "MULTEQ", /* 317 */
(char *) "DIVEQ", /* 318 */
(char *) "MODEQ", /* 319 */
(char *) "POWEQ", /* 320 */
(char *) "PRINT", /* 321 */
(char *) "PRINTF", /* 322 */
(char *) "SPRINTF", /* 323 */
(char *) "ELSE", /* 324 */
(char *) "INTEST", /* 325 */
(char *) "CONDEXPR", /* 326 */
(char *) "POSTINCR", /* 327 */
(char *) "PREINCR", /* 328 */
(char *) "POSTDECR", /* 329 */
(char *) "PREDECR", /* 330 */
(char *) "VAR", /* 331 */
(char *) "IVAR", /* 332 */
(char *) "VARNF", /* 333 */
(char *) "CALL", /* 334 */
(char *) "NUMBER", /* 335 */
(char *) "STRING", /* 336 */
(char *) "REGEXPR", /* 337 */
(char *) "GETLINE", /* 338 */
(char *) "SUBSTR", /* 339 */
(char *) "SPLIT", /* 340 */
(char *) "RETURN", /* 341 */
(char *) "WHILE", /* 342 */
(char *) "CAT", /* 343 */
(char *) "UMINUS", /* 344 */
(char *) "NOT", /* 345 */
(char *) "POWER", /* 346 */
(char *) "INCR", /* 347 */
(char *) "DECR", /* 348 */
(char *) "INDIRECT", /* 349 */
(char *) "LASTTOKEN", /* 350 */
static const char * const printname[94] = {
"FIRSTTOKEN", /* 257 */
"PROGRAM", /* 258 */
"PASTAT", /* 259 */
"PASTAT2", /* 260 */
"XBEGIN", /* 261 */
"XEND", /* 262 */
"NL", /* 263 */
"ARRAY", /* 264 */
"MATCH", /* 265 */
"NOTMATCH", /* 266 */
"MATCHOP", /* 267 */
"FINAL", /* 268 */
"DOT", /* 269 */
"ALL", /* 270 */
"CCL", /* 271 */
"NCCL", /* 272 */
"CHAR", /* 273 */
"OR", /* 274 */
"STAR", /* 275 */
"QUEST", /* 276 */
"PLUS", /* 277 */
"EMPTYRE", /* 278 */
"AND", /* 279 */
"BOR", /* 280 */
"APPEND", /* 281 */
"EQ", /* 282 */
"GE", /* 283 */
"GT", /* 284 */
"LE", /* 285 */
"LT", /* 286 */
"NE", /* 287 */
"IN", /* 288 */
"ARG", /* 289 */
"BLTIN", /* 290 */
"BREAK", /* 291 */
"CLOSE", /* 292 */
"CONTINUE", /* 293 */
"DELETE", /* 294 */
"DO", /* 295 */
"EXIT", /* 296 */
"FOR", /* 297 */
"FUNC", /* 298 */
"SUB", /* 299 */
"GSUB", /* 300 */
"IF", /* 301 */
"INDEX", /* 302 */
"LSUBSTR", /* 303 */
"MATCHFCN", /* 304 */
"NEXT", /* 305 */
"NEXTFILE", /* 306 */
"ADD", /* 307 */
"MINUS", /* 308 */
"MULT", /* 309 */
"DIVIDE", /* 310 */
"MOD", /* 311 */
"ASSIGN", /* 312 */
"ASGNOP", /* 313 */
"ADDEQ", /* 314 */
"SUBEQ", /* 315 */
"MULTEQ", /* 316 */
"DIVEQ", /* 317 */
"MODEQ", /* 318 */
"POWEQ", /* 319 */
"PRINT", /* 320 */
"PRINTF", /* 321 */
"SPRINTF", /* 322 */
"ELSE", /* 323 */
"INTEST", /* 324 */
"CONDEXPR", /* 325 */
"POSTINCR", /* 326 */
"PREINCR", /* 327 */
"POSTDECR", /* 328 */
"PREDECR", /* 329 */
"VAR", /* 330 */
"IVAR", /* 331 */
"VARNF", /* 332 */
"CALL", /* 333 */
"NUMBER", /* 334 */
"STRING", /* 335 */
"REGEXPR", /* 336 */
"GETLINE", /* 337 */
"GENSUB", /* 338 */
"RETURN", /* 339 */
"SPLIT", /* 340 */
"SUBSTR", /* 341 */
"WHILE", /* 342 */
"CAT", /* 343 */
"NOT", /* 344 */
"UMINUS", /* 345 */
"POWER", /* 346 */
"DECR", /* 347 */
"INCR", /* 348 */
"INDIRECT", /* 349 */
"LASTTOKEN", /* 350 */
};
Cell *(*proctab[93])(Node **, int) = {
Cell *(*proctab[94])(Node **, int) = {
nullproc, /* FIRSTTOKEN */
program, /* PROGRAM */
pastat, /* PASTAT */
@ -183,24 +188,25 @@ Cell *(*proctab[93])(Node **, int) = {
awkgetline, /* GETLINE */
substr, /* SUBSTR */
split, /* SPLIT */
gensub, /* GENSUB */
jump, /* RETURN */
whilestat, /* WHILE */
cat, /* CAT */
arith, /* UMINUS */
boolop, /* NOT */
arith, /* UMINUS */
arith, /* POWER */
nullproc, /* INCR */
nullproc, /* DECR */
nullproc, /* INCR */
indirect, /* INDIRECT */
nullproc, /* LASTTOKEN */
};
char *tokname(int n)
const char *tokname(int n)
{
static char buf[100];
if (n < FIRSTTOKEN || n > LASTTOKEN) {
sprintf(buf, "token %d", n);
snprintf(buf, sizeof(buf), "token %d", n);
return buf;
}
return printname[n-FIRSTTOKEN];

View File

@ -43,8 +43,8 @@ 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 int hexstr(const uschar **);
extern int quoted(const uschar **);
extern char *cclenter(const char *);
extern void overflo(const char *);
extern void cfoll(fa *, Node *);
@ -73,12 +73,14 @@ extern Node *node1(int, Node *);
extern Node *node2(int, Node *, Node *);
extern Node *node3(int, Node *, Node *, Node *);
extern Node *node4(int, Node *, Node *, Node *, Node *);
extern Node *node5(int, Node *, Node *, Node *, Node *, Node *);
extern Node *stat3(int, Node *, Node *, Node *);
extern Node *op2(int, Node *, Node *);
extern Node *op1(int, Node *);
extern Node *stat1(int, Node *);
extern Node *op3(int, Node *, Node *, Node *);
extern Node *op4(int, Node *, Node *, Node *, Node *);
extern Node *op5(int, Node *, Node *, Node *, Node *, Node *);
extern Node *stat2(int, Node *, Node *);
extern Node *stat4(int, Node *, Node *, Node *, Node *);
extern Node *celltonode(Cell *, int);
@ -88,7 +90,7 @@ extern Node *pa2stat(Node *, Node *, Node *);
extern Node *linkum(Node *, Node *);
extern void defn(Cell *, Node *, Node *);
extern int isarg(const char *);
extern char *tokname(int);
extern const char *tokname(int);
extern Cell *(*proctab[])(Node **, int);
extern int ptoi(void *);
extern Node *itonp(int);
@ -110,15 +112,16 @@ 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 n);
extern char *qstring(const char *, int);
extern void recinit(unsigned int);
extern void initgetrec(void);
extern void makefields(int, int);
extern void growfldtab(int n);
extern int getrec(char **, int *, int);
extern int getrec(uschar **, int *, int);
extern void nextfile(void);
extern int readrec(char **buf, int *bufsize, FILE *inf);
extern int readrec(uschar **buf, int *bufsize, FILE *inf);
extern char *getargv(int);
extern void setclvar(char *);
extern void fldbld(void);
@ -128,12 +131,14 @@ extern int refldbld(const char *, const char *);
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 *, ...);
extern void FATAL(const char *, ...);
extern void WARNING(const char *, ...);
extern void SYNTAX(const char *, ...)
__attribute__((__format__(__printf__, 1, 2)));
extern void FATAL(const char *, ...)
__attribute__((__format__(__printf__, 1, 2)));
extern void WARNING(const char *, ...)
__attribute__((__format__(__printf__, 1, 2)));
extern void error(void);
extern void eprint(void);
extern void bclass(int);
@ -141,7 +146,7 @@ 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, const char *what);
extern int adjbuf(uschar **pb, int *sz, int min, int q, uschar **pbp, const char *what);
extern void run(Node *);
extern Cell *execute(Node *);
extern Cell *program(Node **, int);
@ -190,6 +195,7 @@ extern Cell *closefile(Node **, int);
extern void closeall(void);
extern Cell *sub(Node **, int);
extern Cell *gsub(Node **, int);
extern Cell *gensub(Node **, int);
extern FILE *popen(const char *, const char *);
extern int pclose(FILE *);

View File

@ -22,9 +22,15 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
****************************************************************/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#define DEBUG
#include <stdio.h>
#include <ctype.h>
#include <wchar.h>
#include <wctype.h>
#include <setjmp.h>
#include <limits.h>
#include <math.h>
@ -32,9 +38,11 @@ THIS SOFTWARE.
#include <stdlib.h>
#include <time.h>
#include "awk.h"
#include "ytab.h"
#include "awkgram.h"
#define tempfree(x) if (istemp(x)) tfree(x); else
#define tempfree(x) do { if (istemp(x)) tfree(x); } while (/*CONSTCOND*/0)
void stdinit(void);
/*
#undef tempfree
@ -70,28 +78,28 @@ extern int pairstack[];
Node *winner = NULL; /* root of parse tree */
Cell *tmps; /* free temporary cells for execution */
static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM };
static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM, NULL };
Cell *True = &truecell;
static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM };
static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM, NULL };
Cell *False = &falsecell;
static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM };
static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM, NULL };
Cell *jbreak = &breakcell;
static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM };
static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM, NULL };
Cell *jcont = &contcell;
static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM };
static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM, NULL };
Cell *jnext = &nextcell;
static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM };
static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM, NULL};
Cell *jnextfile = &nextfilecell;
static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM };
static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM, NULL };
Cell *jexit = &exitcell;
static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM };
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 };
static Cell tempcell ={ OCELL, CTEMP, 0, EMPTY, 0.0, NUM|STR|DONTFREE, NULL };
Node *curnode = NULL; /* the node being executed, for debugging */
/* buffer memory management */
int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
int adjbuf(uschar **pbuf, int *psiz, int minlen, int quantum, uschar **pbptr,
const char *whatrtn)
/* pbuf: address of pointer to buffer being managed
* psiz: address of buffer size variable
@ -110,7 +118,7 @@ int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
/* round up to next multiple of quantum */
if (rminlen)
minlen += quantum - rminlen;
tbuf = (char *) realloc(*pbuf, minlen);
tbuf = realloc(*pbuf, minlen);
dprintf( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, *pbuf, tbuf) );
if (tbuf == NULL) {
if (whatrtn)
@ -127,8 +135,6 @@ int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
void run(Node *a) /* execution of parse tree starts here */
{
extern void stdinit(void);
stdinit();
execute(a);
closeall();
@ -216,11 +222,11 @@ struct Frame { /* stack frame for awk function calls */
struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */
int nframe = 0; /* number of frames allocated */
struct Frame *fp = NULL; /* frame pointer. bottom level unused */
struct Frame *frp = 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 };
static const 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;
@ -233,21 +239,21 @@ Cell *call(Node **a, int n) /* function call. very kludgy and fragile */
if (!isfcn(fcn))
FATAL("calling undefined function %s", s);
if (frame == NULL) {
fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
frp = frame = calloc(nframe += 100, sizeof(*frp));
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), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) );
dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (frp-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], fp=%d:\n", i, (int) (fp-frame)) );
dprintf( ("evaluate args[%d], fp=%d:\n", i, (int) (frp-frame)) );
y = execute(x);
oargs[i] = y;
dprintf( ("args[%d]: %s %f <%s>, t=%o\n",
@ -264,26 +270,25 @@ Cell *call(Node **a, int n) /* function call. very kludgy and fragile */
args[i] = gettemp();
*args[i] = newcopycell;
}
fp++; /* now ok to up frame */
if (fp >= frame + nframe) {
int dfp = fp - frame; /* old index */
frame = (struct Frame *)
realloc((char *) frame, (nframe += 100) * sizeof(struct Frame));
frp++; /* now ok to up frame */
if (frp >= frame + nframe) {
int dfp = frp - frame; /* old index */
frame = realloc(frame, (nframe += 100) * sizeof(*frame));
if (frame == NULL)
FATAL("out of space for stack frames in %s", s);
fp = frame + dfp;
frp = frame + dfp;
}
fp->fcncell = fcn;
fp->args = args;
fp->nargs = ndef; /* number defined with (excess are locals) */
fp->retval = gettemp();
frp->fcncell = fcn;
frp->args = args;
frp->nargs = ndef; /* number defined with (excess are locals) */
frp->retval = gettemp();
dprintf( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) );
dprintf( ("start exec of %s, fp=%d\n", s, (int) (frp-frame)) );
y = execute((Node *)(fcn->sval)); /* execute body */
dprintf( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) );
dprintf( ("finished exec of %s, fp=%d\n", s, (int) (frp-frame)) );
for (i = 0; i < ndef; i++) {
Cell *t = fp->args[i];
Cell *t = frp->args[i];
if (isarr(t)) {
if (t->csub == CCOPY) {
if (i >= ncall) {
@ -312,9 +317,9 @@ Cell *call(Node **a, int n) /* function call. very kludgy and fragile */
if (freed == 0) {
tempfree(y); /* don't free twice! */
}
z = fp->retval; /* return value */
z = frp->retval; /* return value */
dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
fp--;
frp--;
return(z);
}
@ -322,14 +327,18 @@ Cell *copycell(Cell *x) /* make a copy of a cell in a temp */
{
Cell *y;
/* copy is not constant or field */
y = gettemp();
y->tval = x->tval & ~(CON|FLD|REC);
y->csub = CCOPY; /* prevents freeing until call is over */
y->nval = x->nval; /* BUG? */
if (isstr(x))
if (isstr(x) /* || x->ctype == OCELL */) {
y->sval = tostring(x->sval);
y->tval &= ~DONTFREE;
} else
y->tval |= DONTFREE;
y->fval = x->fval;
y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */
/* is DONTFREE right? */
return y;
}
@ -337,11 +346,11 @@ Cell *arg(Node **a, int n) /* nth argument of a function */
{
n = ptoi(a[0]); /* argument number, counting from 0 */
dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );
if (n+1 > fp->nargs)
dprintf( ("arg(%d), fp->nargs=%d\n", n, frp->nargs) );
if (n+1 > frp->nargs)
FATAL("argument #%d of function %s was not supplied",
n+1, fp->fcncell->nval);
return fp->args[n];
n+1, frp->fcncell->nval);
return frp->args[n];
}
Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */
@ -360,14 +369,14 @@ Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */
if (a[0] != NULL) {
y = execute(a[0]);
if ((y->tval & (STR|NUM)) == (STR|NUM)) {
setsval(fp->retval, getsval(y));
fp->retval->fval = getfval(y);
fp->retval->tval |= NUM;
setsval(frp->retval, getsval(y));
frp->retval->fval = getfval(y);
frp->retval->tval |= NUM;
}
else if (y->tval & STR)
setsval(fp->retval, getsval(y));
setsval(frp->retval, getsval(y));
else if (y->tval & NUM)
setfval(fp->retval, getfval(y));
setfval(frp->retval, getfval(y));
else /* can't happen */
FATAL("bad type variable %d", y->tval);
tempfree(y);
@ -393,11 +402,11 @@ Cell *awkgetline(Node **a, int n) /* get next line from specific input */
Cell *r, *x;
extern Cell **fldtab;
FILE *fp;
char *buf;
uschar *buf;
int bufsize = recsize;
int mode;
if ((buf = (char *) malloc(bufsize)) == NULL)
if ((buf = malloc(bufsize)) == NULL)
FATAL("out of memory in getline");
fflush(stdout); /* in case someone is waiting for a prompt */
@ -453,11 +462,11 @@ Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
Cell *x, *y, *z;
char *s;
Node *np;
char *buf;
uschar *buf;
int bufsz = recsize;
int nsub = strlen(*SUBSEP);
if ((buf = (char *) malloc(bufsz)) == NULL)
if ((buf = malloc(bufsz)) == NULL)
FATAL("out of memory in array");
x = execute(a[0]); /* Cell* for symbol table */
@ -467,9 +476,9 @@ Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
s = getsval(y);
if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "array"))
FATAL("out of memory for %s[%s...]", x->nval, buf);
strcat(buf, s);
strlcat(buf, s, bufsz);
if (np->nnext)
strcat(buf, *SUBSEP);
strlcat(buf, *SUBSEP, bufsz);
tempfree(y);
}
if (!isarr(x)) {
@ -492,7 +501,7 @@ Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts *
{
Cell *x, *y;
Node *np;
char *s;
uschar *s;
int nsub = strlen(*SUBSEP);
x = execute(a[0]); /* Cell* for symbol table */
@ -505,8 +514,8 @@ Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts *
x->sval = (char *) makesymtab(NSYMTAB);
} else {
int bufsz = recsize;
char *buf;
if ((buf = (char *) malloc(bufsz)) == NULL)
uschar *buf;
if ((buf = malloc(bufsz)) == NULL)
FATAL("out of memory in adelete");
buf[0] = 0;
for (np = a[1]; np; np = np->nnext) {
@ -514,9 +523,9 @@ Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts *
s = getsval(y);
if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "awkdelete"))
FATAL("out of memory deleting %s[%s...]", x->nval, buf);
strcat(buf, s);
strlcat(buf, s, bufsz);
if (np->nnext)
strcat(buf, *SUBSEP);
strlcat(buf, *SUBSEP, bufsz);
tempfree(y);
}
freeelem(x, buf);
@ -530,7 +539,7 @@ Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
{
Cell *x, *ap, *k;
Node *p;
char *buf;
uschar *buf;
char *s;
int bufsz = recsize;
int nsub = strlen(*SUBSEP);
@ -544,7 +553,7 @@ Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
ap->tval |= ARR;
ap->sval = (char *) makesymtab(NSYMTAB);
}
if ((buf = (char *) malloc(bufsz)) == NULL) {
if ((buf = malloc(bufsz)) == NULL) {
FATAL("out of memory in intest");
}
buf[0] = 0;
@ -571,7 +580,8 @@ Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
Cell *matchop(Node **a, int n) /* ~ and match() */
{
Cell *x, *y;
char *s, *t;
uschar *s;
char *t;
int i;
fa *pfa;
int (*mf)(fa *, const char *) = match, mode = 0;
@ -693,7 +703,7 @@ Cell *gettemp(void) /* get a tempcell */
Cell *x;
if (!tmps) {
tmps = (Cell *) calloc(100, sizeof(Cell));
tmps = calloc(100, sizeof(*tmps));
if (!tmps)
FATAL("out of space for temporaries");
for(i = 1; i < 100; i++)
@ -806,19 +816,20 @@ Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */
int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like conversions */
{
char *fmt;
char *p, *t;
uschar *fmt, *p, *t;
const char *os;
Cell *x;
int flag = 0, n;
int fmtwd; /* format width */
int fmtsz = recsize;
char *buf = *pbuf;
uschar *buf = *pbuf;
int bufsize = *pbufsize;
#define FMTSZ(a) (fmtsz - ((a) - fmt))
#define BUFSZ(a) (bufsize - ((a) - buf))
os = s;
p = buf;
if ((fmt = (char *) malloc(fmtsz)) == NULL)
if ((fmt = malloc(fmtsz)) == NULL)
FATAL("out of memory in format()");
while (*s) {
adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1");
@ -839,12 +850,18 @@ int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like co
for (t = fmt; (*t++ = *s) != '\0'; s++) {
if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3"))
FATAL("format item %.30s... ran format() out of memory", os);
if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L')
if (*s == 'l' || *s == 'h' || *s == 'L')
goto weird;
if (isalpha((uschar)*s))
break; /* the ansi panoply */
if (*s == '*') {
if (a == NULL)
FATAL("not enough args in printf("
"\"%.30s\")", os);
x = execute(a);
a = a->nnext;
sprintf(t-1, "%d", fmtwd=(int) getfval(x));
snprintf(t - 1, FMTSZ(t - 1),
"%d", fmtwd=(int) getfval(x));
if (fmtwd < 0)
fmtwd = -fmtwd;
adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
@ -878,6 +895,7 @@ int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like co
flag = 'c';
break;
default:
weird:
WARNING("weird printf conversion %s", fmt);
flag = '?';
break;
@ -891,18 +909,18 @@ int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like co
n = fmtwd;
adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format5");
switch (flag) {
case '?': sprintf(p, "%s", fmt); /* unknown, so dump it too */
case '?': snprintf(p, BUFSZ(p), "%s", fmt); /* unknown, so dump it too */
t = getsval(x);
n = strlen(t);
if (fmtwd > n)
n = fmtwd;
adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format6");
p += strlen(p);
sprintf(p, "%s", t);
snprintf(p, BUFSZ(p), "%s", t);
break;
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 'f': snprintf(p, BUFSZ(p), fmt, getfval(x)); break;
case 'd': snprintf(p, BUFSZ(p), fmt, (long) getfval(x)); break;
case 'u': snprintf(p, BUFSZ(p), fmt, (int) getfval(x)); break;
case 's':
t = getsval(x);
n = strlen(t);
@ -910,18 +928,18 @@ int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like co
n = fmtwd;
if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format7"))
FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
sprintf(p, fmt, t);
snprintf(p, BUFSZ(p), fmt, t);
break;
case 'c':
if (isnum(x)) {
if (getfval(x))
sprintf(p, fmt, (int) getfval(x));
snprintf(p, BUFSZ(p), fmt, (int) getfval(x));
else {
*p++ = '\0'; /* explicit null byte */
*p = '\0'; /* next output will start here */
}
} else
sprintf(p, fmt, getsval(x)[0]);
snprintf(p, BUFSZ(p), fmt, getsval(x)[0]);
break;
default:
FATAL("can't happen: bad conversion %c in format()", flag);
@ -946,7 +964,7 @@ Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */
char *buf;
int bufsz=3*recsize;
if ((buf = (char *) malloc(bufsz)) == NULL)
if ((buf = malloc(bufsz)) == NULL)
FATAL("out of memory in awksprintf");
y = a[0]->nnext;
x = execute(a[0]);
@ -969,7 +987,7 @@ Cell *awkprintf(Node **a, int n) /* printf */
int len;
int bufsz=3*recsize;
if ((buf = (char *) malloc(bufsz)) == NULL)
if ((buf = malloc(bufsz)) == NULL)
FATAL("out of memory in awkprintf");
y = a[0]->nnext;
x = execute(a[0]);
@ -1153,7 +1171,7 @@ Cell *cat(Node **a, int q) /* a[0] cat a[1] */
getsval(y);
n1 = strlen(x->sval);
n2 = strlen(y->sval);
s = (char *) malloc(n1 + n2 + 1);
s = malloc(n1 + n2 + 1);
if (s == NULL)
FATAL("out of space concatenating %.15s... and %.15s...",
x->sval, y->sval);
@ -1206,6 +1224,7 @@ Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */
return(False);
}
static char regexpr[] = "(regexpr)";
Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
{
Cell *x = 0, *y, *ap;
@ -1223,7 +1242,7 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
x = execute(a[2]);
fs = getsval(x);
} else if (arg3type == REGEXPR)
fs = "(regexpr)"; /* split(str,arr,/regexpr/) */
fs = regexpr; /* split(str,arr,/regexpr/) */
else
FATAL("illegal type of split");
sep = *fs;
@ -1247,7 +1266,7 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
pfa->initstat = 2;
do {
n++;
sprintf(num, "%d", n);
snprintf(num, sizeof(num), "%d", n);
temp = *patbeg;
*patbeg = '\0';
if (is_number(s))
@ -1258,7 +1277,7 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
s = patbeg + patlen;
if (*(patbeg+patlen-1) == 0 || *s == 0) {
n++;
sprintf(num, "%d", n);
snprintf(num, sizeof(num), "%d", n);
setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
pfa->initstat = tempstat;
goto spdone;
@ -1268,7 +1287,7 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
/* cf gsub and refldbld */
}
n++;
sprintf(num, "%d", n);
snprintf(num, sizeof(num), "%d", n);
if (is_number(s))
setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
else
@ -1288,7 +1307,7 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
temp = *s;
*s = '\0';
sprintf(num, "%d", n);
snprintf(num, sizeof(num), "%d", n);
if (is_number(t))
setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
else
@ -1301,7 +1320,7 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
for (n = 0; *s != 0; s++) {
char buf[2];
n++;
sprintf(num, "%d", n);
snprintf(num, sizeof(num), "%d", n);
buf[0] = *s;
buf[1] = 0;
if (isdigit((uschar)buf[0]))
@ -1317,7 +1336,7 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
s++;
temp = *s;
*s = '\0';
sprintf(num, "%d", n);
snprintf(num, sizeof(num), "%d", n);
if (is_number(t))
setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
else
@ -1461,15 +1480,77 @@ Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
return True;
}
void flush_all(void);
static char *nawk_toXXX(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_toXXX(s, toupper, towupper);
}
static char *nawk_tolower(const char *s)
{
return nawk_toXXX(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;
char *p, *buf;
int t, sz;
char *buf, *fmt;
Node *nextarg;
FILE *fp;
void flush_all(void);
time_t tv;
struct tm *tm;
t = ptoi(a[0]);
x = execute(a[1]);
@ -1521,16 +1602,10 @@ Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg lis
break;
case FTOUPPER:
case FTOLOWER:
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);
}
if (t == FTOUPPER)
buf = nawk_toupper(getsval(x));
else
buf = nawk_tolower(getsval(x));
tempfree(x);
x = gettemp();
setsval(x, buf);
@ -1541,10 +1616,40 @@ Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg lis
flush_all(); /* fflush() or fflush("") -> all */
u = 0;
} else if ((fp = openfile(FFLUSH, getsval(x))) == NULL)
u = EOF;
u = -1;
else
u = fflush(fp);
break;
case FSYSTIME:
u = time((time_t *) 0); break;
case FSTRFTIME:
/* strftime([format [,timestamp]]) */
if (nextarg) {
y = execute(nextarg), nextarg = nextarg->nnext;
tv = (time_t) getfval(y);
tempfree(y);
} else
tv = time((time_t *) 0);
tm = localtime(&tv);
if (isrec(x)) {
/* format argument not provided, use default */
fmt = tostring("%a %b %d %H:%M:%S %Z %Y");
} else
fmt = tostring(getsval(x));
sz = 32, buf = NULL;
do {
if ((buf = realloc(buf, (sz *= 2))) == NULL)
FATAL("out of memory in strftime");
} while(strftime(buf, sz, fmt, tm) == 0);
y = gettemp();
setsval(y, buf);
free(fmt);
free(buf);
return y;
default: /* can't happen */
FATAL("illegal function type %d", t);
break;
@ -1613,28 +1718,36 @@ struct files {
FILE *fp;
const char *fname;
int mode; /* '|', 'a', 'w' => LE/LT, GT */
} files[FOPEN_MAX] ={
{ NULL, "/dev/stdin", LT }, /* watch out: don't free this! */
{ NULL, "/dev/stdout", GT },
{ NULL, "/dev/stderr", GT }
};
} *files;
size_t nfiles;
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);
files[0].fp = stdin;
files[0].fname = "/dev/stdin";
files[0].mode = LT;
files[1].fp = stdout;
files[1].fname = "/dev/stdout";
files[1].mode = GT;
files[2].fp = stderr;
files[2].fname = "/dev/stderr";
files[2].mode = GT;
}
FILE *openfile(int a, const char *us)
{
const char *s = us;
int i, m;
size_t i;
int m;
FILE *fp = 0;
if (*s == '\0')
FATAL("null file name in print or getline");
for (i=0; i < FOPEN_MAX; i++)
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;
@ -1644,11 +1757,19 @@ FILE *openfile(int a, const char *us)
if (a == FFLUSH) /* didn't find it, so don't create it! */
return NULL;
for (i=0; i < FOPEN_MAX; i++)
if (files[i].fp == 0)
for (i = 0; i < nfiles; i++)
if (files[i].fp == NULL)
break;
if (i >= FOPEN_MAX)
FATAL("%s makes too many open files", s);
if (i >= nfiles) {
struct files *nf;
size_t nnf = nfiles + FOPEN_MAX;
nf = realloc(files, nnf * sizeof(*nf));
if (nf == NULL)
FATAL("cannot grow files for %s and %zu files", s, nnf);
(void)memset(&nf[nfiles], 0, FOPEN_MAX * sizeof(*nf));
nfiles = nnf;
files = nf;
}
fflush(stdout); /* force a semblance of order */
m = a;
if (a == GT) {
@ -1674,9 +1795,9 @@ FILE *openfile(int a, const char *us)
const char *filename(FILE *fp)
{
int i;
size_t i;
for (i = 0; i < FOPEN_MAX; i++)
for (i = 0; i < nfiles; i++)
if (fp == files[i].fp)
return files[i].fname;
return "???";
@ -1685,24 +1806,28 @@ const char *filename(FILE *fp)
Cell *closefile(Node **a, int n)
{
Cell *x;
int i, stat;
size_t i;
int stat;
n = n;
x = execute(a[0]);
getsval(x);
stat = -1;
for (i = 0; i < FOPEN_MAX; i++) {
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);
stat = pclose(files[i].fp) == -1;
else
stat = fclose(files[i].fp);
if (stat == EOF)
WARNING( "i/o error occurred closing %s", files[i].fname );
stat = fclose(files[i].fp) == EOF;
if (stat) {
stat = -1;
WARNING( "i/o error occurred closing %s",
files[i].fname );
}
if (i > 2) /* don't do /dev/std... */
xfree(files[i].fname);
free(__UNCONST(files[i].fname));
files[i].fname = NULL; /* watch out for ref thru this */
files[i].fp = NULL;
}
@ -1715,17 +1840,22 @@ Cell *closefile(Node **a, int n)
void closeall(void)
{
int i, stat;
size_t i;
int stat;
for (i = 0; i < FOPEN_MAX; i++) {
for (i = 0; i < nfiles; 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);
if (i == 0)
stat = fpurge(files[i].fp) == EOF;
else if (i <= 2)
stat = fflush(files[i].fp) == EOF;
else if (files[i].mode == '|' || files[i].mode == LE)
stat = pclose(files[i].fp) == -1;
else
stat = fclose(files[i].fp);
if (stat == EOF)
stat = fclose(files[i].fp) == EOF;
if (stat)
WARNING( "i/o error occurred while closing %s", files[i].fname );
}
}
@ -1733,24 +1863,25 @@ void closeall(void)
void flush_all(void)
{
int i;
size_t i;
for (i = 0; i < FOPEN_MAX; i++)
for (i = 0; i < nfiles; i++)
if (files[i].fp)
fflush(files[i].fp);
}
void backsub(char **pb_ptr, char **sptr_ptr);
void backsub(uschar **pb_ptr, const uschar **sptr_ptr);
Cell *sub(Node **a, int nnn) /* substitute command */
{
char *sptr, *pb, *q;
const uschar *sptr;
uschar *q;
Cell *x, *y, *result;
char *t, *buf;
uschar *t, *buf, *pb;
fa *pfa;
int bufsz = recsize;
if ((buf = (char *) malloc(bufsz)) == NULL)
if ((buf = malloc(bufsz)) == NULL)
FATAL("out of memory in sub");
x = execute(a[3]); /* target string */
t = getsval(x);
@ -1805,13 +1936,15 @@ Cell *sub(Node **a, int nnn) /* substitute command */
Cell *gsub(Node **a, int nnn) /* global substitute */
{
Cell *x, *y;
char *rptr, *sptr, *t, *pb, *q;
char *buf;
const char *rptr;
const uschar *sptr;
uschar *t, *q;
uschar *pb, *buf;
fa *pfa;
int mflag, tempstat, num;
int bufsz = recsize;
if ((buf = (char *) malloc(bufsz)) == NULL)
if ((buf = malloc(bufsz)) == NULL)
FATAL("out of memory in gsub");
mflag = 0; /* if mflag == 0, can replace empty string */
num = 0;
@ -1903,9 +2036,149 @@ Cell *gsub(Node **a, int nnn) /* global substitute */
return(x);
}
void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */
Cell *gensub(Node **a, int nnn) /* global selective substitute */
/* XXX incomplete - doesn't support backreferences \0 ... \9 */
{
Cell *x, *y, *res, *h;
char *rptr;
const uschar *sptr;
uschar *q, *pb, *t, *buf;
fa *pfa;
int mflag, tempstat, num, whichm;
int bufsz = recsize;
if ((buf = malloc(bufsz)) == NULL)
FATAL("out of memory in gensub");
mflag = 0; /* if mflag == 0, can replace empty string */
num = 0;
x = execute(a[4]); /* source string */
t = getsval(x);
res = copycell(x); /* target string - initially copy of source */
if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
pfa = (fa *) a[1]; /* regular expression */
else {
y = execute(a[1]);
pfa = makedfa(getsval(y), 1);
tempfree(y);
}
y = execute(a[2]); /* replacement string */
h = execute(a[3]); /* which matches should be replaced */
sptr = getsval(h);
if (sptr[0] == 'g' || sptr[0] == 'G')
whichm = -1;
else {
/*
* The specified number is index of replacement, starting
* from 1. GNU awk treats index lower than 0 same as
* 1, we do same for compatibility.
*/
whichm = (int) getfval(h) - 1;
if (whichm < 0)
whichm = 0;
}
tempfree(h);
if (pmatch(pfa, t)) {
char *sl;
tempstat = pfa->initstat;
pfa->initstat = 2;
pb = buf;
rptr = getsval(y);
/*
* XXX if there are any backreferences in subst string,
* complain now.
*/
for(sl=rptr; (sl = strchr(sl, '\\')) && sl[1]; sl++) {
if (strchr("0123456789", sl[1])) {
FATAL("gensub doesn't support backreferences (subst \"%s\")", rptr);
}
}
do {
if (whichm >= 0 && whichm != num) {
num++;
adjbuf(&buf, &bufsz, (pb - buf) + (patbeg - t) + patlen, recsize, &pb, "gensub");
/* copy the part of string up to and including
* match to output buffer */
while (t < patbeg + patlen)
*pb++ = *t++;
continue;
}
if (patlen == 0 && *patbeg != 0) { /* matched empty string */
if (mflag == 0) { /* can replace empty */
num++;
sptr = rptr;
while (*sptr != 0) {
adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gensub");
if (*sptr == '\\') {
backsub(&pb, &sptr);
} else if (*sptr == '&') {
sptr++;
adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gensub");
for (q = patbeg; q < patbeg+patlen; )
*pb++ = *q++;
} else
*pb++ = *sptr++;
}
}
if (*t == 0) /* at end */
goto done;
adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gensub");
*pb++ = *t++;
if (pb > buf + bufsz) /* BUG: not sure of this test */
FATAL("gensub result0 %.30s too big; can't happen", buf);
mflag = 0;
}
else { /* matched nonempty string */
num++;
sptr = t;
adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gensub");
while (sptr < patbeg)
*pb++ = *sptr++;
sptr = rptr;
while (*sptr != 0) {
adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gensub");
if (*sptr == '\\') {
backsub(&pb, &sptr);
} else if (*sptr == '&') {
sptr++;
adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gensub");
for (q = patbeg; q < patbeg+patlen; )
*pb++ = *q++;
} else
*pb++ = *sptr++;
}
t = patbeg + patlen;
if (patlen == 0 || *t == 0 || *(t-1) == 0)
goto done;
if (pb > buf + bufsz)
FATAL("gensub result1 %.30s too big; can't happen", buf);
mflag = 1;
}
} while (pmatch(pfa,t));
sptr = t;
adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gensub");
while ((*pb++ = *sptr++) != 0)
;
done: if (pb > buf + bufsz)
FATAL("gensub result2 %.30s too big; can't happen", buf);
*pb = '\0';
setsval(res, buf);
pfa->initstat = tempstat;
}
tempfree(x);
tempfree(y);
free(buf);
return(res);
}
void backsub(uschar **pb_ptr, const uschar **sptr_ptr)/* handle \\& variations */
{ /* sptr[0] == '\\' */
char *pb = *pb_ptr, *sptr = *sptr_ptr;
uschar *pb = *pb_ptr;
const uschar *sptr = *sptr_ptr;
if (sptr[1] == '\\') {
if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */

View File

@ -22,6 +22,10 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
****************************************************************/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#define DEBUG
#include <stdio.h>
#include <math.h>
@ -29,7 +33,7 @@ THIS SOFTWARE.
#include <string.h>
#include <stdlib.h>
#include "awk.h"
#include "ytab.h"
#include "awkgram.h"
#define FULLTAB 2 /* rehash when table gets this x full */
#define GROWTAB 4 /* grow table by this factor */
@ -108,7 +112,7 @@ void arginit(int ac, char **av) /* set up ARGV and ARGC */
ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */
cp->sval = (char *) ARGVtab;
for (i = 0; i < ac; i++) {
sprintf(temp, "%d", i);
snprintf(temp, sizeof(temp), "%d", i);
if (is_number(*av))
setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab);
else
@ -144,8 +148,8 @@ Array *makesymtab(int n) /* make a new symbol table */
Array *ap;
Cell **tp;
ap = (Array *) malloc(sizeof(Array));
tp = (Cell **) calloc(n, sizeof(Cell *));
ap = malloc(sizeof(*ap));
tp = calloc(n, sizeof(*tp));
if (ap == NULL || tp == NULL)
FATAL("out of space in makesymtab");
ap->nelem = 0;
@ -210,12 +214,15 @@ 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) {
if (n == NULL)
n = "";
if ((p = lookup(n, tp)) != NULL) {
dprintf( ("setsymtab found %p: n=%s s=\"%s\" f=%g t=%o\n",
p, NN(p->nval), NN(p->sval), p->fval, p->tval) );
return(p);
}
p = (Cell *) malloc(sizeof(Cell));
p = malloc(sizeof(*p));
if (p == NULL)
FATAL("out of space for symbol table at %s", n);
p->nval = tostring(n);
@ -250,7 +257,7 @@ void rehash(Array *tp) /* rehash items in small table into big one */
Cell *cp, *op, **np;
nsz = GROWTAB * tp->size;
np = (Cell **) calloc(nsz, sizeof(Cell *));
np = calloc(nsz, sizeof(*np));
if (np == NULL) /* can't do it, but can keep running. */
return; /* someone else will run out later. */
for (i = 0; i < tp->size; i++) {
@ -282,6 +289,7 @@ Awkfloat setfval(Cell *vp, Awkfloat f) /* set float val of a Cell */
{
int fldno;
f += 0.0; /* normalise negative zero to positive zero */
if ((vp->tval & (NUM | STR)) == 0)
funnyvar(vp, "assign to");
if (isfld(vp)) {
@ -361,7 +369,7 @@ Awkfloat getfval(Cell *vp) /* get float val of a Cell */
static char *get_str_val(Cell *vp, char **fmt) /* get string val of a Cell */
{
char s[100]; /* BUG: unchecked */
char s[100];
double dtemp;
if ((vp->tval & (NUM | STR)) == 0)
@ -374,9 +382,9 @@ static char *get_str_val(Cell *vp, char **fmt) /* get string val of a Cel
if (freeable(vp))
xfree(vp->sval);
if (modf(vp->fval, &dtemp) == 0) /* it's integral */
sprintf(s, "%.30g", vp->fval);
snprintf(s, sizeof(s), "%.30g", vp->fval);
else
sprintf(s, *fmt, vp->fval);
snprintf(s, sizeof(s), *fmt, vp->fval);
vp->sval = tostring(s);
vp->tval &= ~DONTFREE;
vp->tval |= STR;
@ -400,7 +408,17 @@ char *tostring(const char *s) /* make a copy of string s */
{
char *p;
p = (char *) malloc(strlen(s)+1);
p = strdup(s);
if (p == NULL)
FATAL("out of space in tostring on %s", s);
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);
strcpy(p, s);
@ -411,10 +429,10 @@ char *qstring(const char *is, int delim) /* collect string up to next delim */
{
const char *os = is;
int c, n;
uschar *s = (uschar *) is;
const uschar *s = (const uschar *) is;
uschar *buf, *bp;
if ((buf = (uschar *) malloc(strlen(is)+3)) == NULL)
if ((buf = malloc(strlen(is)+3)) == NULL)
FATAL( "out of space in qstring(%s)", s);
for (bp = buf; (c = *s) != delim; s++) {
if (c == '\n')