snapshot of project "mawk", label t20100805

This commit is contained in:
Thomas E. Dickey 2010-08-05 09:13:01 -04:00
parent 01f53d3829
commit d7c50b5507
48 changed files with 2263 additions and 1074 deletions

16
CHANGES
View File

@ -1,7 +1,21 @@
-- $MawkId: CHANGES,v 1.127 2010/06/25 09:43:31 tom Exp $
-- $MawkId: CHANGES,v 1.134 2010/07/24 11:59:10 tom Exp $
Changes by Thomas E Dickey <dickey@invisible-island.net>
20100718
+ add configure --enable-trace, to consolidate various debugging
traces which were written to stderr. This writes to Trace.out.
+ modify zmalloc.c to make it simpler to use the --disable-leaks
configure script option to analyze memory leaks. The memory pool
which interferes with analysis can be disabled by defining
DEBUG_ZMALLOC.
+ (IN-PROGRESS) convert gsub() function from recursive, to
non-recursive to lessen use of program stack (Debian #158481).
+ escape some dashes in manpage, to work with groff.
+ change section for Debian package to "interpreters" (Debian #442071).
+ fix printable token value for SC_MATCH in scan.c (report by Heiner
Marxen).
20100625
+ correct translation of octal and hex escapes for system regular
expression library.

View File

@ -1,4 +1,4 @@
MANIFEST for mawk, version t20100625
MANIFEST for mawk, version t20100805
--------------------------------------------------------------------------------
MANIFEST this file
ACKNOWLEDGMENT acknowledgements

20
aclocal.m4 vendored
View File

@ -1,4 +1,4 @@
dnl $MawkId: aclocal.m4,v 1.52 2010/06/22 00:51:55 tom Exp $
dnl $MawkId: aclocal.m4,v 1.55 2010/07/24 12:24:39 tom Exp $
dnl custom mawk macros for autoconf
dnl
dnl The symbols beginning "CF_MAWK_" were originally written by Mike Brennan,
@ -368,7 +368,7 @@ AC_SUBST(SHOW_CC)
AC_SUBST(ECHO_CC)
])dnl
dnl ---------------------------------------------------------------------------
dnl CF_DISABLE_LEAKS version: 5 updated: 2010/03/13 15:14:55
dnl CF_DISABLE_LEAKS version: 6 updated: 2010/07/23 04:14:32
dnl ----------------
dnl Combine no-leak checks with the libraries or tools that are used for the
dnl checks.
@ -387,6 +387,22 @@ AC_MSG_RESULT($with_no_leaks)
if test "$with_no_leaks" = yes ; then
AC_DEFINE(NO_LEAKS)
AC_DEFINE(YY_NO_LEAKS)
fi
])dnl
dnl ---------------------------------------------------------------------------
dnl CF_ENABLE_TRACE version: 1 updated: 2010/07/24 08:23:48
dnl ---------------
AC_DEFUN([CF_ENABLE_TRACE],[
AC_MSG_CHECKING(if you want to enable debugging trace)
CF_ARG_ENABLE(trace,
[ --enable-trace test: turn on debug-tracing],
[with_trace=yes],
[with_trace=])
AC_MSG_RESULT($with_trace)
if test "$with_trace" = "yes"
then
AC_DEFINE(OPT_TRACE)
fi
])dnl
dnl ---------------------------------------------------------------------------

View File

@ -219,6 +219,7 @@ void array_load(
for(i=0;i < cnt; i++) {
cells[i].type = C_MBSTRN ;
cells[i].ptr = split_buff[i] ;
USED_SPLIT_BUFF(i) ;
}
}

View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: bi_funct.c,v 1.25 2010/05/07 22:00:37 tom Exp $
* $MawkId: bi_funct.c,v 1.50 2010/07/28 23:05:53 tom Exp $
* @Log: bi_funct.c,v @
* Revision 1.9 1996/01/14 17:16:11 mike
* flush_all_output() before system()
@ -177,7 +177,7 @@ str_str(char *target, size_t target_len, char *key, size_t key_len)
k1 = key[1];
prior = target;
while (target_len >= key_len && (target = memchr(target, k, target_len))) {
target_len = target_len - (unsigned) (target - prior) - 1;
target_len = target_len - (size_t) (target - prior) - 1;
prior = ++target;
if (target[0] == k1) {
result = target - 1;
@ -189,7 +189,7 @@ str_str(char *target, size_t target_len, char *key, size_t key_len)
key_len--;
prior = target;
while (target_len > key_len && (target = memchr(target, k, target_len))) {
target_len = target_len - (unsigned) (target - prior) - 1;
target_len = target_len - (size_t) (target - prior) - 1;
prior = ++target;
if (memcmp(target, key + 1, key_len) == 0) {
result = target - 1;
@ -398,7 +398,6 @@ bi_sin(CELL * sp)
if (sp->type != C_DOUBLE)
cast1_to_d(sp);
sp->dval = sin(sp->dval);
return sp;
#else
double x;
@ -409,8 +408,8 @@ bi_sin(CELL * sp)
sp->dval = sin(sp->dval);
if (errno)
fplib_err("sin", x, "loss of precision");
return sp;
#endif
return sp;
}
CELL *
@ -420,7 +419,6 @@ bi_cos(CELL * sp)
if (sp->type != C_DOUBLE)
cast1_to_d(sp);
sp->dval = cos(sp->dval);
return sp;
#else
double x;
@ -431,8 +429,8 @@ bi_cos(CELL * sp)
sp->dval = cos(sp->dval);
if (errno)
fplib_err("cos", x, "loss of precision");
return sp;
#endif
return sp;
}
CELL *
@ -443,7 +441,6 @@ bi_atan2(CELL * sp)
if (TEST2(sp) != TWO_DOUBLES)
cast2_to_d(sp);
sp->dval = atan2(sp->dval, (sp + 1)->dval);
return sp;
#else
errno = 0;
@ -453,8 +450,8 @@ bi_atan2(CELL * sp)
sp->dval = atan2(sp->dval, (sp + 1)->dval);
if (errno)
rt_error("atan2(0,0) : domain error");
return sp;
#endif
return sp;
}
CELL *
@ -464,7 +461,6 @@ bi_log(CELL * sp)
if (sp->type != C_DOUBLE)
cast1_to_d(sp);
sp->dval = log(sp->dval);
return sp;
#else
double x;
@ -475,8 +471,8 @@ bi_log(CELL * sp)
sp->dval = log(sp->dval);
if (errno)
fplib_err("log", x, "domain error");
return sp;
#endif
return sp;
}
CELL *
@ -486,7 +482,6 @@ bi_exp(CELL * sp)
if (sp->type != C_DOUBLE)
cast1_to_d(sp);
sp->dval = exp(sp->dval);
return sp;
#else
double x;
@ -498,8 +493,8 @@ bi_exp(CELL * sp)
if (errno && sp->dval)
fplib_err("exp", x, "overflow");
/* on underflow sp->dval==0, ignore */
return sp;
#endif
return sp;
}
CELL *
@ -518,7 +513,6 @@ bi_sqrt(CELL * sp)
if (sp->type != C_DOUBLE)
cast1_to_d(sp);
sp->dval = sqrt(sp->dval);
return sp;
#else
double x;
@ -529,8 +523,8 @@ bi_sqrt(CELL * sp)
sp->dval = sqrt(sp->dval);
if (errno)
fplib_err("sqrt", x, "domain error");
return sp;
#endif
return sp;
}
#ifndef NO_TIME_H
@ -849,7 +843,7 @@ bi_sub(CELL * sp)
front = string(&sc)->str;
if ((middle = REmatch(front, string(&sc)->len, cast_to_re(sp->ptr), &middle_len))) {
front_len = (unsigned) (middle - front);
front_len = (size_t) (middle - front);
back = middle + middle_len;
back_len = string(&sc)->len - front_len - middle_len;
@ -862,8 +856,7 @@ bi_sub(CELL * sp)
}
tc.type = C_STRING;
tc.ptr = (PTR) new_STRING0(
front_len + string(sp + 1)->len + back_len);
tc.ptr = (PTR) new_STRING0(front_len + string(sp + 1)->len + back_len);
{
char *p = string(&tc)->str;
@ -892,102 +885,300 @@ bi_sub(CELL * sp)
return sp;
}
typedef enum {
btFinish = 0,
btNormal,
btEmpty
} GSUB_BT;
typedef struct {
STRING *result;
CELL replace;
char *front;
char *middle;
char *target;
size_t front_len;
size_t middle_len;
size_t target_len;
int empty_ok;
GSUB_BT branch_to;
} GSUB_STK;
#define ThisGSUB gsub_stk[level]
#define ThisBranch ThisGSUB.branch_to
#define ThisEmptyOk ThisGSUB.empty_ok
#define ThisFront ThisGSUB.front
#define ThisFrontLen ThisGSUB.front_len
#define ThisMiddle ThisGSUB.middle
#define ThisMiddleLen ThisGSUB.middle_len
#define ThisReplace ThisGSUB.replace
#define ThisResult ThisGSUB.result
#define ThisTarget ThisGSUB.target
#define ThisTargetLen ThisGSUB.target_len
#define NextGSUB gsub_stk[level + 1]
#define NextBranch NextGSUB.branch_to
#define NextEmptyOk NextGSUB.empty_ok
#define NextFront NextGSUB.front
#define NextFrontLen NextGSUB.front_len
#define NextMiddle NextGSUB.middle
#define NextMiddleLen NextGSUB.middle_len
#define NextReplace NextGSUB.replace
#define NextResult NextGSUB.result
#define NextTarget NextGSUB.target
#define NextTargetLen NextGSUB.target_len
/* #define DEBUG_GSUB 1 */
static size_t gsub_max;
static GSUB_STK *gsub_stk;
static unsigned repl_cnt; /* number of global replacements */
#if OPT_TRACE > 0
static const char *
indent(int level)
{
static const char value[] = "-----------------";
const char *result;
int limit = (int) sizeof(value) - 1;
if (level < limit)
result = value + limit - level;
else
result = "";
return result;
}
#endif
/* recursive global subsitution
dealing with empty matches makes this mildly painful
repl is always of type REPL or REPLV, destroyed by caller
flag is set if, match of empty string at front is OK
empty_ok is set if, match of empty string at front is OK
*/
#ifdef DEBUG_GSUB
static STRING *
gsub(PTR re, CELL * repl, char *target, size_t target_len, int flag)
old_gsub(PTR re, int level)
{
char xbuff[2];
char *in_sval;
char *front = 0, *middle;
STRING *back;
size_t front_len, middle_len;
STRING *ret_val;
CELL xrepl; /* a copy of repl so we can change repl */
if (!(middle = REmatch(target, target_len, cast_to_re(re), &middle_len)))
return new_STRING(target); /* no match */
assert(level >= 0);
assert(level + 1 < (int) gsub_max);
cellcpy(&xrepl, repl);
middle = REmatch(ThisTarget, ThisTargetLen, cast_to_re(re), &middle_len);
if (middle != 0) {
if (!flag && middle_len == 0 && middle == target) {
/* match at front that's not allowed */
if (*target == 0) { /* target is empty string */
repl_destroy(&xrepl);
null_str.ref_cnt++;
return &null_str;
} else if (1 && isAnchored(re)) {
repl_destroy(&xrepl);
return new_STRING1(target, target_len);
} else {
char xbuff[2];
if (!ThisEmptyOk && (middle_len == 0) && (middle == ThisTarget)) {
/* match at front that's not allowed */
front_len = 0;
/* make new repl with target[0] */
repl_destroy(repl);
--target_len;
xbuff[0] = *target++;
xbuff[1] = 0;
repl->type = C_REPL;
repl->ptr = (PTR) new_STRING(xbuff);
back = gsub(re, &xrepl, target, target_len, 1);
}
} else { /* a match that counts */
repl_cnt++;
front = target;
front_len = (unsigned) (middle - target);
if (ThisTargetLen == 0) { /* target is empty string */
null_str.ref_cnt++;
back = &null_str;
} else if (isAnchored(re)) {
back = new_STRING1(ThisTarget, ThisTargetLen);
} else {
/* make new repl with target[0] */
cellcpy(&NextReplace, &ThisReplace);
repl_destroy(&ThisReplace);
xbuff[0] = *ThisTarget;
xbuff[1] = 0;
ThisReplace.type = C_REPL;
ThisReplace.ptr = (PTR) new_STRING1(xbuff, 1);
if (front_len == target_len) { /* matched back of target */
back = &null_str;
null_str.ref_cnt++;
} else {
back = gsub(re,
&xrepl,
middle + middle_len,
target_len - (front_len + middle_len),
0);
NextTarget = ThisTarget + 1;
NextTargetLen = ThisTargetLen - 1;
NextEmptyOk = 1;
NextBranch = btEmpty;
back = old_gsub(re, level + 1);
}
} else { /* a match that counts */
repl_cnt++;
front = ThisTarget;
front_len = (size_t) (middle - ThisTarget);
if (front_len == ThisTargetLen) { /* matched back of target */
back = &null_str;
null_str.ref_cnt++;
} else {
NextTarget = middle + middle_len;
NextTargetLen = ThisTargetLen - (front_len + middle_len);
NextEmptyOk = 0;
NextBranch = btNormal;
cellcpy(&NextReplace, &ThisReplace);
back = old_gsub(re, level + 1);
}
/* patch the &'s if needed */
if (ThisReplace.type == C_REPLV) {
STRING *sval = new_STRING1(middle, middle_len);
replv_to_repl(&ThisReplace, sval);
free_STRING(sval);
}
}
/* patch the &'s if needed */
if (repl->type == C_REPLV) {
STRING *sval = new_STRING0(middle_len);
memcpy(sval->str, middle, middle_len);
replv_to_repl(repl, sval);
free_STRING(sval);
}
}
/* put the three pieces together */
ret_val = new_STRING0(front_len + string(repl)->len + back->len);
{
char *p = ret_val->str;
/* put the three pieces together */
ThisResult = new_STRING0(front_len + string(&ThisReplace)->len + back->len);
TRACE(("old %s front '%.*s', middle '%.*s', back '%.*s'\n",
indent(level),
front_len, front,
string(&ThisReplace)->len, string(&ThisReplace)->str,
back->len, back->str));
in_sval = ThisResult->str;
if (front_len) {
memcpy(p, front, front_len);
p += front_len;
memcpy(in_sval, front, front_len);
in_sval += front_len;
}
if (string(repl)->len) {
memcpy(p, string(repl)->str, string(repl)->len);
p += string(repl)->len;
if (string(&ThisReplace)->len) {
memcpy(in_sval, string(&ThisReplace)->str, string(&ThisReplace)->len);
in_sval += string(&ThisReplace)->len;
}
if (back->len)
memcpy(p, back->str, back->len);
memcpy(in_sval, back->str, back->len);
/* cleanup, repl is freed by the caller */
free_STRING(back);
} else {
/* no match */
ThisResult = new_STRING1(ThisTarget, ThisTargetLen);
}
/* cleanup, repl is freed by the caller */
repl_destroy(&xrepl);
free_STRING(back);
return ThisResult;
}
#endif /* DEBUG_GSUB */
return ret_val;
static STRING *
new_gsub(PTR re, int level)
{
char xbuff[2];
char *in_sval;
STRING *back;
loop:
assert(level >= 0);
assert(level + 1 < (int) gsub_max);
ThisFront = 0;
ThisMiddle = REmatch(ThisTarget, ThisTargetLen, cast_to_re(re), &ThisMiddleLen);
if (ThisMiddle != 0) {
if (!ThisEmptyOk && (ThisMiddleLen == 0) && (ThisMiddle == ThisTarget)) {
/* match at front that's not allowed */
ThisFrontLen = 0;
if (ThisTargetLen == 0) { /* target is empty string */
null_str.ref_cnt++;
back = &null_str;
} else if (isAnchored(re)) {
back = new_STRING1(ThisTarget, ThisTargetLen);
} else {
/* make new repl with target[0] */
cellcpy(&NextReplace, &ThisReplace);
repl_destroy(&ThisReplace);
xbuff[0] = *ThisTarget;
xbuff[1] = 0;
ThisReplace.type = C_REPL;
ThisReplace.ptr = (PTR) new_STRING1(xbuff, 1);
NextTarget = ThisTarget + 1;
NextTargetLen = ThisTargetLen - 1;
NextEmptyOk = 1;
NextBranch = btEmpty;
++level;
goto loop;
empty_match:
back = NextResult;
}
} else { /* a match that counts */
repl_cnt++;
ThisFront = ThisTarget;
ThisFrontLen = (size_t) (ThisMiddle - ThisTarget);
if (ThisFrontLen == ThisTargetLen) { /* matched back of target */
back = &null_str;
null_str.ref_cnt++;
} else {
NextTarget = ThisMiddle + ThisMiddleLen;
NextTargetLen = ThisTargetLen - (ThisFrontLen + ThisMiddleLen);
NextEmptyOk = 0;
NextBranch = btNormal;
cellcpy(&NextReplace, &ThisReplace);
++level;
goto loop;
normal_match:
back = NextResult;
}
/* patch the &'s if needed */
if (ThisReplace.type == C_REPLV) {
STRING *sval = new_STRING1(ThisMiddle, ThisMiddleLen);
replv_to_repl(&ThisReplace, sval);
free_STRING(sval);
}
}
/* put the three pieces together */
ThisResult = new_STRING0(ThisFrontLen + string(&ThisReplace)->len + back->len);
TRACE(("new %s front '%.*s', middle '%.*s', back '%.*s'\n",
indent(level),
(int) ThisFrontLen, ThisFront,
(int) string(&ThisReplace)->len, string(&ThisReplace)->str,
(int) back->len, back->str));
in_sval = ThisResult->str;
if (ThisFrontLen) {
memcpy(in_sval, ThisFront, ThisFrontLen);
in_sval += ThisFrontLen;
}
if (string(&ThisReplace)->len) {
memcpy(in_sval, string(&ThisReplace)->str, string(&ThisReplace)->len);
in_sval += string(&ThisReplace)->len;
}
if (back->len)
memcpy(in_sval, back->str, back->len);
/* cleanup, repl is freed by the caller */
free_STRING(back);
repl_destroy(&ThisReplace);
} else {
/* no match */
ThisResult = new_STRING1(ThisTarget, ThisTargetLen);
repl_destroy(&ThisReplace);
}
switch (ThisBranch) {
case btEmpty:
--level;
goto empty_match;
case btNormal:
--level;
goto normal_match;
case btFinish:
break;
}
return ThisResult;
}
/* set up for call to gsub() */
@ -997,6 +1188,12 @@ bi_gsub(CELL * sp)
CELL *cp; /* pts at the replacement target */
CELL sc; /* copy of replacement target */
CELL tc; /* build the result here */
STRING *result;
#ifdef DEBUG_GSUB
STRING *resul2;
#endif
size_t stack_needs;
int level = 0;
sp -= 2;
if (sp->type != C_RE)
@ -1008,13 +1205,62 @@ bi_gsub(CELL * sp)
if (sc.type < C_STRING)
cast1_to_s(&sc);
stack_needs = (string(&sc)->len + 2) * 2;
if (stack_needs > gsub_max) {
if (gsub_max) {
zfree(gsub_stk, gsub_max * sizeof(GSUB_STK));
}
gsub_stk = zmalloc(stack_needs * sizeof(GSUB_STK));
gsub_max = stack_needs;
}
#ifdef DEBUG_GSUB
{
STRING *target = new_STRING1(string(&sc)->str, string(&sc)->len);
ThisBranch = btFinish;
ThisEmptyOk = 1;
cellcpy(&ThisReplace, sp + 1);
ThisResult = 0;
ThisTarget = target->str;
ThisTargetLen = target->len;
resul2 = old_gsub(sp->ptr, 0);
TRACE(("OLD ->'%.*s'\n", resul2->len, resul2->str));
free_STRING(target);
}
#endif
ThisBranch = btFinish;
ThisEmptyOk = 1;
cellcpy(&ThisReplace, sp + 1);
ThisResult = 0;
ThisTarget = string(&sc)->str;
ThisTargetLen = string(&sc)->len;
repl_cnt = 0;
tc.ptr = (PTR) gsub(sp->ptr, sp + 1, string(&sc)->str, string(&sc)->len, 1);
result = new_gsub(sp->ptr, 0);
tc.ptr = (PTR) result;
#ifdef DEBUG_GSUB
TRACE(("NEW ->'%.*s'\n", result->len, result->str));
if (result->len != resul2->len || memcmp(result->str, resul2->str, result->len))
TRACE(("OOPS\n"));
#endif
if (repl_cnt) {
tc.type = C_STRING;
slow_cell_assign(cp, &tc);
}
#ifdef NO_LEAKS
if (gsub_stk != 0) {
zfree(gsub_stk, stack_needs * sizeof(GSUB_STK));
gsub_stk = 0;
gsub_max = 0;
}
#endif
/* cleanup */
free_STRING(string(&sc));

View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: bi_vars.c,v 1.7 2009/12/16 23:38:14 tom Exp $
* $MawkId: bi_vars.c,v 1.8 2010/07/24 14:25:42 tom Exp $
* @Log: bi_vars.c,v @
* Revision 1.1.1.1 1993/07/03 18:58:09 mike
* move source to cvs
@ -92,3 +92,19 @@ bi_vars_init(void)
BINMODE->type = C_DOUBLE;
#endif
}
#ifdef NO_LEAKS
void
bi_vars_leaks(void)
{
int n;
for (n = 0; n < NUM_BI_VAR; ++n) {
switch (bi_vars[n].type) {
case C_STRING:
free_STRING(string(&bi_vars[n]));
break;
}
}
}
#endif

211
code.c
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: code.c,v 1.5 2010/05/07 09:47:06 tom Exp $
* $MawkId: code.c,v 1.26 2010/08/05 00:17:08 tom Exp $
* @Log: code.c,v @
* Revision 1.6 1995/06/18 19:42:13 mike
* Remove some redundant declarations and add some prototypes
@ -53,6 +53,11 @@ the GNU General Public License, version 2, 1991.
#include "jmp.h"
#include "field.h"
#ifdef NO_LEAKS
#include "repl.h"
#include "scan.h"
#endif
static CODEBLOCK *new_code(void);
CODEBLOCK active_code;
@ -60,7 +65,7 @@ CODEBLOCK active_code;
CODEBLOCK *main_code_p, *begin_code_p, *end_code_p;
INST *begin_start, *main_start, *end_start;
size_t begin_size, main_size;
size_t begin_size, main_size, end_size;
INST *execution_start = 0;
@ -95,6 +100,7 @@ code_shrink(CODEBLOCK * p, size_t *sizep)
*sizep = newsize;
retval = (INST *) zrealloc(p->base, oldsize, newsize);
TRACE(("code_shrink old %p %lu, new %p %lu\n", p->base, oldsize, retval, newsize));
ZFREE(p);
return retval;
}
@ -160,17 +166,16 @@ set_code(void)
execution_start = main_start;
} else { /* only BEGIN */
zfree(code_base, INST_BYTES(PAGESZ));
code_base = 0;
ZFREE(main_code_p);
}
/* set the END code */
if (end_code_p) {
size_t dummy;
active_code = *end_code_p;
code2op(_EXIT0, _HALT);
*end_code_p = active_code;
end_start = code_shrink(end_code_p, &dummy);
end_start = code_shrink(end_code_p, &end_size);
}
/* set the BEGIN code */
@ -242,3 +247,199 @@ be_setup(int scope)
active_code = *end_code_p;
}
}
#ifdef NO_LEAKS
void
free_cell_data(CELL * cp)
{
switch (cp->type) {
case C_RE:
TRACE(("\t... C_RE\n"));
re_destroy(cp->ptr);
zfree(cp, sizeof(CELL));
break;
case C_REPL:
TRACE(("\t... C_REPL\n"));
repl_destroy(cp);
zfree(cp, sizeof(CELL));
break;
case C_REPLV:
TRACE(("\t... C_REPLV\n"));
repl_destroy(cp);
zfree(cp, sizeof(CELL));
break;
case C_MBSTRN:
case C_STRING:
case C_STRNUM:
if (cp >= (field + (nf < 1 ? 1 : nf)) || (cp < field)) {
cell_destroy(cp);
}
break;
}
}
void
free_codes(const char *tag, INST * base, size_t size)
{
INST *cdp;
INST *last = base + (size / sizeof(*last));
CELL *cp;
TRACE(("free_codes(%s) base %p, size %lu\n", tag, base, size));
for (cdp = base; cdp < last; ++cdp) {
TRACE(("code %03d:%s (%d %#x)\n",
(int) (cdp - base),
da_op_name(cdp),
cdp->op,
cdp->op));
switch ((MAWK_OPCODES) (cdp->op)) {
case AE_PUSHA:
case AE_PUSHI:
case A_CAT:
case LAE_PUSHA:
case _MATCH0:
case _MATCH1:
++cdp; /* skip pointer */
cp = (CELL *) (cdp->ptr);
if (cp != 0) {
TRACE(("\tparam %p type %d\n", cp, cp->type));
free_cell_data(cp);
} else {
TRACE(("\tparam %p type ??\n", cp));
}
break;
case A_PUSHA:
case L_PUSHA:
case L_PUSHI:
case LA_PUSHA:
case _BUILTIN:
case _PRINT:
case _PUSHA:
case _PUSHI:
case _PUSHINT:
++cdp; /* skip value */
TRACE(("\tparam %p\n", cdp->ptr));
break;
case _PUSHD:
++cdp; /* skip value */
TRACE(("\tparam %p\n", cdp->ptr));
if (cdp->ptr != &double_one && cdp->ptr != &double_zero)
zfree(cdp->ptr, sizeof(double));
break;
case F_PUSHI:
++cdp; /* skip pointer */
cp = (CELL *) (cdp->ptr);
TRACE(("\tparam %p type %d\n", cp, cp->type));
++cdp; /* skip integer */
break;
case _PUSHS:
++cdp; /* skip value */
TRACE(("\tparam %p\n", cdp->ptr));
free_STRING((STRING *) (cdp->ptr));
break;
case _RANGE:
cdp += 4; /* PAT1 */
break;
case _CALL:
TRACE(("\tskipping %d\n", 1 + cdp[2].op));
cdp += 1 + cdp[2].op;
break;
case A_DEL:
case A_TEST:
case DEL_A:
case FE_PUSHA:
case FE_PUSHI:
case F_ADD_ASG:
case F_ASSIGN:
case F_DIV_ASG:
case F_MOD_ASG:
case F_MUL_ASG:
case F_POST_DEC:
case F_POST_INC:
case F_POW_ASG:
case F_PRE_DEC:
case F_PRE_INC:
case F_PUSHA:
case F_SUB_ASG:
case NF_PUSHI:
case OL_GL:
case OL_GL_NR:
case POP_AL:
case _ADD:
case _ADD_ASG:
case _ASSIGN:
case _CAT:
case _DIV:
case _DIV_ASG:
case _EQ:
case _EXIT0: /* this does free memory... */
case _EXIT:
case _GT:
case _GTE:
case _HALT:
case _JMAIN:
case _LT:
case _LTE:
case _MATCH2:
case _MOD:
case _MOD_ASG:
case _MUL:
case _MUL_ASG:
case _NEQ:
case _NEXT:
case _NOT:
case _OMAIN:
case _POP:
case _POST_DEC:
case _POST_INC:
case _POW:
case _POW_ASG:
case _PRE_DEC:
case _PRE_INC:
case _RET0:
case _RET:
case _STOP:
case _SUB:
case _SUB_ASG:
case _TEST:
case _UMINUS:
case _UPLUS:
break;
case _JNZ:
case _JZ:
case _LJZ:
case _LJNZ:
case _JMP:
case _PUSHC:
case ALOOP:
case LAE_PUSHI:
case SET_ALOOP:
++cdp; /* cdp->op is literal param */
break;
}
}
zfree(base, size);
}
void
code_leaks(void)
{
TRACE(("code_leaks\n"));
if (begin_start != 0) {
free_codes("BEGIN", begin_start, begin_size);
begin_start = 0;
begin_size = 0;
}
if (end_start != 0) {
free_codes("END", end_start, end_size);
end_start = 0;
end_size = 0;
}
if (main_start != 0) {
free_codes("MAIN", main_start, main_size);
main_start = 0;
main_size = 0;
}
}
#endif

182
code.h
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: code.h,v 1.4 2010/05/07 09:49:46 tom Exp $
* $MawkId: code.h,v 1.5 2010/07/28 01:03:52 tom Exp $
* @Log: code.h,v @
* Revision 1.5 1995/06/18 19:42:15 mike
* Remove some redundant declarations and add some prototypes
@ -97,94 +97,96 @@ void dump_code(void);
/* to avoid confusion with a ptr FE_PUSHA must have op code 0 */
/* unfortunately enums are less portable than defines */
#define FE_PUSHA 0
#define FE_PUSHI 1
#define F_PUSHA 2
#define F_PUSHI 3
#define NF_PUSHI 4
#define _HALT 5
#define _STOP 6
#define _PUSHC 7
#define _PUSHD 8
#define _PUSHS 9
#define _PUSHINT 10
#define _PUSHA 11
#define _PUSHI 12
#define L_PUSHA 13
#define L_PUSHI 14
#define AE_PUSHA 15
#define AE_PUSHI 16
#define A_PUSHA 17
#define LAE_PUSHA 18
#define LAE_PUSHI 19
#define LA_PUSHA 20
#define _POP 21
#define _ADD 22
#define _SUB 23
#define _MUL 24
#define _DIV 25
#define _MOD 26
#define _POW 27
#define _NOT 28
#define _TEST 29
#define A_TEST 30
#define A_DEL 31
#define ALOOP 32
#define A_CAT 33
#define _UMINUS 34
#define _UPLUS 35
#define _ASSIGN 36
#define _ADD_ASG 37
#define _SUB_ASG 38
#define _MUL_ASG 39
#define _DIV_ASG 40
#define _MOD_ASG 41
#define _POW_ASG 42
#define F_ASSIGN 43
#define F_ADD_ASG 44
#define F_SUB_ASG 45
#define F_MUL_ASG 46
#define F_DIV_ASG 47
#define F_MOD_ASG 48
#define F_POW_ASG 49
#define _CAT 50
#define _BUILTIN 51
#define _PRINT 52
#define _POST_INC 53
#define _POST_DEC 54
#define _PRE_INC 55
#define _PRE_DEC 56
#define F_POST_INC 57
#define F_POST_DEC 58
#define F_PRE_INC 59
#define F_PRE_DEC 60
#define _JMP 61
#define _JNZ 62
#define _JZ 63
#define _LJZ 64
#define _LJNZ 65
#define _EQ 66
#define _NEQ 67
#define _LT 68
#define _LTE 69
#define _GT 70
#define _GTE 71
#define _MATCH0 72
#define _MATCH1 73
#define _MATCH2 74
#define _EXIT 75
#define _EXIT0 76
#define _NEXT 77
#define _RANGE 78
#define _CALL 79
#define _RET 80
#define _RET0 81
#define SET_ALOOP 82
#define POP_AL 83
#define OL_GL 84
#define OL_GL_NR 85
#define _OMAIN 86
#define _JMAIN 87
#define DEL_A 88
typedef enum {
FE_PUSHA = 0
,FE_PUSHI
,F_PUSHA
,F_PUSHI
,NF_PUSHI
,_HALT
,_STOP
,_PUSHC
,_PUSHD
,_PUSHS
,_PUSHINT
,_PUSHA
,_PUSHI
,L_PUSHA
,L_PUSHI
,AE_PUSHA
,AE_PUSHI
,A_PUSHA
,LAE_PUSHA
,LAE_PUSHI
,LA_PUSHA
,_POP
,_ADD
,_SUB
,_MUL
,_DIV
,_MOD
,_POW
,_NOT
,_TEST
,A_TEST
,A_DEL
,ALOOP
,A_CAT
,_UMINUS
,_UPLUS
,_ASSIGN
,_ADD_ASG
,_SUB_ASG
,_MUL_ASG
,_DIV_ASG
,_MOD_ASG
,_POW_ASG
,F_ASSIGN
,F_ADD_ASG
,F_SUB_ASG
,F_MUL_ASG
,F_DIV_ASG
,F_MOD_ASG
,F_POW_ASG
,_CAT
,_BUILTIN
,_PRINT
,_POST_INC
,_POST_DEC
,_PRE_INC
,_PRE_DEC
,F_POST_INC
,F_POST_DEC
,F_PRE_INC
,F_PRE_DEC
,_JMP
,_JNZ
,_JZ
,_LJZ
,_LJNZ
,_EQ
,_NEQ
,_LT
,_LTE
,_GT
,_GTE
,_MATCH0
,_MATCH1
,_MATCH2
,_EXIT
,_EXIT0
,_NEXT
,_RANGE
,_CALL
,_RET
,_RET0
,SET_ALOOP
,POP_AL
,OL_GL
,OL_GL_NR
,_OMAIN
,_JMAIN
,DEL_A
} MAWK_OPCODES;
#endif /* MAWK_CODE_H */

View File

@ -1,5 +1,5 @@
/*
* $MawkId: config_h.in,v 1.17 2010/05/06 23:36:28 tom Exp $
* $MawkId: config_h.in,v 1.21 2010/07/24 14:29:06 tom Exp $
* vile:cmode
* template for config.h
*/
@ -24,6 +24,8 @@
#undef HAVE_SIGINFO_H
#undef HAVE_STRTOD_OVF_BUG
#undef HAVE_SYS_WAIT_H
#undef HAVE_TDESTROY
#undef HAVE_TSEARCH
#undef HAVE_UNISTD_H
#undef HAVE_WAIT
#undef LOCALE
@ -54,6 +56,7 @@
#undef TURN_OFF_FPE_TRAPS
#undef TURN_ON_FPE_TRAPS
#undef USE_IEEEFP_H
#undef YY_NO_LEAKS
#undef const
#ifndef GCC_NORETURN
@ -64,3 +67,6 @@
#define GCC_UNUSED /* nothing */
#endif
#ifndef OPT_TRACE
#define OPT_TRACE 0
#endif

1160
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
dnl $MawkId: configure.in,v 1.34 2010/06/22 23:12:18 tom Exp $
dnl $MawkId: configure.in,v 1.36 2010/07/24 11:43:55 tom Exp $
dnl configure.in for mawk
dnl
dnl @Log: configure.in,v @
@ -72,12 +72,13 @@ CF_XOPEN_SOURCE
CF_LARGEFILE
CF_DISABLE_LEAKS
CF_ENABLE_TRACE
CF_MAWK_FIND_SIZE_T
CF_LOCALE
CF_CHECK_ENVIRON(environ)
AC_CHECK_FUNCS(fork pipe wait)
AC_CHECK_FUNCS(fork pipe tdestroy tsearch wait)
test "$ac_cv_func_fork" = yes && \
test "$ac_cv_func_pipe" = yes && \
test "$ac_cv_func_wait" = yes && \

90
da.c
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: da.c,v 1.8 2010/05/07 00:56:51 tom Exp $
* $MawkId: da.c,v 1.10 2010/07/31 21:30:31 tom Exp $
* @Log: da.c,v @
* Revision 1.6 1995/06/18 19:19:59 mike
* remove use of comma operator that broke some sysVr3 compilers
@ -55,13 +55,14 @@ the GNU General Public License, version 2, 1991.
#include "repl.h"
#include "field.h"
typedef struct {
char op;
const char *name;
} OP_NAME;
static const char *find_bi_name(PF_CP);
/* *INDENT-OFF* */
static struct sc
{
char op ;
const char *name ;
} simple_code[] =
static OP_NAME simple_code[] =
{
{_STOP, "stop"},
@ -368,7 +369,7 @@ da(INST * start, FILE *fp)
break;
default:
{
struct sc *q = simple_code;
OP_NAME *q = simple_code;
int k = (p - 1)->op;
while (q->op != _HALT && q->op != k)
@ -413,8 +414,9 @@ find_bi_name(PF_CP p)
}
/* next check some special cases */
for (i = 0; special_cases[i].action; i++) {
if (special_cases[i].action == p)
if (special_cases[i].action == p) {
return special_cases[i].name;
}
}
return "unknown builtin";
@ -447,3 +449,75 @@ fdump(void)
ZFREE(p);
}
}
#ifdef NO_LEAKS
/* *INDENT-OFF* */
static OP_NAME other_codes[] = {
{ AE_PUSHA, "ae_pusha" },
{ AE_PUSHI, "ae_pushi" },
{ ALOOP, "aloop" },
{ A_CAT, "a_cat" },
{ A_PUSHA, "a_pusha" },
{ F_PUSHA, "f_pusha" },
{ F_PUSHI, "f_pushi" },
{ LAE_PUSHA, "lae_pusha" },
{ LAE_PUSHI, "lae_pushi" },
{ LA_PUSHA, "la_pusha" },
{ L_PUSHA, "l_pusha" },
{ L_PUSHI, "l_pushi" },
{ SET_ALOOP, "set_al" },
{ _CALL, "call" },
{ _JMP, "jmp" },
{ _JNZ, "jnz" },
{ _JZ, "jz" },
{ _LJNZ, "ljnz" },
{ _LJZ, "ljz" },
{ _MATCH0, "match0" },
{ _MATCH1, "match1" },
{ _PUSHA, "pusha" },
{ _PUSHC, "pushc" },
{ _PUSHD, "pushd" },
{ _PUSHI, "pushi" },
{ _PUSHINT, "pushint" },
{ _PUSHS, "pushs" },
{ _RANGE, "range" },
{ _HALT, 0 },
};
/* *INDENT-ON* */
const char *
da_op_name(INST * cdp)
{
int n;
const char *result = 0;
if (cdp->op == _BUILTIN) {
result = find_bi_name((PF_CP) cdp[1].ptr);
} else if (cdp->op == _PRINT) {
result = ((PF_CP) cdp->ptr == bi_printf
? "printf"
: "print");
} else if (cdp->op == _HALT) {
result = "halt";
} else {
for (n = 0; simple_code[n].op != _HALT; ++n) {
if (simple_code[n].op == cdp->op) {
result = simple_code[n].name;
break;
}
}
if (result == 0) {
for (n = 0; other_codes[n].op != _HALT; ++n) {
if (other_codes[n].op == cdp->op) {
result = other_codes[n].name;
break;
}
}
}
if (result == 0) {
result = "unknown";
}
}
return result;
}
#endif

35
error.c
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: error.c,v 1.11 2009/12/17 00:05:10 tom Exp $
* $MawkId: error.c,v 1.14 2010/07/28 23:05:21 tom Exp $
* @Log: error.c,v @
* Revision 1.6 1995/06/06 00:18:22 mike
* change mawk_exit(1) to mawk_exit(2)
@ -143,7 +143,7 @@ missing(int c, const char *n, unsigned ln)
off our back.
*/
void
yyerror(char *s GCC_UNUSED)
yyerror(const char *s GCC_UNUSED)
{
const char *ss = 0;
struct token_str *p;
@ -420,3 +420,34 @@ simple_vfprintf(FILE *fp, char *format, va_list argp)
}
#endif /* USE_SIMPLE_VFPRINTF */
#if OPT_TRACE > 0
static FILE *trace_fp;
void
Trace(const char *format,...)
{
va_list args;
if (trace_fp == 0)
trace_fp = fopen("Trace.out", "w");
if (trace_fp == 0)
rt_error("cannot open Trace.out");
va_start(args, format);
vfprintf(trace_fp, format, args);
va_end(args);
}
#ifdef NO_LEAKS
void
trace_leaks(void)
{
if (trace_fp != 0) {
fclose(trace_fp);
trace_fp = 0;
}
}
#endif
#endif

View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: execute.c,v 1.16 2010/05/07 22:03:19 tom Exp $
* $MawkId: execute.c,v 1.20 2010/08/04 23:02:35 tom Exp $
* @Log: execute.c,v @
* Revision 1.13 1996/02/01 04:39:40 mike
* dynamic array scheme
@ -200,6 +200,7 @@ execute(INST * cdp, /* code ptr, start execution here */
#ifdef DEBUG
CELL *entry_sp = sp;
#endif
int force_exit = (end_start == 0);
if (fp) {
/* we are a function call, check for deep recursion */
@ -218,7 +219,7 @@ execute(INST * cdp, /* code ptr, start execution here */
old_stack_base = (CELL *) 0;
}
while (1)
while (1) {
switch ((cdp++)->op) {
/* HALT only used by the disassemble now ; this remains
@ -261,9 +262,9 @@ execute(INST * cdp, /* code ptr, start execution here */
SAMESEG(cp, field) &&
#endif
cp >= NF && cp <= LAST_PFIELD)) {
/* its a real field $1, $2 ...
If its greater than $NF, we have to
make sure its set to "" so that
/* it is a real field $1, $2 ...
If it is greater than $NF, we have to
make sure it is set to "" so that
(++|--) and g?sub() work right
*/
t = field_addr_to_index(cp);
@ -1126,23 +1127,30 @@ execute(INST * cdp, /* code ptr, start execution here */
case _EXIT0:
if (!end_start)
if (force_exit)
mawk_exit(exit_code);
cdp = end_start;
end_start = (INST *) 0; /* makes sure next exit exits */
force_exit = 1; /* makes sure next exit exits */
if (begin_start)
zfree(begin_start, begin_size);
if (main_start)
zfree(main_start, main_size);
if (begin_start) {
free_codes("BEGIN", begin_start, begin_size);
begin_start = 0;
begin_size = 0;
}
if (main_start) {
free_codes("MAIN", main_start, main_size);
main_start = 0;
main_size = 0;
}
sp = eval_stack - 1; /* might be in user function */
CLEAR_ALOOP_STACK(); /* ditto */
break;
case _JMAIN: /* go from BEGIN code to MAIN code */
zfree(begin_start, begin_size);
begin_start = (INST *) 0;
free_codes("BEGIN", begin_start, begin_size);
begin_start = 0;
begin_size = 0;
cdp = main_start;
break;
@ -1165,12 +1173,13 @@ execute(INST * cdp, /* code ptr, start execution here */
size_t len;
if (!(p = FINgets(main_fin, &len))) {
if (!end_start)
if (force_exit)
mawk_exit(0);
cdp = end_start;
zfree(main_start, main_size);
main_start = end_start = (INST *) 0;
main_start = (INST *) 0;
force_exit = 1;
} else {
set_field0(p, len);
cdp = restart_label;
@ -1188,12 +1197,13 @@ execute(INST * cdp, /* code ptr, start execution here */
size_t len;
if (!(p = FINgets(main_fin, &len))) {
if (!end_start)
if (force_exit)
mawk_exit(0);
cdp = end_start;
zfree(main_start, main_size);
main_start = end_start = (INST *) 0;
main_start = (INST *) 0;
force_exit = 1;
} else {
set_field0(p, len);
cdp = restart_label;
@ -1333,6 +1343,7 @@ execute(INST * cdp, /* code ptr, start execution here */
default:
bozo("bad opcode");
}
}
}
/*

43
field.c
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: field.c,v 1.13 2010/05/07 22:03:19 tom Exp $
* $MawkId: field.c,v 1.21 2010/08/04 23:35:07 tom Exp $
* @Log: field.c,v @
* Revision 1.5 1995/06/18 19:17:47 mike
* Create a type Int which on most machines is an int, but on machines
@ -265,6 +265,7 @@ split_field0(void)
while (cnt > 0) {
cell_destroy(field + cnt);
field[cnt].ptr = (PTR) split_buff[cnt - 1];
USED_SPLIT_BUFF(cnt - 1);
field[cnt--].type = C_MBSTRN;
}
@ -662,3 +663,43 @@ set_binmode(int x)
}
#endif /* USE_BINMODE */
#ifdef NO_LEAKS
void
field_leaks(void)
{
int n;
free_STRING(string(CONVFMT));
free_STRING(string(FS));
free_STRING(string(OFMT));
free_STRING(string(RS));
cell_destroy(&field[0]);
for (n = 1; n <= nf; ++n) {
cell_destroy(&field[n]);
}
switch (fs_shadow.type) {
case C_RE:
re_destroy(fs_shadow.ptr);
break;
case C_STRING:
case C_STRNUM:
case C_MBSTRN:
cell_destroy(&fs_shadow);
break;
default:
break;
}
switch (rs_shadow.type) {
case SEP_STR:
free_STRING(((STRING *) (&rs_shadow.ptr)));
break;
case SEP_RE:
re_destroy(rs_shadow.ptr);
break;
}
}
#endif

52
field.h
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: field.h,v 1.8 2010/05/07 22:03:31 tom Exp $
* $MawkId: field.h,v 1.9 2010/07/24 14:42:26 tom Exp $
* @Log: field.h,v @
* Revision 1.2 1995/06/18 19:42:16 mike
* Remove some redundant declarations and add some prototypes
@ -34,17 +34,17 @@ the GNU General Public License, version 2, 1991.
#include "nstd.h"
#include "types.h"
void set_field0(char *, size_t);
void split_field0(void);
size_t space_split(char *, size_t);
size_t re_split(STRING *, PTR);
size_t null_split(char *, size_t);
void field_assign(CELL *, CELL *);
char *is_string_split(PTR, unsigned *);
void slow_cell_assign(CELL *, CELL *);
CELL *slow_field_ptr(int);
int field_addr_to_index(CELL *);
void set_binmode(int);
extern void set_field0(char *, size_t);
extern void split_field0(void);
extern size_t space_split(char *, size_t);
extern size_t re_split(STRING *, PTR);
extern size_t null_split(char *, size_t);
extern void field_assign(CELL *, CELL *);
extern char *is_string_split(PTR, unsigned *);
extern void slow_cell_assign(CELL *, CELL *);
extern CELL *slow_field_ptr(int);
extern int field_addr_to_index(CELL *);
extern void set_binmode(int);
#define NUM_PFIELDS 5
extern CELL field[FBANK_SZ + NUM_PFIELDS];
@ -63,23 +63,23 @@ extern CELL *fbank[NUM_FBANK]; /* fbank[0] == field */
#undef CONVFMT
#undef OFMT
/* the pseudo fields, assignment has side effects */
#define NF (field + MAX_SPLIT + 1) /* must be first */
#define RS (field + MAX_SPLIT + 2)
#define FS (field + MAX_SPLIT + 3)
#define CONVFMT (field + MAX_SPLIT + 4)
#define OFMT (field + MAX_SPLIT + 5) /* must be last */
#define LAST_PFIELD OFMT
/* some compilers choke on (NF-field) in a case statement
even though it's constant so ...
*/
#define NF_field (MAX_SPLIT+1)
#define RS_field (MAX_SPLIT+2)
#define FS_field (MAX_SPLIT+3)
#define CONVFMT_field (MAX_SPLIT+4)
#define OFMT_field (MAX_SPLIT+5)
#define NF_field (MAX_SPLIT + 1)
#define RS_field (MAX_SPLIT + 2)
#define FS_field (MAX_SPLIT + 3)
#define CONVFMT_field (MAX_SPLIT + 4)
#define OFMT_field (MAX_SPLIT + 5)
/* the pseudo fields, assignment has side effects */
#define NF (field + NF_field) /* must be first */
#define RS (field + RS_field)
#define FS (field + FS_field)
#define CONVFMT (field + CONVFMT_field)
#define OFMT (field + OFMT_field) /* must be last */
#define LAST_PFIELD OFMT
extern int nf; /* shadows NF */

72
files.c
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: files.c,v 1.16 2010/06/25 21:56:01 tom Exp $
* $MawkId: files.c,v 1.17 2010/07/24 13:43:03 tom Exp $
*
* @Log: files.c,v @
* Revision 1.9 1996/01/14 17:14:10 mike
@ -107,6 +107,31 @@ static FILE *tfopen(const char *, const char *);
static void efflush(FILE *);
static void close_error(FILE_NODE * p);
static FILE_NODE *
alloc_filenode(void)
{
FILE_NODE *result;
result = ZMALLOC(FILE_NODE);
#ifdef NO_LEAKS
result->name = 0;
#endif
return result;
}
static void
free_filenode(FILE_NODE * p)
{
#ifdef NO_LEAKS
if (p->name != 0) {
free_STRING(p->name);
}
#endif
zfree(p, sizeof(FILE_NODE));
}
/* find a file on file_list */
PTR
file_find(STRING * sval, int type)
@ -119,7 +144,7 @@ file_find(STRING * sval, int type)
while (1) {
if (!p) {
/* open a new one */
p = ZMALLOC(FILE_NODE);
p = alloc_filenode();
switch (p->type = (short) type) {
case F_TRUNC:
@ -144,7 +169,7 @@ file_find(STRING * sval, int type)
case F_IN:
if (!(p->ptr = (PTR) FINopen(name, 0))) {
zfree(p, sizeof(FILE_NODE));
free_filenode(p);
return (PTR) 0;
}
break;
@ -158,7 +183,7 @@ file_find(STRING * sval, int type)
if (type == PIPE_OUT)
goto out_failure;
else {
zfree(p, sizeof(FILE_NODE));
free_filenode(p);
return (PTR) 0;
}
}
@ -205,7 +230,7 @@ file_find(STRING * sval, int type)
/* NOTREACHED */
}
/* Close a file and delete it's node from the file_list.
/* Close a file and delete its node from the file_list.
Walk the whole list, in case a name has two nodes,
e.g. < "/dev/tty" and > "/dev/tty"
*/
@ -237,15 +262,16 @@ file_close(STRING * sval)
switch (p->type) {
case F_TRUNC:
case F_APPEND:
if (fclose((FILE *) p->ptr) != 0)
if (fclose((FILE *) p->ptr) != 0) {
close_error(p);
}
retval = 0;
break;
case PIPE_OUT:
if (fclose((FILE *) p->ptr) != 0)
if (fclose((FILE *) p->ptr) != 0) {
close_error(p);
}
#ifdef HAVE_REAL_PIPES
retval = wait_for(p->pid);
#endif
@ -275,10 +301,9 @@ file_close(STRING * sval)
break;
}
free_STRING(p->name);
hold = p;
p = p->link;
ZFREE(hold);
free_filenode(hold);
} else {
q = p;
p = p->link;
@ -352,9 +377,10 @@ efflush(FILE *fp)
void
close_out_pipes(void)
{
register FILE_NODE *p = file_list;
FILE_NODE *p = file_list;
while (p) {
if (IS_OUTPUT(p->type)) {
if (fclose((FILE *) p->ptr) != 0) {
/* if another error occurs we do not want to be called
@ -362,9 +388,9 @@ close_out_pipes(void)
file_list = p->link;
close_error(p);
}
if (p->type == PIPE_OUT)
} else if (p->type == PIPE_OUT) {
wait_for(p->pid);
}
}
p = p->link;
@ -392,8 +418,9 @@ close_fake_pipes(void)
p = file_list;
while (p) {
if (p->type == PIPE_OUT) {
if (fclose(p->ptr) != 0)
if (fclose(p->ptr) != 0) {
close_error(p);
}
close_fake_outpipe(p->name->str, p->pid);
}
p = p->link;
@ -549,13 +576,13 @@ set_stderr(void) /* and stdout */
needed because we want to output errors encountered on closing
stdout. */
q = ZMALLOC(FILE_NODE);
q = alloc_filenode();
q->link = (FILE_NODE *) 0;
q->type = F_TRUNC;
q->name = new_STRING("/dev/stderr");
q->ptr = (PTR) stderr;
p = ZMALLOC(FILE_NODE);
p = alloc_filenode();
p->link = q;
p->type = F_TRUNC;
p->name = new_STRING("/dev/stdout");
@ -614,6 +641,19 @@ stdout_init(void)
static void
close_error(FILE_NODE * p)
{
TRACE(("close_error(%s)\n", p->name->str));
errmsg(errno, "close failed on file %s", p->name->str);
mawk_exit(2);
}
#ifdef NO_LEAKS
void
files_leaks(void)
{
while (file_list != 0) {
FILE_NODE *p = file_list;
file_list = p->link;
free_filenode(p);
}
}
#endif

32
files.h
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: files.h,v 1.8 2009/12/16 23:45:58 tom Exp $
* $MawkId: files.h,v 1.10 2010/07/24 14:30:55 tom Exp $
* @Log: files.h,v @
* Revision 1.3 1996/01/14 17:14:11 mike
* flush_all_output()
@ -46,29 +46,29 @@ the GNU General Public License, version 2, 1991.
extern const char *shell; /* for pipes and system() */
PTR file_find(STRING *, int);
int file_close(STRING *);
int file_flush(STRING *);
void flush_all_output(void);
PTR get_pipe(char *, int, int *);
int wait_for(int);
void close_out_pipes(void);
extern PTR file_find(STRING *, int);
extern int file_close(STRING *);
extern int file_flush(STRING *);
extern void flush_all_output(void);
extern PTR get_pipe(char *, int, int *);
extern int wait_for(int);
extern void close_out_pipes(void);
#ifdef HAVE_FAKE_PIPES
void close_fake_pipes(void);
int close_fake_outpipe(char *, int);
char *tmp_file_name(int, char *);
extern void close_fake_pipes(void);
extern int close_fake_outpipe(char *, int);
extern char *tmp_file_name(int, char *);
#endif
#ifdef MSDOS
int DOSexec(char *);
void enlarge_output_buffer(FILE *);
extern int DOSexec(char *);
extern void enlarge_output_buffer(FILE *);
#endif
#if USE_BINMODE
int binmode(void);
void set_binmode(int);
void stdout_init(void);
extern int binmode(void);
extern void set_binmode(int);
extern void stdout_init(void);
#endif
#endif /* MAWK_FILES_H */

21
fin.c
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: fin.c,v 1.27 2010/06/25 21:53:18 tom Exp $
* $MawkId: fin.c,v 1.28 2010/07/30 00:02:43 tom Exp $
* @Log: fin.c,v @
* Revision 1.10 1995/12/24 22:23:22 mike
* remove errmsg() from inside FINopen
@ -442,6 +442,7 @@ static FIN *
next_main(int open_flag) /* called by open_main() if on */
{
register CELL *cp;
CELL *cp0;
CELL argc; /* copy of ARGC */
CELL c_argi; /* cell copy of argi */
CELL argval; /* copy of ARGV[c_argi] */
@ -462,21 +463,27 @@ next_main(int open_flag) /* called by open_main() if on */
c_argi.dval = argi;
argi += 1.0;
if (!(cp = array_find(Argv, &c_argi, NO_CREATE)))
if (!(cp0 = array_find(Argv, &c_argi, NO_CREATE)))
continue; /* its deleted */
/* make a copy so we can cast w/o side effect */
cell_destroy(&argval);
cp = cellcpy(&argval, cp);
cp = cellcpy(&argval, cp0);
cell_destroy(cp0);
if (cp->type < C_STRING)
cast1_to_s(cp);
if (string(cp)->len == 0)
if (string(cp)->len == 0) {
/* file argument is "" */
cell_destroy(cp);
continue;
/* file argument is "" */
}
/* it might be a command line assignment */
if (is_cmdline_assign(string(cp)->str))
if (is_cmdline_assign(string(cp)->str)) {
cell_destroy(cp);
continue;
}
/* try to open it -- we used to continue on failure,
but posix says we should quit */
@ -488,7 +495,7 @@ next_main(int open_flag) /* called by open_main() if on */
/* success -- set FILENAME and FNR */
cell_destroy(FILENAME);
cellcpy(FILENAME, cp);
free_STRING(string(cp));
cell_destroy(cp);
cell_destroy(FNR);
FNR->type = C_DOUBLE;
FNR->dval = 0.0;

50
hash.c
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: hash.c,v 1.7 2010/05/07 08:18:31 tom Exp $
* $MawkId: hash.c,v 1.14 2010/08/05 09:13:01 tom Exp $
* @Log: hash.c,v @
* Revision 1.3 1994/10/08 19:15:43 mike
* remove SM_DOS
@ -32,6 +32,10 @@ the GNU General Public License, version 2, 1991.
#include "memory.h"
#include "symtype.h"
#ifdef NO_LEAKS
#include "bi_vars.h"
#endif
/*
* FNV-1 hash function
* http://www.isthe.com/chongo/tech/comp/fnv/index.html
@ -67,8 +71,6 @@ typedef struct hash {
SYMTAB symtab;
} HASHNODE;
static HASHNODE *delete(const char *);
static HASHNODE *hash_table[HASH_PRIME];
/*
@ -258,3 +260,45 @@ reverse_find(int type, PTR ptr)
}
return uk;
}
#ifdef NO_LEAKS
void
hash_leaks(void)
{
int i;
HASHNODE *p;
CELL *cp;
TRACE(("hash_leaks\n"));
for (i = 0; i < HASH_PRIME; i++) {
while ((p = hash_table[i]) != 0) {
TRACE(("...deleting hash %s %d\n", p->symtab.name, p->symtab.type));
p = delete(p->symtab.name);
switch (p->symtab.type) {
case ST_FUNCT:
free_codes(p->symtab.name,
p->symtab.stval.fbp->code,
p->symtab.stval.fbp->size);
zfree(p->symtab.stval.fbp, sizeof(FBLOCK));
break;
case ST_VAR:
cp = p->symtab.stval.cp;
if (cp != 0
&& (cp < bi_vars || cp > bi_vars + NUM_BI_VAR)) {
switch (cp->type) {
case C_STRING:
case C_STRNUM:
case C_MBSTRN:
free_STRING(string(cp));
break;
}
zfree((PTR) (p->symtab.name), strlen(p->symtab.name) + 1);
zfree(cp, sizeof(CELL));
}
break;
}
zfree(p, sizeof(HASHNODE));
}
}
}
#endif

35
init.c
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: init.c,v 1.23 2010/05/07 21:58:49 tom Exp $
* $MawkId: init.c,v 1.25 2010/08/02 09:15:21 tom Exp $
* @Log: init.c,v @
* Revision 1.11 1995/08/20 17:35:21 mike
* include <stdlib.h> for MSC, needed for environ decl
@ -349,7 +349,6 @@ process_cmdline(int argc, char **argv)
pfile_name = argv[nextarg];
i = nextarg + 1;
goto no_more_opts;
break;
case W_INTERACTIVE:
interactive_flag = 1;
@ -462,6 +461,7 @@ set_ARGV(int argc, char **argv, int i)
st_p = insert("ARGV");
st_p->type = ST_ARRAY;
Argv = st_p->stval.array = new_ARRAY();
no_leaks_array(Argv);
argi.type = C_DOUBLE;
argi.dval = 0.0;
cp = array_find(st_p->stval.array, &argi, CREATE);
@ -517,3 +517,34 @@ load_environ(ARRAY ENV)
p++;
}
}
#ifdef NO_LEAKS
typedef struct _all_arrays {
struct _all_arrays *next;
ARRAY a;
} ALL_ARRAYS;
static ALL_ARRAYS *all_arrays;
void
array_leaks(void)
{
while (all_arrays != 0) {
ALL_ARRAYS *next = all_arrays->next;
array_clear(all_arrays->a);
ZFREE(all_arrays->a);
free(all_arrays);
all_arrays = next;
}
}
/* use this to identify array leaks */
void
no_leaks_array(ARRAY a)
{
ALL_ARRAYS *p = calloc(1, sizeof(ALL_ARRAYS));
p->next = all_arrays;
p->a = a;
all_arrays = p;
}
#endif

18
main.c
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: main.c,v 1.8 2009/12/14 00:23:56 tom Exp $
* $MawkId: main.c,v 1.20 2010/08/03 00:50:24 tom Exp $
* @Log: main.c,v @
* Revision 1.4 1995/06/09 22:57:19 mike
* parse() no longer returns on error
@ -44,6 +44,7 @@ the GNU General Public License, version 2, 1991.
/* main.c */
#include "mawk.h"
#include "bi_vars.h"
#include "init.h"
#include "code.h"
#include "files.h"
@ -87,6 +88,21 @@ mawk_exit(int x)
#ifdef HAVE_FAKE_PIPES
close_fake_pipes();
#endif
#endif
#ifdef NO_LEAKS
code_leaks();
scan_leaks();
rexp_leaks();
bi_vars_leaks();
hash_leaks();
array_leaks();
files_leaks();
field_leaks();
zmalloc_leaks();
#if OPT_TRACE > 0
trace_leaks();
#endif
#endif
exit(x);

View File

@ -1,4 +1,4 @@
.\" $MawkId: mawk.1,v 1.7 2010/02/01 00:56:37 tom Exp $
.\" $MawkId: mawk.1,v 1.8 2010/07/19 09:16:34 tom Exp $
.TH MAWK 1 "USER COMMANDS"
.\" strings
.ds ex \fIexpr\fR
@ -135,8 +135,8 @@ are recognized and on some systems \fB\-W\fRe is mandatory to avoid
command line length limitations.
.PP
.B mawk
allows multiple \fB-W\fP options to be combined by separating the options
with commas, e.g., -Wsprint=2000,posix.
allows multiple \fB\-W\fP options to be combined by separating the options
with commas, e.g., \-Wsprint=2000,posix.
.SH "THE AWK LANGUAGE"
.SS "\fB1. Program structure"
An AWK program is a sequence of
@ -441,7 +441,7 @@ unary (*, + or ?).
For example,
.nf
.sp
/^[_a\-zA-Z][_a\-zA\-Z0\-9]*$/ and
/^[_a\-zA\-Z][_a\-zA\-Z0\-9]*$/ and
/^[\-+]?([0\-9]+\e\|.?|\e\|.[0\-9])[0\-9]*([eE][\-+]?[0\-9]+)?$/
.sp
.fi
@ -659,7 +659,7 @@ execution.
number of command line arguments.
.TP
.B ARGV
array of command line arguments, 0..ARGC-1.
array of command line arguments, 0..ARGC\-1.
.TP
.B CONVFMT
format for internal conversion of numbers to string,
@ -825,7 +825,7 @@ Arithmetic functions
.ds Pi pi
.el \
.ds Pi \\(*p
atan2(\fIy,x\fR) Arctan of \fIy\fR/\fIx\fR between -\*(Pi and \*(Pi.
atan2(\fIy,x\fR) Arctan of \fIy\fR/\fIx\fR between \-\*(Pi and \*(Pi.
.PP
cos(\fIx\fR) Cosine function, \fIx\fR in radians.
.PP
@ -1224,7 +1224,7 @@ the execution phase of the program.
.B ARGV[0]
is set the name of the AWK interpreter and
\fBARGV[1]\fR ...
.B ARGV[ARGC-1]
.B ARGV[ARGC\-1]
holds the remaining command line arguments exclusive of
options and program source.
For example with
@ -1260,7 +1260,7 @@ equals 1,
the input stream is set to stdin,
else the command line arguments
.BR ARGV[1] " ...
.B ARGV[ARGC-1]
.B ARGV[ARGC\-1]
are examined for a file argument.
.PP
The command line arguments divide into three sets:
@ -1389,7 +1389,7 @@ or subsequent error.
3. count the number of unique "real words".
BEGIN { FS = "[^A-Za-z]+" }
BEGIN { FS = "[^A\-Za\-z]+" }
{ for(i = 1 ; i <= NF ; i++) word[$i] = "" }
@ -1495,7 +1495,7 @@ often improve performance. For example,
redoing example 3 from above,
.nf
.sp
BEGIN { RS = "[^A-Za-z]+" }
BEGIN { RS = "[^A\-Za\-z]+" }
{ word[ $0 ] = "" }

122
mawk.h
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: mawk.h,v 1.19 2010/05/07 22:01:59 tom Exp $
* $MawkId: mawk.h,v 1.32 2010/08/04 23:02:20 tom Exp $
* @Log: mawk.h,v @
* Revision 1.10 1996/08/25 19:31:04 mike
* Added work-around for solaris strtod overflow bug.
@ -64,6 +64,10 @@ the GNU General Public License, version 2, 1991.
#define GCC_NORETURN /* nothing */
#endif
#ifndef GCC_PRINTFLIKE
#define GCC_PRINTFLIKE(fmt,var) /* nothing */
#endif
#ifndef GCC_UNUSED
#define GCC_UNUSED /* nothing */
#endif
@ -136,7 +140,7 @@ extern unsigned rt_nr, rt_fnr; /* ditto */
#ifdef DEBUG
#define cell_destroy(cp) DB_cell_destroy(cp)
#else
/* Note: type is only C_STRING to C_MBSTRN */
#define cell_destroy(cp) \
do { \
if ( (cp)->type >= C_STRING && \
@ -147,53 +151,97 @@ extern unsigned rt_nr, rt_fnr; /* ditto */
/* prototypes */
void cast1_to_s(CELL *);
void cast1_to_d(CELL *);
void cast2_to_s(CELL *);
void cast2_to_d(CELL *);
void cast_to_RE(CELL *);
void cast_for_split(CELL *);
void check_strnum(CELL *);
void cast_to_REPL(CELL *);
Int d_to_I(double);
UInt d_to_U(double d);
extern void cast1_to_s(CELL *);
extern void cast1_to_d(CELL *);
extern void cast2_to_s(CELL *);
extern void cast2_to_d(CELL *);
extern void cast_to_RE(CELL *);
extern void cast_for_split(CELL *);
extern void check_strnum(CELL *);
extern void cast_to_REPL(CELL *);
extern Int d_to_I(double);
extern UInt d_to_U(double d);
#define d_to_i(d) ((int)d_to_I(d))
int test(CELL *); /* test for null non-null */
CELL *cellcpy(CELL *, CELL *);
CELL *repl_cpy(CELL *, CELL *);
void DB_cell_destroy(CELL *);
void overflow(const char *, unsigned);
void rt_overflow(const char *, unsigned);
void rt_error(const char *,...) GCC_NORETURN;
void mawk_exit(int) GCC_NORETURN;
void da(INST *, FILE *);
char *rm_escape(char *, size_t *);
char *re_pos_match(char *, size_t, PTR, size_t *);
int binmode(void);
extern int test(CELL *); /* test for null non-null */
extern CELL *cellcpy(CELL *, CELL *);
extern CELL *repl_cpy(CELL *, CELL *);
extern void DB_cell_destroy(CELL *);
extern void overflow(const char *, unsigned);
extern void rt_overflow(const char *, unsigned);
extern void rt_error(const char *,...) GCC_NORETURN GCC_PRINTFLIKE(1,2);
extern void mawk_exit(int) GCC_NORETURN;
extern void da(INST *, FILE *);
extern char *rm_escape(char *, size_t *);
extern char *re_pos_match(char *, size_t, PTR, size_t *);
extern int binmode(void);
#ifndef REXP_H
char *str_str(char *, size_t, char *, size_t);
extern char *str_str(char *, size_t, char *, size_t);
#endif
void parse(void);
int yylex(void);
int yyparse(void);
void yyerror(char *);
void scan_cleanup(void);
extern void parse(void);
extern int yylex(void);
extern int yyparse(void);
extern void yyerror(const char *);
extern void scan_cleanup(void);
void bozo(const char *) GCC_NORETURN;
void errmsg(int, const char *,...);
void compile_error(const char *,...);
extern void bozo(const char *) GCC_NORETURN;
extern void errmsg(int, const char *,...) GCC_PRINTFLIKE(2,3);
extern void compile_error(const char *,...) GCC_PRINTFLIKE(1,2);
void execute(INST *, CELL *, CELL *);
const char *find_kw_str(int);
void da_string(FILE *fp, const char *, size_t);
extern void execute(INST *, CELL *, CELL *);
extern const char *find_kw_str(int);
extern void da_string(FILE *fp, const char *, size_t);
#ifdef HAVE_STRTOD_OVF_BUG
double strtod_with_ovf_bug(const char *, char **);
extern double strtod_with_ovf_bug(const char *, char **);
#define strtod strtod_with_ovf_bug
#endif
#if OPT_TRACE > 0
extern void Trace(const char *,...) GCC_PRINTFLIKE(1,2);
#define TRACE(params) Trace params
#if OPT_TRACE > 1
#define TRACE2(params) Trace params
#endif
#endif
#ifndef TRACE
#define TRACE(params) /* nothing */
#endif
#ifndef TRACE2
#define TRACE2(params) /* nothing */
#endif
#ifdef NO_LEAKS
extern const char *da_op_name(INST *);
extern void free_cell_data(CELL *);
extern void free_codes(const char *, INST *, size_t);
extern void array_leaks(void);
extern void bi_vars_leaks(void);
extern void code_leaks(void);
extern void field_leaks(void);
extern void files_leaks(void);
extern void hash_leaks(void);
extern void rexp_leaks(void);
extern void scan_leaks(void);
extern void trace_leaks(void);
extern void zmalloc_leaks(void);
#else
#define free_codes(tag, base, size) zfree(base, size)
#endif
/*
* Sometimes split_buff[] pointers are moved rather than copied.
* Optimize-out the assignment to clear the pointer in the array.
*/
#ifdef NO_LEAKS
#define USED_SPLIT_BUFF(n) split_buff[n] = 0
#else
#define USED_SPLIT_BUFF(n) /* nothing */
#endif
#endif /* MAWK_H */

View File

@ -1,3 +1,9 @@
mawk-cur (1.3.4-20100718) unstable; urgency=low
* bug-fixes
-- Thomas E. Dickey <dickey@invisible-island.net> Sun, 18 Jul 2010 05:26:54 -0400
mawk-cur (1.3.4-20100625) unstable; urgency=low
* Add package scripts to upstream source, for test-builds.

View File

@ -1,7 +1,7 @@
Source: mawk-cur
Maintainer: Thomas E. Dickey <dickey@invisible-island.net>
Section: devel
Priority: extra
Section: interpreters
Priority: optional
Standards-Version: 3.8.4
Build-Depends: debhelper (>= 5)
Homepage: http://invisible-island.net/mawk/

View File

@ -1,8 +1,8 @@
Summary: mawk - pattern scanning and text processing language
%define AppProgram mawk
%define AppVersion 1.3.4
%define AppRelease 20100625
# $MawkId: mawk.spec,v 1.3 2010/06/25 09:44:29 tom Exp $
%define AppRelease 20100718
# $MawkId: mawk.spec,v 1.4 2010/07/18 09:26:17 tom Exp $
Name: %{AppProgram}
Version: %{AppVersion}
Release: %{AppRelease}

74
parse.c
View File

@ -2,13 +2,10 @@
static const char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93";
#endif
#include <stdlib.h>
#include <string.h>
#define YYBYACC 1
#define YYMAJOR 1
#define YYMINOR 9
#define YYPATCH 20100216
#define YYPATCH 20100610
#define YYEMPTY (-1)
#define yyclearin (yychar = YYEMPTY)
@ -17,19 +14,7 @@ static const char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93";
#define YYPREFIX "yy"
/* compatibility with bison */
#ifdef YYPARSE_PARAM
/* compatibility with FreeBSD */
#ifdef YYPARSE_PARAM_TYPE
#define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM)
#else
#define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
#endif
#else
#define YYPARSE_DECL() yyparse(void)
#endif /* YYPARSE_PARAM */
extern int YYPARSE_DECL();
#define YYPURE 0
#line 81 "parse.y"
#include <stdio.h>
@ -87,7 +72,31 @@ CA_REC *ca_p ;
int ival ;
PTR ptr ;
} YYSTYPE;
#line 90 "y.tab.c"
#line 75 "y.tab.c"
/* compatibility with bison */
#ifdef YYPARSE_PARAM
/* compatibility with FreeBSD */
# ifdef YYPARSE_PARAM_TYPE
# define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM)
# else
# define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
# endif
#else
# define YYPARSE_DECL() yyparse(void)
#endif
/* Parameters sent to lex. */
#ifdef YYLEX_PARAM
# define YYLEX_DECL() yylex(void *YYLEX_PARAM)
# define YYLEX yylex(YYLEX_PARAM)
#else
# define YYLEX_DECL() yylex(void)
# define YYLEX yylex()
#endif
extern int YYPARSE_DECL();
extern int YYLEX_DECL();
#define UNEXPECTED 257
#define BAD_DECIMAL 258
#define NL 259
@ -1113,10 +1122,6 @@ static const char *yyrule[] = {
};
#endif
#if YYDEBUG
#include <stdio.h>
#endif
/* define the initial stack-sizes */
#ifdef YYSTACKSIZE
#undef YYMAXDEPTH
@ -1143,9 +1148,6 @@ typedef struct {
YYSTYPE *l_base;
YYSTYPE *l_mark;
} YYSTACKDATA;
#define YYPURE 0
int yyerrflag;
int yychar;
YYSTYPE yyval;
@ -1161,13 +1163,12 @@ static void
resize_fblock(FBLOCK *fbp)
{
CODEBLOCK *p = ZMALLOC(CODEBLOCK) ;
size_t dummy ;
code2op(_RET0, _HALT) ;
/* make sure there is always a return */
*p = active_code ;
fbp->code = code_shrink(p, &dummy) ;
fbp->code = code_shrink(p, &fbp->size) ;
/* code_shrink() zfrees p */
if ( dump_code_flag )
@ -1253,6 +1254,7 @@ check_array(SYMTAB *p)
case ST_NONE : /* a new array */
p->type = ST_ARRAY ;
p->stval.array = new_ARRAY() ;
no_leaks_array(p->stval.array);
break ;
case ST_ARRAY :
@ -1391,7 +1393,15 @@ parse(void)
if ( compile_error_count != 0 ) mawk_exit(2) ;
if ( dump_code_flag ) { dump_code() ; mawk_exit(0) ; }
}
#line 1394 "y.tab.c"
#line 1396 "y.tab.c"
#if YYDEBUG
#include <stdio.h> /* needed for printf */
#endif
#include <stdlib.h> /* needed for malloc, etc */
#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
{
@ -1414,7 +1424,7 @@ static int yygrowstack(YYSTACKDATA *data)
if (newss == 0)
return -1;
data->s_base = newss;
data->s_base = newss;
data->s_mark = newss + i;
newvs = (data->l_base != 0)
@ -1481,7 +1491,7 @@ yyloop:
if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
if (yychar < 0)
{
if ((yychar = yylex()) < 0) yychar = 0;
if ((yychar = YYLEX) < 0) yychar = 0;
#if YYDEBUG
if (yydebug)
{
@ -2643,7 +2653,7 @@ case 171:
code_call_id(yyval.ca_p, yystack.l_mark[-1].stp) ;
}
break;
#line 2646 "y.tab.c"
#line 2656 "y.tab.c"
}
yystack.s_mark -= yym;
yystate = *yystack.s_mark;
@ -2661,7 +2671,7 @@ break;
*++yystack.l_mark = yyval;
if (yychar < 0)
{
if ((yychar = yylex()) < 0) yychar = 0;
if ((yychar = YYLEX) < 0) yychar = 0;
#if YYDEBUG
if (yydebug)
{

View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: parse.y,v 1.9 2010/05/07 10:51:08 tom Exp $
* $MawkId: parse.y,v 1.11 2010/08/02 08:56:20 tom Exp $
* @Log: parse.y,v @
* Revision 1.11 1995/06/11 22:40:09 mike
* change if(dump_code) -> if(dump_code_flag)
@ -1152,13 +1152,12 @@ static void
resize_fblock(FBLOCK *fbp)
{
CODEBLOCK *p = ZMALLOC(CODEBLOCK) ;
size_t dummy ;
code2op(_RET0, _HALT) ;
/* make sure there is always a return */
*p = active_code ;
fbp->code = code_shrink(p, &dummy) ;
fbp->code = code_shrink(p, &fbp->size) ;
/* code_shrink() zfrees p */
if ( dump_code_flag )
@ -1244,6 +1243,7 @@ check_array(SYMTAB *p)
case ST_NONE : /* a new array */
p->type = ST_ARRAY ;
p->stval.array = new_ARRAY() ;
no_leaks_array(p->stval.array);
break ;
case ST_ARRAY :

View File

@ -1,7 +1,7 @@
/*
* $MawkId: patchlev.h,v 1.28 2010/06/25 09:44:17 tom Exp $
* $MawkId: patchlev.h,v 1.29 2010/07/18 09:24:03 tom Exp $
*/
#define PATCH_BASE 1
#define PATCH_LEVEL 3
#define PATCH_STRING ".4"
#define DATE_STRING "20100625"
#define DATE_STRING "20100718"

View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: re_cmpl.c,v 1.10 2010/05/07 08:15:08 tom Exp $
* $MawkId: re_cmpl.c,v 1.16 2010/08/04 09:17:25 tom Exp $
* @Log: re_cmpl.c,v @
* Revision 1.6 1994/12/13 00:14:58 mike
* \\ -> \ on second replacement scan
@ -47,8 +47,8 @@ the GNU General Public License, version 2, 1991.
#include "repl.h"
typedef struct re_node {
RE_DATA re; /* keep this first, for re_destroy() */
STRING *sval;
RE_DATA re;
struct re_node *link;
} RE_NODE;
@ -134,6 +134,29 @@ re_uncompile(PTR m)
#endif
}
void
re_destroy(PTR m)
{
RE_NODE *p = (RE_NODE *) m;
RE_NODE *q;
RE_NODE *r;
if (p != 0) {
free_STRING(p->sval);
REdestroy(p->re.compiled);
for (q = re_list, r = 0; q != 0; r = q, q = q->link) {
if (q == p) {
if (r != 0)
r->link = q->link;
else
re_list = q->link;
free(q);
break;
}
}
}
}
/*=================================================*/
/* replacement operations */
@ -197,13 +220,16 @@ REPL_compile(STRING * sval)
if (count == 1 && split_buff[0]) {
cp->type = C_REPL;
cp->ptr = (PTR) split_buff[0];
USED_SPLIT_BUFF(0);
} else {
STRING **sp = (STRING **)
(cp->ptr = zmalloc(sizeof(STRING *) * count));
VCount j = 0;
while (j < count)
while (j < count) {
*sp++ = split_buff[j++];
USED_SPLIT_BUFF(j - 1);
}
cp->type = C_REPLV;
cp->vcnt = count;
@ -220,9 +246,9 @@ repl_destroy(CELL * cp)
register STRING **p;
VCount cnt;
if (cp->type == C_REPL)
if (cp->type == C_REPL) {
free_STRING(string(cp));
else { /* an C_REPLV */
} else { /* an C_REPLV */
p = (STRING **) cp->ptr;
for (cnt = cp->vcnt; cnt; cnt--) {
if (*p) {

View File

@ -1,4 +1,6 @@
/* $MawkId: regexp.c,v 1.4 2010/07/31 00:15:13 tom Exp $ */
#ifdef LOCAL_REGEXP
# include "mawk.h"
# include "rexp.c"
# include "rexp0.c"
# include "rexp1.c"
@ -10,3 +12,31 @@
# include "rexp4.c"
# include "regexp_system.c"
#endif
#ifdef NO_LEAKS
void
rexp_leaks(void)
{
#ifdef LOCAL_REGEXP
if (bv_base) {
BV **p = bv_base;
while (p != bv_next) {
RE_free(*p);
++p;
}
RE_free(bv_base);
bv_base = 0;
bv_limit = 0;
bv_next = 0;
}
if (RE_run_stack_base) {
RE_free(RE_run_stack_base);
RE_run_stack_base = 0;
}
if (RE_pos_stack_base) {
RE_free(RE_pos_stack_base);
RE_pos_stack_base = 0;
}
#endif
}
#endif

View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: regexp.h,v 1.9 2010/05/07 08:10:40 tom Exp $
* $MawkId: regexp.h,v 1.10 2010/07/28 09:44:18 tom Exp $
* @Log: regexp.h,v @
* Revision 1.1.1.1 1993/07/03 18:58:19 mike
* move source to cvs
@ -26,6 +26,7 @@ the GNU General Public License, version 2, 1991.
#include "nstd.h"
PTR REcompile(char *, size_t);
void REdestroy(PTR);
int REtest(char *, size_t, PTR);
char *REmatch(char *, size_t, PTR, size_t *);
void REmprint(PTR, FILE *);

View File

@ -1,5 +1,5 @@
/*
* $MawkId: regexp_system.c,v 1.31 2010/06/25 20:43:03 tom Exp $
* $MawkId: regexp_system.c,v 1.34 2010/08/01 17:34:35 tom Exp $
*/
#include <sys/types.h>
#include <stdio.h>
@ -18,14 +18,6 @@ typedef struct {
static mawk_re_t *last_used_regexp = NULL;
static int err_code = 0;
/*#define MAWK_EXTRACT_REGEXP_DEBUG*/
#ifdef MAWK_EXTRACT_REGEXP_DEBUG
#define TRACE(params) fprintf params
#else
#define TRACE(params) /*nothing */
#endif
#define AT_LAST() ((size_t) (source - base) >= limit)
#define MORE_CH() ((size_t) (source - base) < limit)
#define NEXT_CH() (char) (MORE_CH() ? *source : 0)
@ -55,7 +47,7 @@ prepare_regexp(char *regexp, const char *source, size_t limit)
int value = 0;
int added;
TRACE((stderr, "in : \"%s\"\n", base));
TRACE(("in : \"%s\"\n", base));
while ((ch = LIMITED()) != 0) {
if (escape) {
@ -279,7 +271,7 @@ prepare_regexp(char *regexp, const char *source, size_t limit)
*tail = '\0';
TRACE((stderr, "out: \"%s\"\n", regexp));
TRACE(("out: \"%s\"\n", regexp));
return tail;
}
@ -324,6 +316,12 @@ REcompile(char *regexp, size_t len)
return re;
}
void
REdestroy(PTR ptr)
{
(void) ptr;
}
/*
* Test the regular expression in 'q' against the string 'str'.
* The 'len' parameter is ignored since POSIX regular expressions assume 'str'
@ -334,15 +332,15 @@ REtest(char *str, size_t str_len GCC_UNUSED, PTR q)
{
mawk_re_t *re = (mawk_re_t *) q;
TRACE((stderr, "REtest: \"%s\" ~ /%s/", str, re->regexp));
TRACE(("REtest: \"%s\" ~ /%s/", str, re->regexp));
last_used_regexp = re;
if (regexec(&re->re, str, (size_t) 0, NULL, 0)) {
TRACE((stderr, "=1\n"));
TRACE(("=1\n"));
return 0;
} else {
TRACE((stderr, "=0\n"));
TRACE(("=0\n"));
return 1;
}
}
@ -355,16 +353,16 @@ REmatch(char *str, size_t str_len GCC_UNUSED, PTR q, size_t *lenp)
mawk_re_t *re = (mawk_re_t *) q;
regmatch_t match[MAX_MATCHES];
TRACE((stderr, "REmatch: \"%s\" ~ /%s/", str, re->regexp));
TRACE(("REmatch: \"%s\" ~ /%s/", str, re->regexp));
last_used_regexp = re;
if (!regexec(&re->re, str, (size_t) MAX_MATCHES, match, 0)) {
*lenp = (size_t) (match[0].rm_eo - match[0].rm_so);
TRACE((stderr, "=%i/%lu\n", match[0].rm_so, (unsigned long) *lenp));
TRACE(("=%i/%lu\n", match[0].rm_so, (unsigned long) *lenp));
return str + match[0].rm_so;
} else {
TRACE((stderr, "=0\n"));
TRACE(("=0\n"));
return NULL;
}
}

5
repl.h
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: repl.h,v 1.4 2009/07/27 21:47:40 tom Exp $
* $MawkId: repl.h,v 1.6 2010/08/04 08:53:16 tom Exp $
* @Log: repl.h,v @
* Revision 1.1.1.1 1993/07/03 18:58:19 mike
* move source to cvs
@ -28,7 +28,7 @@ the GNU General Public License, version 2, 1991.
#include "types.h"
typedef struct re_data {
int anchored; /* use to limit recursion in gsub */
int anchored; /* use to limit recursion in gsub */
PTR compiled;
} RE_DATA;
@ -44,6 +44,7 @@ char *re_uncompile(PTR);
CELL *repl_compile(STRING *);
char *repl_uncompile(CELL *);
void re_destroy(PTR);
void repl_destroy(CELL *);
CELL *replv_cpy(CELL *, CELL *);
CELL *replv_to_repl(CELL *, STRING *);

30
rexp.c
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: rexp.c,v 1.10 2009/09/13 22:43:29 tom Exp $
* $MawkId: rexp.c,v 1.14 2010/08/04 00:23:35 tom Exp $
* @Log: rexp.c,v @
* Revision 1.3 1996/09/02 18:47:36 mike
* Make ^* and ^+ syntax errors.
@ -215,6 +215,34 @@ REcompile(char *re, size_t len)
}
}
void
REdestroy(PTR ptr)
{
int done = 0;
int n = 0;
STATE *q = (STATE *) ptr;
TRACE(("REdestroy %p\n", q));
while (!done) {
TRACE(("...%d type %d\n", n, q->s_type));
switch (q->s_type) {
case M_ACCEPT:
done = 1;
break;
case M_STR:
RE_free(q->s_data.str);
break;
default:
if (q->s_type < 0 || q->s_type > END_ON)
done = -1;
break;
}
++q;
++n;
}
RE_free(ptr);
}
/* getting here means a logic flaw or unforeseen case */
void
RE_panic(const char *s)

50
rexp.h
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: rexp.h,v 1.22 2010/05/07 22:05:59 tom Exp $
* $MawkId: rexp.h,v 1.23 2010/07/30 08:21:09 tom Exp $
* @Log: rexp.h,v @
* Revision 1.2 1993/07/23 13:21:35 mike
* cleanup rexp code
@ -55,8 +55,14 @@ the GNU General Public License, version 2, 1991.
#include <stdio.h>
#include <setjmp.h>
PTR RE_malloc(size_t);
PTR RE_realloc(void *, size_t);
extern PTR RE_malloc(size_t);
extern PTR RE_realloc(void *, size_t);
#ifdef NO_LEAKS
extern void RE_free(void *);
#else
#define RE_free(p) free(p)
#endif
/* finite machine state types */
@ -162,29 +168,29 @@ void RE_error_trap(int);
#define GCC_NORETURN /* nothing */
#endif
MACHINE RE_u(void);
MACHINE RE_start(void);
MACHINE RE_end(void);
MACHINE RE_any(void);
MACHINE RE_str(char *, size_t);
MACHINE RE_class(BV *);
void RE_cat(MACHINE *, MACHINE *);
void RE_or(MACHINE *, MACHINE *);
void RE_close(MACHINE *);
void RE_poscl(MACHINE *);
void RE_01(MACHINE *);
void RE_panic(const char *) GCC_NORETURN;
extern MACHINE RE_u(void);
extern MACHINE RE_start(void);
extern MACHINE RE_end(void);
extern MACHINE RE_any(void);
extern MACHINE RE_str(char *, size_t);
extern MACHINE RE_class(BV *);
extern void RE_cat(MACHINE *, MACHINE *);
extern void RE_or(MACHINE *, MACHINE *);
extern void RE_close(MACHINE *);
extern void RE_poscl(MACHINE *);
extern void RE_01(MACHINE *);
extern void RE_panic(const char *) GCC_NORETURN;
#ifndef MAWK_H
char *str_str(char *, size_t, char *, size_t);
extern char *str_str(char *, size_t, char *, size_t);
#endif
void RE_lex_init(char *, size_t);
int RE_lex(MACHINE *);
void RE_run_stack_init(void);
void RE_pos_stack_init(void);
RT_STATE *RE_new_run_stack(void);
RT_POS_ENTRY *RE_new_pos_stack(void);
extern void RE_lex_init(char *, size_t);
extern int RE_lex(MACHINE *);
extern void RE_run_stack_init(void);
extern void RE_pos_stack_init(void);
extern RT_STATE *RE_new_run_stack(void);
extern RT_POS_ENTRY *RE_new_pos_stack(void);
extern RT_STATE *RE_run_stack_base;
extern RT_STATE *RE_run_stack_limit;

15
rexp0.c
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: rexp0.c,v 1.23 2010/05/07 22:18:57 tom Exp $
* $MawkId: rexp0.c,v 1.25 2010/07/31 00:15:35 tom Exp $
* @Log: rexp0.c,v @
* Revision 1.5 1996/11/08 15:39:27 mike
* While cleaning up block_on, I introduced a bug. Now fixed.
@ -684,13 +684,12 @@ do_class(char **start, MACHINE * mp)
#define BV_GROWTH 6
static BV *
store_bvp(
BV * bvp)
{
static BV **bv_base, **bv_limit;
static BV **bv_next; /* next empty slot in the array */
static BV **bv_base, **bv_limit;
static BV **bv_next; /* next empty slot in the array */
static BV *
store_bvp(BV * bvp)
{
register BV **p;
unsigned t;
@ -721,7 +720,7 @@ store_bvp(
bv_next++;
} else {
/* we already have it */
free(bvp);
RE_free(bvp);
}
return *p;

37
rexp1.c
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: rexp1.c,v 1.12 2010/05/07 22:05:40 tom Exp $
* $MawkId: rexp1.c,v 1.13 2010/07/30 08:44:14 tom Exp $
* @Log: rexp1.c,v @
* Revision 1.3 1993/07/24 17:55:10 mike
* more cleanup
@ -124,7 +124,7 @@ RE_cat(MACHINE * mp, MACHINE * np)
mp->start = (STATE *) RE_realloc(mp->start, sz * STATESZ);
mp->stop = mp->start + (sz - 1);
memcpy(mp->start + sz1, np->start, sz2 * STATESZ);
free(np->start);
RE_free(np->start);
}
/* replace m by a machine that recognizes m|n */
@ -140,13 +140,13 @@ RE_or(MACHINE * mp, MACHINE * np)
p = (STATE *) RE_malloc((szm + szn + 1) * STATESZ);
memcpy(p + 1, mp->start, szm * STATESZ);
free(mp->start);
RE_free(mp->start);
mp->start = p;
(mp->stop = p + szm + szn)->s_type = M_ACCEPT;
p->s_type = M_2JA;
p->s_data.jump = (int) (szm + 1);
memcpy(p + szm + 1, np->start, szn * STATESZ);
free(np->start);
RE_free(np->start);
(p += szm)->s_type = M_1J;
p->s_data.jump = (int) szn;
}
@ -173,7 +173,7 @@ RE_close(MACHINE * mp)
sz = (unsigned) (mp->stop - mp->start + 1);
p = (STATE *) RE_malloc((sz + 3) * STATESZ);
memcpy(p + 2, mp->start, sz * STATESZ);
free(mp->start);
RE_free(mp->start);
mp->start = p;
mp->stop = p + (sz + 2);
p->s_type = M_2JA;
@ -202,7 +202,7 @@ RE_poscl(MACHINE * mp)
sz = (unsigned) (mp->stop - mp->start + 1);
p = (STATE *) RE_malloc((sz + 2) * STATESZ);
memcpy(p + 1, mp->start, sz * STATESZ);
free(mp->start);
RE_free(mp->start);
mp->start = p;
mp->stop = p + (sz + 1);
p++->s_type = M_SAVE_POS;
@ -223,7 +223,7 @@ RE_01(MACHINE * mp)
sz = (unsigned) (mp->stop - mp->start + 1);
p = (STATE *) RE_malloc((sz + 1) * STATESZ);
memcpy(p + 1, mp->start, sz * STATESZ);
free(mp->start);
RE_free(mp->start);
mp->start = p;
mp->stop = p + sz;
p->s_type = M_2JB;
@ -237,9 +237,11 @@ MEMORY ALLOCATION
PTR
RE_malloc(size_t sz)
{
register PTR p;
PTR p;
if (!(p = malloc(sz)))
p = malloc(sz);
TRACE(("RE_malloc(%lu) ->%p\n", (unsigned long) sz, p));
if (p == 0)
RE_error_trap(MEMORY_FAILURE);
return p;
}
@ -247,7 +249,20 @@ RE_malloc(size_t sz)
PTR
RE_realloc(PTR p, size_t sz)
{
if (!(p = realloc(p, sz)))
PTR q;
q = realloc(p, sz);
TRACE(("RE_realloc(%p, %lu) ->%p\n", p, (unsigned long) sz, q));
if (q == 0)
RE_error_trap(MEMORY_FAILURE);
return p;
return q;
}
#ifdef NO_LEAKS
void
RE_free(PTR p)
{
TRACE(("RE_free(%p)\n", p));
free(p);
}
#endif

View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: rexp2.c,v 1.18 2010/05/07 22:08:36 tom Exp $
* $MawkId: rexp2.c,v 1.19 2010/07/21 23:05:59 tom Exp $
* @Log: rexp2.c,v @
* Revision 1.3 1993/07/24 17:55:12 mike
* more cleanup
@ -193,7 +193,7 @@ slow_push(
stackp->m = (mx); \
stackp->s = (sx); \
stackp->u = (ux); \
stackp->sp = (px) - RE_pos_stack_base; \
stackp->sp = (int) ((px) - RE_pos_stack_base); \
stackp->tp = (px)->prev_offset; \
} while(0)
#endif
@ -263,7 +263,7 @@ REtest(char *str, /* string to test */
goto reswitch;
case M_STR + U_ON + END_ON:
t = (str_end - s) - m->s_len;
t = (int) (str_end - s) - m->s_len;
if (t < 0 || memcmp(s + t, m->s_data.str, (size_t) m->s_len))
goto refill;
s = str_end;

View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: rexp3.c,v 1.25 2010/05/07 22:09:39 tom Exp $
* $MawkId: rexp3.c,v 1.26 2010/07/21 23:06:24 tom Exp $
* @Log: rexp3.c,v @
* Revision 1.3 1993/07/24 17:55:15 mike
* more cleanup
@ -54,7 +54,7 @@ the GNU General Public License, version 2, 1991.
stackp = RE_new_run_stack() ;\
stackp->m = (mx); \
stackp->s = (sx); \
stackp->sp = (px) - RE_pos_stack_base; \
stackp->sp = (int) ((px) - RE_pos_stack_base); \
stackp->tp = (px)->prev_offset; \
stackp->ss = (ssx); \
stackp->u = (ux); \

32
scan.c
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: scan.c,v 1.22 2010/06/25 22:34:36 tom Exp $
* $MawkId: scan.c,v 1.29 2010/08/01 20:12:39 tom Exp $
* @Log: scan.c,v @
* Revision 1.8 1996/07/28 21:47:05 mike
* gnuish patch
@ -76,6 +76,9 @@ the GNU General Public License, version 2, 1991.
#include "files.h"
double double_zero = 0.0;
double double_one = 1.0;
/* static functions */
static void scan_fillbuff(void);
static void scan_open(void);
@ -146,7 +149,7 @@ scan_cleanup(void)
{
if (program_fd >= 0)
zfree(buffer, (size_t) (BUFFSZ + 1));
else
if (program_string)
free_STRING(program_string);
if (program_fd > 0)
@ -314,6 +317,10 @@ yylex(void)
token_lineno = lineno;
#ifdef NO_LEAKS
memset(&yylval, 0, sizeof(yylval));
#endif
reswitch:
switch (scan_code[c = next()]) {
@ -448,7 +455,7 @@ yylex(void)
ct_ret(RBOX);
case SC_MATCH:
string_buff[0] = '~';
string_buff[1] = '~';
string_buff[0] = 0;
yylval.ival = 1;
ct_ret(MATCH);
@ -568,8 +575,6 @@ yylex(void)
{
double d;
int flag;
static double double_zero = 0.0;
static double double_one = 1.0;
if ((d = collect_decimal(c, &flag)) == 0.0) {
if (flag)
@ -644,6 +649,7 @@ yylex(void)
zmalloc(sizeof(FBLOCK));
stp->stval.fbp->name = stp->name;
stp->stval.fbp->code = (INST *) 0;
stp->stval.fbp->size = 0;
yylval.fbp = stp->stval.fbp;
current_token = FUNCT_ID;
} else {
@ -960,7 +966,7 @@ collect_string(void)
case 0: /* unterminated string */
compile_error(
"runaway string constant \"%.10s ...",
string_buff, token_lineno);
string_buff);
mawk_exit(2);
case SC_ESCAPE:
@ -1066,7 +1072,7 @@ collect_RE(void)
case 0: /* unterminated re */
compile_error(
"runaway regular expression /%.10s ...",
string_buff, token_lineno);
string_buff);
mawk_exit(2);
case SC_ESCAPE:
@ -1098,3 +1104,15 @@ collect_RE(void)
free_STRING(sval);
return RE;
}
#ifdef NO_LEAKS
void
scan_leaks(void)
{
TRACE(("scan_leaks\n"));
if (yylval.ptr) {
free(yylval.ptr);
yylval.ptr = 0;
}
}
#endif

9
scan.h
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: scan.h,v 1.3 2009/12/13 19:43:23 Jonathan.Nieder Exp $
* $MawkId: scan.h,v 1.4 2010/07/30 22:18:26 tom Exp $
* @Log: scan.h,v @
* Revision 1.3 1995/06/18 19:42:26 mike
* Remove some redundant declarations and add some prototypes
@ -37,10 +37,13 @@ the GNU General Public License, version 2, 1991.
#include "symtype.h"
#include "parse.h"
void eat_nl(void);
extern double double_zero;
extern double double_one;
extern void eat_nl(void);
/* in error.c */
void unexpected_char(void);
extern void unexpected_char(void);
#define ct_ret(x) return current_token = (x)

View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: symtype.h,v 1.7 2010/05/07 08:18:41 tom Exp $
* $MawkId: symtype.h,v 1.11 2010/08/02 09:16:19 tom Exp $
* @Log: symtype.h,v @
* Revision 1.6 1996/02/01 04:39:43 mike
* dynamic array scheme
@ -80,7 +80,7 @@ typedef struct al_state {
ANODE *ptr;
} ALOOP_STATE;
int inc_aloop_state(ALOOP_STATE *);
extern int inc_aloop_state(ALOOP_STATE *);
#endif
/* for parsing (i,j) in A */
@ -96,12 +96,13 @@ typedef struct {
typedef struct fblock {
const char *name;
INST *code;
size_t size;
unsigned short nargs;
char *typev; /* array of size nargs holding types */
} FBLOCK; /* function block */
void add_to_fdump_list(FBLOCK *);
void fdump(void);
extern void add_to_fdump_list(FBLOCK *);
extern void fdump(void);
/*-------------------------
elements of the symbol table
@ -171,21 +172,27 @@ typedef struct fcall {
extern FCALL_REC *resolve_list;
void resolve_fcalls(void);
void check_fcall(FBLOCK *callee, int call_scope, int move_level,
FBLOCK *call, CA_REC *arg_list);
void relocate_resolve_list(int, int, FBLOCK *, int, unsigned, int);
extern void resolve_fcalls(void);
extern void check_fcall(FBLOCK * callee, int call_scope, int move_level,
FBLOCK * call, CA_REC * arg_list);
extern void relocate_resolve_list(int, int, FBLOCK *, int, unsigned, int);
/* hash.c */
unsigned hash(const char *);
unsigned hash2(const char *, size_t);
SYMTAB *insert(const char *);
SYMTAB *find(const char *);
const char *reverse_find(int, PTR);
SYMTAB *save_id(const char *);
void restore_ids(void);
extern unsigned hash(const char *);
extern unsigned hash2(const char *, size_t);
extern SYMTAB *insert(const char *);
extern SYMTAB *find(const char *);
extern const char *reverse_find(int, PTR);
extern SYMTAB *save_id(const char *);
extern void restore_ids(void);
/* error.c */
void type_error(SYMTAB *);
extern void type_error(SYMTAB *);
#ifdef NO_LEAKS
extern void no_leaks_array(ARRAY);
#else
#define no_leaks_array(a) /* nothing */
#endif
#endif /* SYMTYPE_H */

31
types.h
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: types.h,v 1.7 2010/05/07 00:52:42 tom Exp $
* $MawkId: types.h,v 1.8 2010/07/28 01:04:09 tom Exp $
* @Log: types.h,v @
* Revision 1.3 1993/07/15 23:56:18 mike
* general cleanup
@ -33,22 +33,19 @@ the GNU General Public License, version 2, 1991.
/* CELL types */
#define C_NOINIT 0
#define C_DOUBLE 1
#define C_STRING 2
#define C_STRNUM 3
#define C_MBSTRN 4
/*could be STRNUM, has not been checked */
#define C_RE 5
#define C_SPACE 6
/* split on space */
#define C_SNULL 7
/* split on the empty string */
#define C_REPL 8
/* a replacement string '\&' changed to & */
#define C_REPLV 9
/* a vector replacement -- broken on & */
#define NUM_CELL_TYPES 10
typedef enum {
C_NOINIT
,C_DOUBLE
,C_STRING
,C_STRNUM
,C_MBSTRN /*could be STRNUM, has not been checked */
,C_RE
,C_SPACE /* split on space */
,C_SNULL /* split on the empty string */
,C_REPL /* a replacement string '\&' changed to & */
,C_REPLV /* a vector replacement -- broken on & */
,NUM_CELL_TYPES
} MAWK_CELL_TYPES;
/* these defines are used to check types for two
CELLs which are adjacent in memory */

View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: version.c,v 1.9 2010/06/21 21:44:34 tom Exp $
* $MawkId: version.c,v 1.10 2010/07/31 01:05:40 tom Exp $
*
* @Log: version.c,v @
* Revision 1.10 1996/07/28 21:47:07 mike
@ -147,5 +147,5 @@ print_version(void)
fprintf(stderr, fmt, "max NF", (long) MAX_FIELD);
fprintf(stderr, fmt, "sprintf buffer", (long) SPRINTF_SZ);
print_aux_limits();
exit(0);
mawk_exit(0);
}

191
zmalloc.c
View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: zmalloc.c,v 1.12 2010/05/07 22:11:34 tom Exp $
* $MawkId: zmalloc.c,v 1.21 2010/07/30 09:23:48 tom Exp $
* @Log: zmalloc.c,v @
* Revision 1.6 1995/06/06 00:18:35 mike
* change mawk_exit(1) to mawk_exit(2)
@ -49,6 +49,16 @@ the GNU General Public License, version 2, 1991.
#include "mawk.h"
#include "zmalloc.h"
#ifdef NO_LEAKS
#if defined(HAVE_TDESTROY) && defined(HAVE_TSEARCH)
#define USE_TSEARCH 1
#endif
#endif
#ifdef USE_TSEARCH
#include <search.h>
#endif
#define ZSHIFT 3
#define ZBLOCKSZ BlocksToBytes(1)
@ -72,14 +82,145 @@ the GNU General Public License, version 2, 1991.
#define CHUNK 256
/* number of blocks to get from malloc */
/*****************************************************************************/
/*
* zmalloc() implements a scheme which makes it hard to use memory-checking
* tools such as valgrind to audit the program to find where there are leaks.
* That is due to its maintaining (for speed...) pools of memory chunks.
*
* Define DEBUG_ZMALLOC to build mawk with a simpler interface to the system
* malloc, which verifies whether the size-parameter passed to zfree() is
* consistent with the zmalloc() parameter.
*/
/* #define DEBUG_ZMALLOC 1 */
#ifdef DEBUG_ZMALLOC
#define IsPoolable(blocks) ((blocks) == 0)
#define Malloc(n) calloc(1,n)
#else
#define IsPoolable(blocks) ((blocks) <= POOLSZ)
#define Malloc(n) malloc(n)
#endif
#ifdef USE_TSEARCH
typedef struct {
PTR ptr;
size_t size;
} PTR_DATA;
static void *ptr_data;
#if 0
static void
show_tsearch(const void *nodep, const VISIT which, const int depth)
{
const PTR_DATA *p = *(PTR_DATA * const *) nodep;
if (which == postorder || which == leaf) {
TRACE(("show_data %d:%p ->%p %lu\n", depth, p, p->ptr, p->size));
}
}
static void
show_ptr_data(void)
{
twalk(ptr_data, show_tsearch);
}
#define ShowPtrData() show_ptr_data()
#else
#define ShowPtrData() /* nothing */
#endif
static void
free_ptr_data(void *a)
{
TRACE(("free_ptr_data %p\n", a));
free(a);
}
static int
compare_ptr_data(const void *a, const void *b)
{
const PTR_DATA *p = (const PTR_DATA *) a;
const PTR_DATA *q = (const PTR_DATA *) b;
int result;
TRACE2(("compare %p->%p %p->%p\n", p, p->ptr, q, q->ptr));
if (p->ptr > q->ptr) {
result = 1;
} else if (p->ptr < q->ptr) {
result = -1;
} else {
result = 0;
}
return result;
}
static void
record_ptr(PTR ptr, size_t size)
{
PTR_DATA *item;
PTR_DATA **result;
item = malloc(sizeof(PTR_DATA));
item->ptr = ptr;
item->size = size;
TRACE(("record_ptr %p -> %p %lu\n", item, ptr, (unsigned long) size));
result = tsearch(item, &ptr_data, compare_ptr_data);
assert(result != 0);
assert(*result != 0);
TRACE2(("->%p (%p %lu)\n",
(*result), (*result)->ptr,
(unsigned long) (*result)->size));
ShowPtrData();
}
static void
finish_ptr(PTR ptr, size_t size)
{
PTR_DATA dummy;
PTR_DATA **item;
dummy.ptr = ptr;
dummy.size = size;
TRACE2(("finish_ptr (%p) -> %p %lu\n", &dummy, ptr, (unsigned long) size));
item = tfind(&dummy, &ptr_data, compare_ptr_data);
assert(item != 0);
assert(*item != 0);
TRACE(("finish_ptr %p -> %p %lu\n",
(*item),
(*item)->ptr,
(unsigned long) (*item)->size));
tdelete(item, &ptr_data, compare_ptr_data);
ShowPtrData();
}
#define FinishPtr(ptr,size) finish_ptr(ptr,size)
#define RecordPtr(ptr,size) record_ptr(ptr,size)
#else
#define FinishPtr(ptr,size) /* nothing */
#define RecordPtr(ptr,size) /* nothing */
#endif
/*****************************************************************************/
static void
out_of_mem(void)
{
static char out[] = "out of memory";
if (mawk_state == EXECUTION)
if (mawk_state == EXECUTION) {
rt_error(out);
else {
} else {
/* I don't think this will ever happen */
compile_error(out);
mawk_exit(2);
@ -103,17 +244,19 @@ PTR
zmalloc(size_t size)
{
unsigned blocks = BytesToBlocks(size);
size_t bytes = (size_t) BlocksToBytes(blocks);
register ZBLOCK *p;
static unsigned amt_avail;
static ZBLOCK *avail;
if (blocks > POOLSZ) {
p = (ZBLOCK *) malloc((size_t) BlocksToBytes(blocks));
if (!IsPoolable(blocks)) {
p = (ZBLOCK *) Malloc(bytes);
if (!p)
out_of_mem();
RecordPtr(p, size);
} else {
if ((p = pool[blocks - 1])) {
if ((p = pool[blocks - 1]) != 0) {
pool[blocks - 1] = p->link;
} else {
@ -124,15 +267,18 @@ zmalloc(size_t size)
pool[amt_avail] = avail;
}
if (!(avail = (ZBLOCK *) malloc((size_t) (CHUNK * ZBLOCKSZ)))) {
if (!(avail = (ZBLOCK *) Malloc((size_t) (CHUNK * ZBLOCKSZ)))) {
/* if we get here, almost out of memory */
amt_avail = 0;
p = (ZBLOCK *) malloc((size_t) BlocksToBytes(blocks));
p = (ZBLOCK *) Malloc(bytes);
if (!p)
out_of_mem();
RecordPtr(p, bytes);
return (PTR) p;
} else
} else {
RecordPtr(avail, CHUNK * ZBLOCKSZ);
amt_avail = CHUNK;
}
}
/* get p from the avail pile */
@ -149,9 +295,10 @@ zfree(PTR p, size_t size)
{
unsigned blocks = BytesToBlocks(size);
if (blocks > POOLSZ)
if (!IsPoolable(blocks)) {
free(p);
else {
FinishPtr(p, size);
} else {
((ZBLOCK *) p)->link = pool[--blocks];
pool[blocks] = (ZBLOCK *) p;
}
@ -162,10 +309,19 @@ zrealloc(PTR p, size_t old_size, size_t new_size)
{
register PTR q;
TRACE(("zrealloc %p %lu ->%lu\n", p, old_size, new_size));
if (new_size > (BlocksToBytes(POOLSZ)) &&
old_size > (BlocksToBytes(POOLSZ))) {
if (!(q = realloc(p, new_size)))
if (!(q = realloc(p, new_size))) {
out_of_mem();
}
FinishPtr(p, old_size);
RecordPtr(q, new_size);
#ifdef DEBUG_ZMALLOC
if (new_size > old_size) {
memset((char *) q + old_size, 0, new_size - old_size);
}
#endif
} else {
q = zmalloc(new_size);
memcpy(q, p, old_size < new_size ? old_size : new_size);
@ -173,3 +329,14 @@ zrealloc(PTR p, size_t old_size, size_t new_size)
}
return q;
}
#ifdef NO_LEAKS
void
zmalloc_leaks(void)
{
#ifdef USE_TSEARCH
TRACE(("zmalloc_leaks\n"));
tdestroy(ptr_data, free_ptr_data);
#endif
}
#endif

View File

@ -10,7 +10,7 @@ the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: zmalloc.h,v 1.4 2010/05/07 00:39:08 tom Exp $
* $MawkId: zmalloc.h,v 1.6 2010/07/24 14:32:48 tom Exp $
* @Log: zmalloc.h,v @
* Revision 1.2 1993/07/04 12:52:22 mike
* start on autoconfig changes
@ -30,12 +30,11 @@ the GNU General Public License, version 2, 1991.
#include "nstd.h"
PTR zmalloc(size_t);
void zfree(PTR, size_t);
PTR zrealloc(PTR, size_t, size_t);
extern PTR zmalloc(size_t);
extern void zfree(PTR, size_t);
extern PTR zrealloc(PTR, size_t, size_t);
#define ZMALLOC(type) ((type*)zmalloc(sizeof(type)))
#define ZFREE(p) zfree(p,sizeof(*(p)))
#endif /* ZMALLOC_H */
#endif /* ZMALLOC_H */