mirror of
https://github.com/ThomasDickey/mawk-snapshots.git
synced 2026-01-26 19:09:15 +00:00
snapshot of project "mawk", label t20100805
This commit is contained in:
parent
01f53d3829
commit
d7c50b5507
16
CHANGES
16
CHANGES
@ -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.
|
||||
|
||||
2
MANIFEST
2
MANIFEST
@ -1,4 +1,4 @@
|
||||
MANIFEST for mawk, version t20100625
|
||||
MANIFEST for mawk, version t20100805
|
||||
--------------------------------------------------------------------------------
|
||||
MANIFEST this file
|
||||
ACKNOWLEDGMENT acknowledgements
|
||||
|
||||
20
aclocal.m4
vendored
20
aclocal.m4
vendored
@ -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 ---------------------------------------------------------------------------
|
||||
|
||||
1
array.c
1
array.c
@ -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) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
416
bi_funct.c
416
bi_funct.c
@ -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));
|
||||
|
||||
18
bi_vars.c
18
bi_vars.c
@ -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
211
code.c
@ -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
182
code.h
@ -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 */
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
90
da.c
@ -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
35
error.c
@ -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
|
||||
|
||||
45
execute.c
45
execute.c
@ -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
43
field.c
@ -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
52
field.h
@ -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
72
files.c
@ -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
32
files.h
@ -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
21
fin.c
@ -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
50
hash.c
@ -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
35
init.c
@ -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
18
main.c
@ -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);
|
||||
|
||||
20
man/mawk.1
20
man/mawk.1
@ -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
122
mawk.h
@ -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 */
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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/
|
||||
|
||||
@ -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
74
parse.c
@ -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)
|
||||
{
|
||||
|
||||
6
parse.y
6
parse.y
@ -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 :
|
||||
|
||||
@ -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"
|
||||
|
||||
36
re_cmpl.c
36
re_cmpl.c
@ -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) {
|
||||
|
||||
30
regexp.c
30
regexp.c
@ -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
|
||||
|
||||
3
regexp.h
3
regexp.h
@ -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 *);
|
||||
|
||||
@ -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
5
repl.h
@ -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
30
rexp.c
@ -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
50
rexp.h
@ -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
15
rexp0.c
@ -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
37
rexp1.c
@ -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
|
||||
|
||||
6
rexp2.c
6
rexp2.c
@ -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;
|
||||
|
||||
4
rexp3.c
4
rexp3.c
@ -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
32
scan.c
@ -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
9
scan.h
@ -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)
|
||||
|
||||
|
||||
39
symtype.h
39
symtype.h
@ -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
31
types.h
@ -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 */
|
||||
|
||||
@ -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
191
zmalloc.c
@ -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
|
||||
|
||||
11
zmalloc.h
11
zmalloc.h
@ -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 */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user