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 (see71934570
,ca3ec200
) and astconf_long (seec2ac69b2
), 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:
parent
07fc64f52b
commit
e569f23ef9
25 changed files with 58 additions and 300 deletions
|
@ -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 ---
|
||||
|
|
|
@ -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'))
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
# ======
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
||||
# ======
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
iff AST_API
|
||||
|
||||
ver ast 20111111
|
||||
ver ast 20220101
|
||||
|
||||
api ast 20120528 regexec regnexec regrexec regsubexec strgrpmatch
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue