1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

libast: Update cdt(3): Allow empty strings in (dt)trees

This backports most of the Cdt (container data types) mechanism
from the ksh 93v- beta, based on ground work done by OpenSUSE:
https://build.opensuse.org/package/view_file/shells/ksh/ksh93-dttree-crash.dif
plus adaptations to match ksh 93u+m and an updated manual page
(src/lib/libast/man/cdt.3) added directly from the 93v- sources.

| Thu Dec 20 12:48:02 UTC 2012 - werner@suse.de
|
| - Add ksh93-dttree-crash.dif - Allow empty strings in (dt)trees
|   (bnc#795324)
|
| Fri Oct 25 14:07:57 UTC 2013 - werner@suse.de
|
| - Rework patch ksh93-dttree-crash.dif

As usual, precious little information is available because the
OpenSUSE bug report is currently closed to the public:
https://bugzilla.opensuse.org/show_bug.cgi?id=795324

However, a cursory inspection suggests that this code contains
improvements to do with concurrent processing and related
robustness. The new cdt.3 manual page adds a lot about that.

This has been in production use on OpenSUSE for a long time,
so hopefully this will make ksh a little more stable again.
Only one way to find out: let's commit and test this...

BTW, to get a nice manual, use groff and ghostscript's ps2pdf:
$ groff -tman src/lib/libast/man/cdt.3 | ps2pdf - cdt.3.pdf
This commit is contained in:
Martijn Dekker 2021-01-28 02:29:55 +00:00
parent aa2644ab84
commit cc4927529b
21 changed files with 708 additions and 210 deletions

View file

@ -52,11 +52,13 @@ static int htable(Dt_t* dt)
if((n = hash->tblz) > 0 && (hash->type&H_FIXED) )
return 0; /* fixed size table */
if(n == 0 && disc && disc->eventf) /* let user have input */
if(disc && disc->eventf) /* let user have input */
{ if((*disc->eventf)(dt, DT_HASHSIZE, &n, disc) > 0 )
{ if(n < 0) /* fix table size */
{ hash->type |= H_FIXED;
n = -n;
n = -n; /* desired table size */
if(hash->tblz >= n ) /* table size is fixed now */
return 0;
}
}
}
@ -234,12 +236,13 @@ static Void_t* hstat(Dt_t* dt, Dtstat_t* st)
for(endt = (t = hash->htbl) + hash->tblz; t < endt; ++t)
{ for(n = 0, l = *t; l; l = l->_rght)
{ if(n < DT_MAXSIZE)
st->lsize[n] += 1;
n += 1;
}
st->mlev = n > st->mlev ? n : st->mlev;
if(n < DT_MAXSIZE) /* if chain length is small */
{ st->msize = n > st->msize ? n : st->msize;
st->lsize[n] += n;
}
st->msize = n > st->msize ? n : st->msize;
}
}
@ -310,7 +313,7 @@ int type;
hsh = _DTHSH(dt,key,disc);
tbl = hash->htbl + (hsh & (hash->tblz-1));
pp = ll = NIL(Dtlink_t*);
pp = ll = NIL(Dtlink_t*); /* pp is the before, ll is the here */
for(p = NIL(Dtlink_t*), l = *tbl; l; p = l, l = l->_rght)
{ if(hsh == l->_hash)
{ o = _DTOBJ(disc,l); k = _DTKEY(disc,o);
@ -342,20 +345,41 @@ int type;
_dtfree(dt, ll, type);
DTRETURN(obj, _DTOBJ(disc,ll));
}
else if(type & DT_INSTALL )
{ if(dt->meth->type&DT_BAG)
goto do_insert;
else if(!(lnk = _dtmake(dt, obj, type)) )
DTRETURN(obj, NIL(Void_t*) );
else /* replace old object with new one */
{ if(pp) /* remove old object */
pp->_rght = ll->_rght;
else *tbl = ll->_rght;
o = _DTOBJ(disc,ll);
_dtfree(dt, ll, DT_DELETE);
DTANNOUNCE(dt, o, DT_DELETE);
goto do_insert;
}
}
else
{ /**/DEBUG_ASSERT(type&(DT_INSERT|DT_ATTACH|DT_APPEND|DT_RELINK));
if(!(dt->meth->type&DT_BAG) )
if((dt->meth->type&DT_BAG) )
goto do_insert;
else
{ if(type&(DT_INSERT|DT_APPEND|DT_ATTACH) )
type |= DT_SEARCH; /* for announcement */
type |= DT_MATCH; /* for announcement */
else if(lnk && (type&DT_RELINK) )
{ /* remove a duplicate */
o = _DTOBJ(disc, lnk);
_dtfree(dt, lnk, DT_DELETE);
DTANNOUNCE(dt, o, DT_DELETE);
}
DTRETURN(obj, _DTOBJ(disc,ll));
}
else goto do_insert;
}
}
else /* no matching object */
{ if(!(type&(DT_INSERT|DT_APPEND|DT_ATTACH|DT_RELINK)) )
{ if(!(type&(DT_INSERT|DT_INSTALL|DT_APPEND|DT_ATTACH|DT_RELINK)) )
DTRETURN(obj, NIL(Void_t*));
do_insert: /* inserting a new object */