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

bump internal libast version; various minor cleanups

These are minor things I accumulated over the last month or so.

Notable changes:

src/lib/libast/features/api,
src/lib/libast/misc/state.c,
src/lib/libast/comp/conf.tab,
src/cmd/ksh93/include/defs.h:
- Bump internal libast version to 20220101L. We've made a few
  additions to the API, at least pathicase (see 71934570, ca3ec200)
  and astconf_long (see c2ac69b2), so this should have been done
  already. This also updates '/opt/ast/bin/getconf _AST_VERSION'.
- Use AST_VERSION instead of outdated _AST_VERSION.
- In state.c, use AST_VERSION instead of hardcoding the version.

src/cmd/ksh93/sh/xec.c:
- Remove 'restorefd' variable, unused as of 42becab6.
- Remove 'cmdrecurse' function and SH_RUNPROG macro; this was once
  used by a few libcmd commands, but ast-open-archive reveals it's
  unused as of ast 1999-12-25.

src/cmd/ksh93/sh/*.c:
- Where available, use e_dot instead of "." for consistency; it is
  defined as an extern so we might as well use it.

src/cmd/ksh93/tests/*.sh:
- When reporting signal names in fails, include the SIG prefix.
- Fix a broken process hang test in subshell.sh.

src/lib/libast/man/sfdisc.3:
- Removed. The interfaces described here never made it out of AT&T;
  they do not exist in any libast version in ast-open-archive.
  Resolves: https://github.com/ksh93/ksh/issues/426
This commit is contained in:
Martijn Dekker 2022-01-14 16:56:41 +00:00
parent 07fc64f52b
commit e569f23ef9
25 changed files with 58 additions and 300 deletions

View file

@ -2344,7 +2344,7 @@ ____
the original trap wasn't executed.
01-11-26 +The value for 0 is now preceded by the base number when
the base was not 10.
01-11-26 +The default has compilation mode has been changes so that
01-11-26 +The default compilation mode has been changed so that
viraw mode will always be on.
01-10-31 --- Release ksh93m ---

View file

@ -2,7 +2,7 @@
* *
* This software is part of the ast package *
* Copyright (c) 1982-2012 AT&T Intellectual Property *
* Copyright (c) 2020-2021 Contributors to ksh 93u+m *
* Copyright (c) 2020-2022 Contributors to ksh 93u+m *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
@ -326,7 +326,7 @@ int ed_expand(Edit_t *ep, char outbuff[],int *cur,int *eol,int mode, int count)
sh_onoption(SH_MARKDIRS);
{
register char **com;
char *cp=begin, *left=0, *saveout=".";
char *cp=begin, *left=0, *saveout=(char*)e_dot;
int nocase=0,narg,cmd_completion=0;
register int size='x';
while(cp>outbuff && ((size=cp[-1])==' ' || size=='\t'))

View file

@ -2,7 +2,7 @@
* *
* This software is part of the ast package *
* Copyright (c) 1982-2012 AT&T Intellectual Property *
* Copyright (c) 2020-2021 Contributors to ksh 93u+m *
* Copyright (c) 2020-2022 Contributors to ksh 93u+m *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
@ -430,7 +430,7 @@ static History_t* hist_trim(History_t *hp, int n)
*last = '/';
}
else
pathtmp(tmpname,".","hist",NIL(int*));
pathtmp(tmpname,e_dot,"hist",NIL(int*));
if(rename(name,tmpname) < 0)
{
free(tmpname);

View file

@ -29,8 +29,8 @@
#define defs_h_defined
#include <ast.h>
#if !defined(AST_VERSION) || AST_VERSION < 20111111L
#error libast version 20111111 or later is required
#if !defined(AST_VERSION) || AST_VERSION < 20220101
#error libast version 20220101 or later is required
#endif
#if !_lib_fork
#error In 2021, ksh joined the 21st century and started requiring fork(2).

View file

@ -2,7 +2,7 @@
* *
* This software is part of the ast package *
* Copyright (c) 1982-2012 AT&T Intellectual Property *
* Copyright (c) 2020-2021 Contributors to ksh 93u+m *
* Copyright (c) 2020-2022 Contributors to ksh 93u+m *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
@ -469,8 +469,7 @@ extern int sh_waitsafe(void);
extern int sh_exec(const Shnode_t*,int);
/*
* As of 93u+m, direct access to sh is no longer obsolete, and
* shgd ("global data") is no longer a separately allocated struct;
* As of 93u+m, direct access to sh is no longer obsolete;
* sh_getinterp() is here for compatibility with the documented interface.
*/
extern Shell_t sh;
@ -504,6 +503,5 @@ extern Shell_t sh;
#define SH_SIGSET 4
#define SH_EXITSIG 0400 /* signal exit bit */
#define SH_EXITMASK (SH_EXITSIG-1) /* normal exit status bits */
#define SH_RUNPROG -1022 /* needs to be negative and < 256 */
#endif /* !shell_h_defined */

View file

@ -319,7 +319,7 @@ static char *dotpaths_lib(Pathcomp_t *pp, char *path)
if(last)
*last = 0;
else
path = ".";
path = (char*)e_dot;
r = stat(path,&statb);
if(last)
*last = '/';
@ -1671,7 +1671,7 @@ Pathcomp_t *path_addpath(Pathcomp_t *first, register const char *path,int type)
if(*cp==':')
{
if(type!=PATH_FPATH)
first = path_addcomp(first,old,".",type);
first = path_addcomp(first,old,e_dot,type);
while(*++path == ':');
}
else

View file

@ -2,7 +2,7 @@
* *
* This software is part of the ast package *
* Copyright (c) 1982-2012 AT&T Intellectual Property *
* Copyright (c) 2020-2021 Contributors to ksh 93u+m *
* Copyright (c) 2020-2022 Contributors to ksh 93u+m *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
@ -71,7 +71,6 @@ static void coproc_init(int pipes[]);
static void *timeout;
static char nlock;
static char pipejob;
static int restorefd;
struct funenv
{
@ -1325,7 +1324,7 @@ int sh_exec(register const Shnode_t *t, int flags)
if(!sh.pwd)
path_pwd();
if(sh.pwd)
stat(".",&statb);
stat(e_dot,&statb);
sfsync(NULL);
share = sfset(sfstdin,SF_SHARE,0);
sh_onstate(SH_STOPOK);
@ -1371,7 +1370,7 @@ int sh_exec(register const Shnode_t *t, int flags)
bp->data = (void*)save_data;
if(sh.exitval && errno==EINTR && sh.lastsig)
sh.exitval = SH_EXITSIG|sh.lastsig;
else if(!nv_isattr(np,BLT_EXIT) && sh.exitval!=SH_RUNPROG)
else if(!nv_isattr(np,BLT_EXIT))
sh.exitval &= SH_EXITMASK;
}
else
@ -1410,7 +1409,7 @@ int sh_exec(register const Shnode_t *t, int flags)
if(sh.pwd)
{
struct stat stata;
stat(".",&stata);
stat(e_dot,&stata);
/* restore directory changed */
if(statb.st_ino!=stata.st_ino || statb.st_dev!=stata.st_dev)
chdir(sh.pwd);
@ -1614,7 +1613,6 @@ int sh_exec(register const Shnode_t *t, int flags)
}
#endif /* SHOPT_BGX */
nv_getval(RANDNOD);
restorefd = sh.topfd;
if(type&FCOOP)
{
pipes[2] = 0;
@ -3409,20 +3407,6 @@ int sh_fun(Namval_t *np, Namval_t *nq, char *argv[])
return(sh.exitval);
}
/*
* This dummy routine is called by built-ins that do recursion
* on the file system (chmod, chgrp, chown). It causes
* the shell to invoke the non-builtin version in this case
*/
int cmdrecurse(int argc, char* argv[], int ac, char* av[])
{
NOT_USED(argc);
NOT_USED(argv[0]);
NOT_USED(ac);
NOT_USED(av[0]);
return(SH_RUNPROG);
}
/*
* set up pipe for cooperating process
*/

View file

@ -693,7 +693,7 @@ got=$(set +x; { "$SHELL" -c '
echo baz # 7
'; } 2>&1)
((!(e = $?))) && [[ $got == "$exp" ]] || err_exit 'Redirection in DEBUG trap corrupts the trap' \
"(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))"
"(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))"
# The DEBUG trap crashed when re-trapping inside a subshell
exp=$'trap -- \': main\' EXIT\ntrap -- \': main\' ERR\ntrap -- \': main\' KEYBD\ntrap -- \': main\' DEBUG'
@ -707,7 +707,7 @@ got=$(set +x; { "$SHELL" -c '
done
'; } 2>&1)
((!(e = $?))) && [[ $got == "$exp" ]] || err_exit 'Pseudosignal trap failed when re-trapping in subshell' \
"(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))"
"(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))"
# Field splitting broke upon evaluating an unquoted expansion in a DEBUG trap
exp=$'a\nb\nc'
@ -720,7 +720,7 @@ got=$(set +x; { "$SHELL" -c '
printf "%s\n" "$@"
'; } 2>&1)
((!(e = $?))) && [[ $got == "$exp" ]] || err_exit 'Field splitting broke after executing DEBUG trap' \
"(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))"
"(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))"
# The DEBUG trap had side effects on the exit status
trap ':' DEBUG

View file

@ -1162,7 +1162,7 @@ then got=$( { "$SHELL" -c '
done
'; } 2>&1)
((!(e = $?))) || err_exit 'crash with alarm and IFS' \
"(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))"
"(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))"
fi
# ======

View file

@ -1340,7 +1340,7 @@ cat >$tmp/crash_rhbz1117404.ksh <<-'EOF'
EOF
got=$( { "$SHELL" "$tmp/crash_rhbz1117404.ksh"; } 2>&1)
((!(e = $?))) || err_exit 'crash while handling function-local trap' \
"(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))"
"(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))"
# ======
exit $((Errors<125?Errors:125))

View file

@ -714,7 +714,7 @@ got=$(command -x cat <(command -x echo foo) 2>&1) || err_exit "process substitut
exit
' empty_redir_crash_test "$tmp"
((!(e = $?))) || err_exit 'crash on null-command redirection with DEBUG trap' \
"(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))"
"(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))"
# ======
# stdout was misdirected if an EXIT/ERR trap handler was defined in a -c script

View file

@ -477,7 +477,7 @@ e=$?
trap - TERM INT
[[ $sleep_pid ]] && kill $sleep_pid
((!e)) && [[ $(<$ofile) == ok ]] || err_exit "PATH containing .paths directory:" \
"got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$(<$ofile)")"
"got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$(<$ofile)")"
# ======
# Check that 'command -p' and 'command -p -v' do not use the hash table (a.k.a. tracked aliases).
@ -560,7 +560,7 @@ trap - TERM INT
if [[ ${ kill -l "$e"; } == KILL ]]
then warning "'command -x' test killed, probably due to lack of memory; skipping test"
else if let "e > 0"
then err_exit "'command -x' test yielded exit status $e$( let "e>128" && print -n / && kill -l "$e")"
then err_exit "'command -x' test yielded exit status $e$( let "e>128" && print -n /SIG && kill -l "$e")"
fi
if [[ ! -s $ofile ]]
then err_exit "'command -x' test failed to produce output"
@ -698,7 +698,7 @@ e=$?
trap - TERM INT
[[ $sleep_pid ]] && kill $sleep_pid
((e == 127)) || err_exit "Long nonexistent command name:" \
"got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$(<$ofile)")"
"got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$(<$ofile)")"
# ======
# A function autoload recursion loop used to crash
@ -716,7 +716,7 @@ $SHELL: function, built-in or type definition for self2 not found in $tmp/fun.$$
$SHELL: function, built-in or type definition for self not found in $tmp/fun.$$/self"
got=$({ FPATH=$tmp/fun.$$ "$SHELL" -c self; } 2>&1)
(((e = $?) == 126)) || err_exit 'Function autoload recursion loop:' \
"got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got")"
"got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got")"
# ======
# If a shared-state ${ command substitution; } changed the value of $PATH, the variable

View file

@ -496,7 +496,7 @@ got=$(export sig; "$SHELL" -c '
trap - "$sig"
' 2>&1)
((!(e = $?))) && [[ $got == "$exp" ]] || err_exit "failed to handle SIG$sig from subshell" \
"(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))"
"(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))"
got=$(export sig; "$SHELL" -c '
function tryTrap
@ -508,7 +508,7 @@ got=$(export sig; "$SHELL" -c '
trap - "$sig"
' 2>&1)
((!(e = $?))) && [[ $got == "$exp" ]] || err_exit "failed to handle SIG$sig from ksh function" \
"(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))"
"(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))"
# ======
# ksh-style functions didn't handle signals other than SIGINT and SIGQUIT (rhbz#1454804)
@ -526,7 +526,7 @@ got=$(export exp; "$SHELL" -c '
' 2>&1)
got=${got% } # rm final space
((!(e = $?))) && [[ $got == "$exp" ]] || err_exit "ksh function ignores global signal traps" \
"(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))"
"(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))"
# ======
# Signal incorrectly issued when function returns with status > 256 and EXIT trap is active

View file

@ -551,11 +551,16 @@ $SHELL <<- \EOF
print -u2 done
}
out=$(eval "foo | cat" 2>&1)
(( ${#out} == 96011 )) || err_exit "\${#out} is ${#out} should be 96011"
print "${#out}" >out
EOF
} & pid=$!
$SHELL -c "{ sleep .4 && kill $pid ;}" 2> /dev/null
(( $? == 0 )) && err_exit 'process has hung'
(sleep 4; kill -s KILL "$pid" 2>/dev/null) & # another bg job to kill frozen test job
{ wait "$pid"; } 2>/dev/null # get job's exit status, suppressing signal messages
if ((!(e = $?)))
then [[ $(<out) == '96011' ]] || err_exit "\${#out} is $(printf %q "$(<out)"), should be 96011"
else err_exit "process has hung (got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"))"
fi
kill "$!" 2>/dev/null # kill sleep process
{
x=$( $SHELL <<- \EOF
@ -848,7 +853,7 @@ test_pid=$!
(sleep 10; kill -s KILL "$test_pid" 2>/dev/null) & # another bg job to kill frozen test job
sleep_pid=$!
{ wait "$test_pid"; } 2>/dev/null # get job's exit status, suppressing signal messages
((!(e = $?))) || err_exit "backtick comsub crash/freeze (got status $e$( ((e>128)) && print -n / && kill -l "$e"))"
((!(e = $?))) || err_exit "backtick comsub crash/freeze (got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"))"
kill "$sleep_pid" 2>/dev/null
# ======
@ -858,7 +863,7 @@ test_pid=$!
(sleep 2; kill -s KILL "$test_pid" 2>/dev/null) &
sleep_pid=$!
{ wait "$test_pid"; } 2>/dev/null
((!(e = $?))) || err_exit "backtick comsub hang (got status $e$( ((e>128)) && print -n / && kill -l "$e"))"
((!(e = $?))) || err_exit "backtick comsub hang (got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"))"
kill "$sleep_pid" 2>/dev/null
# Backtick command substitution with pipe hangs when filling out pipe buffer (rhbz#1138751)
@ -867,7 +872,7 @@ test_pid=$!
(sleep 2; kill -s KILL "$test_pid" 2>/dev/null) &
sleep_pid=$!
{ wait "$test_pid"; } 2>/dev/null
((!(e = $?))) || err_exit "backtick comsub with pipe hangs (got status $e$( ((e>128)) && print -n / && kill -l "$e"))"
((!(e = $?))) || err_exit "backtick comsub with pipe hangs (got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"))"
kill "$sleep_pid" 2>/dev/null
# ======
@ -924,7 +929,7 @@ cat >$tmp/crash_rhbz1117404.ksh <<-'EOF'
EOF
got=$( { "$SHELL" "$tmp/crash_rhbz1117404.ksh"; } 2>&1)
((!(e = $?))) || err_exit 'crash while handling subshell trap' \
"(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))"
"(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))"
# ======
# Segmentation fault when using cd in a subshell, when current directory cannot be determined
@ -941,14 +946,14 @@ got=$(set +x; { "$SHELL" -c '(subshfn() { bad; }; cd ..; echo "subPWD: $PWD"); t
exp="PWD=$PWD"
got=$(set +x; { "$SHELL" -c '(cd /; (cd /)); print -r -- "PWD=$PWD"'; } 2>&1)
((!(e = $?))) && [[ $got == "$exp" ]] || err_exit 'failed to restore nonexistent PWD on exiting a virtual subshell' \
"(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))"
"(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))"
mkdir "$tmp/recreated"
cd "$tmp/recreated"
tmp=$tmp "$SHELL" -c 'cd /; rmdir "$tmp/recreated"; mkdir "$tmp/recreated"'
exp="PWD=$PWD"
got=$(set +x; { "$SHELL" -c '(cd /); print -r -- "PWD=$PWD"'; } 2>&1)
((!(e = $?))) && [[ $got == "$exp" ]] || err_exit 'failed to restore re-created PWD on exiting a virtual subshell' \
"(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))"
"(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))"
cd "$tmp"
# ======

View file

@ -113,7 +113,7 @@ HOME=$saveHOME
if builtin .sh.tilde 2>/dev/null
then got=$(.sh.tilde & wait "$!" 2>&1)
((!(e = $?))) || err_exit ".sh.tilde builtin crashes the shell" \
"(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))"
"(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))"
fi
# ... and replaced by a proper use of discipline functions that allows customising tilde expansion.
@ -164,7 +164,7 @@ do (
if ((!(e = $?)))
then read Errors <$tmp/Errors
else err_exit ".sh.tilde.$disc discipline function crashes the shell" \
"(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$(<crashmsg)"))"
"(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$(<crashmsg)"))"
fi
done

View file

@ -1052,7 +1052,7 @@ $SHELL -c '
exit $((errors + 1)) # a possible erroneous asynchronous fork would cause exit status 0
' unset_test "$@"
(((e = $?) == 1)) || err_exit "Failure in unsetting one or more special variables" \
"(exit status $e$( ((e>128)) && print -n / && kill -l "$e"))"
"(exit status $e$( ((e>128)) && print -n /SIG && kill -l "$e"))"
# ... unset in virtual subshell inside of nested function
$SHELL -c '
@ -1082,7 +1082,7 @@ $SHELL -c '
exit $((errors + 1)) # a possible erroneous asynchronous fork would cause exit status 0
' unset_subsh_fun_test "$@"
(((e = $?) == 1)) || err_exit "Unset of special variable(s) in a virtual subshell within a nested function fails" \
"(exit status $e$( ((e>128)) && print -n / && kill -l "$e"))"
"(exit status $e$( ((e>128)) && print -n /SIG && kill -l "$e"))"
# ... readonly in subshell
$SHELL -c '
@ -1106,7 +1106,7 @@ $SHELL -c '
exit $((errors + 1)) # a possible erroneous asynchronous fork would cause exit status 0
' readonly_test "$@"
(((e = $?) == 1)) || err_exit "Failure in making one or more special variables readonly in a subshell" \
"(exit status $e$( ((e>128)) && print -n / && kill -l "$e"))"
"(exit status $e$( ((e>128)) && print -n /SIG && kill -l "$e"))"
# ... subshell leak test
$SHELL -c '
@ -1123,7 +1123,7 @@ $SHELL -c '
exit $((errors + 1))
' subshell_leak_test "$@"
(((e = $?) == 1)) || err_exit "One or more special variables leak out of a subshell" \
"(exit status $e$( ((e>128)) && print -n / && kill -l "$e"))"
"(exit status $e$( ((e>128)) && print -n /SIG && kill -l "$e"))"
# ... upper/lowercase test
$SHELL -c '
@ -1159,7 +1159,7 @@ $SHELL -c '
exit $((errors + 1))
' changecase_test "$@"
(((e = $?) == 1)) || err_exit "typeset -l/-u doesn't work on special variables" \
"(exit status $e$( ((e>128)) && print -n / && kill -l "$e"))"
"(exit status $e$( ((e>128)) && print -n /SIG && kill -l "$e"))"
# ... unset followed by launching a forked subshell
$SHELL -c '
@ -1176,7 +1176,7 @@ $SHELL -c '
exit $?
' unset_to_fork_test "$@"
(((e = $?) == 1)) || err_exit "Failure in unsetting one or more special variables followed by launching forked subshell" \
"(exit status $e$( ((e>128)) && print -n / && kill -l "$e"))"
"(exit status $e$( ((e>128)) && print -n /SIG && kill -l "$e"))"
# ======
# ${.sh.pid} should be the forked subshell's PID

View file

@ -6240,11 +6240,6 @@ make install
done man/setenviron.3
exec - test '' = 'man/setenviron.3' || ${STDCMP} 2>/dev/null -s man/setenviron.3 ${INSTALLROOT}/man/man3/setenviron.3 || { ${STDMV} ${INSTALLROOT}/man/man3/setenviron.3 ${INSTALLROOT}/man/man3/setenviron.3.old 2>/dev/null || true; ${STDCP} man/setenviron.3 ${INSTALLROOT}/man/man3/setenviron.3 ;}
done ${INSTALLROOT}/man/man3/setenviron.3 generated
make ${INSTALLROOT}/man/man3/sfdisc.3
make man/sfdisc.3
done man/sfdisc.3
exec - test '' = 'man/sfdisc.3' || ${STDCMP} 2>/dev/null -s man/sfdisc.3 ${INSTALLROOT}/man/man3/sfdisc.3 || { ${STDMV} ${INSTALLROOT}/man/man3/sfdisc.3 ${INSTALLROOT}/man/man3/sfdisc.3.old 2>/dev/null || true; ${STDCP} man/sfdisc.3 ${INSTALLROOT}/man/man3/sfdisc.3 ;}
done ${INSTALLROOT}/man/man3/sfdisc.3 generated
make ${INSTALLROOT}/man/man3/sfio.3
make man/sfio.3
done man/sfio.3

View file

@ -614,7 +614,7 @@ VDISABLE POSIX PC 1 FUW
VERSION POSIX SC 1 CDFSU 200112
VERSION POSIX SC 2 CDFSU 200112
VERSION XOPEN SC 1 CDFSU 600
VERSION AST XX 1 MS _AST_VERSION
VERSION AST XX 1 MS AST_VERSION
VERSION SVID SI 1 S
VERSION XPG SC 3 DFSU
VERSION XPG SC 4 DFSU

View file

@ -2412,7 +2412,7 @@ default_setlocale(int category, const char* locale)
/*
* workaround for Solaris and FreeBSD systems
* the call free() with addresses that look like the came from the stack
* they call free() with addresses that look like they came from the stack
*/
extern int _vmkeep(int);

View file

@ -1,6 +1,6 @@
iff AST_API
ver ast 20111111
ver ast 20220101
api ast 20120528 regexec regnexec regrexec regsubexec strgrpmatch

View file

@ -105,25 +105,19 @@ int asoloop(uintmax_t);
int asorelax(long);
.Ce
.SH DESCRIPTION
.PP
\fIASO\fP provides functions to perform atomic scalar operations.
The functions on the type \f3uint32_t\fP will be fully described below.
Other functions work similarly on their respective types.
Some of the functions may be macros that call other functions.
64 bit operations are provided if the compiler supports 64 bit integers and/or pointers.
.PP
.Ss "TYPES"
.PP
\f3uint8_t, uint16_t, uint32_t, uint64_t\fP
These are \fIunsigned integer\fP types of different sizes in bits.
For example, \f3uint32_t\fP represents the type of unsigned integer with 32 bits or 4 bytes.
.PP
.Ss "OPERATIONS"
.PP
.Ss " uint32_t asoget32(uint32_t* from);"
This function returns the value \f3*from\fP.
.PP
.Ss " uint32_t asoinc32(uint32_t* dest);"
.Ss " uint32_t asodec32(uint32_t* dest);"
These functions increment \f3*dest\fP by 1 and decrement \f3*dest\fP by 1 in an atomic step.
@ -138,19 +132,16 @@ That should be contrasted with a situation where, instead of \f3asoinc32()\fP or
only normal increment (++) or decrement (--) were used.
Then, the end result could be either \f3*dest += 1\fP or \f3*dest += 2\fP,
depending on states of the hardware cache and process scheduling.
.PP
.Ss " uint32_t asocas32(uint32_t* dest, uint32_t tstval, uint32_t newval);"
This function provides the atomic \fIcompare-and-swap\fP operation.
If the current content of \f3dest\fP is equal to \f3tstval\fP then it will be set to \f3newval\fP.
If multiple threads/processes are performing the same operations only one will succeed with a
return value of \f3tstval\fP.
The return value is the old value in \f3*dest\fP.
.PP
.Ss " void asorelax(long nsec)"
This function causes the calling process or thread to briefly pause
for \f3nsec\fP nanoseconds.
It is useful to implement tight loops that occasionally yield control.
.PP
.Ss " int asolock(unsigned int* lock, unsigned int key, int type)"
This function uses \f3key\fP, a non-zero unsigned integer, to lock or unlock the \f3lock\fP.
It returns \f30\fP on success and \f3-1\fP on failure.
@ -174,7 +165,6 @@ this call will always wait until the lock is open, then lock it with the given \
Note that, if the lock is already locked with \f3key\fP, this call can result
in a deadlock unless that lock can be opened by some other mechanism, e.g.,
by a different process or thread.
.PP
.Ss " int asoloop(uintmax_t iteration);"
This function is used to implement spin locks that periodically relinquish the processor:
.Cs
@ -194,9 +184,7 @@ If \f3Asodisc_t.hung != 0\fP and \f3Asodisc_t.errorf != 0\fP and
\f3iteration mod (2**Asodisc_t.hung-1)\fP is \f30\fP,
then \f3Asodisc_t.errorf\fP is called with type \f3ASO_HUNG\fP
and \f3-1\fP is returned.
.PP
.Ss "DISCIPLINE"
.PP
The Asodisc_t discipline structure allows the caller to modify default behavior.
The \fIASO\fP discipline is global for all threads and forked children of the current process.
The discipline is set and modified by the \f3asoinit()\fP function, described below.
@ -220,12 +208,9 @@ If \f3errorf\fP != \f30\fP then it is called for each \fIASO\fP fatal library co
\f32**Asometh_t.hung\fP times with no access to the loop resource.
\f3mesg\fP is a 0-terminated message description.
.Ss " void ASODISC(Asodisc_t* disc, Asoerror_f errorf);"
.PP
This function-like-macro initializes \f3disc->version = ASO_VERSION\fP, \f3disc->errorf = errorf\fP,
and the remaining \f3disc\fP members to \f30\fP.
.PP
.Ss "METHODS"
.PP
Several atomic locking methods are implemented for atomic operations
not supported by \fIintrinsic\fP functions or assembly instructions.
Methods are controlled by the \f3asometh()\fP and \f3asoinit()\fP
@ -337,7 +322,6 @@ if (data || !(asometh(0, 0)->type & (ASO_INTRINSIC|ASO_THREAD))) {
A multi-process application would check for \f3(ASO_INTRINSIC|ASO_PROCESS)\fP
instead of \f3(ASO_INTRINSIC|ASO_THREAD)\fP.
.PP
.SH IMPLEMENTATION NOTES
Unlike other \fIAST\fP library discipline/method functions which can instantiate
multiple discipline/method handles within a single process, the \fIASO\fP
@ -352,6 +336,5 @@ so the subsequent \fIASO\fP operation operates on the physical memory location
instead of the cached location. There is currently no other portable mechanism
that guarantees this other than the \f3ASO_INTRINSIC\fP method.
.PP
.SH AUTHOR
Kiem-Phong Vo, Adam Edgar, and Glenn Fowler

View file

@ -65,11 +65,11 @@ Dtmethod_t* Dtdeque;
.Cs
#define DTOFFSET(struct_s,member)
#define DTDISC(disc,key,size,link,makef,freef,comparf,hashf,memoryf,eventf)
typedef void* (*Dtmake_f)(Dt_t*, void*, Dtdisc_t*);
typedef void* (*Dtmake_f)(Dt_t*, void*, Dtdisc_t*);
typedef void (*Dtfree_f)(Dt_t*, void*, Dtdisc_t*);
typedef int (*Dtcompar_f)(Dt_t*, void*, void*, Dtdisc_t*);
typedef unsigned int (*Dthash_f)(Dt_t*, void*, Dtdisc_t*);
typedef void* (*Dtmemory_f)(Dt_t*, void*, size_t, Dtdisc_t*);
typedef void* (*Dtmemory_f)(Dt_t*, void*, size_t, Dtdisc_t*);
typedef int (*Dtevent_f)(Dt_t*, int, void*, Dtdisc_t*);
.Ce
.Ss "OBJECT OPERATIONS"
@ -115,31 +115,21 @@ unsigned int dtstrhash(unsigned int h, char* str, int n);
.PP
\fICdt\fP manages run-time dictionaries using standard container data types:
unordered set/multiset, ordered set/multiset, list, stack, and queue.
.PP
.Ss "DICTIONARY TYPES"
.PP
.Ss " void*"
This type is used to pass objects between \fICdt\fP and application code.
\f3void\fP is defined as \f3void\fP for ANSI C and C++
and \f3char\fP for older C compilation environments.
.PP
.Ss " Dt_t"
This is the type of a dictionary handle.
It contains a field \f3Dt_t.user\fP of type \f3Dtuser_t*\fP (see below).
.PP
.Ss " Dtdisc_t"
This defines the type of a discipline structure which define the lay-out of
an object and functions to compare, hash, make, delete objects, etc. (see \f3dtdisc()\fP).
.PP
.Ss " Dtmethod_t"
This defines the type of a container method.
.PP
.Ss " Dtlink_t"
This is the type of a dictionary object holder (see \f3dtdisc()\fP).
.PP
.Ss " Dtstat_t"
This is the type of a structure to return dictionary statistics (see \f3dtstat()\fP).
.PP
.Ss " Dtuser_t"
This is the type of a structure pointed to by \f3Dt_t.user\fP.
If a discipline function \f3memoryf()\fP was defined, this structure
@ -155,26 +145,21 @@ to use this structure in anyway that it sees fit.
void* data; /* for application-specific data */
} Dtuser_t;
.Ce
.PP
.Ss "DICTIONARY CONTROL"
.PP
.Ss " Dt_t* dtopen(const Dtdisc_t* disc, const Dtmethod_t* meth)"
This creates a new dictionary.
\f3disc\fP is a discipline structure to describe object format.
\f3meth\fP specifies a manipulation method.
\f3dtopen()\fP returns the new dictionary or \f3NULL\fP on error.
See also the events \f3DT_OPEN\fP and \f3DT_ENDOPEN\fP below.
.PP
.Ss " int dtclose(Dt_t* dt)"
This deletes \f3dt\fP and its objects.
Note that \f3dtclose()\fP fails if \f3dt\fP is being viewed by
some other dictionaries (see \f3dtview()\fP).
\f3dtclose()\fP returns \f30\fP on success and \f3-1\fP on error.
See also the events \f3DT_CLOSE\fP and \f3DT_ENDCLOSE\fP below.
.PP
.Ss " void dtclear(Dt_t* dt)"
This deletes all objects in \f3dt\fP without closing \f3dt\fP.
.PP
.Ss " Dtdisc_t* dtdisc(Dt_t* dt, const Dtdisc_t* disc, int type)"
If \f3disc\fP is \f3NULL\fP, \f3dtdisc()\fP returns the current discipline.
Otherwise, it changes the discipline of \f3dt\fP to \f3disc\fP.
@ -186,13 +171,11 @@ thus obviating the need for reordering or removing new duplicates.
thus obviating the need to rehash.
\f3dtdisc()\fP returns the previous discipline on success
and \f3NULL\fP on error.
.PP
.Ss " Dtmethod_t dtmethod(Dt_t* dt, const Dtmethod_t* meth)"
If \f3meth\fP is \f3NULL\fP, \f3dtmethod()\fP returns the current method.
Otherwise, it changes the storage method of \f3dt\fP to \f3meth\fP.
Objects may be rehashed, reordered, or removed as appropriate.
\f3dtmethod()\fP returns the previous method or \f3NULL\fP on error.
.PP
.Ss " Dt_t* dtview(Dt_t* dt, Dt_t* view)"
A viewpath allows a search or walk starting from a dictionary to continue to another.
\f3dtview()\fP first terminates any current view from \f3dt\fP to another dictionary.
@ -204,7 +187,6 @@ It is an error to have dictionaries on a viewpath with different storage methods
In addition, dictionaries on the same view path should
treat objects in a consistent manner with respect to comparison or hashing.
If not, undefined behaviors may result.
.PP
.Ss " int dtcustomize(Dt_t* dt, int type, int action)"
This customizes a storage method. The \f3type\fP argument
is composed of bits indicating different types of customization.
@ -228,7 +210,6 @@ by the operation before returning (See the DISCIPLINE section below).
This causes the underlying method to optimize its internal
data structure. For example, the splay tree underlying \f3Dtoset\fP
would be balanced.
.PP
.Ss " int dtuserlock(Dt_t* dt, unsigned int key, int action)"
This manipulates the lock \f3dt->user->lock\fP.
It returns 0 on success and -1 on failure.
@ -253,35 +234,29 @@ is just a service provided to the
application for their own use and has nothing to do with dictionary operations
which may or may not employ their own locking schemes based on the semantics
of the container data structures in use.
.PP
.Ss " void* dtuserdata(Dt_t* dt, void* data, int set)"
This function returns the current value of \f3dt->user->data\fP.
In addition, if \f3set\fP is non-zero,
the value of \f3dt->user->data\fP will be changed to \f3data\fP.
.PP
.Ss " int dtuserevent(Dt_t* dt, int flags, void* data)"
This function invokes the discipline event function
with the event \f3DT_ANNOUNCE|DT_USER|flags\fP and the given data.
.PP
.Ss "STORAGE METHODS"
.PP
Storage methods are of type \f3Dtmethod_t*\fP.
\fICdt\fP supports the following methods:
.PP
.Ss " Dtoset"
.Ss " Dtobag"
Objects are ordered by comparisons.
\f3Dtoset\fP keeps unique objects.
\f3Dtobag\fP allows repeatable objects.
.PP
.Ss " Dtset"
.Ss " Dtbag"
Objects are unordered.
\f3Dtset\fP keeps unique objects.
\f3Dtbag\fP allows repeatable objects.
The underlying data structure is a hash table with chaining to handle collisions.
.PP
.Ss " Dtrhset"
.Ss " Dtrhbag"
These methods are like \f3Dtset\fP and \f3Dtbag\fP but are based on
@ -289,7 +264,6 @@ a recursive hashing data structure that allows table extension without
object relocation. The data structure also supports lock-free
concurrent search operations for shared dictionaries and nearly lock-free
insertions and deletions.
.PP
.Ss " Dtlist"
Objects are kept in a list.
\fIA current object\fP is always defined to be either the head of
@ -297,22 +271,18 @@ the list or an object resulting from a recent search or insert operation.
The calls \f3dtinsert()\fP and \f3dtinstall()\fP will insert a new object
in front of such a current object
while the call \f3dtappend()\fP will append in back of it.
.PP
.Ss " Dtdeque"
Objects are kept in a deque. This is similar to \f3Dtlist\fP
except that objects are always inserted at the front and appended at the tail
of the list.
.PP
.Ss " Dtstack"
Objects are kept in a stack, i.e., in reverse order of insertion.
Thus, the last object inserted is at stack top
and will be the first to be deleted.
.PP
.Ss " Dtqueue"
Objects are kept in a queue, i.e., in order of insertion.
Thus, the first object inserted is at queue head
and will be the first to be deleted.
.PP
.Ss "DISCIPLINE"
.PP
Object format and associated management functions are
@ -338,7 +308,6 @@ If \f3size\fP is zero, the key is a null-terminated string with starting address
\f3(void*)((char*)obj+key)\fP.
Finally, if \f3size\fP is positive, the key is a byte array of length \f3size\fP
starting at \f3(void*)((char*)obj+key)\fP.
.PP
.Ss " ssize_t link"
Let \f3obj\fP be an object to be inserted into \f3dt\fP.
If \f3link\fP is negative, an object holder of type \f3Dtlink_t\fP
@ -346,18 +315,15 @@ will be allocated to hold \f3obj\fP.
Otherwise, \f3obj\fP should have
a \f3Dtlink_t\fP structure embedded \f3link\fP bytes into it,
i.e., at address \f3(Dtlink_t*)((char*)obj+link)\fP.
.PP
.Ss " void* (*makef)(Dt_t* dt, void* obj, Dtdisc_t* disc)"
If \f3makef\fP is not \f3NULL\fP,
\f3dtinsert()\fP, \f3dtinstall()\fP or \f3dtappend()\fP will call it
to make a copy of \f3obj\fP suitable for insertion into \f3dt\fP.
If \f3makef\fP is \f3NULL\fP, \f3obj\fP itself will be inserted into \f3dt\fP.
.PP
.Ss " void (*freef)(Dt_t* dt, void* obj, Dtdisc_t* disc)"
If not \f3NULL\fP,
\f3freef\fP is used to destroy data associated with \f3obj\fP.
.PP
.Ss "int (*comparf)(Dt_t* dt, void* key1, void* key2, Dtdisc_t* disc)"
.Ss " int (*comparf)(Dt_t* dt, void* key1, void* key2, Dtdisc_t* disc)"
If not \f3NULL\fP, \f3comparf\fP is used to compare two keys.
Its return value should be \f3<0\fP, \f3=0\fP, or \f3>0\fP to indicate
whether \f3key1\fP is smaller, equal to, or larger than \f3key2\fP.
@ -366,14 +332,12 @@ For other methods, a zero value
indicates equality and a non-zero value indicates inequality.
If \f3(*comparf)()\fP is \f3NULL\fP, an internal function is used
to compare the keys as defined by the \f3Dtdisc_t.size\fP field.
.PP
.Ss " unsigned int (*hashf)(Dt_t* dt, void* key, Dtdisc_t* disc)"
If not \f3NULL\fP,
\f3hashf\fP is used to compute the hash value of \f3key\fP.
It is required that keys compared equal will also have same hash values.
If \f3hashf\fP is \f3NULL\fP, an internal function is used to hash
the key as defined by the \f3Dtdisc_t.size\fP field.
.PP
.Ss " void* (*memoryf)(Dt_t* dt, void* addr, size_t size, Dtdisc_t* disc)"
If not \f3NULL\fP, \f3memoryf\fP is used to allocate and free memory.
When \f3addr\fP is \f3NULL\fP, a memory segment of size \f3size\fP is requested.
@ -381,7 +345,6 @@ If \f3addr\fP is not \f3NULL\fP and \f3size\fP is zero, \f3addr\fP is to be free
If \f3addr\fP is not \f3NULL\fP and \f3size\fP is positive,
\f3addr\fP is to be resized to the given size.
If \f3memoryf\fP is \f3NULL\fP, \fImalloc(3)\fP is used.
.PP
.Ss " int (*eventf)(Dt_t* dt, int type, void* data, Dtdisc_t* disc)"
If not \f3NULL\fP, \f3eventf\fP announces various events.
Each event may have particular handling of the return values from \f3eventf\fP.
@ -488,18 +451,14 @@ For \f3dtinsert()\fP, the former case will be announced as \f3DT_ANNOUNCE|DT_INS
the latter as \f3DT_ANNOUNCE|DT_INSERT|DT_SEARCH\fP.
For \f3dtattach()\fP, the events will be similarly announced as \f3DT_ANNOUNCE|DT_ATTACH\fP
and \f3DT_ANNOUNCE|DT_ATTACH|DT_SEARCH\fP.
.PP
.Ss "#define DTOFFSET(struct_s,member)"
This macro function computes the offset of \f3member\fP from the start
of structure \f3struct_s\fP. It is useful for getting the offset of
a \f3Dtlink_t\fP embedded inside an object.
.PP
.Ss "#define DTDISC(disc,key,size,link,makef,freef,comparf,hashf,memoryf,eventf)"
This macro function initializes the discipline pointed to by \f3disc\fP
with the given values.
.PP
.Ss "OBJECT OPERATIONS"
.PP
.Ss " void* dtinsert(Dt_t* dt, void* obj)"
.Ss " void* dtinstall(Dt_t* dt, void* obj)"
.Ss " void* dtappend(Dt_t* dt, void* obj)"
@ -516,7 +475,6 @@ object then insert the new object.
On failure, \f3dtinsert()\fP and \f3dtinstall()\fP return \f3NULL\fP.
Otherwise, the return value is either the newly inserted object
or the matching object as noted.
.PP
.Ss " void* dtdelete(Dt_t* dt, void* obj)"
.Ss " void* dtremove(Dt_t* dt, void* obj)"
When \f3obj\fP is not \f3NULL\fP, \f3dtdelete()\fP removes some object \fImatching\fP \f3obj\fP
@ -525,22 +483,18 @@ When \f3obj\fP is \f3NULL\fP, if the method is \f3Dtstack\fP or \f3Dtqueue\fP
then the stack top or queue head is respectively deleted.
See \f3Dtdisc_t.freef\fP for object destruction.
\f3dtdelete()\fP and \f3dtremove()\fP return the deleted object or \f3NULL\fP.
.PP
.Ss " void* dtattach(Dt_t* dt, void* obj)"
This function is similar to \f3dtinsert()\fP but \f3obj\fP itself
will be inserted into \f3dt\fP even if a discipline
function \f3makef\fP is defined.
.PP
.Ss " void* dtdetach(Dt_t* dt, void* obj)"
This function is similar to \f3dtdelete()\fP but the object to be deleted
from \f3dt\fP will not be freed (via the discipline \f3freef\fP function).
.PP
.Ss " void* dtsearch(Dt_t* dt, void* obj)"
.Ss " void* dtmatch(Dt_t* dt, void* key)"
These functions find an object matching \f3obj\fP or \f3key\fP either from \f3dt\fP or
from some dictionary accessible from \f3dt\fP via a viewpath (see \f3dtview()\fP).
The return value is the matching object or \f3NULL\fP.
.PP
.Ss " void* dtfirst(Dt_t* dt)"
.Ss " void* dtnext(Dt_t* dt, void* obj)"
.Ss " void* dtlast(Dt_t* dt)"
@ -584,7 +538,6 @@ If it is not in the dictionary but still matching a group of objects,
then the returned object will be immediately after the last or before the first
of the group respectively.
.PP
.PP
.Ss " void* dtatleast(Dt_t* dt, void* obj)"
.Ss " void* dtatmost(Dt_t* dt, void* obj)"
\f3dtatleast()\fP returns the smallest object greater or equal to \f3obj\fP.
@ -603,7 +556,6 @@ on an object not in the dictionary and still get a meaningful result.
Storage methods other than \f3Dtoset\fP and \f3Dtobag\fP do not have
an explicit ordering so \f3dtatmost()\fP
and \f3dtatleast()\fP will return \f3NULL\fP when there are no matching objects.
.PP
.Ss " dtwalk(Dt_t* dt, int (*userf)(Dt_t*, void*, void*), void* data)"
This function calls \f3(*userf)(walk,obj,data)\fP on each object in \f3dt\fP and
other dictionaries viewable from it.
@ -611,7 +563,6 @@ other dictionaries viewable from it.
If \f3userf()\fP returns a \f3<0\fP value,
\f3dtwalk()\fP terminates and returns the same value.
\f3dtwalk()\fP returns \f30\fP on completion.
.PP
.Ss " Dtlink_t* dtflatten(Dt_t* dt)"
.Ss " Dtlink_t* dtlink(Dt_t* dt, Dtlink_t* link)"
.Ss " void* dtobj(Dt_t* dt, Dtlink_t* link)"
@ -637,7 +588,6 @@ Beware that a flattened object list is not guaranteed to maintain integrity
if any dictionary operation other than \f3dtlink()\fP is performed
(for example, this is important to watch out for
if a dictionary is in \f3DT_SHARE\fP mode).
.PP
.Ss " void* dtstart(Dt_t* dt, void* obj);"
This function starts a path for walking a dictionary.
Note that such a path is restricted to \f3dt\fP only while disregarding
@ -649,10 +599,8 @@ Otherwise, \f3NULL\fP is returned.
If \f3obj\fP is \f3NULL\fP, the path starts at the same object returned by \f3dtfirst()\fP.
If \f3obj\fP is not \f3NULL\fP, it must match some object in the dictionary \f3dt\fP
and the path will start there. No matching object will result in error.
.PP
.Ss " void* dtstop(Dt_t* dt, void* path);"
This function ends a path and releases all memory source associated with it.
.PP
.Ss " void* dtstep(Dt_t* dt, void* path);"
This function returns the object at current position in the given \f3path\fP.
Successive calls move forward one object at a time in the same order that \f3dtnext()\fP
@ -672,7 +620,6 @@ most efficient manner possible as supported by the underlying data structures.
}
dtstop(dt, path);
.Ce
.PP
.Ss " Dtlink_t* dtextract(Dt_t* dt)"
.Ss " Dtlink_t* dtrestore(Dt_t* dt, Dtlink_t* list)"
\f3dtextract()\fP extracts the list of objects from \f3dt\fP and makes it appear empty.
@ -682,9 +629,7 @@ It is important that the same discipline and method are in use at both
extraction and restoration. Otherwise, undefined behaviors may result.
These functions return \f3NULL\fP on error.
.PP
.Ss "DICTIONARY INFORMATION"
.PP
.Ss " Dt_t* dtvnext(Dt_t* dt)"
This returns the dictionary that \f3dt\fP is viewing, if any.
.Ss " ssize_t dtvcount(Dt_t* dt)"
@ -694,7 +639,6 @@ This returns the dictionary \f3v\fP viewable from \f3dt\fP
where an object was found from the most recent search or walk operation.
.Ss " ssize_t dtsize(Dt_t* dt)"
This function returns the number of objects stored in \f3dt\fP.
.PP
.Ss " ssize_t dtstat(Dt_t *dt, Dtstat_t* st)"
This function reports dictionary statistics.
It returns the number of objects stored in \f3dt\fP.
@ -727,9 +671,7 @@ The reported levels is limited to less than \f3DT_MAXSIZE\fP.
.Tp
\f3char* mesg\fP:
A summary message of some of the statistics.
.PP
.Ss "HASH FUNCTIONS"
.PP
.Ss " unsigned int dtstrhash(unsigned int h, char* str, int n)"
This function computes a new hash value from string \f3str\fP and seed value \f3h\fP.
If \f3n\fP is positive, \f3str\fP is a byte array of length \f3n\fP;

View file

@ -1,118 +0,0 @@
.fp 5 CW
.TH SFDISC 3 "16 June 1993"
.SH NAME
\fBsfdisc\fR \- \fBsfio\fP disciplines
.SH SYNOPSIS
.de Tp
.fl
.ne 2
.TP
..
.de Ss
.fl
.ne 2
.SS "\\$1"
..
.ta 1.0i 2.0i 3.0i 4.0i 5.0i
.nf
.ft 5
#include <sfdisc.h>
extern Sfdisc_t* dcnewskable(Sfio_t* f);
extern int dcdelskable(Sfdisc_t* disc);
extern Sfdisc_t* dcnewtee(Sfio_t* tee);
extern int dcdeltee(Sfdisc_t* disc);
extern Sfdisc_t* dcnewfilter(char* cmd);
extern int dcdelfilter(Sfdisc_t* disc);
extern Sfdisc_t* dcnewsubstream(Sfio_t* f, long offset, long extent);
extern int dcdelsubstream(Sfdisc_t* disc);
extern Sfdisc_t* dcnewlzw(void);
extern int dcdellzw(Sfdisc_t* disc);
extern Sfdisc_t* dcnewunion(Sfio_t** flist, int n);
extern int dcdelunion(Sfdisc_t* disc);
.ft 1
.fi
.SH DESCRIPTION
.PP
I/O disciplines are used to extend the data processing power of
\fIsfio\fP streams. The convention for using the disciplines
in this package is to use the call \f3dcnewXXX()\fP to create
a discipline of the type \f3XXX\fP and to use \f3dcdelXXX()\fP
to destroy it.
A discipline is enable by inserting it into the desired
stream using the \f3sfdisc()\fP call. A discipline can be used on only
one stream. It is unsafe to share a discipline on two or more streams
since the discipline may maintain states between successive IO calls.
For multiple uses, \f3dcnewXXX()\fP should be used
to create a distinct discipline for each stream.
Each discipline structure is equipped with an exception handler
that causes self-destruction when the associated stream is closed.
.PP
.Ss " Sfdisc_t* dcnewskable(Sfio_t* f);"
.Ss " int dcdelskable(Sfdisc_t* disc);"
\f3dcnewskable()\fP creates a discipline that when inserted
on the stream \f3f\fP will ensure that \f3f\fP is seekable.
If \f3f\fP is originally unseekable, data will be shadowed
in a temporary file stream to allow seekability.
\f3dcnewskable()\fP returns the discipline on success and \f3NULL\fP on failure.
.Ss " Sfdisc_t* dcnewtee(Sfio_t* tee);"
.Ss " int dcdeltee(Sfdisc_t* disc);"
\f3dcnewtee()\fP creates a discipline that
when inserted into a stream \f3f\fP will duplicate to the stream \f3tee\fP
any data written to \f3f\fP.
\f3dcnewtee()\fP returns the discipline on success and \f3NULL\fP on failure.
.Ss " Sfdisc_t* dcnewfilter(char* cmd);"
.Ss " int dcdelfilter(Sfdisc_t* disc);"
\f3dcnewfilter()\fP creates a discipline that
when inserted into a stream \f3f\fP will run the command \f3cmd\fP
to process any input data before making it available to the application.
For example, \f3dcnewfilter("uncompress")\fP is an equivalent but slower
alternative to the lzw discipline below.
\f3dcnewfilter()\fP returns the discipline on success and \f3NULL\fP on failure.
.Ss " Sfdisc_t* dcnewsubstream(Sfio_t* base, long offset, long extent);"
.Ss " int dcdelsubstream(Sfdisc_t* disc);"
\f3dcnewsubstream()\fP creates a discipline that
reserves a portion of the stream \f3base\fP starting at \f3offset\fP
with length \f3extent\fP and makes this portion appear as if it is
a stream. When this discipline is inserted into a stream, it will make
cause all IO operations on this stream to take place in the reserved
portion of the \f3base\fP stream.
\f3dcnewsubstream()\fP returns the discipline on success and \f3NULL\fP on failure.
.Ss " Sfdisc_t* dcnewlzw(void);
.Ss " int dcdellzw(Sfdisc_t* disc);"
\f3dcnewlzw()\fP creates a discipline that when inserted into
a stream \f3f\fP will run the \fBuncompress\fP algorithm
on input data from \f3f\fP before making it available to the
application. This is useful to allow applications to process
data from a file packed with the UNIX \fBcompress\fP utility
as if the data is in plain text.
\f3dcnewlzw()\fP returns the discipline on success and \f3NULL\fP on failure.
.Ss " Sfdisc_t* dcnewunion(Sfio_t** list, int n);
.Ss " int dcdelunion(Sfdisc_t* disc);"
\f3dcnewunion()\fP creates a discipline that concatenates
input data from all \f3n\fP streams in \f3list\fP.
When inserted into a stream \f3f\fP, this discipline will cause
all input operations on \f3f\fP to come from the merged data stream.
\f3dcnewunion()\fP returns the discipline on success and \f3NULL\fP on failure.
.SH ACKNOWLEDGMENTS
Dave Korn contributed the substream discipline.
Jim Arnold contributed the lzw discipline.
.SH NOTES
Since we are not sure of the legal responsibilities concerning the lzw patent,
the lzw discipline is not currently distributed with any release of sfio
outside of AT&T.
.SH AUTHOR
Kiem-Phong Vo, kpv@research.att.com.

View file

@ -306,7 +306,6 @@ There are three \fIstandard streams\fP:
\f3sfstdout\fP for normal output (file descriptor \f31\fP), and
\f3sfstderr\fP for error output (file descriptor \f32\fP).
.PP
.Ss "LIBRARIES"
.PP
This version of Sfio can be built and used for both single-threaded and multi-threaded
@ -321,26 +320,20 @@ The libraries \fBlibstdio.a\fP and \fBlibstdio-mt.a\fP provide
corresponding Stdio functions to link with code already compiled using the
native header \fBstdio.h\fP instead of the one provided by Sfio.
.PP
.Ss "DATA TYPES"
.PP
.Ss " void*"
This defines a type suitable to exchange
data of unknown types between application and Sfio.
\f3void\fP is a macro defined as \f3void\fP for ANSI C and C++ and
\f3char\fP for other compilation environments.
.PP
.Ss " Sfoff_t"
This defines an integral type suitable to address
the largest possible file extent.
.PP
.Ss " Sfulong_t, Sflong_t, Sfdouble_t"
These are respectively the largest
unsigned integer, signed integer, and floating point value types on the local platform.
.PP
.Ss " Sfio_t"
This defines the type of a stream handle.
.PP
.Ss " Sfdisc_t"
.Ss " ssize_t (*Sfread_f)(Sfio_t*, void*, size_t, Sfdisc_t*)"
.Ss " ssize_t (*Sfwrite_f)(Sfio_t*, const void*, size_t, Sfdisc_t*)"
@ -352,7 +345,6 @@ of discipline functions to replace the system calls:
\f3read(2)\fP, \f3write(2)\fP and \f3lseek(2)\fP.
\f3Sfexcept_f\fP is the type of an event-handling function.
See \f3sfdisc()\fP for more details.
.PP
.Ss " Sffmt_t"
.Ss " int (*Sffmtext_f)(Sfio_t*, void*, Sffmt_t*)"
.Ss " int (*Sffmtevent_f)(Sfio_t*, int, void*, Sffmt_t*)"
@ -361,7 +353,6 @@ to extend scanning and printing in the \f3sfprint()/sfscanf()\fP
functions. \f3Sffmtext_f\fP and \f3Sffmtevent_f\fP define the types
of extension functions definable in \f3Sffmt_t\fP.
See \f3Sffmt_t\fP below for more details.
.PP
.Ss " SFIO_VERSION"
This is a macro value of type \f3long int\fP that defines
the current version number of Sfio. For example, the Sfio2000's
@ -462,9 +453,7 @@ that certain operating systems (e.g., BSD Unix systems) may automatically
resume interrupted system calls outside the scope of the library. On such systems,
\f3SF_IOINTR\fP will be ineffective.
.PP
.Ss "OPENING/CLOSING STREAMS"
.PP
.Ss " Sfio_t* sfnew(Sfio_t* f, void* buf, size_t size, int fd, int flags)"
This function creates or renews a stream.
It returns the new stream on success and \f3NULL\fP on error.
@ -622,7 +611,6 @@ In either case, if the exception handler returns a negative value,
If the exception handler returns a positive value,
\f3sfclose()\fP will immediately return a zero value.
.PP
.Ss "THREAD SAFETY"
.PP
The libraries \f3libsfio.a\fP and \f3libstdio.a\fP (providing binary
@ -648,7 +636,6 @@ the flag \f3SF_MTSAFE\fP or the option \f3m\fP were specified.
Stdio-based code can also make a Stdio stream single-threaded by
using the option \f3u\fP when opening a file.
.PP
.Ss "int sfmutex(Sfio_t* f, int type)"
This function acquires or releases a mutex
(mutually exclusive) lock on the stream \f3f\fP.
@ -691,9 +678,7 @@ Resetting the lock count to \f30\fP and releasing the stream.
As with \f3SFMTX_LOCK\fP,
an attempt to clear the lock count without a previously successful lock
may result in undefined behavior.
.PP
.Ss "INPUT/OUTPUT OPERATIONS"
.PP
.Ss " int sfgetc(Sfio_t* f)"
.Ss " int sfputc(Sfio_t* f, int c)"
These functions read/write a byte from/to stream \f3f\fP.
@ -932,7 +917,6 @@ then rewrites the new data back to the stream:
.fi
.ne 6
.PP
.Ss "DATA FORMATTING"
.PP
Data printing and scanning are done via the
@ -1411,7 +1395,6 @@ to be passed to the extension function \f3Sffmt_t.extf\fP.
Parentheses shall be balanced.
If \f3extfdata\fP is \f3*\fP, the string is obtained from the argument list.
.PP
.Ss " int sfscanf(Sfio_t* f, const char* format, ...)"
.Ss " int sfsscanf(const char* s, const char* format, ...)"
.Ss " int sfvsscanf(const char* s, const char* format, va_list args)"
@ -1568,9 +1551,7 @@ If \fIbase\fP is larger than \f336\fP, the set of digits is:
.ft 1
.fi
.PP
.Ss "BUFFERING, SYNCHRONIZATION"
.PP
.Ss " void* sfsetbuf(Sfio_t* f, void* buf, size_t size)"
This function changes the buffering scheme for the stream \f3f\fP.
The stream will be synchronized before any buffer modification.
@ -1698,7 +1679,6 @@ After purging, if \f3f\fP has flag \f3SF_IOCHECK\fP,
the event \f3SF_PURGE\fP is raised.
\f3sfpurge()\fP returns \f3-1\fP for failure and \f30\fP for success.
.PP
.Ss "DISCIPLINE, EVENT-HANDLING"
.PP
A file stream uses the system calls \f3read(2)\fP, \f3write(2)\fP
@ -1891,9 +1871,7 @@ They should not be used in any other context.
On error, all three functions return a negative value which should be \f3-1\fP
or the value returned by the exception handler.
.PP
.Ss "STREAM CONTROL"
.PP
.Ss " int sfresize(Sfio_t* f, Sfoff_t size)"
This function resizes the stream \f3f\P so that its extent is \f3size\fP.
If the stream corresponds to a file, the file size is set to \f3size\fP
@ -1976,9 +1954,7 @@ If \f3f2\fP is \f3NULL\fP, a new stream is constructed as a duplicate of \f3f1\f
\f3sfswap()\fP returns \f3f2\fP or \f3f1\fP duplicate on success and
\f3NULL\fP on failure.
.PP
.Ss "STREAM INFORMATION"
.PP
.Ss " Sfoff_t sfsize(Sfio_t* f)"
This function returns the size of stream \f3f\fP (see \f3sfnew()\fP).
If \f3f\fP is not seekable or if its size is not determinable,
@ -2070,9 +2046,7 @@ opened for reading. Similarly, \f3sfwalk(walkf, data, SF_READ|SF_WRITE)\fP
iterates over all streams opened for both reading and writing.
Lastly, \f3sfwalk(walkf, data, 0)\fP iterates over all streams.
.PP
.Ss "MISCELLANEOUS FUNCTIONS"
.PP
.Ss " ssize_t sfmaxr(ssize_t maxr, int set)"
Certain records may require too much memory for storage, thus, causing
undesirable side effects. Therefore, the library normally bounds the amount
@ -2122,9 +2096,7 @@ If \f3action <= 0\fP, \f3sfpkrd()\fP will not peek and there are two cases.
If \f3rsc < 0\fP, an attempt is made to read \f3n\fP bytes.
If \f3rsc >= 0\fP, an attempt is made to read one record.
.PP
.Ss "FULL STRUCTURE SFIO_T"
.PP
.Ss " #include <sfio_t.h>"
Most applications based on Sfio only need to include
the header file \f3sfio.h\fP which defines an abbreviated \f3Sfio_t\fP
@ -2152,7 +2124,6 @@ This is composed from bit flags described above.
\f3disc\fP:
This defines a discipline if any.
.PP
.Ss "EXAMPLE DISCIPLINES"
.PP
The below functions create disciplines and insert them into
@ -2201,7 +2172,6 @@ the Unix \fBcompress\fP program.
This creates a discipline for reading/writing data compressed by zlib.
The argument \f3opt\fP defines the optimization level.
.PP
.Ss "STDIO-COMPATIBILITY"
.PP
Sfio provides compatibility functions for all various popular
@ -2301,7 +2271,6 @@ int clearerr(FILE* stream);
.ft 1
.fi
.PP
.Ss "RECENT CHANGES"
.PP
A few exception types have been added. In particular, exception handlers shall

View file

@ -21,7 +21,7 @@
* *
***********************************************************************/
static const char id[] = "\n@(#)$Id: ast (AT&T Research) 2012-05-28 $\0\n";
static const char id[] = "\n@(#)$Id: ast (ksh 93u+m) $\0\n";
#include <ast.h>
@ -36,7 +36,7 @@ _Ast_info_t _ast_info =
0,0,
1, /* mb_cur_max */
0,0,0,0,0,0,0,
20100102 /* version */
AST_VERSION /* version */
};
__EXTERN__(_Ast_info_t, _ast_info);